Arduino Plattform

Die MSXFAQ ist beileibe keine Webseite für Hardware Basteleien aber es muss auch nicht immer ein großer Server mit vollwertigem Betriebssystem sein, um Spaß mit Programmierung zu haben. In meiner Lehrzeit war "Eletronikbasteln" noch überwiegend analoge Technik (Transistoren, Operationsverstärker) oder Digitaltechnik mit TTL-Chips. (74xx Serie). die zwar billig waren aber meist auch nur ein paar Gatter hatten. Die ersten Computer waren entsprechende TTL-Gräber und 1 MHz Taktrate, 64kByte RAM etc. waren schon Luxus.

Einstufung

Heute sieht die Zeit im Zeichen von PIC-Chips (AVR/ATtiny etc.), RaspberryPi (ARM) und auch Arduino schon anders aus. Ein Arduino ordne ich von der Rechenleistung, Speicherkapazität und universalität unter einem RaspberryPi ein. Der hat ja doch ein vollwertiges Betriebssystem (Basierend auf Linux) an Bord, so dass sogar Skriptsprachen (PHP, PERL) laufen. Unterhalb des Arduino gibt es die noch sparsameren, kleineren Chips der PIC-Serie, die aber auch etwas aufwändiger zu programmieren sind.

Hardware

Der Arduino ist eine schöne Plattform in der Mitte, die relativ preiswert ist, aber letztlich mit ganz wenig Aufwand und einer einfachen Programmieroberfläche den Einstieg in die hardwarenahe Entwicklung erlaubt. Entwickelt wurde die Plattform in Italien wobei die Hardware selbst "offengelegt" wurde. Zudem wurde eine IDE zum Schreiben von Programmen entwickelt, die über Parameter flexibel auf verschiedene Geräte angepasst werden kann. Entsprechend gibt es mittlerweile neben dem "originalen" Arduino auch viele Nachbauten (speziell aus China) oder andere Varianten.

Gerade der zweite Link zeigt, wie vielfältig die Boards heute sein können sowohl in der Bauart und Größe als auch in der Anzahl der Pins. Sogar "waschbare" Boards die kleiner als eine Münze sind, sind dabei. für mich als alter Elektronik-Bastler ist es schon faszinierend, was mit ein bisschen Software umgesetzt werden kann, wofür man früher ganze diskrete Bauteile errechnet und gelötet hat. Mit ganz wenig externer Beschaltung lassen sich ganz viele Probleme lösen. Und Spaß macht es auch noch.

Da die Entwickler alles um Arduino als "Open Source" veröffentlichen, gibt es sehr viele Nachbauten. Insbesondere über Ebay finden sich Arduino-Clones, die oft weniger als 4 Euro/Stück kosten und portofrei in 3-6 Wochen per Post kommen und durchaus brauchbar sind. Denken Sie aber dran, das das Projekt auch von den Einnahmen die Weiterentwicklung finanziert.

Mit "Wiring" gibt es eine ähnliche Plattform, zu der auch verschiedene Hersteller interessante Hardware liefern und die IDE für die Entwicklung sehr ähnlich ist. Es ist schließlich die gleiche Prozessorfamilie
http://wiring.org.co/hardware/ , https://store.spark.io/ (z.B. Photon und Core-Boards)

Achtung USB und SERIAL
Die ersten Arduino werden per serieller Kommunikation programmiert und genutzt. Mit einem USB-Anschluss war ein USB-Serial-Adapter erforderlich, der bei einem Reset des Arduino aber im PC "sichtbar" geblieben ist. Neuere Arduino, die direkt USB auf dem Board haben., basieren auf dem auf dem ATmega32u4, der direkt USB unterstützt. Bei einem Reset verliert aber auch kurz der PC den virtuellen COM-Port.
Anfang 2014 sind dies die Serien Leonardo, Mega, Micro, Yun und LilyPad USB.

Die kleinen Arduinos kommen mit viel weniger Strom aus, als ein großer Computer und können Signale daher auch autark erfasst und speichern. Über Schnittstellen können die Daten ja immer noch ausgelesen und weiter verarbeitet werden. Das ist insbesondere z.B. für Zählen (Energieimpulse) und müssen (Spannungen) interessant, wo ich gar nicht einen PC mit Interrupt belegen will.

Einsatz bei der MSXFAQ

Den Weg zurück zur "Elektronik" habe ich über mehrere Anforderungen gefunden:

  • Gebäudeautomatisierung
    Durch den Bau eines Eigenheims habe ich mich natürlich mit den verschiedenen Möglichkeiten einer Steuerung beschäftigt, sei es KNX, LCN, HomeMatic um letztlich dann noch erst mal "klassisch" zu bauen. Wenn ich in ein Zimmer gehe und den Schalter drücke, dann muss das Licht angehen. Da ist der Mehrwert über eine Steuerung nicht immer nachvollziehbar. Nur die Rollläden werden zentral gesteuert. Zukünftig denke ich, dass allein die Menge an Altbauten für Nachrüstungen viele Produkte hervor bringt, die über das Stromkabel oder Funk sehr einfach funktionieren. Aber natürlich schaut man sich auch Dinge wie FHEM u.a. an.
  • Energiezählung (z.B. Arduino und S0)
    Ein klassisches Thema ist natürlich "Zählen von Impulsen". Auslöser war eine gefühlt hohe Stromrechnung für den Net at Work Serverbetrieb und die Klimaanlage. Zwischenzähler mit S0-Schnittstelle waren schnell installiert aber ablesen ist uncool. Und dann haben noch viele anderen Kollegen etwas "zählen" wollen aber keinen PC dafür abstellen. Auch ein RasPI bekommt native nicht alle Impulse sicher mit. Also was liegt näher als mit einem Arduino die Daten zu zählen und dann per COM-Port oder Ethernet abzufragen ?
  • Netzwerk-Probe
    Ein RaspberryPi, ein "Arduino Ethernet" bzw. ein Netduino bringen mich auf den Gedanken, diese kleinen Boxen einfach als Ethernet-Probe zu verwenden um die Qualität der Netzwerkverbindungen zu müssen. So ein kleiner Arduino Ethernet könnte das sicher. Allerdings nicht mit großem Durchsatz. Dazu gibt es mitterlweile bessere Plattformen.

Die ersten Schritte

Wer bislang mit Windows gearbeitet hat, muss sich bei Arduino und anderen dieser kleinen Knechte erst mal umstellen. Auf dem System selbst lässt sich nicht wirklich entwickeln.

  • Die EntwicklungsUmgebung
    Sie benötigen also eine EntwicklungsUmgebung mit Editor und Compiler, was bei Arduino aber eine Java-gestützt EntwicklungsUmgebung ist. Ich habe mit der einfachen Arduino IDE begonnen, die die komplexen "Compile, Build, Flash"-Schritte stark vereinfacht.

