Arduino-Weihnachtsstern mit wählbaren Leuchtmustern
von Michael Gaus
In
diesem Projekt wird ein Weihnachtsstern als Aufsteckplatine (Shield)
bestehend aus 20 LEDs für den Arduino realisiert. Es können
beliebige Leuchtmuster komfortabel mit einem PC-Tool generiert und in
die Arduino-Firmware integriert werden. Der Hardwareaufbau erfolgt auf
einer Standard-Lochrasterplatine, sodass keine Platine geätzt
werden muss.
Ein Video, auf dem der Weihnachtsstern in Aktion zu sehen ist, gibt es hier: www.youtube.com/watch?v=1E1VOpvfQK0
Hardwareaufbau
Folgende zusätzliche Bauteile sind erforderlich:
20
LEDs, 20 Widerstände mit je 1,5 kOhm, Stiftleisten RM 2,54mm (2x
8-polig und 2x 6-polig), Lochrasterplatine mit Lötpunkten
Die
Schaltung kann auf einem Stück Lochrasterplatine aufgelötet
werden und über die Stiftleisten dann als sogenanntes "Shield"
direkt auf die Buchsen der Arduino Platine aufgesteckt werden.
Die
Vorwiderstände für jede LED werden auf der
Platinenrückseite montiert, sodass auf der Platinenoberseite nur
die 20 LEDs zu sehen sind. Zur Montage der Stiftleisten sollte am
besten folgendermaßen vorgegangen werden:
- Zuerst die Stiftleisten in die Buchsen auf der Arduino-Platine einstecken.
-
Die Lochrasterplatine auf die Stiftleisten mit etwas Abstand aufsetzen,
sodass diese später noch auf der Platinenunterseite verlötet
werden können. Hierbei müssen manche Stiftleisten leicht
schräg aufgedrückt werden, da der Abstand der Buchsenleisten
auf der Arduino-Platine leider nicht dem Standard von 2,54mm entspricht.
-
Wenn nun die Arduino-Platine auf die Seite gedreht wird, können
Sie Stiftleisten mit den Lötpunkten auf der Lochrasterplatine
verlötet werden.
Programmierung der Arduino Platine
In
der Entwicklungsumgebung Arduino wird der Sketch star.pde geladen,
kompiliert und per Upload-Button auf den Arduino übertragen.
Hier
sind bereits einige Sequenzen mit Leuchtmustern enthalten. Diese
können nach Belieben geändert werden, z.B. mit dem
beiliegenden PC-Tool.
PC-Tool zur Generierung von Leuchtmusterabläufen
Um
komfortabel Leuchtmuster generieren zu können, wurde ein PC-Tool
mit Visual C++ 2005 entworfen. Das Tool inkl. komplettem Quellcode ist
in der ZIP-Datei pc_tool
enthalten. Eine ausführbare EXE-Datei ist im Unterverzeichnis
release zu finden. Die beiden Dateien on.gif und off.gif werden zur
Darstellung der LEDs benötigt. Wenn eine Änderung des
Quellcodes gewünscht ist, kann die Projektdatei xmasstar.vcproj im
Unterverzeichnis xmasstar geöffnet werden.
Die
Bedienung des Tools ist weitgehend selbsterklärend. Im oberen
LED-Stern "Eingabe" kann ein gewünschtes Leuchtmuster durch Klick
auf die LEDs zusammengestellt werden sowie die gewünschte
Anzeigedauer im gleichnamigen Feld in Millisekunden angegeben werden.
Durch Klick auf den Button "Muster am Ende anhängen" wird das
erstellte Muster an die Sequenz rechts in der Listbox hinten
angehängt. Mit den anderen Buttons kann das Muster entsprechend an
anderer Stelle eingefügt werden oder auch gelöscht werden.
Das Muster in der selektierten Zeile der Listbox wird im unteren
LED-Stern "Ausgabe" dargestellt. Durch Klick auf den Button
"Simulation" kann hier die erstellte Sequenz komplett abgespielt werden.
Mit den Buttons "Speichern" sowie "Laden" können die Sequenzen in Textdateien gesichert bzw. geladen werden.
Das Datenformat sieht folgendermaßen aus:
Hexwert
für die LEDs 1-6 (z.B. 0x3F), Hexwert für die LEDs 7-14 (z.B.
0xFF), Hexwert für die LEDs 15-20 (z.B. 0x3F), Dezimalwert
für die Anzeigedauer in Millisekunden (z.B. 250), am Ende ein
Zeilenumbruch.
Um die Leuchtmustersequenz in das
Arduino-Programm einbinden zu können, muss es mit dem Button
"Speichern" zuerst als Textdatei gespeichert werden. Die Textdatei kann
dann mit einem Texteditor (z.B. Notepad) geöffnet werden und der
Inhalt über die Zwischenablage in das Array im Arduino-Programm
eingefügt werden. Als Beispiel ist im Arduino-Programm das Array
patternDemo zu finden, zwischen den Kommentarzeilen "Start" und "Ende"
muss die Leuchtmustersequenz eingefügt werden.
Arduino Quellcode und Funktionsprinzip
Der
Code für den ATmega168 auf der Arduino Platine wurde mit der
Version arduino-0021 erstellt. Das komplette Projekt ist in der
ZIP-Datei Star.zip enthalten (Name der Sketchdatei ist star.pde).
In der Funktion setup werden die Portpins für die LEDs als Ausgang konfiguriert und alle LEDs ausgeschaltet.
In
der Hauptschleife loop kann durch Aufruf der Funktion
displayPatternWithDuration eine in einem Array vorhandene
Leuchtmustersequenz abgearbeitet werden. Als Beispiel soll ein Array
namens patternDemo eingebunden werden, dies sieht folgendermaßen
aus:
struct STR_PATTERN patternDemo[] PROGMEM =
{
//
Start: ab der nächsten Zeile beginnt die Leuchtmustersequenz, die
mit dem PC-Tool erstellt und aus der Textdatei kopiert wurde
0x01,0x00,0x00,100,
0x03,0x00,0x00,100,
// Ende: hier endet die Leuchtmustersequenz, die mit dem PC-Tool erstellt wurde
// die nächste Zeile wird als Endekennung des Arrays benötigt und darf nicht gelöscht werden
0xFF,0xFF,0xFF,0 // end marker, do not remove
};
Der Aufruf in der Hauptschleife loop sieht dann wie folgt aus:
displayPatternWithDuration(patternDemo);
Das
Schlüsselwort PROGMEM bewirkt, dass das Array im
Programm-Flashspeicher des ATmega168 abgelegt wird. Somit können
auch mehrere große Arrays angelegt werden, ohne dass es
Speicherplatz-Problemen mit dem wesentlich kleineren SRAM kommt.
Um
manuell ein Leuchtmuster für die 20 LEDs auszugeben, kann die
Funktion ledPattern verwendet, diese erwartet als Parameter die 3
Hexwerte für die LED-Gruppen
#include <avr/pgmspace.h>
// LEDs:
// LED 1-6: PORTC.0-PORTC.5
// LED 7-14: PORTD.0-PORTD.7
// LED 15-20: PORTB.0-PORTB.5
struct STR_PATTERN
{ // Definition der Struktur eines Arrays für eine Leuchtmustersequenz
unsigned char leds_1_6;
unsigned char leds_7_14;
unsigned char leds_15_20;
unsigned int duration;
};
// ein Array namens patternDemo sieht z.B. folgendermaßen aus:
struct STR_PATTERN patternDemo[] PROGMEM =
{
// Start: ab der nächsten Zeile beginnt die Leuchtmustersequenz, die mit dem PC-Tool erstellt und aus der Textdatei kopiert wurde
0x01,0x00,0x00,100,
0x03,0x00,0x00,100,
// Ende: hier endet die Leuchtmustersequenz, die mit dem PC-Tool erstellt wurde
// die nächste Zeile wird als Endekennung des Arrays benötigt und darf nicht gelöscht werden
0xFF,0xFF,0xFF,0 // end marker, do not remove
};
struct STR_PATTERN pattern0[] PROGMEM =
{
0x01,0x00,0x00,100,
0x02,0x00,0x00,100,
0x04,0x00,0x00,100,
0x08,0x00,0x00,100,
0x10,0x00,0x00,100,
0x20,0x00,0x00,100,
0x00,0x01,0x00,100,
0x00,0x02,0x00,100,
0x00,0x04,0x00,100,
0x00,0x08,0x00,100,
0x00,0x10,0x00,100,
0x00,0x20,0x00,100,
0x00,0x40,0x00,100,
0x00,0x80,0x00,100,
0x00,0x00,0x01,100,
0x00,0x00,0x02,100,
0x00,0x00,0x04,100,
0x00,0x00,0x08,100,
0x00,0x00,0x10,100,
0x00,0x00,0x20,100,
0x00,0x00,0x00,100,
0xFF,0xFF,0xFF,0 // end marker, do not remove
};
struct STR_PATTERN pattern1[] PROGMEM =
{
0x00,0x00,0x00,100,
0x01,0x00,0x00,100,
0x03,0x00,0x00,100,
0x07,0x00,0x00,100,
0x0F,0x00,0x00,100,
0x1F,0x00,0x00,100,
0x3F,0x00,0x00,100,
0x3F,0x01,0x00,100,
0x3F,0x03,0x00,100,
0x3F,0x07,0x00,100,
0x3F,0x0F,0x00,100,
0x3F,0x1F,0x00,100,
0x3F,0x3F,0x00,100,
0x3F,0x7F,0x00,100,
0x3F,0xFF,0x00,100,
0x3F,0xFF,0x01,100,
0x3F,0xFF,0x03,100,
0x3F,0xFF,0x07,100,
0x3F,0xFF,0x0F,100,
0x3F,0xFF,0x1F,100,
0x3F,0xFF,0x3F,100,
0x3F,0xFF,0x3F,100,
0x3E,0xFF,0x3F,100,
0x3C,0xFF,0x3F,100,
0x38,0xFF,0x3F,100,
0x30,0xFF,0x3F,100,
0x20,0xFF,0x3F,100,
0x00,0xFF,0x3F,100,
0x00,0xFE,0x3F,100,
0x00,0xFC,0x3F,100,
0x00,0xF8,0x3F,100,
0x00,0xF0,0x3F,100,
0x00,0xE0,0x3F,100,
0x00,0xC0,0x3F,100,
0x00,0x80,0x3F,100,
0x00,0x00,0x3F,100,
0x00,0x00,0x3E,100,
0x00,0x00,0x3C,100,
0x00,0x00,0x38,100,
0x00,0x00,0x30,100,
0x00,0x00,0x20,100,
0x00,0x00,0x00,100,
0xFF,0xFF,0xFF,0 // end marker, do not remove
};
struct STR_PATTERN pattern2[] PROGMEM =
{
0x3C,0x01,0x00,300,
0x00,0x1F,0x00,300,
0x00,0xF0,0x01,300,
0x00,0x00,0x1F,300,
0x07,0x00,0x30,300,
0xFF,0xFF,0xFF,0 // end marker, do not remove
};
struct STR_PATTERN pattern3[] PROGMEM =
{
0x11,0x44,0x04,300,
0x33,0xCC,0x0C,300,
0x37,0xDD,0x1D,300,
0x3F,0xFF,0x3F,300,
0x00,0x00,0x00,300,
0xFF,0xFF,0xFF,0 // end marker, do not remove
};
struct STR_PATTERN pattern4[] PROGMEM =
{
0x11,0x44,0x04,300,
0x22,0x88,0x08,300,
0x04,0x11,0x11,300,
0x08,0x22,0x22,300,
0xFF,0xFF,0xFF,0 // end marker, do not remove
};
struct STR_PATTERN pattern5[] PROGMEM =
{
0x00,0x00,0x00,300,
0x11,0x44,0x04,300,
0x3B,0xEE,0x2E,300,
0x3F,0xFF,0x3F,300,
0x3F,0xFF,0x3F,300,
0x3B,0xEE,0x2E,300,
0x11,0x44,0x04,300,
0x00,0x00,0x00,300,
0xFF,0xFF,0xFF,0 // end marker, do not remove
};
struct STR_PATTERN patternBlink[] PROGMEM =
{
0x3F,0xFF,0x3F,300,
0x00,0x00,0x00,300,
0xFF,0xFF,0xFF,0 // end marker, do not remove
};
void ledPattern(unsigned char led_1_6, unsigned char led_7_14, unsigned char led_15_20)
{
PORTC = led_1_6;
PORTD = led_7_14;
PORTB = led_15_20;
}
void displayPatternWithDuration(struct STR_PATTERN * PROGMEM pattern)
{
unsigned int j = 0;
while(pgm_read_byte(&pattern[j].leds_1_6) != 0xFF)
{
ledPattern(pgm_read_byte(&pattern[j].leds_1_6), pgm_read_byte(&pattern[j].leds_7_14), pgm_read_byte(&pattern[j].leds_15_20));
delay(pgm_read_word(&pattern[j].duration));
j++;
}
}
void clearPattern(void)
{
PORTC = 0;
PORTD = 0;
PORTB = 0;
}
void setup()
{
PORTB = 0;
DDRB |= 0x3F;
PORTD = 0;
DDRD |= 0xFF;
PORTC = 0;
DDRC |= 0x3F;
}
void loop()
{
unsigned char i;
clearPattern();
displayPatternWithDuration(pattern0);
for(i = 0; i < 3; i++)
{
displayPatternWithDuration(patternBlink);
}
displayPatternWithDuration(pattern1);
for(i = 0; i < 3; i++)
{
displayPatternWithDuration(pattern2);
}
for(i = 0; i < 3; i++)
{
displayPatternWithDuration(pattern3);
}
for(i = 0; i < 3; i++)
{
displayPatternWithDuration(pattern4);
}
for(i = 0; i < 3; i++)
{
displayPatternWithDuration(pattern5);
}
}
zurück