Digispark-Arduino - ein Überblick
Bascom oder Arduino?
Bascom ist immer noch mein Spitzenreiter, wenn es um AVR-Programmierung
geht, hat aber als "closed source" auch einige Nachteile, und unter
Linux läuft die GUI eher schlecht als recht.
Deshalb gucke ich immer mal wieder nach Alternativen. Die
bekannteste und einfachste ist das Arduino-System; die Sprache ist zwar
nicht so übersichtlich wie BASCOM, die Programmierumgebung etwas
unkomfortabler, die Kompilate sind grösser, aber die Software ist frei
- nicht nur frei wie in "Freibier", sondern frei wie in "Freiheit".
Man kann probemlos ältere Versionen downloaden und zu ihnen
zurückwechseln, falls mal etwas nicht funktioniert. Man muss sich nicht
mit Kopierschutz, Seriennummern und irgendwelchen Online-Updatern
rumärgern, man kann leichter in den Konfigurationsdateien
"herumpfuschen" und so das Verhalten und Aussehen eigenen Bedürfnissen
anpassen, man findet freie Erweiterungen für Dritt-Hardware, und man
kann (mit Vorsicht und Einschränkungen) auch mehrere Versionen
nebeneinander betreiben.
Softwarefirmen sind halt wie Pflanzen: die möchten einmal im
Jahr bestäubt werden und locken mit einladenden bunten Blüten, aber den
Rest des Jahres sind sie damit beschäftigt, ihren Fressfeinden das
Leben schwer zu machen - auch denen, die sie während der Blüte als
Bestäuber benötigen.
Die grösste Schwäche des Arduino-Systems ist aus meiner Sicht
die Hardware. Sie ist auf Nutzer zugeschnitten, die von Elektronik
wenig Ahnung haben, die nur schnell mal etwas zusammenstecken können
und die hinnehmen müssen, dass die Hardware meist überdimensioniert und
für eigene Erweiterungen schlecht geeignet ist.
Am besten gefallen mir noch der Wattuino (ein preiswerter Arduino-Mini-Clone von www.watterott.com)
und der Arduino Micro. Beide haben bastelfreundliche DIL-Anschlüsse,
wenig Hardware-Overhead und der Arduino Micro basiert (wie der Arduino
Leonardo) auf einem ATmega32u4, so dass man mit ihm auch sehr einfach
virtuelle USB-Geräte programmieren kann.
Für viele Projekte sind die aber immer noch zu gross (und
vergleichweise teuer), und leider neigt das Arduino-Projekt zu immer
komplexerer Hardware (z.B. mit ATmega 2560 bzw. ARM-Prozessoren), statt
das Spektrum "nach unten" abzurunden.
Arduino-kompatible Winzlinge
Aber erfreulicherweise kommen da Drittanbieter ins Spiel. Zwei Konzepte habe ich ausprobiert - Arduino Trinket von
www.adafruit.com und DigiSpark von
www.digistump.com - allerdings zunächst auf einem Streifenrasterplatinen-Nachbau (Bild oben rechts).
Beide Konzepte basieren auf Mikrocontrollern ATtiny 85 und
weisen wie die grossen Arduinos einen USB-Anschluss und einen
Bootloader auf. Da die VUSB-Library auf die "Kleinen" portiert wurde,
kann man sogar einige virtuelle USB-Geräteklassen damit realisieren.
Konzipiert sind sie aber eher als winzige Arduino-Varianten, die man
einmal programmiert und dann (mitsamt der dann nutzlosen USB-Hardware)
in einem vom PC unabhängigen Projekt verbaut. Man kann in seinem
Projekt die USB-Pins mit verwenden, so dass man immerhin 5 IOs zur
Verfügung hat. Für viele Anwendungen wird das reichen, und man hat dann
nur 9 Euro versenkt statt 25 Euro für ein "ausgewachsenes"
Arduino-Board (das Olimex-Board in der Mitte kostet als Bausatz sogar
nur unter 5 Euro).
Man muss allerdings "im Hinterkopf behalten", dass die
USB-Pins mit Z-Dioden beschaltet sind und an einem weiteren Port eine
LED mit Vorwiderstand hängt, so dass man nicht ganz frei bei der
Beschaltung der Ports ist.
Für das Digispark-Board (Bild oben links) gibt es einen deutschen Importeur.
Das Board habe ich aber nur für das Foto gekauft, denn das Konzept mit
den SMD-Mini-Shields finde ich sehr unpraktisch.
Die Hardware des Olimexino-85-Kit (Bild oben Mitte, erhältlich bei
Watterott) gefiel mir besser, weil sie eine "richtige" USB-Buchse
aufweist und die Steckleiste auf Steckboards und Streifenrasterplatinen
besser einsetzbar ist. Das Board hat keinen Spannungsregler, aber zwei
Dioden in Durchlassrichtung, so dass der Mikrocontroller am USB mit nur
3,3V versorgt wird. Er ist mit konventionellen Bauteilen bestückt, der
Attiny im DIP-Gehäuse ist gesockelt. Das Board hat im Gegensatz zum
Digispark einen Reset-Taster, während der Original-Digispark den
Reset-Pin als IO-Pin verwendet (der Reset-Pin wurde "weggefust").
Adafruits Trinket-Hardware und die Website wirken
professioneller, das Board lässt sich gut auf Steckboards und
Streifenraster-Platinen einsetzen, aber der Trinket-Bootloader wird
unter Linux nicht zuverlässig erkannt, während die Digispark-Variante
"micronucleus" anstandslos funktioniert. Daher habe ich mich für die
Digispark-Software (und selbstgebaute Hardware) entschieden.
Die Boards weisen Unterschiede bei Betriebsspannung und
Taktrate auf (bei 3,3V Betriebsspannung ist kein sicherer Betrieb mit
16,5 Mhz Takt gewährleistet). Adafruit Trinket gibt es in einer 5V- und
in einer 3,3V-Ausführung, beide arbeiten aber mit 8 MHz (bzw. im
USB-Programmiermodus vermutlich mit 12 MHz) Takt aus der PLL. Gleiches
gilt für Olimexino. Digispark verwendet 5V und 16,5 MHz Takt.
Man kann alle Boards als virtuelle USB-Geräte programmieren, wenn man
als Takt 16,5 MHz Takt wählt, aber die 3,3V-Versionen arbeiten dann
jenseits der Spezifikation.
Leider gibt es weitere Einschränkungen beim Einsatz der
"Kleinen". Viele Arduino-Libraries setzen Hardware-Ressourcen voraus,
die es beim ATtiny 85 nicht gibt (z.B. 16bit-Timer). Man kann nur
spezielle Libraries verwenden; etwa dreissig werden mitinstalliert.
Ein schmerzhafter Mangel gegenüber den grossen Arduinos ist,
dass das serielle Terminal nicht einfach so funktioniert. Die ATtinies
haben nun mal keinen Hardware-UART.
Es gibt zwar die Software-Serial-Library, aber die "frisst"
einiges an Ressourcen und stellt lediglich ein serielles Signal mit
TTL-Pegel (oder mit invertiertem TTL-Pegel) an zwei IO-Pins zur
Verfügung. Man kann aber damit einen Seriell-USB-Wandler (bzw. eine
echte serielle PC-Schnittstelle) ansteuern und dann jedes Terminal auf
dem PC verwenden (auch das interne Terminal der Arduino-IDE). Ist der
ATtiny gesockelt (wie auf dem Olimex-Board), kann man ihn z.B. einfach
auf die LP Mikrocontroller-Platine umstecken und dort mit ihm so
kommunizieren wie von einem ATtiny 13 gewohnt.
Ein weiterer Workaround ist eine spezielle USB-Lib (DigiUSB),
die mit speziellen Programmen für den PC kommunizieren kann. Das
PC-Terminalprogramm "digiusb" (es ist in diesem Paket
enthalten) ist etwas unkomfortabel, reicht aber, um Ausgaben des
Mikrocontrollers auszugeben und Befehle an ihn abzusetzen - mehr kann
das Terminal der Arduino-IDE auch nicht ;-)
Neuerdings gibt es sogar eine serielle CDC-USB-Library, mit
der der "Kleine" eine serielle USB-Schnittstelle emuliert, aber die ist
noch nicht ganz ausgereift.
Leider gilt generell, dass der ATtiny durch die USB-Library
stark ausgelastet ist und nur wenig Ressourcen für die Anwendung übrig
bleiben.
Ressourcenverbrauch
Eine einfache Blinkroutine verbraucht schon 650 Bytes Flash-Speicher; da ist der Bascom- oder C-User erst einmal irritiert:
void setup() {
pinMode(1, OUTPUT);
}
void loop() {
digitalWrite(1, HIGH);
delay (100);
digitalWrite(1, LOW);
delay (900);
}
Selbst wenn die Setup-Funktion und die Loop-Funktion völlig leer sind, werden schon 300 Bytes belegt.
Lässt man die beiden Delay-Befehle weg, toggelt der DigiSpark
schnellstmöglich, aber an dem Pin liegen (bei 8 MHz Prozessortakt) nur
schlappe 62 kHz an, weil das Toggeln 2 * 8 µs dauert (der
Speicherbedarf sinkt dann auf knapp 500 Bytes). Unter Bascom ist der
ATtiny sogar bei 1 Mhz Takt schneller....
Die Arduino-IDE scheint also recht ineffizienten Code zu
produzieren, aber das stimmt nicht so ganz, denn auch der folgende
Sketch, der jedoch kein delay() nutzt, belegt nur etwa 700 Bytes:
/* RGB-"Stimmungsleuchte" */
/* Pins definieren */
unsigned char Rot = 0;
unsigned char Gruen = 4;
unsigned char Blau = 3;
/* Anfangswerte */
unsigned char R = 254;
unsigned char G = 0;
unsigned char B = 0;
unsigned char N;
void Schalten() {
do {
N++;
if (R > N) {
digitalWrite(Rot, HIGH);
}
else {
digitalWrite(Rot, LOW);
}
if (G > N) {
digitalWrite(Gruen, HIGH);
}
else {
digitalWrite(Gruen, LOW);
}
if (B > N) {
digitalWrite(Blau, HIGH);
}
else {
digitalWrite(Blau, LOW);
}
} while (N < 255);
}
void setup() {
// initialize the digital pin as an output.
pinMode(Rot, OUTPUT);
pinMode(Gruen, OUTPUT);
pinMode(Blau, OUTPUT);
}
void loop() {
// digitalWrite(led0, HIGH);
while (true) {
do {
G++;
R = 254 - G;
Schalten();
} while (R > 0);
do {
B++;
G = 254 - B;
Schalten();
} while (G > 0);
do {
R++;
B = 254 - R;
Schalten();
} while (B > 0);
}
}
Der
Basis-Speicherbedarf ist vergleichsweise hoch, er steigt aber nur noch
moderat, wenn man mit den eingebundenen Funktionen herumrechnet.
Der Digispark als USB-Gadget
Seine Stärken zeigt das Arduino-Konzept mit diesem
Beispielsketch. Ein paar Zeilen machen den Digispark zu einem
virtuellen USB Keyboard, das im Abstand von 5 Sekunden "Hello World!"
in ein beliebiges PC-Programm hineinschreibt:
#include "DigiKeyboard.h"
void setup() {
}
void loop() {
DigiKeyboard.sendKeyStroke(0);
DigiKeyboard.println("Hello World!");
DigiKeyboard.delay(5000);
}
Verglichen mit C-Implementierungen
oder Bascom-Implementierungen
ist das eine dramatische Vereinfachung. Ähnlich wie bei der Variante mit einem Arduino
Leonardo bzw. Micro
wird die Komplexität des USB in der Library DigiKeyboard verborgen.
Kaum komplizierter ist die Realisierung eines Slideshow
Presenters. Der Mikrocontroller fungiert als virtuelles
Zwei-Tasten-USB-Keyboard, an seinen Eingängen B0 und B1 liegen zwei
Taster gegen Masse, die ein "Bild-rauf"- bzw. "Bild-runter"-Signal
erzeugen. Der Sketch ist in der ZIP-Datei beigefügt.
Download: digispark-beispiele.zip