http://arduino.cc/en/Main/Software

  • Lerne die Sprache
    Dann müssen Sie sich die Programmiersprache aneignen, was aber schon aufgrund der beschränkten Funktionen relativ zügig möglich ist, zumindest wenn Sie bislang schon mit C++ oder auch PowerShell gearbeitet haben. Entsprechende Beispiele unterstützen.
  • Code Deployment
    Zuletzt müssen Sie den fertigen Code kompilieren und auf den Arduino "flashen". Auch das geht aber mit der IDE sehr einfach. Ein richtiges "Betriebssystem" gibt es also nicht. Der erzeugte Code wird direkt auf dem Prozesse ausgeführt.
  • Code Debugging
    Einen richtigen "Debugger" gibt es leider nicht. Die Fehlersuche ist wie bei den früheren Skripten und Batchfiles, dass man an den fraglichen Stellen eine "Ausgabe" addiert. Beim Arduino wird dies meist ein schreiben auf den seriellen Port sein. Denkbar ist auch eine LED blinken zu lassen. Die Ausgabe auf dem Port ist natürlich ungeschickt, wenn dieser zugleich auch als Schnittstelle zur Kommunikation mit dem Programm genutzt werden soll. Einige Arduino haben einen zweiten COM-Port oder sie opfern ein paar Leitungen und klemmen z.B. ein LCD für die Fehlersuche an. Klassisch

Aber genau das macht es ja interessant. Auf dem Arduino kann quasi auch immer nur ein Programm geladen (geflashed) und entsprechend ausgeführt werden. Da das alles sehr hardwarenah ist, startet das Programm auch direkt nach dem Einschalten. Ein langes "Booten" etc. gibt es nicht wirklich.

Introduction to Arduino
https://www.youtube.com/watch?v=jRqLFn9rDJs  
Ca. 8h Video mit Links zu Sketchbooks etc. Ziemlich zäh

Everything You Need To Know About Arduino
https://www.youtube.com/watch?v=E6KwXYmMiak

Tutorial Videos
http://makecourse.weebly.com/arduino-videos.html

Es gibt durchaus noch andere EntwicklungsUmgebungen:

Programmieren mit ISP

Die meisten Arduino können über den seriellen Port programmiert werden. Teilweise ist dazu ein USB2Serial (TTL)-Adapter erforderlich oder der Arduino hat direkt schon einen USB-Anschluss mit serieller Funktion.

Achtung: Bei einigen neueren Modellen wie z.B. der Micro ist die USB-Anbindung teil des Chips und beim Reset nach dem Flash "verschwindet" kurz auch das USB-Device am Host. Das kann nerven aber die direkte Einbindung erlaubt auch, dass ein Arduino z.B. sich als Tastatur ausgibt.

In diesen Fällen können Sie immer noch einen ISP nutzen, und den Chip direkt programmieren. Einige missbrauchen dazu selbst einen anderen Arduino. Es gibt aber auch fertige Module. Die Nutzung eines ISP ist immer dann erforderlich, wenn der Mikrocontroller selbst noch gar keinen Bootcode hat, damit er sich per serieller Schnittstelle programmieren lässt. Zudem kann man über diese Seiteneingang mit dem AVR Studio auch den Code auf dem Chip debuggen. Es gibt mehrere Typen von Programmierern:

Kurzname Beschreibung Preise

AVRISP

Dieser Programmierer kommt direkt von Atmel, dem Hersteller des Prozessors und ist damit am leistungsfähigsten. Er erlaubt z.B. auch das Debugging von Code auf dem Chip. Allerdings ist er auch am teuersten und eher für professionelle Entwickler und Designer, die auch mit dem AVR Studio arbeiten. Das Gehäuse ist enthalten
http://www.atmel.com/tools/avrispmkii.aspx

35€

USBTinyISP

Eine Alternative zum AVRISP, die Kompatibel zur Atmel Software aber günstiger ist, wenn man selbst baut
http://www.ladyada.net/make/USBtinyisp/. http://www.mikrocontroller.net/articles/AVR-ISP-Stick

20€

USBasp

Die billigste Variante aber mit Einschränkungen. Scheinbar gibt es viele Hersteller und nicht jeder installiert eine aktuelle Firmware. Dafür ist das sehr günstig
http://www.fischl.de/USBasp/ , https://www.das-labor.org/wiki/USBasp, http://www.ulrichradig.de/home/index.php/avr/USB-avr-prog, http://www.fundf.net/USBasp/

ab 3€

Parallel

Es gibt auch Programmierer, die über den parallelen Port des PCs angeschlossen werden. Da diese Schnittstelle aber immer mehr verschwindet, machen diese Programmier auch immer weniger Sinn.

 

Ob der Programmierer nun 6 oder 10 Pins hat ist nicht relevant, da die 4 zusätzlichen Pins redundant oder nicht anschlossen sind. Hier eine Auswahl an weiteren Links

Gerade der uSPASP V2.0 scheint sehr günstig zu sein. Ist es doch auch nur ein kleiner Atmel mit eingebautem USB-Anschluss und einer kleinen Firmware zum Programmieren. Allerdings muss man für die ArduinoIDE drei Änderungen vornehmen, damit die IDE den Sketch direkt per ISP-Schnittstelle in den Arduino lädt:

  • Editieren von C:\Documents and Settings\”user”\Application Data\Arduino\preferences.txt
    Hier müssen Sie die Zeile "upload.using = bootloader" durch "upload.using = USBasp" ersetzen
  • C:\Program Files (x86)\Arduino\hardware\arduino\programmers.txt
    Hier müssen Sie eventuell die zwei Zeilen am Ende addieren, wenn Sie noch nicht enthalten sind:
USBasp.name=USBasp USBasp.protocol=USBasp

Eine Suche nach "isp programmer" z.B. auf Ebay zeigt sehr viele weitere kostengünstige Alternativen. Stellen Sie aber sicher, dass diese nicht nur mit dem AVR Studio von Atmel, sondern auch mit der Arduino IDE funktionieren.

Alternative IDEs

Eine "dicke IDE" wie Visual Studio ist für Batchfile, PowerShell-Skripte etc. einfach zu schwerfällig. Der kleine Notepad aber reicht hinten und vorne nicht aus. Vor vielen Jahren bin ich Auf Notepad++ gestoßen, der mich seit dem begleitet. Die Arduino IDE ist relativ überschaubar in den Funktionen. Also war es nur eine Frage der Zeit, bis ich Notepad++ als Editor verwenden wollte. Das ist auch relativ einfach, da es entsprechende "Sprachdateien" für Notepad++ schon gibt und er auch den Compile/upload aufrufen kann.

Hier nur eine kleine Auswahl der Blogs, die ähnliches beschreiben.

Atmel Studio
http://www.atmel.com/tools/atmelstudio.aspx

Die Arduino IDE enthält auch ein "Terminal Fenster", welches mit CTRL-SHIFT-M erreichbar ist. Nach meinen Beobachtungen initiiert dieses Fenster aber einen "RESET" des Arduino. So kann man schön den Startup beobachten aber das ist natürlich stören, wenn der Arduino schon einige Zeit läuft und sie sich erst dann aufschalten wollen.

Die Funktion "setup()"

Diese Funktion wird einmal beim Start des Code ausgeführt und könnte wie folgt aussehen

void setup() { 
  // Dieser Code wird beim Einschalten oder Start einmalig ausgefuerht.
  // ideal für die Initialisierung von Variablen und Vorarbeiten
  // Normal wird der serielle Port initialisiert für spätere Ausgaben.
  Serial.begin(9600);
   while (!Serial) {
    ; // wait für serial port to connect. Needed für Leonardo only
  }
  Serial.println("Setup gestartet");
}

Sie ist auch ein idealer Platz Variablen initial zu belegen. Die Funktion kann natürlich andere unterfunktionen aufrufen, die durchaus auch im Code weiter hinten stehen können. So bleibt die Übersichtlichkeit gewahrt.

Die Funktion "loop()"

Nachdem das "setup()" durch ist führt der Arduino-Loader diese Funktion immer wieder aus. Ich muss also nicht extra eine "while true {}"-Schleife" bauen. Hier passiert sequentiell die Magie.

void loop() {
  // Diese Funktion wird nach dem Setup immer wieder wiederholt.
  Serial.println("Loop gestartet");
  delay(1000)
}

Dieses Beispiel enthält nun natürlich keinen wirklichen Sinn. Zudem kann der Arduino die Daten schneller ausgeben als der serielle Port die Daten überträgt. Insofern muss man beim Debugging auch wieder sich beschränken oder den Code absichtlich "verlangsamen".

Schlafen und Interrupts

Nun kann es durchaus sein, dass ein Code nicht andauern "pollen" soll. Das kostet einfach Energie. Wenn der Arduino eh mit mehr Spannung betrieben wird und der Spannungsregler auf dem Board darauf 5Volt macht, dann ist das Einsparpotential gering, da der Spannungsregler schon 10mA "verheizt". Wer dann noch eine LED als Signal angeschlossen hat, wird noch ein paar mA mehr verbrauchen. Interessant ist dies also, wenn der Arduino z.B. über Batterien betrieben wird.

Wenn ein Arduino einmal "schlafen" gelegt wurde, dann kann ihn nur ein Interrupt oder ein Reset wieder erwecken. Sie müssen also "Vorarbeiten", das einer der beiden Eingänge 2 oder 3 immer dann ein Signal sendet, wenn es etwas zu tun gibt und sie müssen eine Funktion einbauen, die dann aufgerufen wird. Die Funktion eines Interrupt ist aber auch hilfreich, wenn Sie auf Vorgänge reagieren wollen, z.B. StatusÄnderungen einer Leitung. Wichtig ist nur zu wissen, dass nicht alle Eingänge auch einen "Interrupt" auslösen. Die Leitung 2 ist aber meist auch mit dem seriellen Port verbunden, so dass ein eingehendes Zeichen einen Interrupt auslöst. So können Sie den Arduino auch vom PC aus ansteuern-

Auf einigen Arduino gibt es sogar noch weitere vorgefertigte Funktionen die in der Basis oder über Libraries verfügbar werden. Der ATMega 328 hat eine ganze Liste:

Interrupt Bezeichnung Auslöser

1

Reset

kein

2

External Interrupt Request 0 (pin D2)

INT0_vect

3

External Interrupt Request 1 (pin D3)

INT1_vect

4

Pin Change Interrupt Request 0 (pins D8 to D13)

PCINT0_vect 

5

Pin Change Interrupt Request 1 (pins A0 to A5)

PCINT1_vect

6

Pin Change Interrupt Request 2 (pins D0 to D7)

PCINT2_vect

7

Watchdog Time-out Interrupt

WDT_vect

8

Timer/Counter2 Compare Match A

TIMER2_COMPA_vect

9

Timer/Counter2 Compare Match B

TIMER2_COMPB_vect

10

Timer/Counter2 Overflow

TIMER2_OVF_vect

11

Timer/Counter1 Capture Event

TIMER1_CAPT_vect

12

Timer/Counter1 Compare Match A

TIMER1_COMPA_vect

13

Timer/Counter1 Compare Match B

TIMER1_COMPB_vect

14

Timer/Counter1 Overflow

TIMER1_OVF_vect

15

Timer/Counter0 Compare Match A

TIMER0_COMPA_vect

16

Timer/Counter0 Compare Match B

TIMER0_COMPB_vect

17

Timer/Counter0 Overflow

TIMER0_OVF_vect

18

SPI Serial Transfer Complete

SPI_STC_vect

19

USART Rx Complete

USART_RX_vect

20

USART, Data Register Empty

USART_uDRE_vect

21

USART, Tx Complete

USART_TX_vect

22

ADC Conversion Complete

ADC_vect

23

EEPROM Ready

EE_READY_vect

24

Analog Comparator

ANALOG_COMP_vect

25

2-wire Serial Interface (I2C)

TWI_vect

26

Store Program Memory Ready

SPM_READY_vect

Davon ist aber nur eine Teilmenge für den normalen. Arduino Entwickler sinnvoll zu nutzen. Sehr viele werden nämlich schon innerhalb der entsprechenden Klassen verwendet, so dass man sich eigentlich nur im die Pins 2 und 3 kümmert. Und selbst dann muss man immer beachten. dass nur eine Interrupt Service Routine laufen kann und in der Zeit weitere Interrupts blockiert sind.

Wenn eine Routine also auf etwas "länger warten" muss, aber andere Codeteile weiter arbeiten sollen, dann sollten Sie einfach ihren Code überspringen und  bei jedem Durchlauf erkennen, ob sie schon was tun können.

Performance, Timing und Multitasking

