(English version) An dieser Stelle will ich auf ein nützliches Programm hinweisen:
TinyCAD
Mit diesem Programm kann man auf extrem einfache Weise Schaltkreise zeichnen und als Bild exportieren, kein Account erstellen oder ähnliches ist nötig. Einarbeitungszeit benötigt es auch keine, alles funktioniert intuitiv.
Eine Sammlung von meinen Projekten aus den Bereichen Physik, Elektronik, Informatik und sogar ein bisschen Botanik. Dieser Blog soll einerseits Hilfestellung bei Problemen geben aber andererseits auch als Anregung für weitere Projekte dienen. Falls es zu einem Thema Fragen oder Anregungen gibt: Einfach schnell einen Kommentar schreiben oder das Kontaktformular rechts unten benutzen, ich beantworte das normalerweise innerhalb von einem Tag.
AdSense
Montag, 17. Februar 2014
LED-Band mit ATmega / Arduino ansteuern
(English version) In letzter Zeit erfreuen sich LED-Streifen erhöhter Beliebtheit. Inzwischen gibt es sogar schon für Preise unter 20 Euro LED-Streifen aus China bei Ebay. Normalerweise hat ein LED-Streifen ein Steuergerät, ein Netzteil und eine Fernbedienung. Für die meisten Menschen mag das reichen, wer aber mehr will (z.B. gezielt Sequenzen durchfahren) der muss ein (ganz kleines) bisschen Arbeit hineinstecken.
Zuerst zum Aufbau des LED-Streifens: Es gibt 4 Anschlüsse, einer für + 12 V und dann noch einen je Farbe, also rot, grün und blau. Der Streifen funktioniert nun so: Schließt man + 12 V an und legt dann an einen Farb-Kanal Masse, so leuchtet diese Farbe. Die Helligkeit pro Farbe wird normalerweise per PWM eingestellt. Um den Streifen komplett selber anzusteuern braucht man jetzt:
Vom Microcontroller wird der entsprechende Kanal folgendermaßen geschaltet:
Dieser Befehl würde nun den Transistor, welcher an Pin 8 angeschlossen ist auf 50% setzen (255 ist Maximum), sodass die daran angeschlossene Farbe mit 50% der Helligkeit leuchtet. Zu beachten ist, dass man natürlich nur PWM-Kanäle benutzen kann (Im Datenblatt sind PWM-Kanäle mit OCR gekennzeichnet).
Um nun beliebige Farben zu mischen geht man folgendermaßen vor:
Man sucht sich eine Farbe im RGB-Raum aus, z.B. orange: diese ist R: 255, G: 255, B:0. Genau das lässt man nun den Microcontroller machen:
Es kann vorkommen dass verschiedene Farben unterschiedlich hell sind, das müsste man ausprobieren und dann z.B. für grün 127 als obere Grenze festlegen (grün wird vom Auge sehr stark wahrgenommen, daher wird es vermutlich zu hell erscheinen).
Zuerst zum Aufbau des LED-Streifens: Es gibt 4 Anschlüsse, einer für + 12 V und dann noch einen je Farbe, also rot, grün und blau. Der Streifen funktioniert nun so: Schließt man + 12 V an und legt dann an einen Farb-Kanal Masse, so leuchtet diese Farbe. Die Helligkeit pro Farbe wird normalerweise per PWM eingestellt. Um den Streifen komplett selber anzusteuern braucht man jetzt:
- Einen Microcontroller (ATmega / Arduino).
- 3 bipolare Transistoren (NPN), diese sollten einen ausreichend hohen Strom vertragen!
Vom Microcontroller wird der entsprechende Kanal folgendermaßen geschaltet:
analogWrite(8, 127);
Dieser Befehl würde nun den Transistor, welcher an Pin 8 angeschlossen ist auf 50% setzen (255 ist Maximum), sodass die daran angeschlossene Farbe mit 50% der Helligkeit leuchtet. Zu beachten ist, dass man natürlich nur PWM-Kanäle benutzen kann (Im Datenblatt sind PWM-Kanäle mit OCR gekennzeichnet).
Um nun beliebige Farben zu mischen geht man folgendermaßen vor:
Man sucht sich eine Farbe im RGB-Raum aus, z.B. orange: diese ist R: 255, G: 255, B:0. Genau das lässt man nun den Microcontroller machen:
analogWrite(RED_PIN, 255);
analogWrite(GREEN_PIN, 255);
analogWrite(BLUE_PIN, 0);
Es kann vorkommen dass verschiedene Farben unterschiedlich hell sind, das müsste man ausprobieren und dann z.B. für grün 127 als obere Grenze festlegen (grün wird vom Auge sehr stark wahrgenommen, daher wird es vermutlich zu hell erscheinen).
Kategorien:
Arduino,
ATmega,
Beleuchtung
Sonntag, 16. Februar 2014
"Home Automation" mit dem Arduino und 433 MHz - Die komplette Fernsteuerung
(English version) Seit meinem letzten Beitrag zu diesem Thema sind ja nun einige Monate vergangen. Aber nun habe ich es endlich mal geschafft, die Steuerung für die Steckdose und den Rolladen in ein Programm zu bringen und vorallem das ganze vom Steckbrett auf eine Platine zu übertragen.
Hardware
Die Hardware ist recht unspektakulär:
Im Prinzip besteht die Fernbedinung nur aus einem Attiny44A, einem Pullup-Widerstand für den Reset-Eingang, drei Knöpfen (hoch, runter, stopp), einem Halter für eine CR3032-Knopfzelle und natürlich dem 433MHz-Sender. Die drei Knöpfe sind jeweils mit einem Eingang des Attiny verbunden und ziehen den Eingang bei Betätigung auf Ground
Software
Die einzelnen Funktionen der Software wurden bereits in den vorhergehenden Posts zum Thema erläutert. Außerdem ist der Code (für meine Verhältnisse) gut kommentiert. Ich werde daher nicht auf den kompletten Code eingehen.
Hardware
Die Hardware ist recht unspektakulär:
Im Prinzip besteht die Fernbedinung nur aus einem Attiny44A, einem Pullup-Widerstand für den Reset-Eingang, drei Knöpfen (hoch, runter, stopp), einem Halter für eine CR3032-Knopfzelle und natürlich dem 433MHz-Sender. Die drei Knöpfe sind jeweils mit einem Eingang des Attiny verbunden und ziehen den Eingang bei Betätigung auf Ground
Software
Die einzelnen Funktionen der Software wurden bereits in den vorhergehenden Posts zum Thema erläutert. Außerdem ist der Code (für meine Verhältnisse) gut kommentiert. Ich werde daher nicht auf den kompletten Code eingehen.
#include <RCSwitch.h> #include <avr/sleep.h> #include <avr/wdt.h> RCSwitch mySwitch = RCSwitch(); unsigned char buttonDown = 10; unsigned char buttonStopp = 9; unsigned char buttonUp = 7; unsigned char buttonPressed = 0; char stopRequest = 0; void setup() { //Interrupts global deaktivieren cli(); //Pins initialisieren pinMode(buttonDown, INPUT_PULLUP); pinMode(buttonStopp, INPUT_PULLUP); pinMode(buttonUp, INPUT_PULLUP); //Funkmodul intialisieren und Steckdose ausschalten mySwitch.enableTransmit(0); //Sender hängt an Pin 0 mySwitch.setProtocol(1); mySwitch.switchOff("11011", "10000"); //Energie sparen ADCSRA &= ~(1<<ADEN); //Deaktiviere ADC ACSR = (1<<ACD); //Deaktiviere Analog Comparator //Pin-Change-Interrupt intialisieren PCMSK1 |= (1<<PCINT8); //Pin-Change-Interrupt an Pin 2 (Arduino Pin 10) PCMSK1 |= (1<<PCINT9); //Pin-Change-Interrupt an Pin 3 (Arduino Pin 9) PCMSK0 |= (1<<PCINT7); //Pin-Change-Interrupt an Pin 6 (Arduino Pin 7) //Power-Down-Modus vorbereiten set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Interrupts global aktivieren sei(); } void loop() { sendCommand(); powerDown(); } void sendCommand() { if (buttonPressed == buttonDown) { mySwitch.switchOn("11011", "10000"); delay(750); sendCommandDown(); powerDown(25); mySwitch.switchOff("11011", "10000"); buttonPressed = 0; } else if (buttonPressed == buttonUp) { mySwitch.switchOn("11011", "10000"); delay(750); sendCommandUp(); powerDown(25); mySwitch.switchOff("11011", "10000"); buttonPressed = 0; } } //Befehl Rolladen rauf void sendCommandUp() { mySwitch.setProtocol(4); mySwitch.sendQuadState("0F0F0100QQ0F100F0F0F"); mySwitch.sendQuadState("0F0F0100QQ0F100F0F1Q"); mySwitch.setProtocol(1); } //Befehl Rolladen stopp void sendCommandStopp() { mySwitch.setProtocol(4); mySwitch.sendQuadState("0F0F0100QQ0F100FFFFF"); mySwitch.setProtocol(1); } //Befehl Rolladen runter void sendCommandDown() { mySwitch.setProtocol(4); mySwitch.sendQuadState("0F0F0100QQ0F100F0101"); mySwitch.sendQuadState("0F0F0100QQ0F100F0110"); mySwitch.setProtocol(1); } //lässt Attiny für time Sekunden warten void powerDown(char time) { GIMSK |= (1<<PCIE1); //Pin-Change-Interrupt aktivieren GIMSK |= (1<<PCIE0); stopRequest = 0; for (char i = 1; i<= time*1000; i++) { if (stopRequest == 0) { delay(1); } } GIMSK &= ~(1<<PCIE1); //Pin-Change-Interrupt deaktivieren GIMSK &= ~(1<<PCIE0); } //setzt Attiny solange in Powerdown-Modus, bis Pin-Change-Interrupt ausgelöst wurde void powerDown() { GIMSK |= (1<<PCIE1); //Pin-Change-Interrupt aktivieren GIMSK |= (1<<PCIE0); sleep_mode(); //Schlafen gehen //hier gehts weiter nach aufwachen GIMSK &= ~(1<<PCIE1); //Pin-Change-Interrupt deaktivieren GIMSK &= ~(1<<PCIE0); } void checkButton() { if (digitalRead(buttonDown) == LOW) { buttonPressed = buttonDown; } else if (digitalRead(buttonStopp) == LOW) { stopRequest = 1; mySwitch.switchOff("11011", "10000"); } else if (digitalRead(buttonUp) == LOW) { buttonPressed = buttonUp; } } //ISR für PCINT1 und PCINT0 (Pin-Change-Interrupts) ISR(PCINT1_vect) { checkButton(); } ISR(PCINT0_vect) { checkButton(); }Einige Details der Software möchte ich dennoch erläutern. Die Spannungsversorgung der Fernbedienung erfolgt über eine CR2032-Knopfzelle. Da diese so lange wie möglich halten soll und die Fernbedienung 99,999% der Zeit sowieso nur rum liegt und nichts tut, geht der Attiny bei Inaktivität mit der Funktion powerdown() in den Schlaf-Modus. Er schläft so lange, bis er durch einen Tastendruck (Pin Change Interrupt) wieder geweckt wird. Um im Schlaf-Modus so wenig Energie wie möglich zu verbrauchen, wird zu Beginn zusätzlich der AD-Wandler sowie der Analog Comparator abgeschaltet. Dadurch sinkt der Ruhestrom auf wenige µA.
Kategorien:
433 MHz,
Arduino,
ATtiny,
Home Automation
Sonntag, 27. Oktober 2013
Arduino-Code auf dem ATmega 1284P
(English version) Um Arduino-Code auf dem ATmega 1284P auszuführen muss man lediglich ein paar kleine Schritte durchführen. Zuerst muss das folgende Archiv heruntergeladen werden:
https://github.com/maniacbug/mighty-1284p/zipball/master
Der Inhalt wird dann nach C:\Program Files (x86)\Arduino\hardware\mighty-1284p entpackt (bzw. in den entsprechenden Ordner, je nachdem wohin die Entwicklungsumgebung installiert wurde). Anschließend startet man die Entwicklungsumgebung neu und kann unter Board auch schon den 1284 auswählen. Ich benutze Original Mighty 1284p 16MHz. Die Pin-Belegung ist nun natürlich auch anders und zwar wie folgt (Die Zahl in Klammern ist für den Arduino relevant):
https://github.com/maniacbug/mighty-1284p/zipball/master
Der Inhalt wird dann nach C:\Program Files (x86)\Arduino\hardware\mighty-1284p entpackt (bzw. in den entsprechenden Ordner, je nachdem wohin die Entwicklungsumgebung installiert wurde). Anschließend startet man die Entwicklungsumgebung neu und kann unter Board auch schon den 1284 auswählen. Ich benutze Original Mighty 1284p 16MHz. Die Pin-Belegung ist nun natürlich auch anders und zwar wie folgt (Die Zahl in Klammern ist für den Arduino relevant):
+---\/---+
(D 0) PB0 1| |40 PA0 (AI 0 / D24)
(D 1) PB1 2| |39 PA1 (AI 1 / D25)
INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D26)
PWM (D 3) PB3 4| |37 PA3 (AI 3 / D27)
PWM/SS (D 4) PB4 5| |36 PA4 (AI 4 / D28)
MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D29)
PWM/MISO (D 6) PB6 7| |34 PA6 (AI 6 / D30)
PWM/SCK (D 7) PB7 8| |33 PA7 (AI 7 / D31)
RST 9| |32 AREF
VCC 10| |31 GND
GND 11| |30 AVCC
XTAL2 12| |29 PC7 (D 23)
XTAL1 13| |28 PC6 (D 22)
RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI
TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO
RX1/INT0 (D 10) PD2 16| |25 PC3 (D 19) TMS
TX1/INT1 (D 11) PD3 17| |24 PC2 (D 18) TCK
PWM (D 12) PD4 18| |23 PC1 (D 17) SDA
PWM (D 13) PD5 19| |22 PC0 (D 16) SCL
PWM (D 14) PD6 20| |21 PD7 (D 15) PWM
+--------+
Donnerstag, 24. Oktober 2013
RGB-LED mit ATmega16A ansteuern
(English version) RGB-LEDs sind ziemlich interessant (z.B. in LED-Streifen oder
ähnlichem). Daher möchte ich heute erklären, wie man mit einem ATmega16A
eine RGB-LED ansteuert. Zuerst einmal zur RGB-LED. Ich benutze diese LED von Tayda Electronics. Diese
LED besteht praktisch aus drei verschiedenen LEDs welche alle in einem
Gehäuse sind. Daher gibt es 3 Pins für die verschiedenen LEDs und eine
gemeinsame Kathode (-). Legt man nun PWM-Signale an diese 3 Pins, so kann man die Farbe der LED einstellen. Den ATmega16A benutze ich, da der ATmega8 nur 2 PWM-Kanäle hat, das reicht leider nicht für 3 Pins. Damit ist eigentlich auch alles geklärt, hier mal der Code von mir, welcher durch den kompletten Farbkreis läuft:
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
int main(void)
{
DDRA = 0xFF;//Output
DDRD = 0xFF;
ICR1 = 256;
TCCR2 = (1<<WGM20) | (1<<COM21) | (1<<CS20); // PWM, phase correct, 8 bit.
TCCR1A = (1<<WGM10) | (1<<COM1A1) | (1<<COM1B1); // PWM, phase correct, 8 bit.
TCCR1B = (1<<CS10);// | (1<<CS10); // Prescaler 64 = Enable counter, sets the frequency
double rCounter = 255;
double rMax=255;
double bCounter = 255;
double bMax = 180;
double gCounter = 0;
double gMax = 70;
int stages = 0;
while(1)
{
switch (stages)
{
case 0:
bCounter --;
if (bCounter <= 0)
{
stages = 1;
}
break;
case 1:
gCounter ++;
if (gCounter >= 255)
{
stages = 2;
}
break;
case 2:
rCounter --;
if (rCounter <= 0)
{
stages = 3;
}
break;
case 3:
bCounter ++;
if (bCounter >= 255)
{
stages = 4;
}
break;
case 4:
gCounter --;
if (gCounter <= 0)
{
stages = 5;
}
break;
case 5:
rCounter ++;
if (rCounter >= 255)
{
stages = 0;
}
break;
}
OCR1B = (int)(bCounter*bMax*bCounter/255/255);
OCR1A = (int)(gCounter*gMax*gCounter/255/255);
OCR2 = (int)(rCounter*rMax*rCounter/255/255);
_delay_ms(5);
}
}
Kategorien:
ATmega,
Beleuchtung
Dienstag, 8. Oktober 2013
C# - Alle Dateien in Ordner und Unterordnern anzeigen
(English version) Alle Dateien in einem Ordner auszulesen ist recht simpel (siehe dazu auch C# Tipps und Tricks). Will man das rekursiv machen ist das auch nicht weiter schwer. Der Code, welchen ich dafür benutze ist der folgende:
Um dieses Ergebnis nun weiter zu filtern kann man ein .Where hinten anhängen, im folgenden Code werden also nur Audio-Dateien zurückgegeben:
var allfiles = System.IO.Directory.GetFiles( @"C:\YourFolder", "*.*", System.IO.SearchOption.AllDirectories);foreach (string file in allfiles)
{}
Um dieses Ergebnis nun weiter zu filtern kann man ein .Where hinten anhängen, im folgenden Code werden also nur Audio-Dateien zurückgegeben:
var allfiles = System.IO.Directory.GetFiles( @"C:\YourFolder", "*.*", System.IO.SearchOption.AllDirectories).Where( s => s.EndsWith(".mp3") || s.EndsWith(".wav") || s.EndsWith(".wma"));
foreach (string file in allfiles)
{}
Kategorien:
C#
Montag, 7. Oktober 2013
LCD Display mit Arduino / ATmega
(English version) Ich habe mir dieses LCD-Modul gekauft und diesen I2C-Controller dafür. In diesem Post werde ich erklären, wie man nun Text auf das Display schreiben kann. Zuerst benötigt man die LiquidCrystal_I2C Library von hier. (Ich habe einfach die neueste Version genommen). Nun kann man auch schon direkt in der Arduino-Entwicklungsumgebung anfangen. Zuerst die Includes:
Als nächstes müssen einige Sachen definiert werden, die in der Library nicht ganz für das LCD-Modul passen:
Nun muss das Display definiert werden:
Als nächstes fängt man in der setup()-Funktion an. Zuerst sagt man dem Programm um was für ein Display es sich handelt (also die Größe, ich benutze ein 20 x 4 Zeichen Display).
Den Rest benötigt man, damit man mit
Nun kann man Sachen auf das Display schreiben. Das geht so:
Um den Cursor an eine Stelle zu setzen macht man folgendes:
Damit sollten die grundsätzlichen Funktionen geklärt sein. Um alles zu löschen ruft man einfach
Noch ein kleiner Hinweis, dieses Problem bereitete mir am Anfang viel Kopfzerbrechen: Programmiert man einen ATmega und steckt ihn dann direkt in ein Steckbrett, so funktioniert meistens gar nichts, der ATmega braucht einen Reset, nachdem er im Steckbrett steckt. Das liegt vermutlich daran, dass der ATmega schon losläuft auch wenn nur ein paar Pins mit dem Steckbrett verbunden sind.
#include <Wire.h> #include <LCD.h> #include <LiquidCrystal_I2C.h>
Als nächstes müssen einige Sachen definiert werden, die in der Library nicht ganz für das LCD-Modul passen:
#define I2C_ADDR 0x20 #define BACKLIGHT_PIN 3 #define En_pin 2 #define Rw_pin 1 #define Rs_pin 0 #define D4_pin 4 #define D5_pin 5 #define D6_pin 6 #define D7_pin 7 #define LED_OFF 1 #define LED_ON 0
Nun muss das Display definiert werden:
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
Als nächstes fängt man in der setup()-Funktion an. Zuerst sagt man dem Programm um was für ein Display es sich handelt (also die Größe, ich benutze ein 20 x 4 Zeichen Display).
lcd.begin (20,4);
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(LED_ON);
Den Rest benötigt man, damit man mit
lcd.backlight(); die Beleuchtung anschalten kann. Danach wird das LCD-Display resettet: lcd.clear();
delay(1000);
lcd.home();
Nun kann man Sachen auf das Display schreiben. Das geht so:
lcd.print("Hello, world!");
Um den Cursor an eine Stelle zu setzen macht man folgendes:
lcd.setCursor(5,1);
Damit sollten die grundsätzlichen Funktionen geklärt sein. Um alles zu löschen ruft man einfach
lcd.clear(); auf.Noch ein kleiner Hinweis, dieses Problem bereitete mir am Anfang viel Kopfzerbrechen: Programmiert man einen ATmega und steckt ihn dann direkt in ein Steckbrett, so funktioniert meistens gar nichts, der ATmega braucht einen Reset, nachdem er im Steckbrett steckt. Das liegt vermutlich daran, dass der ATmega schon losläuft auch wenn nur ein paar Pins mit dem Steckbrett verbunden sind.
Abonnieren
Posts (Atom)


