© prettyboy80/Shutterstock.com
Ein einfaches Projekt: Der Arduino als Schachuhr

Arduino lernt Schach


Der Arduino eröffnet dem Softwareentwickler, der bisher nur mit weitgehend geschlossenen Systemen gearbeitet hat, einen einfachen Weg zur Erforschung der Interaktion mit der Außenwelt – über Sensoren, die Ereignisse wahrnehmen, Aktoren, die Veränderungen an verbundenen Komponenten vornehmen, und Programme, die das Zusammenspiel der Komponenten steuern. Hat man sich dann einen Arduino gekauft, stellt sich als Nächstes die Frage „Was fange ich damit jetzt an?“. Eine Antwort lautet: „Lernen und dabei Spaß haben!“. Und das geht am besten, wenn man ein eigenes Projekt umsetzt – in diesem Artikel eine Schachuhr – und sich von der Frage der Sinnhaftigkeit nicht unnötig einschüchtern lässt.

Zu den wichtigsten Hypethemen der jüngeren Zeit gehören neben Mobile-Computing und Cloud das Feld des IoT (Internet of Things), oder in seiner deutschen Adaption für die Wirtschaft „Industrie 4.0“. Was hat das aber nun mit dem Thema dieses Artikels zu tun? Letzteren ist gemeinsam, dass sehr kleine, relativ leistungsschwache, gleichzeitig aber auch verbrauchsarme und billige Computer eine tragende Rolle spielen. Architekturen, die von großen Zentralrechnern (Servern und Backbones) dominiert werden, verändern sich dahingehend, dass heterogene Netzwerke entstehen, in denen eine Vielzahl verschiedener Knoten Informationen erfassen, verarbeiten und weiterleiten.

Für viele Einsatzzwecke, insbesondere im Embedded-Bereich, ist ein Einsatz eines vollwertigen PCs oder adäquater Hardware schlicht nicht effizient. Die Überwachung von einfachen Klimadaten wie Wasserstand, Temperatur, Luftdruck etc. unterfordert solche Hardware – gleichzeitig entstehen beim Einsatz aber die üblichen Kosten für den Betrieb (hoher Anschaffungspreis für Hardware und ggf. Betriebssystem, teure Wartung z. B. durch Betriebssystemupdates, hoher Stromverbrauch). Hinzu kommen Faktoren wie Platzverbrauch und Störungsanfälligkeit (je komplexer ein System ist, desto fehleranfälliger wird es). Es ist daher in vielen Fällen angemessen, statt eines für den Einsatzzweck überdimensionierten Universalcomputers, einen viel einfacheren Computer zu verwenden, der in Anschaffung, Wartung und Stromverbrauch billiger, kleiner und weniger störungsanfällig ist als seine großen Brüder.

Diese Überlegung ist nicht neu. In Waschmaschinen und Küchenmaschinen werkeln schon seit Jahrzehnten Mikrocontroller, die für die zu erledigenden Aufgaben gerade die notwendige Leistung bieten. Zudem werden ebenfalls seit Jahrzehnten in entsprechenden Aufgabenbereichen Einplatinencomputer der verschiedensten Bauformen verwendet. Was sich hier im Wesentlichen geändert hat, ist, dass auch diese Kleinstcomputer deutlich leistungsfähiger sind als ihre Vorfahren, und dass Plattformen entstanden sind, die – nicht zuletzt aufgrund der gestiegenen Leistungsfähigkeit – die Verwendung stark vereinfachen.

Beispiele für solche Plattformen sind Raspberry Pi und Arduino. Sie verbindet, dass sie unter dem Gesichtspunkt entworfen wurden, einen einfachen Einstieg zu ermöglichen. Sie unterscheidet im Wesentlichen die Leistung und die Komplexität: Während der Raspberry Pi auch in seiner einfachsten Version ein zwar minimaler, aber technisch vollwertiger PC ist, ist der Arduino im Grunde genommen ein nackter Rechner, der nur einfache Programme ausführen kann. Im Unterschied zum Raspberry Pi kann der Arduino dabei auch mit analogen Signalen arbeiten und daher in Bereichen eingesetzt werden, in denen für den Raspberry Pi Hardwareerweiterungen nötig wären.

Was den Arduino in diesem Zusammenhang attraktiv macht, ist die beschriebene Einfachheit für den Einsteiger. Der Arduino besitzt eine USB-Schnittstelle, und es existiert eine IDE, mit der Programme erstellt und über die USB-Schnittstelle auf die Einheit übertragen werden können – es entfällt damit der Bedarf für einen Programmer, der zwar billig ist, dessen Beschaffung und Verwendung aber für den Einsteiger wieder eine Hürde darstellen könnte. Darüber hinaus existiert eine große Community von Anwendern und damit viel Know-how, auf das zurückgegriffen werden kann.

Arduino UNO

Die technische Spezifikation für den Arduino UNO findet sich unter [1]. Merkmale sind unter anderem:

  • Verwendung eines Controllers vom Typ ATmega328P
  • vierzehn verfügbare I/O-Anschlüsse
  • davon sechs für Pulse-width Modulation (PWM) verwendbar
  • sechs analoge Eingänge
  • 16 MHz Taktfrequenz
  • 32 kB Flash-Speicher
  • 2 kB SRAM (statischer Speicher)
  • 1 kB EPROM

Insbesondere hinsichtlich des verfügbaren Speichers wird der Arduino sogar von vielen Heimcomputern aus den 1980er-Jahren übertroffen. Das ist aber kein Designfehler, sondern Absicht – für die Einsatzbereiche des Arduinos sind die geringe Speichergröße und Taktfrequenz vorteilhaft, da sie einen sehr geringen Stromverbrauch bewirken.