Auch wenn ein Arduino mit ein paar Megahertz arbeitet, so fühlt man sich schon wieder etwas in die alte 8Bit Welt (6502/Z80) versetzt, bei der man noch zu jedem Assembler-Befehl wusste, wie viele CPU-Takte dieser benötigte und wenn ein Programm zu "schnell" war, hat man eben ein paar Schleifen mit einem "NOOP" (No Operation) addiert und so die Verzögerungen in Takten festgelegt. Beim Arduino geht das mit dem "DELAY" einfacher, da er den Prozessor einfach die angegebene Zeit in Millisekunden anhält. Allerdings ist das dann auch eine richtiges "HALT", denn ein Multitaskting kennt der Arduino nicht.

Wer also etwas verzögern will, aber dennoch quasi "parallel" noch andere Dinge verarbeiten will, sollte das Programm nicht über "DELAY" anhalten, sondern über die Funktion "Millis" besser prüfen, ob die Wartezeit schon vorbei ist und ansonsten den Codeteil einfach überspringen.

So bekommt man zwar kein "Multitasking" hin, aber wenn die verschiedenen Bestandteile eines Codes untereinander stehen und keiner der Teile den Code "blockt" sondern einfach rausspringt und später wieder aufgenommen wird, dann kann man was ähnlich erreichen. Alternativ können Sie natürlich immer noch auf Interrupts reagieren, sofern das Programm nicht mit einem "Delay" zum Schlafen gesendet wurde.

Eine Abfrage wie "Serial.available()" blockt übrigens nicht den Prozess. Aber auch ein "Serial.read()" liefert nur ein "-1", wenn kein Zeichen ansteht aber blockiert nicht durch ein Warten auf eine Eingabe.

Performance Messwerte

Interessant ist natürlich schon, wie "schnell" bestimmte Aktionen erfolgen, Ich habe mir daher ein paar kleine Beispielcodes gebaut, die ganz trivial bestimmte Aktionen oft genug durchführen und am Ende die Zeit in "Millis()" müssen. Per Default puffert der Arduino bis zu 64 Zeichen auf dem seriellen Port.

