[:de]Projekt Lavalampe, Teil 2 – Firmware[:en]Lava lamp project, part 2 – firmware[:]
[:de]In Teil 1 habe ich die Hardware meines Projektes einer fernsteuerbaren Lavalampe beschrieben. In diesem zweiten Teil will ich etwas auf die notwendige Firmware eingehen, also das Programm, das notwendig ist, um dem Picaxe Microcontroller die gewünschte Funktionalität beizubringen.
Es gibt dabei zwei Themenkreise im Auge zu behalten:
- Von der seriellen Schnittstelle müssen die Sollgrössen gelesen werden, also die gewünschten Farbintensitäten der drei Grundfarben Grün, Rot und Blau.
- Diese Sollgrössen müssen in Licht des gewünschten Farbtons und der gewüschten Intensität umgesetzt werden. Sprich, die LEDs müssen zum Leuchten gebracht werden.
Ein paar Worte zum Picaxe
Der Picaxe hat einen vorgefertigten Befehlssatz, der BASIC nachempfunden ist und der ziemlich mächtig ist. Beispielsweise lässt sich mit nur einem Befehl eine ganze Reihe von Input-Daten einlesen und Speicherplätzen zuweisen. Allerdings ist die Taktgeschwindigkeit des Mikroprozessors nicht sehr hoch, die Arbeitsgeschwindigkeit beschränkt. Das ist auch verständlich, bei grösseren Arbeitsgeschwindigkeiten würden sich höhere Verlustleistungen ergeben und dann müsste er gekühlt werden, was den Aufwand für ein Gerät mit diesen Prozessoren erheblich in die Höhe treiben würde.
Es gibt den Picaxe in verschiedenen Ausführungen, die sich in Bauform, Gehäusegrössen, und Sonderausstattung wie etwa der Anzahl D/A-Wandler oder Pulsbreitenmodulatoren unterscheiden. Das kleinste Modell mit 8 Dual-Inline-Anschlüssen hat folgende Pinbelegung:
- 2 Anschlüsse für 5V und Masse (Speisung)
- 2 Anschlüsse für seriellen Ein- und Ausgang. Diese werden für die Programmierung und später für die Farb-Sollvorgaben benutzt. Im Prinzip könnten sie aber bei Bedarf stattdessen auch als normaler digitaler Eingang und als digitaler oder analoger Ausgang benutzt werden.
- 1 digitaler Eingang
- 3 wahlweise Ein- und Ausgänge mit verschiedenen Sonderfunktionen
Hier findest Du das Datenblatt zum PICAXE.
Für den Picaxe steht eine Integrierte Entwicklungsumgebung namens „Picaxe Editor 6“ zur Verfügung, mit der Programme entwickelt, simuliert und auf den Picaxe übertragen werden können. Ebenfalls stehen kostengünstige Prototypenboards zur Verfügung. Ich habe mir dieses Board hier beschafft für meine ersten Gehversuche.
Funktionsprinzip der Firmware
Die Leuchtstärke von LEDs wird nicht daduch gesteuert, dass die Speisespannung variiert wird (das könnte ein analoger Ausgang leisten), sondern man arbeitet mit Pulsbreitenmodulation, englisch Pulse Width Modulation, PWM, genannt. Der von mir verwendete Picaxe-08M2 verfügt über einen PWM-Ausgang, wie man im obigen Bild sieht. Der reicht aber leider nur für eine der drei Grundfarben, nicht für alle drei. Erst mit den deutlich grösseren Modellen 14M2 oder 20M2 hätte ich drei oder sogar vier PWM-Ausgänge zur Verfügung. Ich muss daher die Pulsbreitenmodulation „von Hand“ programmieren, was leider nur mit beschränker Geschwindigkeit klappt, was wiederum dazu führt, dass meine LED-Steuerung flimmert. Das ist schade, aber mit dem beschränkten Platz nicht zu vermeiden. Für einen grösseren Picaxe-Baustein würde der Platz im Sockel der Lavalampe nicht ausreichen, dann müsste ein grösseres Lampengehäuse her.
Um die zur Verfügung stehende Rechenleistung optimal auszunutzen, habe ich meine Firmware wie folgt aufgebaut:
Eine grosse Schleife wiederholt sich endlos. Innerhalb dieser Schleife passiert folgendes:
- Alle drei LEDs werden zunächst eingeschaltet, falls die Anzahl Arbeitszyklen überhaupt grösser als Null ist.
- In einer inneren Scheife, die immer gleich häufig durchlaufen wird,
- …wird jede Farbe, deren Leuchtzyklen abgelaufen ist, ausgeschaltet.
- …ausserdem wird jetzt 3 Millisekunden lang auf den Beginn eines Input-Telegramms gewartet. Falls ein „C“ erkannt wird, dann wird ein Unterprogramm angesprungen, das den Rest des Telegramms einliest und verarbeitet.
- Nach Ablauf der inneren Schleifenzyklen kehren wir zur äusseren Schleife zurück und der Vorgang beginnt von vorne.
Ein Durchlauf durch die äussere Schleife bestimmt das Flimmern der LEDs. Je kürzer ein Durchgang, desto geringer das Flimmern.
Ein Durchgang durch die innere Schleife wird bestimmt durch die Wartezeit auf den seriellen Input, die regelmässig durchlaufen werden muss, damit der Picaxe Änderungen der Wunschfarbe und -Helligkeit, die vom angeschlossenen PC mitgeteilt wird, mitbekommt. Je länger diese Wartezeit ist, desto zuverlässiger werden ankommende serielle Zeichen erkannt. Ich habe mich hier auf 3 Millisekunden festgelegt. Wenn in dieser Zeit ein „C“ festgestellt wird, dann wird kurz aus der Schleife gesprungen und drei zusätzliche Bytes eingelesen, als Farbwerte für die drei Grundfarben. Die Anzahl Durchgänge n durch die innere Schleife bestimmt die Anzahl der möglichen Helligkeitsstufen von 0 („dauernd aus“) bis n+1 („dauernd ein“).
Die Anzahl innerer Zyklen pro Durchgang der äusseren Schleife bestimmt die „Flimmerfrequenz“ der LEDs, und zwar umgekehrt proportional. Das heisst, je weniger die LEDs flimmern sollen, desto weniger häufig darf die innere Schleife durchlaufen werden, und desto weniger Helligkeitstufen sind möglich. Je mehr Helligkeitstufen möglich sein sollen, desto stärker werden die LEDs flimmern. Einen für mein Gefühl sinnvollen Kompromiss meine ich mit 7 inneren Zyklen gefunden zu haben.
Am seriellen Port wird die gewünschte Farbe und Leuchtstärke durch ein „Telegramm“ aus vier Bytes übermittelt. Jedes Telegramm wird mit einem „C“ eingeleitet und die folgenden drei Bytes sind die Anzahl innerer Zyklen der Grundfarben Rot, Grün und Blau als ASCII-Ziffer. Ein paar Beispiele:
- ‚C000‘ – LED ist vollkommen ausgeschaltet, also dunkel
- ‚C888‘ – LED ist vollkommen eingeschaltet, leuchtet also weiss
- ‚C800‘ – LED leuchtet rot
- ‚C080‘ – LED leuchtet grün
- ‚C008‘ – LED leuchtet blau
- ‚C440‘ – LED leuchtet gelb mit halber Leuchtkraft
- ‚C808‘ – LED leuchtet violett mit voller Leuchtkraft
- ‚C740‘ – LED leuchtet braun
- und so weiter
Leider ist der serielle Empfänger nicht zuverlässig genug, dass jedes Telegramm sauber empfangen wird. In der Regel muss der Computer das Telegramm mehrmals senden, bis es durchkommt. Eine Quittierung für erfolgreichen Empfang des Telegramms ist in meinem Code momentan nicht vorgesehen.
Verbesserungsmöglichkeiten
Der Code könnte flexibler gestaltet werden, beispielsweise indem die Anzahl innerer Schleifendurchläufe variabel gemacht wird und etwa durch ein anderes Telegramm programmiert werden kann. Damit könnte vom Computer her das Flimmern reduziert werden, wenn nur wenige Helligkeitsstufen benötigt werden.
Eine Quittierung für den Empfang eines Telegramms wäre nützlich, um dem angeschlossenen Computer mitzuteilen, dass er jetzt aufhören kann, sein letztes Telegramm zu wiederholen.
Ausserdem wäre es nett, wenn ein Schalter am Eingang eine Wirkung entfalten würde, etwa Ein- und Ausschalten der LED, oder das Starten eines besonderen Leuchtprogramms der LED.
Natürlich kann mit allen Stellgrössen experimentier werden:
- Taktfrequenz des Prozessors. Aktuell 16 MHz. Je schneller, desto weniger Flimmern. 16 MHz ist für den Picaxe 08M2 das Maximum.
- Anzahl innerer Zyklen für eine Arbeitszyklus. Aktuell 7. Je weniger Zyklen, desto weniger Flimmern. Je mehr innere Zyklen, desto mehr Helligkeitsstufen stehen zur Verfügung.
- Wartezeit auf Telegrammbeginn. Aktuell 3ms. Je länger diese Zeit, desto zuverlässiger werden Telegramme erkannt, aber desto stärker ist das Flimmern.
Listing
Ich will hier nicht das ganze Programm auflisten. Sie können es bei Interesse bei mir nachfragen.[:en]In part 1, I described the hardware of my project of a computer controllable lava lamp. In this second part, I want to discuss the necessary firmware, which is the software necessary to teach the Picaxe Microcontroller the desired functionality.
We need to keep two areas in focus:
- We need to be able to read the desired color values from the USB serial port, defining the desired intensities of the colors green, red and blue.
- These desired values have to be turned into actual light in desired color and intensity. This means, the LEDs have to be turned on.
A few words about the Picaxe
The Picaxe has a predefined set of commands, which is similar to BASIC and which is quite powerful. For example, a single commannd can read in a row of input data assign them to memory. But the processor speed is limited. This is understandable, greater working speeds would mean more heat dissipation and then the microcontroller would need cooling. This would significantly increase the effort required for designing a device with this kind of processor.
The Picaxe is available in different versions, which differ in package size and special equipment, such as the number of digital/analog converters or pulse width modulators. The smallest model is available as a 8 pin dual-in-line chip and sports the following pin out:
- 2 pins for 5V and ground (power supply)
- 2 pins for serial input and output. These pins are being used for programming and later for transmission of the desired color values. They could also be used as normal input or output pins if desired.
- 1 digital input
- 3 very versatile input/output pins with numerous special functions
Here is the data sheet for the PICAXE.
The Picaxe has an integrated development environment (IDE), called „Picaxe Editor 6„, which can be used for developing, simulating and transferring programs to the Picaxe. There are cost effective prototyping boards available as well. I bought myself his board for my first attempts.
Functional principles of the firmware
The lighting intensity of LEDs is not controlled by varying the power supply voltage (which could be done using a analog output), as is done for light bulbs. Instead it is done by varying the width of pulses at an appropriate frequency fast enough so that the flicker is not noticed by the human eye. The small Picaxe-08M2 used by me has one pulse-width-modulation (pwm) output, as can be seen in the above pin out. But that is only enough for one of the colors red, green or blue, not for all three of them. Only the significantly larger models 14M2 or 20M2 would have 3, or even 4, pwm outputs. For this reason, I have to program my own pwm output manually, which, alas, can only be done with limited speed, which means that my LED flickers slightly. That is a pity, but it can not be avoided within the limited space. The larger Picaxe chips would require more space not available inside the lava lamp.
To use the processing power of the Picaxe as effective as possible, I built my firmware like this:
One big loop is repeating for ever. Inside this loop, the following things are happening:
- First, all three color LEDs are turned on, if their correponding number of duty cycles is greater than zero.
- In an inside loop, which is always performed the same number of times
- …each color, whose duty cycle expired, is being turned off.
- …also, we wait 3 Milliseconds for the beginning of an input datagram
- If a character „C“ is recognized, we jump to a subprogram, which reads the rest of the datagram and recalculates and adjusts the duty cycles of each color.
- After the number of inside loop cycles is reached, we jump back to the outer loop and the whole cycle starts from scratch.
The length of an outside loop cycle determines the amount of flickering of the LEDs. The shorter one outside loop cycle, the less flickering.
The inside loop cycle length is determined by the serial input waiting time, which has to be performed regularly, in order to read desired color changes transmitted from the connected computer. The longer this waiting time, the more reliably datagrams will be recognized, but the more flickering occurs as well. I figured 3 milliseconds should be quite ok. If during this time, a character „C“ is noticed, we quickly jump out of the inside loop and perform a subpgram to read three more characters, whose value defines the brightness of the colors red, green and blue, respectively. The possible brightness values go from 0 („constant off“) to n+1 („constant on“).
The number of inner cycles defines the „flicker frequency“ of the LEDs, inversely proportional. This means: The less the LEDs are supposed to flicker, the less times the inner loop can be performed, and the less number of brightness levels are possible. The more levels of brightness are desired, the more the LEDs will flicker. I thought that 7 inner cycles make a useful compromise.
The serial port receives the desired color and brightness through a „datagram“ consisting of four bytes of data. Every datagram starts with a „C“, and the following three digits define the number of inner cycles for the colors red, green and blue. Here are a few examples:
- ‚C000‘ – LED is completely turned off, or dark
- ‚C888‘ – LED is completely turned on, or white
- ‚C800‘ – LED is rot
- ‚C080‘ – LED is green
- ‚C008‘ – LED is blue
- ‚C440‘ – LED is yellow with about half intensity
- ‚C808‘ – LED is purple with full power
- ‚C740‘ – LED is brown
- etc.
Unfortunately, the serial receiver is not dependable enough to receive every datagram cleanly. Most of the time, the computer has to send the datagram multiple times until it is received. An acknowledgement is not currently implemented in my code.
Possible improvements
The code could be made more flexible, for example by making the number of inside loop cycles variable. With this, the computer could reduce the flicker, if only a few brightness levels are required.
An ackowledgment mechanism for signalling successful reception of a datagram to the computer would be useful so that it knows it can stop repeating its last datagram.
Also, it would be nice to make the switch or key do something, such as turning the LED on or off, or starting a special color program on the LED.
You can, of course, also experiment with the adjustments:
- Clock frequency of the processor. Currently set to 16 MHz. The faster, the less flicker. 16 MHz is the maximum frequency possible for the Picaxe 08M2.
- Number of inner loop cycles for one working cycle. Currently 7. The less cycles, the less flicker. The more inner cycles, the more levels of brightness are available.
- Waiting time for begin of datagram. Currently 3ms. The longer this time the more reliably datagrams will be recognized, but the greater the flicker.
Listing
I don’t want to list the whole firmware program here. Just ask me, if you are interested[:]


