In diesem Jahr sollte der Kita-Fasching mit einem zünftigen Roboterkostüm bestritten werden. Der passende Helm wurde vom kleinen Roboter höchstselbst in Handarbeit gefertigt. Die Spezial-Lichteffekte durfte ich beisteuern.
Erleuchtung sollen 16 LEDs bringen, die von einem Arduino Micro gesteuert werden. Praktischerweise liefen die auserkorenen LEDs mit 2,5 Volt - so dass einfach immer zwei in Reihe geschaltet werden konnten und somit nur acht 5V-Ausgänge des Micro belegt waren. Aber Achtung - für das Betreiben von LEDs OHNE Vorwiderstand kommt man laut einiger ernstzunehmender Quellen direkt in die Elektroniker-Hölle!!! Besonders, wenn man sogar mehrere Leuchtedinger in Reihe schaltet. Aber egal. Funktioniert trotzdem und spart eine Menge Bauteile und Löterei.
Wer möchte, kann die LED-Paare natürlich untereinander parallel schalten und vor jede LED einen Vorwiderstand setzen. Das wäre viel sicherer, denn es würde verhindern, dass einzelne LEDs auf Grund von Serienstreuungen überlastet werden. Ich war zunächst auch skeptisch, habe jedoch festgestellt, dass die LEDs bei meiner Anwendung gleichmäßig hell leuchten und somit keine LED überlastet zu sein scheint. Und überhaupt ist die Leuchtdauer immer nur sehr kurz.
Für die Stromversorgung muss ein 9V-Block herhalten. Da der kleine Benutzer aber gerne das Ausschalten vergisst und damit der Spaß trotzdem nicht bereits nach kurzer Zeit zu Ende ist, wird ein Pololu Pushbutton Powerswitch zwischen Batterie und Arduino geschaltet. Damit erhält der Arduino die Möglichkeit, sich stets nach einigen Sekunden Laufzeit wieder vom Strom zu trennen.
![]() Platine mit Arduino und Reihenschaltung der LED-Paare | ![]() Vorderseite mit LED-Zeile, Pololu-Switch und Batterie | ![]() Der Helm | ![]() Batterie- und Schalterplatine im Helm | ![]() LED-Platine an Ort und Stelle | ![]() Happy Robot |
Erste Versuche nach dem Zusammenlöten
Der Helm mit den verschiedenen Blinkmustern
Der Arduino-Sketch macht das Folgende (und gibt dabei auch ein paar Statusinfos auf die serielle Schnittstelle aus):
Damit jedes Mal beim Einschalten ein anderes Blinkmuster gezeigt wird, wird die Nummer des zuletzt gezeigten Musters im EEPROM des Arduinos abgelegt. Bekanntermaßen vertragen EEPROMS nur eine gewisse Anzahl Schreibvorgänge, weshalb nach jedem Schreibzyklus eine andere Speicherstelle beschrieben wird, um den Speicher möglichst gleichmäßig zu belasten.
Auf die Schnelle sind mir sieben verschiedene Blinkmuster in den Sinn gekommen. Die Liste kann aber recht einfach durch Anpassung der Variable DESIGN_COUNT und Erweiterung des if…then-Konstrukts um weitere Ideen ergänzt werden.
Die LED-Zeile wird mit der Funktion ligtLeds(int val) angesteuert, wobei die ersten acht Bit von val bestimmen, ob das jeweils dazugehörige LED-Paar ein- oder ausgeschaltet wird.
Nach jedem Schleifendurchlauf wird geprüft, ob die vorgesehene Gesamtlaufzeit (RUN_DURATION) überschritten ist. Ist dies der Fall, dann wird der Pin, der mit dem OFF-Pin des Pololu-Switches verbunden ist, auf HIGH gesetzt, was zum Unterbrechen der Stromzufuhr führt.
/******************** * LED-Zeile * * www.yeat.net * ********************/ #include <EEPROM.h> int LED_PINS[] = {2, 3, 4, 5, 6, 7, 8, 9}; int LED_VALS[] = {1, 2, 4, 8, 16, 32, 64, 128}; int SWITCH_PIN = 10; int RUN_DURATION = 20000; int DESIGN_COUNT = 7; long counter; int design; void setup() { Serial.begin(9600); for (int pin=0; pin<8; pin++) { pinMode(LED_PINS[pin], OUTPUT); digitalWrite(LED_PINS[pin], HIGH); } pinMode(SWITCH_PIN, OUTPUT); //determine and increase the run counter byte base = EEPROM.read(0); bool foundIt = false; int curPos = 0; while ((!foundIt) && (curPos<EEPROM.length())) { curPos++; foundIt = (EEPROM.read(curPos) != base); if (foundIt) EEPROM.write(curPos, base); } if (!foundIt) { base++; EEPROM.write(0, base); curPos=0; } counter = ((int)base * 1024) + curPos; design = counter % DESIGN_COUNT; Serial.print("run counter = "); Serial.print(counter); Serial.print(" -> design = "); Serial.println(design); } //global vars vor designs 0 and 1 int curVal=0; int cyc=1; int dir=1; void loop() { int dly; //====================================== if (design==0) { dly = 35; for (int i=0; i<8; i++) { int pos; if (dir==1) pos=i; else pos=7-i; curVal += (LED_VALS[pos] * cyc); lightLeds(curVal); delay(dly); } cyc *= -1; if (cyc == 1) { dir *= -1; } else { lightLeds[0]; delay(dly); } //====================================== } else if (design==1) { dly = 75; dir *= -1; for (int i=0; i<8; i++) { int pos; if (dir==1) pos=i; else pos=7-i; lightLeds(LED_VALS[pos]); delay(dly); } //====================================== } else if (design==2) { dly = 750; lightLeds(195); delay(dly); lightLeds(36); delay(dly); for (int i=0; i<25; i++) { lightLeds(24); delay(35); lightLeds(0); delay(35); } lightLeds(24); delay(dly*3); //====================================== } else if (design==3) { dly = 75; byte steps[] = {129, 66, 36, 24}; dir *= -1; for (int i=0; i<4; i++) { int pos; if (dir==1) pos=i; else pos=3-i; lightLeds(steps[pos]); delay(dly); } //====================================== } else if (design==4) { dly = 150; byte steps[] = {170, 85}; lightLeds(steps[curVal % 2]); curVal++; delay(dly); //====================================== } else if (design==5) { dly = 50; dir *= -1; for (int i=0; i<8; i++) { int pos; if (dir==1) pos=i; else pos=7-i; lightLeds(~LED_VALS[pos]); delay(dly); } //====================================== } else if (design==6) { dly = 75; byte steps[] = {24, 60, 126, 255, 231, 195, 129, 0}; for (int pos=0; pos<8; pos++) { lightLeds(steps[pos]); delay(dly); } } if (millis() >= RUN_DURATION) switchOff(); } void lightLeds(int val) { for (int pin=0; pin<8; pin++) { int ledStat=LOW; int ledVal=LED_VALS[pin]; if ((val & ledVal) == ledVal) { ledStat=HIGH; } digitalWrite(LED_PINS[pin], ledStat); } } void switchOff() { Serial.print("switching off: run counter="); Serial.print(counter); Serial.print(", design="); Serial.println(design); digitalWrite(SWITCH_PIN, HIGH); } void resetCounter() { lightLeds(255); EEPROM.write(0, 0); for (int i=1; i<EEPROM.length(); i++) EEPROM.write(i, 255); lightLeds(0); }