Als Testsystem diente ein "Arduino Ethernet Rev 2" (http://arduino.cc/en/Main/ArduinoBoardEthernet)mit ATmega328

Messung  Ergebnis  Code

DigitalRead 

Ich habe einen digitalen Port einfach 100.000 mal abgefragt ohne weitere Verarbeitung. Das dauert weniger als eine halbe Sekunde, d.h. 466ms/100.000 = 4,66 Mikrosekunden. Die Zahl ist natürlich nicht repräsentativ.

Ohne Berechnung könnte man also 214592 "digitale Zustände " pro Sekunde ermitteln.

liest man in jedem Durchlauf 4 Ports ein, dann dauert dies mit 1720ms etwas weniger als 4mal so lang.

466ms

Einfluss Serial Output

Ich habe dann absichtlich "viele Zeichen" ausgegeben. Sofern man also mit dem Arduino und den COM-Port mit dem PC kommunizieren will, kann dies ein Engpass werden. Die Ausgabe von 10 Zeichen kostet ca. 1ms aber danach 8ms und dann weiter 22ms. (Die Ausgabe enthält auch noch die Strings !

Es scheint als wenn der Puffer von ca. 64 Zeichen voll ist und noch nicht ausgelesen wurde, dann wird das Programm verzögert. Das ist beim Datenaustausch über die "Serial"-Schnittstelle zu beachten.

Liste wird fortgesetzt

 

 

Das sind natürlich sehr optimistischer Werte. Einfache mathematische Funktionen und Schleifen sind gar nicht mal das Problem, aber z.B. Serielle eingaben und Ausgaben, die "blockieren" können die Reaktionszeit deutlich verlängern.

Serial Input / Output

Kommen wir gleich zu der primären Schnittstelle, mit der eine Software mit dem Entwickler kommunizieren kann. Es ist sehr einfach mit Serial.print und Serial.PrintLn ausgaben auf die Console zu schreiben und mit Serial.ReadString auch wieder Eingaben anzunehmen. Aber zuerst müssen Sie natürlich den seriellen Port initialisieren. Ich mache das immer am Anfang der SETuP-Funktion.

void setup() {
  Serial.begin(9600);             // INIT Serial Port
  while (!Serial) {blinkled(300);} // wait für serial port to connect. Needed für Leonardo only
  Serial.println("----- Sketch SETuP Start -----");

Bei neueren Boards mit dem ATmega32u4 sollten Sie auf den Port "warten", da er per USB bereit gestellt wird und nach dem Reset der PC vielleicht etwas braucht. Die Funktion "blinkled" ist weiter unten beschrieben. Beim Einlesen gibt es nun einige Optionen:

String command = Serial.readString();           // Liest alle Zeichen ein bis zum Timeout (100ms)
String command = Serial.readStringuntil('\n');  // List alle Zeichen ein bis zum Timeout oder dem angegebenes Zeichen

char inputchar = Serial.read();                 // Liest genau ein Zeichen ein
String command= String(inputchar);  // convert char to string

Auch wenn "ReadString" sehr einfach ist, so wird das ausgeführte Programm bis zu 1 Sek "angehalten". Wenn das Skript dann natürlich kurze Impulse (z. B. S0 = 30ms) zählen soll, dann führt so eine Ausgabe zu Verzögerungen.

Dann sollten Sie besser mit Serial.Available() die Anzahl er im 64 Byte langen Buffer stehenden Bytes ermitteln und manuell einlesen und entsprechend parsen., auch wenn das etwas umständlicher ist. Es ist keine gute Idee, den Timeout sehr klein zu stellen, da er dann auf alle von der "Stream"-Klasse abgeleitete Routinen angewendet wird, z.B. auch Wire, EthernetServer, EthernetClient, SD-Card etc.

Eine einfache Version, die ein einzelnes Zeichen einliest. habe ich hier veröffentlicht. Ich konvertiere das Zeichen aber zu einem String, damit ich die Groß/Kleinschrift nicht selbst behandeln muss und vielleicht brauche ich die Funktion ja noch mal um mehr Zeichen zu lesen.

 (Serial.available()>0) {
    char inputchar = Serial.read();
    String command= String(inputchar);  // convert char to string
    
    if (command.equalsIgnoreCase("0")) {
      debuglevel = 0; 
      Serial.println("Debuglegel = 0");
    }

Wenn Sie direkt mit dem "Char" weiter arbeiten wollen, dann denken Sie beim Vergleichen mit "if" daran, dass die Anführungszeichen entscheidend sind. Einen "Char" sollten sie mit einem Buchstaben in einfachen Anführungszeichen vergleichen.

Hinweis:
Wenn mehr Zeichen empfangen werden, als der Buffer speichern kann, dann werden alle überzähligen Zeichen verworfen. Der Ringbuffer wird also nicht überschrieben.

if (inputchar == 'a') {...   // kann ausgeführt werden
if (inputchar == "a") {...   // wird nie ausgeführt da ein Char <> String

Auch bezüglich der Ausgabe sollten Sie immer beachten, dass der Ausgabepuffer 64 Zeichen umfasst und das Skript ausgebremst wird, wenn der Buffer voll ist und die Bytes langsam versendet werden. Seit Arduino 1.0 arbeitet zwar Serial.Print asynchron, d.h. kommt auch wieder zurück, ehe die Bytes versendet werde, aber eben nur, solange der Buffer die auszugebenden Bytes auch vorhalten kann. 

Wer demnach Mehr als 64 Bytes/Zeichen innerhalb der maximalen Zeit senden will, muss mit einer Verzögerung des Programms rechnen oder Vorkehrungen treffen, z.B. indem man selbst einen Buffer mitführt und bei jedem Durchlauf prüft, ob man nicht "zu schnell" ist, denn ansonsten wartet das Programm.

// If the output buffer is full, there's nothing für it other than to
// wait für the interrupt handler to empty it a bit
Quelle: HardwareSerial.cpp Zeile 464 Stand: 14 August 2012

Leider enthält der Code keine Funktion um zu ermitteln, wie voll die Sendequeue ist.

Tipp: In vielen Beispielen wird der serielle Port mit 9600 Baud initialisiert. Natürlich können auch höhere Datenraten (z.B. 115200) genutzt werden. Sie müssen dann aber auch ihre Auslesesoftware auf dem PC entsprechend anpassen.

param (
   [string]$comport = "COM4",
   [long]$bitrate = "9600",  # default baud rate
)

$port= new-Object System.IO.Ports.SerialPort $comport,$bitrate,None,8,one
$port.ReadTimeout=5000
$port.WriteTimeout=5000
write-host "Open Port $comport"
$port.open()

#write-host "Send Command"
#$port.WriteLine('P')
#write-host "Delay 1 Sec"
#start-sleep -milliseconds 1000
write-host "Start Reading output"
write-host $port.readline()
$port.Close()

Schön dabei ist, dass Windows das komplette "Puffern" übernimmt.

Debugging, LED, LCD

Ich habe schon ein paar Zeilen vorher gesagt, dass es mit dem "Debugging" nicht so einfach ist. Ausgaben aus SERIAL kann ich nur am PC lesen, die Arduino-IDE erlaubt kein integriertes Debugging. Insofern wäre es doch hilfreich eine weitere Ausgabe zu haben. Natürlich könne man einen der viele l/O-Ports mit einem Vorwiderstand und LED bestücken und z.B. "Blinksignale" geben. Ich habe mir dazu mehrere Bausteine bereit gelegt:

Sie werden gleich sehen, das ich kein "Vollblut Programmierer" bin. andere würden diese Code-Schnipsel sicher in einer Library oder Class verstecken oder eine bestehende Library nutzen.

Der erste ist eine "DEBuG"-Ausgabe, die zwar auf die serielle Schnittstelle schreibt, aber einen "Level" respektiert

// Global variable für debug output settings 
int debuglevel = 0; 

void loop () {
   debug(3,true,"Debug Level 3); 
}


void debug(int level, boolean newline, String message) {
  if (level <= debuglevel ) {
    if (newline) {
      Serial.println(message);
    }
    else {
      Serial.print(message);
    }
  }
}

So kann ich überall im Code meine "debug"-Ausgaben addieren und über die globale Variable vorgeben, wie detailliert ich das haben will..

Der zweite Block ist ein "Lebenszeichen". Nahezu jeder Arduino hat eine LED aufgelötet, die an Pin 9 oder 13 angeschlossen ist und per Software geschaltet wird. Wenn dieser Port für nichts anderes verwendet wird, dann habe ich mir angewöhnt hier per "Blinken" zu zeigen, dass das Programm noch läuft. Ich brauche dazu natürlich ein paar globale Variablen. Denn der Code sollte immer mal wieder aufgerufen werden, z.B. am Anfang der Loop-Funktion. Der Code selbst ist aber "non blocking", d.h. die LED wird im angegebenen Takt ein uns ausgeschaltet, aber der Code" wartet" nicht sondern prüft, ob die Wartezeit schon vorbei ist.

// Global variabled für blinking status led
const int statusledport= 9;  // Arduino Ethernet. status LED to show flashing status  normally 13
boolean statusledstate = true; unsigned long statusledmillis = 0;


void loop() {
  blinkled(1000);  // Call BlinkingLED to indicate, that everything is fine

}

void blinkled(long blinkms) {
  // Flash Heartbeat LED 
  if ((millis() - statusledmillis) > blinkms) {  // Wait für elapsed time blink
    statusledmillis = millis();
    if (!statusledstate) {
      debug(3,true,"HeartbeatLED:HIGH");
      digitalWrite(statusledport, HIGH);
      statusledstate=1;
    }
    else { 
      debug(3,true,"HeartbeatLED:LOW");
      digitalWrite(statusledport, LOW);
      statusledstate=0;
    }
  }
}

Bei Gelegenheit wollte ich diese Funktion vielleicht noch um eine Art "Morsezeichen" abwandeln. Aber gerade am Anfang habe ich im Code auch immer die Anforderung ein "richtiges Problem" zu melden und den Code anzuhalten. Dazu habe ich mir eine "finalerrorstatus"-Funktion gebaut, die den Fehler auf den serial-Post ausgibt aber parallel die LED eine anzugebende Anzahl von Impulsen blinken lässt und nach einer Pause widerholt.

void finalerrorstatus (int errorcount, String message) {
  debug(0,true," Raeaching a finalerrorstatus!");
  while(true){      // no point in carrying on, so do nothing forevermore: für (int ledcount = 1; ledcount <= errorcount; ledcount++) {
      digitalWrite(statusledport, HIGH);   // turn the LED on
      delay(500);               
      digitalWrite(statusledport, LOW);    // turn the LED off
      delay(500);               
    }
    delay(4000);
    debug(0,false,"Final Error Status");
    debug(0,false,message);
    debug(0,false,"Error:");
    debug(0,false,String(errorcount,DEC));
  }
}

Diese Funktion ist natürlich im Gegensatz zur "blinkled"-Funktion blockierend. Das ist aber auch so gewollt.

Alles viel schöner geht das natürlich, wenn der Arduino auch eine Ausgabe "schreiben" kann, die nicht den COM-Port belegt. Leider hat der Arduino im Gegensatz zum RaspberryPI keinen Video oder HDMI-Ausgang und daher bleibt nur der Weg, ein LCD an die Ports anzuschließen. Das ist nicht schwer und auch nicht teuer aber je nach Anbindung kostet es viele, weniger oder ganz wenige Ports. Und da man mit Ports für eigene Ansteuerungen eher sparsam umgeht, würde ich ein Display mit I2C, TwoWire-Interface (TWI) vorziehen und nicht die kostenbaren Digitalports dazu verwenden. mit I2C kommt man mit zwei Leitungen hin und kann sogar noch andere Geräte an den gleichen Bus anschließen.

Ich habe noch kein LCD-Modul angeschlossen. Ich plane ein 2x16 oder 4x20 Zeichen Module über TWI/I2C anzuschließen, um damit Ausgaben zu ermöglichen.

Ethernet und LAN

Es ist erstaunlich, wie einfach so ein kleiner Minirechner auch im Ethernet mitspielen darf. Mit dem "Arduino Ethernet" gibt es gleich ein Board, auf dem ein Ethernet-Anschluss gleich drauf ist. Aber auch die anderen Boards lassen sich recht schnell mit Ethernet nachrüsten. Entsprechende Module gibt es über ebay aus China für unter 5 Euro.

Allen gemeinsam ist, dass vier PINs des Arduino benötigt werden und damit nicht mehr für andere Zwecke verwendet werden können. Die verwendeten Pins hängen von der verwendeten Library und dem Modul ab.

  Library 
Pin-Funktion EtherCard uIPEthernet ETHER_28J60
Chip Select (SE)

10

10

8

Daten vom Ethernet empfangen (MISO)

11

11

11

Daten zum Ethernet senden (MOSI)

12

12

12

CLK

13

13

13

Das liegt auch daran, dass es nicht nur genau ein Ethernet Shield gibt, sondern verschiedene Chips per SPI angebunden werden können, unterschiedliche Hersteller eigene Erweiterungen für die offene Arduino-Plattform entwickelt haben und damit unterschiedliche Libraries für den Einsatz notwendig sind. Hier ein Bild eines sehr günstigen Shields basierend auf dem 28J60-Chip mit aufgestecktem Arduino Nano

Die meisten Adapter unterstützen nur 10/100 MBit und ich kenne keinen mit dem man per PoE den Arduino versorgen könnte. Wäre PoE noch nett, so ist Gigabit komplett überflüssig. Zudem erfolgt die Übertragung "seriell" und das hat direkt Auswirkungen auf die erreichbare Performance. Hinzu kommt, dass z.B. das W5100 nur bis zu 4 Ports direkt selbst in seiner IPv4-Engine verwalten kann. Muss man mehr Ports bedienen, muss man per MACRAW direkt alles selbst umsetzen. Zudem ist das SPI Interface nur für 4MHz spezifiziert und erlaubt nur "Single Byte"-Transfers. Erst das W5200 Modul hebt diese Grenzen leicht an.

Viel mehr als 100kByte/Sek wird ein Arduino kaum senden können und das nur, wenn er nicht noch was anderes macht. Auch beim Empfang sollten Sie keine Wunder erwarten. Auf der anderen Seite gibt es aber auch nicht viele Daten, die ein kleiner Arduino mit 16MHz Taktfrequenz, 16kb Programmspeicher und 2k RAM senden oder empfangen kann.

Arduino und WiFi

Mittlerweile gibt es von Adafruit auch ein Shield, welches auf dem Texas Instruments CC3000 basiert und per SPI an die verschiedenen Arduino-Systeme angebunden werden kann. Damit kann ein Arduino oder anderes Device mit SPI-Schnittstelle relativ einfach in ein WIFI-Netzwerk angebunden werden. Das ist insbesondere interessant, wenn am Einsatzort kein LAN zur Verfügung steht oder der Arduino mobil ist. Es gibt z.B. von Adafruit ein Modul, welches über SPI sich anmelden und für unter 40 US-$ erhältlich ist.

Es geht aber noch billiger, da es mittlerweile WiFi -Boards gibt, die seriell angeschlossen werden, z.B. auf Basis des "ESP8266". Allein über 4 Kabel (GND, +3,3V, RxD und TxD) wird das Modul programmiert und die Daten übertragen.

Da kann man natürlich keine "highSpeed"-Übertragung erwarten aber es reicht, um kleine Heartbeat-Signale oder z.B. Infos per UDP ins LAN zu schreiben. Es kann aber auch eine TCP-Verbindung als Client oder Server aufgebaut werden.

Mittlerweile gibt es aber sogar schon Arduino Nano Clones mit direkt angelötetem ESP8266, die von Conrad, Franzis etc. für 25-35€ vertrieben werden: Die serielle Verbindung des ESP8266 wird dabei auf die Datenpins D11/D12 gelegt und mit der SerialIO-Library angesteuert.

 

 

Fehler, die mir selbst auch schon unterlaufen sind

Während meiner eigenen Arduino Programmierübungen bin ich natürlich auch in die ein oder andere Falle getappt:

  • Zu viele Ausgaben per "Serial.print"
    9600 Baud sind ca. 100 Zeichen/Sek, und das ist nicht viel, wenn man zum "Debugging" an jede Stelle eine Diagnoseausgabe setzt. Das verändert schon die Laufzeit. Das können Sie am unten vorgestellten S0-Zähler sogar "sehen", dass bei der Ausgabe das "Blinken" der LED quasi "angehalten" wird. Er also viele Daten auszugeben hat, sollte diese entweder "kompakt" speichern oder nicht auf einmal sondern in mehreren Schüben ausgeben.
  • Eingaben mit "Serial.ReadString"
    Wenn der String am Ende abgeschlossen ist, dann wartet das Skript auf das Ende. Wer nun zwei Zeichen mit 9600Baud sendet, braucht min 10ms pro Zeichen. Sobald das erste Zeichen anliegt, wartet das Skript auf mehr bis zu einem Timeout (1Sek ?) Besser ist es mit Serial.read zeichenweise abzuholen und das Skript weiter laufen zu lassen.
  • Grenzen von Variablen beachten
    Wenn man eine Variable als "INT" (integer) definiert, dann sollte man sowas nicht machen:

    Diese Schleife kommt nie zurück da bei 32768 ein Rollover erfolgt und die 100.000 nie erreicht wird.
  • LowerCase und upperCase
    C++ ist "Case Sensibel", d.h. Befehle aber auch Variablen und Konstanten müssen genau eingegeben werden. Ein Stück weit unterstützt die IDE die Eingabe von vordefinierten Konstanten durch eine farbliche Kennzeichnung. Dennoch passiert es auch mir immer wieder, mich zu "vertippen". Schön wenn der Compiler sich dann beschwert. Unglücklich, wenn man zwei Variablen verwendet, die unterschiedlich geschrieben sind.
  • CHAR und String im Vergleich
    Es ist ein unterschied, ob man "a" oder 'a' schreibt. In der PowerShell ist es fast gleich, nur dass bei einer auch Variablen ersetzt werden. Beim Arduino aber ist das doppelte Anführungszeichen ein "string" während der einfache Anführungsstrich ein "CHAR" ist. Das ist bei Vergleichen genau zu prüfen.
  • CTRL-SHIFT-M = SerialMonitor
    Wenn man in der Arduino IDE den seriellen Monitor startet, dann zeigt er nicht nur an, was ab dem Moment dann ausgegeben wird, sondern bei mir hat er auch einen Reset zum Arduino gesendet, so dass das Programm wieder vom Anfang an losgelaufen ist.

Die Liste wird fortgesetzt.

Praktisches Beispiel

Auf der Seite Arduino und S0 habe ich ein Beispiel, wie der Arduino Ethernet eine S0-Schnittstelle liest und diese Daten per HTTP erreichbar macht. Auf der Seite Arduino Ethernet Probe habe ich weitere Beispiele für den Arduino mit Ethernet beschrieben. Ich hatte auch mal vor die UCWA-Schnittstelle von Lync mit einem Arduino direkt abzufragen aber das ist natürlich durch die Pflege von Zugangsdaten und Kennworten als "Code" nicht sehr einfach.

Auf dieser Seite beschränke ich mich wieder mit dem Aufbau eines S0-Zählers, der einfach nur die vielen Eingänge des Arduino abliest, aufaddiert und über den COM-Port bereit stellt. Da aber nur der Port 2 und 3 einen Interrupt auslösen und ich mir eine Zusatzschaltung über ODER-Gatter ersparen wollte, lese ich die Werte im "Polling" aus. Schnell genug ist der Arduino ja und durch den USB-Anschluss am PC zur Stromversorgung und Datenübergabe kommt es nicht auf das letzte mW an. Das Flussidagramm ist also überschaubar:

 

Das SETuP-Routine initialisiert den seriellen Port für die Datenausgabe, die Debug-Ausgabe, und Variablen. Die Loop-Routine liest dann einfach immer die Eingänge nacheinander ab und sucht an einer "Veränderung". Auf der Seite Arduino und S0 habe ich mehr Details über S0-Bus lesen und "Entprellung" per Software geschrieben. Die Zustände müssen 30ms anhalten, also wenn ich alle 10ms die Daten ablesen und zwei Messung "gleich" sind, dann habe ich einen stabilen Pegel und kann dies als "Wert" ansehen. Da der Arduino aber deutlich schneller ist, muss ich sogar die Messung verzögern. Um dabei aber nicht das gesamte Programm aufzuhalten, prüfe ich das über die "millis()" abfrage und vergleich ob die erforderliche Zeit schon verstrichen ist. In einen "Stromsparmode" fällte der Arduino damit natürlich nicht.

Aber damit kann ich in einem zweiten Schritt natürlich prüfen, ob eine Anfrage über den seriellen Port eingegangen ist, auf die ich antworten muss. Hier habe ich mir den Spaß erlaubt, gleich mehrere Funktionen anhand der Steuerung exemplarisch abzubilden. Um die Abfrage aber "einfach" zu halten, habe ich mich auf ein Zeichen beschränkt um nicht noch auf CR oder LF achten zu müssen.

  • 0-0-5 = Ich kann damit über den COM-Port den "Debuglevel" entsprechend setzen.
  • P = Ausgabe der Zählerstände gleich im "PRTG-Format"
  • L = Ausgabe als "Liste
  • S = Kurze (Short) Liste mit allen Werten in einer Zeile durch ";" getrennt um Verzögerungen durch die Ausgabe zu minimieren
  • Alles andere
    Eine kleine "Online Hilfe" mit den verfügbaren Programmen.

Hier erst mal der Code als Muster

arduino-sample.ino.txt

Gerade bei der Auswertung der Rückgabe ist immer abzuwägen, ob die Ausgabe von vom Code auf dem Arduino für das Zielsystem aufbereitet wird oder ob eine Zwischenskript die komprimierten Daten für das Ziel umsetzt, was deutlich Flexibler bei Änderungen des Ziels ist.

mögliche Erweiterungen

  • Zählerspeicherung
    Der Arduino Ethernet hat einen 2KByte SRAM-Speicher, in dem man natürlich z.B.: die Zählerstände hinterlegen könnte. Das hätte aber den Nachteil, dass nach einer Spannungsunterbrechung nicht erkannt würde, dass die Zähler gestanden haben. So fangen die Zähler wieder bei "0" an und ein Monitoring kann dies erkennen
  • Zählerstandsreihe
    Interessanter wäre hier schon die Funktion, die Messreihe zu speichern und so auch zu überbrücken, wenn der Host die Daten nicht zeitnah abholt. Den Zählerstand alle Minute in einer Variablen zu halten und dem Host dann die letzten 60 Minuten zu liefern könnte kurze Unterbrechungen des Hosts neutralisieren.
  • Min/Max-Erkennung anhand des Abstands
    Wenn man nur Impulse zählt und der Host regelmäßig die Daten abfragt, dann bekommt man auch nur Mittelwerte aber keine Spitzenwerte oder Minimalwerte. für den Arduino ist es ein einfaches nicht nur die Impulse sondern auch die Abstände dazwischen im Millisekunden/Mikrosekunden (micros())  zu müssen und damit auch Lastspitzen zu erfassen.

Arduino und Lync ?

Der Arduino kann per Ethernet angesteuert werden aber interessant ist auch die Funktion des "Arduino Ethernet", welcher über IP und HTTP kommunizieren kann. Damit könnten sich natürlich neue Optionen anbieten, z.B. dass der Arduino per SIP oder UCWA sich am Lync Server anmeldet. Allerdings gibt es noch keine passende SIP-Library und selbst der HTTP-Client ist schon recht beschränkt. Zudem stellt sich natürlich die Frage, wie die Anmeldedaten auf den kleinen Arduino kommen. Sicher könnte man die per serieller Kommunikation übertragen, aber einfach wird das nicht.

Für den USB-Anschluss gibt es mit dem Busylight, Lync I-Buddy und Hinweisen (Statuslicht und Ideen) schon viele passable Lösungen. Ob es da sinnvoll ist, mit dem Arduino Ethernet z.B. eine Kommunikation zum Lync Server zu entwickeln, steht in den Sternen. Denkbar wäre natürlich eine Umsetzung über eine Middleware, z.B. eine IIS-Applikation auf dem Lync Server stellt ausgewählte Informationen über einen einfachen (anonymen) HTTP-GET bereit.

Dann wäre es natürlich sehr viel einfacher, einen Arduino dazu zu verwenden, z.B. abhängig vom Status einer Person eine Signalleuchte zu steuern oder auf bestimmte Aktionen (INPuT) eine Meldung an Lync zu senden. Es gibt ganz viele Dinge zu entdecken.

Arduino zum Lernen

Es ist relativ einfach, mit einem Arduino erst mal etwas zu bauen, was es schon gibt. Man kann dennoch dabei sehr viel Lernen. Überlegen Sie mal:

  • "Fahrradcomputer"
    Klar gibt es die beim Discounter schon für <10 Euro aber es geht ja um den Lerneffekt. Ein Arduino, ein per I2C angeschlossenes LCD-Display und ein Magnetschalter an einem der digitalen Eingänge erlaubt ihnen schon sehr viele Themen zu bearbeiten, z.B. Entprellung von Tasten, Frequenzzählung und Ausgabe auch dem LCD
  • Voltmeter/Multimeter
    Auch die gibt es schon für wenig Geld aber mit den analogen Eingängen (0-5V) und einem LCD lässt sich natürlich auch ein Voltmeter nachbauen. Mit etwas externer Beschaltung (Wiederstand) auch ein Amperemeter.
  • Transistor-Meter/Grapher
    Für das einfache LCD ist das sicher nicht mehr ausreichend, aber ein Arduino könnte sicher problemlos einen Transistor analog ansteuern und z.B. dessen Verstärkungsgrad ermitteln.
  • Morse-Zeichen
    Die ersten Übertragung von Informationen per Kabel und Funk erfolgt über kurze und lange Töne. Lassen wir erst mal die LED in dem Takt blinken, wie die Zeichen z.B.: per COM-Port an den Arduino gesendet werden. Etwas schwieriger ist die Gegenrichtung, die Signale auf einem Eingang auszuwerten, da hier eine veränderliche Geschwindigkeit und die Trennung von Zeichen erkannt werden muss. Aber technisch geht das minimalen externen Beschaltungen.
  • Logik Analysator
    Wenn man einen größeren Arduino nimmt, dann könne man damit z.B., einen CMOS/TTL-Chip-Tester bauen. Wobei heute immer weniger noch TTL-Gräber auf Basis eines 74xx bauen.
  • Wecker
    Warum nicht einfach den Arduino mit einer I2C-Echtzeituhr ausstatten und mit dem LCD die uhrzeit anzeigen. Ein paar Taster gibt es sicher noch um die Zeit zu stellen oder vielleicht sogar eine Alarmfunktion einzubauen. So einen Wecker hat wohl niemand sonst neben seinem Bett stehen.
  • Würfelsimulation
    Bei der ICE-Fahrt habe ich zwei Kinder beobachtet, die "Mensch ärgere dich nicht" gespielt haben. Klar dass der Würfel mehr auf dem Fußboden rumflog als auf dem Tisch landete. Natürlich gibt es auch fertige Bausätze für 4-10 Euro, aber es geht ja um den Bastelspaß.
  • Reaktionstester
    Der Arduino schaltet in Licht ein und zählt die Dauer die der Spieler braucht um eine Taste zu drücken. Die Dauer kann er auf einem LCD ausgeben oder eine LED-Zeile. Wer reagiert wohl am schnellsten.
  • Arduino als Kennwortsafe
    Es gibt Arduinos, die sehen schon aus wie ein USB-Stick und erscheinen nicht nur als COM-Port, sondern können sogar eine Tastatur/Maus emulieren. Da könnte man doch mit einer kleinen Software auf dem Host ein paar Steuerdaten an den COM-Port senden, so dass der Arduino dann das passende Kennwort als Tastatur "eintippt". Gerne noch mit einer PIN-Eingabe auf dem Arduino. Und schon wäre das Kennwort ein stück sicherer.
  • Netzwerk-Thermometer
    Kombiniert man einen Arduino Nano mit einem Ethernet-Shield, dann hat man für ca. 12€ schon einen "Netzwerk Arduino". Verpasst man dem dann noch z.B. einen LM75 Temperatursensor per I2C-Bus. Dann hat man ruck zuck ein Ethernet Thermometer. Alternativ kann man per 1-Wire Bus Sensoren wie den DS18B20 verwenden und das gleiche erreichen. Klar geht das auch mit einem RaspberryPi aber mit viel mehr Overhead. Allerdings muss man die Daten schon noch abfragen und weiter verarbeiten.

Je länger ich drüber nachdenke, desto mehr kleine Projekte fallen mir ein. Daher höre ich hier nun einfach mal auf.

Ardunio "Verwandte"

Der Erfolg der Arduino-Plattform und deren "Offenheit" fördert natürlich auch andere Projekte. Aus China bekommen Sie sehr billig jede Art von Arduino-Nachbau aber es gibt auch Leute, die spezielle Versionen daraus weiter entwickeln, z.B. solche mit Funktechniken oder sehr kleine Geräte

Es gibt sicher noch einige andere Geräte und ich kann unmöglich hier einen Marktüberblick oder eine Empfehlung geben. Nutzen Sie einfach eine Suchmaschine.

Mini Atmels ATTiny85

Es gibt natürlich mittlerweile auch viele andere Boards, die auf Basis einer ATMEL-CPu und einigen Tricks auch mit der Arduino-IDE programmiert werden können. Wer es noch kleiner mag, kann z.B. auf Basis des ATTiny85 Lösungen bauen, die mit wenigen Ein/Ausgänge zurecht kommen

Achten Sie aber darauf, dass Sie nicht Nachbauten aus China erwischen, die von vorneherein defekt oder nicht entsprechend vorprogrammiert sind. Die Foren sind z.B. voll von einer Rev 3, die nicht öffentlich ging oder Nachbauten, deren Schutzdiode nicht funktioniert.

Weitere Links

Arduino Tutorial - 15 Videos a a 10 -20min zu Arduino
https://www.youtube.com/playlist?list=PLE0C7D8863F6DACCE