Die Architektur des Arduino folgt der Harvard-Architektur [2] im Unterschied zu einer Von-Neumann-Architektur [3], wie sie etwa der Raspberry verwendet, d. h. der Arduino unterscheidet zwischen Speicher für Daten und Programme.

Zusammengefasst: Für einen ersten Einstieg in die Verwendung von Minimalcomputern ist die Arduino-Plattform eine gute Wahl, weshalb sie auch in diesem Artikel eingesetzt wird. Nicht verschwiegen werden soll, dass Implementierungen auf Basis der Arduino-Plattform in vieler Hinsicht suboptimal sein können, da das Konzept dieser Plattform einen Kompromiss zwischen Anwenderfreundlichkeit und Leistungsfähigkeit beinhaltet.

Eine Schachuhr implementieren

In Rahmen dieses Artikels soll eine Schachuhr [4] prototypisch implementiert werden. Da vielleicht nicht jeder weiß, was eine Schachuhr ist, wird sie hier kurz beschrieben. Bei zugbasierten Strategiespielen, wie Schach oder Go, ist es für den Spieler, der gerade setzen muss, von Vorteil, wenn er möglichst lange über einen Zug nachdenken kann. Wird die Bedenkzeit nicht begrenzt, können sich Partien endlos hinziehen. Um das zu verhindern, und damit Turniere fair gestalten zu können, wurde die Schachuhr erfunden. Das Prinzip ist einfach. Für beide Spieler wird eine Gesamtzeit festgelegt, die sie in der gesamten Partie verbrauchen können. Für beide Spieler gibt es Uhren, die auf diese Zeit eingestellt werden. Die Uhr eines Spielers wird dann aktiviert, wenn er am Zug ist, und zählt die Zeit herunter. Sobald Spieler A seinen Zug gemacht hat, drückt er einen Knopf, der zweierlei bewirkt: Einerseits wird seine Uhr angehalten, andererseits wird die Uhr des anderen Spielers (B) aktiviert, und zählt ihrerseits dessen Zeit herunter, und zwar so lange, bis dieser Spieler B seinen Zug gemacht hat und seinen Knopf drückt. Damit ist der Spieler A wieder am Zug, und entsprechend wird die Uhr von Spieler B gestoppt und die Uhr von Spieler A wieder aktiviert. Ist die Uhr eines Spielers abgelaufen, hat er seine Bedenkzeit verbraucht und das Spiel verloren. Die Uhr gibt daher beim Ablaufen ein (meist akustisches) Signal, und die Partie ist beendet. Die verbleibende Bedenkzeit wird dabei von beiden Uhren für jeden Spieler immer angezeigt.

Schachuhren gibt es in verschiedenen Ausführungen. Es gibt rein mechanische Varianten, in denen zwei mechanische Uhren verwendet werden, sowie digitale Varianten, die erweiterte Möglichkeiten bieten. Übrigens: Da Schachuhren in Turnieren eine wichtige (oft spielentscheidende) Rolle spielen, müssen die entsprechenden Modelle vom Veranstalter des Turniers zugelassen werden, um Manipulationen oder Fehler auszuschließen. Insofern ist unsere Schachuhr zwar eine nette Etüde, wird es aber wohl kaum in ein reguläres Turnier schaffen.

Fassen wir nach diesem Exkurs kurz die Anforderungen an unsere Schachuhr zusammen:

  • Es muss die Möglichkeit geben, die Bedenkzeit pro Partie einzustellen
  • Die Spieler brauchen die Möglichkeit, zu signalisieren, dass sie ihren Zug beendet haben
  • Die verbleibende Zeit für beide Spieler muss angezeigt werden
  • Das Auslaufen der Bedenkzeit eines Spielers muss signalisiert werden

Zustände und Übergänge

Um etwas formaler zu verdeutlichen, wie unsere Schachuhr funktioniert, welche Eingabemöglichkeiten wir benötigen, und letztendlich auch als Blaupause für die Programmierung, verwenden wir ein Zustandsdiagramm, das in Abbildung 1 wiedergegeben ist. Wir verwenden dabei folgende Notation:

  • Abgerundete Kästen repräsentieren Zustände. Optional in den Kästen aufgeführte Bezeichner geben die für den Zustand relevanten Variablen wieder.
  • Pfeile repräsentieren Übergänge von einem Zustand in den nächsten.
  • Für die Beschriftung der Übergänge verwenden wir eine so genannte Trigger-Action-Schreibweise. Die Syntax ist dabei [Trigger]/[Action]. Beispielsweise bedeutet Button1 pressed, dass der Zustandsübergang ausgelöst wird, wenn das Ereignis Button1 pressed eintritt; Button1 pressed/min +=1, dass bei Eintritt von Button1 pressed der Wert min um 1 erhöht wird, und /min = 10; sec = 10, dass der Zustandsübergang unabhängig von einer Bedingung immer ausgeführt wird, und dabei min und sec auf 10 gesetzt werden.
image

Abb. 1: Zustandsdiagramm

Der Start unseres Automaten beginnt mit dem Übergang vom Startpunkt (der schwarze gefüllte Kreis) in den Zustand Ready. Zusätzlich zu den Zuständen werden hier noch weitere Variablen vorgehalten: min gibt die Gesamtzeit in Minuten, sec in Sekunden an. Diese beiden Werte wurden beim Übergang in diesen Zustand jeweils mit 0 belegt. Die übrigen Variablen sind zunächst undefiniert.

Der Pfeil nach links is...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang