Bastelprojekt Lasershow mit Arduino: Vektorgrafiken an die Wand projizieren

Retro-Games und -Grafik sind wieder in Mode. Im Bastelprojekt lassen wir einen Laserstrahl Retro-Vektorgrafiken im ganz großem Stil an die Wand zeichnen.

In Pocket speichern vorlesen Druckansicht 5 Kommentare lesen
Make-Schriftzug, Asteroids-Spiel und Pong-Spiel als bunte Laserlinien auf einem schwarzen Hintergrund.
Lesezeit: 18 Min.
Von
  • Ulrich Schmerold
Inhaltsverzeichnis

Beim Bau der Laserharfe habe ich mich intensiv mit Galvo-Scannern beschäftigt: Das sind elektromagnetisch angetriebene Drehachsen, an deren Ende ein Spiegel zur Umlenkung von Laserstrahlen befestigt ist. Für mein elektronisches Musikinstrument brauchte ich allerdings nur einen der zwei Galvo-Scanner, die im Set enthalten waren, das ich seinerzeit gekauft hatte. Da keimte bald in mir der Wunsch, auch den zweiten Scanner in Betrieb zu nehmen und den Laserstrahl in zwei Dimensionen lenken zu können, um damit Grafiken zu zeichnen.

Der Aufbau war schnell bewerkstelligt und schon nach einer knappen Stunde konnte ich die ersten Formen an die Wand werfen. Als ich jedoch versuchte, mit dem Laser schräge Linien zu zeichnen, stieß ich bereits an Grenzen, die ich erst nach und nach überwinden konnte – im Zuge monatelanger Recherchen, Forschungen, Dutzender Lochrasterplatinen und Arduino-Sketche. Immer wieder wurde ich im Internet von Laser-Enthusiasten verunsichert, die es schlichtweg für unmöglich hielten, mit einfachen Galvo-Scannern und einem Arduino Spiele-Klassiker wie Asteroids oder Pong an die Wand zu zaubern.

Doch allen Zweifeln zum Trotz kann sich das Endprodukt durchaus sehen lassen – und hier stelle ich es zum Nachbau vor: Licht aus für LaserGambling, den Lasershow-Apparat im Eigenbau, der nicht nur Spiele wie Pong oder Asteroids wandfüllend projiziert, sondern auch selbst programmierte Animationen und Vektorgrafiken, die man mit einem kleinen Windows-Programm schnell zusammenklickt.

Kurzinfo
  • Laser-Projektor aus Galvo-Scanner
  • Digital-Analog-Wandlung mit R2R-Netz
  • Effizient Vektorgrafiken anzeigen

Checkliste

  • Zeitaufwand: ein Wochenende
  • Kosten: 170 bis 200 Euro
  • Löten: einfache Lötarbeiten
  • Elektronik: Grundkenntnisse
  • Programmieren: Arduino-Grundkenntnisse
  • Holzbearbeitung: Holz- und/oder Metallbearbeitung für das Chassis und ggf. Gehäuse, je nach eigenen Materialvorlieben
  • Unfallgefahr: verantwortungsvoller Umgang mit Lasern

Material

  • Die komplette Materialliste inklusive Bezugsquellen finden Sie im Download-Paket.

Grundlage für dieses Projekt sind die Galvo-Scanner, die ich auch schon bei der Laserharfe verwendet habe. Sie sind inklusive der benötigten Ansteuerelektronik, Kabeln und Netzteil bei eBay für etwa 120 Euro zu haben. Die Bezugsquellen für alle verwendeten Teile finden Sie im Download-Paket zum Artikel. Im Artikel zur Laserharfe, in dem näher erklärt wird, wie die Galvos arbeiten. Bei der Beschreibung ist mir damals jedoch eine kleine Ungenauigkeit unterlaufen. Die Ansteuerelektronik der Galvos erwartet als Signal nicht, wie damals angegeben, eine Spannung von 0–5 V, sondern eine symmetrische Spannung von ±5 V. Die volle Auslenkung des Spiegels wird also erreicht, wenn entweder an beiden Signalleitungen +5 V gegen GND (Masse) oder –5 V gegen GND anliegt. Die gleiche Auslenkung erreicht man jedoch auch, wenn an die Signalleitungen ±10 V angelegt werden. Diese Spannung von ±10 V leitet sich aus dem ILDA-Standard ab.

Das Galvo-Scanner-Set, das für diesen Artikel verwendet wurde, wird komplett mit Steuerplatinen geliefert und kostet etwa 120 Euro.

Das verwendete Galvo-Scanner-Paar schafft eine Geschwindigkeit von 20 Kpps (Kilo points per second).

Eigentlich ist die ILDA (International Laser Display Association) ein weltweit tätiger Verband, um Laser in den Bereichen Bildung, Unterhaltung und Kunst zu etablieren. Unter dem Begriff ILDA werden aber auch Standards zur Speicherung von Lasersteuerdaten, Testbilder für den Vergleich von Scannergeschwindigkeiten und Schnittstellendefinitionen zur einheitlichen Ansteuerung von Galvo-Scannern und Lasern zusammengefasst.

Schema des ILDA-Testbilds

Die Geschwindigkeit von Galvo-Scannern wird in Kpps (Kilo points per second) angegeben. Entscheidend ist, dass die Scanner bei einer konkreten Geschwindigkeit das Standard-ILDA-Testbild bei 8 Grad optischer Auslenkung noch fehlerfrei darstellen. Je höher der Kpps-Wert, desto hochwertiger ist der Galvo-Scanner.

Die ILDA- Schnittstelle wird meistens an einem DB25-Connector ausgegeben. Die Signale für Galvo-Scanner sind nach dem ILDA-Standard mit ±10 V angegeben. Die Signale für die einzelnen Farb-Laser sind mit einem Differential von 5 V festgelegt (etwa –2,5 V bis +2,5 V oder 0 V bis 5 V).

Alle technischen Standards sind im Internet dokumentiert.

Als Mikrocontroller verwendete ich anfangs den Arduino Nano. Aufgrund der geringen Anzahl an Portleitungen und des mit 2 KB zu kleinen Variablenspeichers führten die Experimente damit jedoch schnell ins Aus. Somit besorgte ich mir einen Arduino Mega, der mit 8 KB Variabelspeicher, 54 I/O-Pins und 16 Input-Pins mehr als üppig ausgestattet ist.

Die zahlreichen Portleitungen benötige ich zur Erzeugung der beiden Analog-Signale zur Ansteuerung der Galvos. Die Entscheidung zur Signalerzeugung mit einem R2R-Netzwerk, einer Kaskade aus Widerständen, fiel auch erst nach und nach im Verlauf dieses Projektes. Da ich als Mikrocontroller bei einem Arduino bleiben wollte, musste ich alles versuchen, um möglichst viel Rechenleistung einzusparen. Hierbei zeigte das R2R seine unschlagbare Stärke: Erstens gibt es keine schnellere Methode zur Konvertierung von digitalen zu analogen Signalen (DAC), und zweitens genügt zur Ansteuerung des Netzwerks ein einzelner Befehl. Den Details des R2R-Netzwerks und anderen DAC-Methoden widmet sich der Artikel " Gängige Verfahren zur Digital-Analog-Wandlung ".

Das R2R-Netzwerk habe ich auf eine eigene Lochrasterplatine gelötet und mit Stecker-Buchse-Jumperkabeln mit den Ports PA (Pin 71–78) und PC (Pin 53–60) des Arduino Mega verbunden. Da die Pins am Port PA nach links aufsteigen und am Port PC nach rechts, habe ich auch das R2R-Netzwerk einmal von rechts nach links und das andere von links nach rechts verlegt. Außen auf der Platine liegt jeweils GND, innen befinden sich die Signal-Ausgänge des Netzwerks.

Das R2R-Netzwerk wurde auf eine eigene Lochrasterplatine gelötet.

Prinzipiell kann der Ausgang des R2R-Netzwerks direkt mit der Ansteuer-Elektronik der Galvos verbunden werden. Man ist damit zwar nicht ILDA-konform, kann aber auch so die volle Galvo-Scanner-Auslenkung erreichen. Dazu müssen lediglich die beiden mit "Inputscale" bezeichneten Trimmpotis auf den Ansteuerplatinen der Galvos nachgeregelt werden. Aber Vorsicht: Werden die Galvos später einmal mit einer ILDA-konformen Steuerung verbunden, so müssen unbedingt vorher die Trimm-Potentiometer wieder zurückgedreht werden. Anderenfalls werden die Galvos zerstört.

Wer lieber gleich (nahezu) ILDA-konform bleiben möchte, kann mit der hier gezeigten Schaltung aus einer 5-V-Spannung eine Spannung im Bereich ±10 V erzeugen. Dafür ist eine synchrone Spannung von ±12 V nötig, wofür sich das Modul SIM2-0512D eignet. An den Trimmpotis meiner Schaltung lassen sich die maximale Auslenkung der Galvos (Gain) und die Lage des Bildes (Offset) einstellen.

Um Retro-Games wie Asteroids spielen zu können, braucht es den passenden Controller. Dafür eignet sich hervorragend der Wii Nunchuk von Nintendo, der einfach an die I2C-Schnittstelle angeschlossen wird. Die für die Kommunikation benötigte Library für die Arduino IDE gibt es im Netz.

Ein Joystick, zwei Tasten (Z und C genannt), Bewegungssensoren: Wii Nunchuk

Der Nunchuk-Controller für die Spielkonsole Wii von Nintendo lässt sich sehr leicht in eigene Projekte integrieren. Erfreulicherweise kommuniziert er über das I2C-Protokoll. Dabei gilt es zu beachten, dass der Nunchuk als Versorgungsspannung (VCC) 3,3 V verwendet.

Die für die Kommunikation benötigte Library muss man zuvor aus dem Netz laden und in die Arduino-IDE über das Menü Add Library integrieren. Im Code des Arduino-Sketchs muss zusätzlich zur wiinunchuck.h auch Wire.h eingebunden werden.

nunchuk_init();
delay(100);
nunchuk_calibrate_joy();
delay(100);

Die Daten werden dann im Programmablauf mit nunchuk_get_data(); angefordert. Dann kann man sie im eigenen Programm verwenden:

int Y = nunchuk_cjoy_y();
int X = nunchuk_cjoy_x();
boolean ButtonC = nunchuk_cbutton();
boolean ButtonZ = nunchuk_zbutton();

Da ich kein passendes Gegenstück zum Nunchuk-Stecker hatte, klemmte ich den Originalstecker ab, lötete die Anschlüsse auf eine 2×3-Stiftleiste und formte mit Heißkleber eine Zugentlastung. Achtung: Die Aderfarbe rot steht hier nicht für +3,3 V und schwarz auch nicht für Masse!

Nunchuk-Stecker: GND = Masse, VCC = Versorgungsspannung (3,3 V), SDA an Pin 20 des Arduino Mega anschließen, SCL an Pin 21

Für Pong hingegen braucht man zwei spezielle Paddles mit einem Drehknopf. Die habe ich aus je einem Handgehäuse von Conrad für 3,50 Euro selber gefertigt. Sie enthalten jeweils lediglich ein 1-KΩ-Potenziometer. Für den Anschluss musste ein Audiokabel herhalten.

Das fertige Eigenbau-Shield mit den beiden Paddles und dem Wii-Nunchuk-Controller.

Zum leichteren Anschließen und Entfernen der Bedienelemente lötete ich die Anschlussbuchsen auf einen Arduino Mega Shield. Hinzu kam noch ein Taster für den Spiel-Neustart. Den Reset-Taster habe ich ebenfalls auf den Shield montiert, da jener des Mega-Boards durch den Shield verdeckt wurde. Später kam noch ein Kodierschalter zur Programmauswahl hinzu. Damit lässt sich bequem zwischen den Spielen, den Animationen und den Testbildern umschalten, ohne jedes Mal einen neuen Sketch in den Arduino übertragen zu müssen.

Da ich die Jumperkabel für das R2R-Netzwerk direkt auf den Arduino Mega aufsteckte, habe ich an der Shield-Platine die entsprechenden Lötpunkte abgesägt. So musste ich nicht immer alle Jumperkabel abziehen, um am Shield etwas einlöten zu können.

Der Aufbau in der Gesamtansicht

Die komplette Schaltung mit R2R-Netzwerk und SIM2-0512D für ILDA-Konformität. Der Laseranschluss wurde hier der Übersichtlichkeit halber weggelassen.

Als Laser gönnte ich mit für dieses Projekt einen RGB-Laser, den ich mir ebenfalls für rund 160 Euro aus China schicken ließ. Natürlich funktioniert das Projekt auch mit einem günstigeren und einfarbigen Laser, die farbige Variante ist allerdings ansprechender und auch vielseitiger, denn damit kann man bei Spielen etwa unterschiedliche Objekte in verschiedenen Farben zeichnen.

Wer den beschriebenen Aufbau mit einem monochromen Laser betreibt, muss in der Datei Laser.ino in der Zeile #define Farblaser den Eintrag true in false ändern.

Beim RGB-Laser sind die halbdurchlässigen Dircho-Spiegel deutlich zu erkennen: Sie reflektieren jeweils nur Licht einer spezifische Wellenlänge. Die anderen Farben dringen fast ungehindert hindurch.
Achtung, Laser!
Warnsymbol: Laserstrahl (schwarz in gelbem Dreieck).

Schauen Sie nie direkt den Laserstrahl! Schützen Sie Ihre Augen außerdem mit einer geeigneten Schutzbrille, wenn Sie mit dem Laser arbeiten. Achten Sie auch auf dessen Energie – manche RGB-Laser im Handel kommen auf 1000 mW und mehr. Gefährlich sind dabei vor allem stehende Laserstrahlen, wenn sich also die Galvos nicht bewegen und der Laser zwischendrin nicht ausgeschaltet wird (Blanking) – ein Laser mit genügend Leistung ist bei unbewegtem Strahl durchaus in der Lage, Brandlöcher in Möbeln zu hinterlassen.

Ist die Anlage komplett aufgebaut, müssen zuerst die Galvoscanner und – sofern RGB-Laser verwendet werden – die Laser eingestellt werden. Dazu leistet das ILDA-Testbild sehr gute Dienste. Eine einfache Variante dieses Bildes habe ich in den Arduino-Sketch integriert. Die Anweisung ShowIldaTestbild(); zeigt es an.

Hilfreich beim Kalibrieren können auch die weiteren Testbilder sein. Sie wurden in die Datei Debugging.ino integriert. Jedoch ist es praktisch unmöglich, eine Einstellung zu finden, bei der alle Testbilder perfekt angezeigt werden, man muss sich eher an einen zufriedenstellenden Kompromiss herantasten.

Zusätzliche Grafik in der Datei Debugging.ino: Testbild_1()

Zusätzliche Grafik in der Datei Debugging.ino: Testbild_2()

Bei Anzeige des ILDA-Testbilds können sich unterschiedliche Phänomene zeigen, je nach Einstellung der Galvo-Steuerungen. Auf den Bildern sehen sie einige der gängigsten Abweichungen, die Aufschluss darüber geben, an welchem Regler geschraubt werden muss.

An den Trimmpotenziometern der Ansteuerplatine wird justiert, bis das ILDA-Testbild korrekt erscheint.

Mit Hilfe der beiden Innensechskantschrauben und der Madenschraube kann der Spiegel ausgerichtet werden.

Die Hardware steht, die Lasershow läuft – im Prinzip. Fehlen nur noch die passenden Retro-Spiele, also ran ans Coden!

Beim Programmieren von Asteroids stieß ich allerdings auf ein zentrales Problem: Je umfangreicher die Berechnungen wurden, desto mehr ruckelte das Bild. Somit musste ich das Berechnen der einzelnen Frames unabhängig von der Galvo-Steuerung bewerkstelligen. An einem PC wäre dies in Zeiten von Multitasking sicher kein Problem gewesen. Aber bei einem Arduino?

Anfangs versuchte ich, mit zwei Frame-Arrays zu arbeiten. In das eine werden die berechneten Daten geschrieben, während das zweite zur selben Zeit die Galvos mit Daten versorgt. Anschließend werden die zwei Arrays getauscht. Leider kam ich dabei schnell an die Grenzen des Variablenspeichers des Arduino Mega. 8 KB sind halt auch nicht die Welt.

Gelöst habe ich das Problem schließlich mit einer Art Stream: Die Berechnungsroutinen zu Positionen von Objekten und Ähnlichem legen ihre Ergebnisse in einem Array ab. Genaugenommen handelt es sich dabei um drei Arrays, die parallel befüllt werden, eines für die X-Koordinaten, eines für die Y-Koordinaten und das dritte für die Laserfarbe. Daraus werden Timer-Interrupt-gesteuert die Galvos und die Laser mit Daten versorgt. Das Befüllen (PointerSet) mit Daten kann dabei sowohl vor dem Anzeigezeiger (PointerShow) als auch hinter dem Anzeigezeiger erfolgen. Man muss beim Programmieren lediglich darauf achten, dass die Berechnung eines Frames weniger Zeit in Anspruch nimmt als seine Anzeige. Anderenfalls beginnt das Bild wieder zu ruckeln, denn der Anzeigezeiger kann den Berechnungszeiger nicht überholen. Der möglichen Komplexität von Spielen und anderen Arduino-Anwendungen sind also Grenzen gesetzt.

An der ersten Stelle des Streams steht immer die Bildmitte als Koordinate. Das Ende des Streams signalisiert ein Color-Wert von 128 (binär 10000000). Die maximale Länge des Streams und damit auch die maximale Anzahl an Punkten ist MAXPOS.

Nachdem diese technischen Voraussetzungen geschaffen wurden, geht es nun ans Zeichnen. Auch hier gilt es jede Menge zu beachten. Leider genügt es nicht, die Galvo-Spiegel auf die Startposition zu bewegen, den Laser einzuschalten und dann die Spiegel auf die Endposition zu dirigieren. Anders als ein Elektronenstrahl in einer Fernsehröhre oder einem Oszilloskop kommt bei Galvo-Spiegeln die Trägheit ins Spiel, denn auch die besten und schnellsten Galvos besitzen eine Masse, die beschleunigt und am Ende wieder abgebremst werden muss. Dafür ist Zeit nötig, die bei der Programmierung berücksichtigt werden muss, um ein sauberes Bild zu erhalten.

Um eine gleichmäßige Linie zeichnen zu können, muss man diese in einzelne Teile zerlegen. Befindet sich der Laser auf der Startposition, wird er eingeschaltet. Dann bewegt man die Spiegel in festgelegten Zeitintervallen immer um einen kleinen Teilbereich weiter (Parameter maxDistDrawn). Ist die rechnerische Zielposition erreicht, wird der Laser jedoch nicht sofort ausgeschaltet, sondern noch für eine festgelegte Zeit (post Draw) gewartet, bis die Spiegel tatsächlich am Ziel angelangt sind und abgebremst haben.

Anschließend bewegen wir die Spiegel bei ausgeschaltetem Laser wieder zur Startposition zurück. Diesen Vorgang nennt man Blanking. Hierbei spielt es keine Rolle, welchen Weg der Laser dabei nimmt, er sollte nur möglichst kurz sein, um nicht unnötig Zeit für das Blanking zu verschwenden. Jedoch muss auch beim Blanking dem Laser genügend Zeit fürs Schalten eingeräumt (preBlanking) und am Ende gewartet werden, damit die Zielposition sicher erreicht werden kann (postBlanking).

Die Grafik zeigt den Ablauf beim Zeichnen einer Linie mit dem Laser, der anschließend ausgeschaltet und an den Ursprungsort zurückfährt. Zur Vereinfachung wird nur die Bewegung in einer Dimension gezeigt. Die Parameter maxDistDrawn, postDraw, preBlanking und postBlanking sind am Beginn der Datei Draw.ino definiert.

Es kann übrigens sehr interessant sein, sich einmal die Wege des Lasers beim Blanking anzeigen zu lassen. Dazu müssen Sie in der Datei Draw.ino in der Routine blanking(byte x, byte y) lediglich in der Zeile DrawFastLine(x, y, 0); die 0 durch eine 1 ersetzen. Zum einen lässt sich dann erkennen, welche interessanten Bahnen der Laser beim Blanking beschreibt. Zum anderen bietet es auch die Chance, den Programmablauf zu optimieren und unnötige Blanking-Strecken einzusparen.

Pong mit sichtbarem Blanking

Asteroids mit sichtbarem Blanking

Die Datei Draw.ino enthält Methoden zum Zeichnen von Linien und Kreisen etwa mit Hilfe des Bresenham-Algorithmus. Unter Umständen ergeben sich damit genauere Resultate, wobei allerdings dann auch die Zeichengeschwindigkeit darunter leiden könnte.

Bei Computergrafiken taucht beim Zeichnen von schrägen Linien das Problem der Rasterung auf. Dabei muss die Linie auf Punkte aufgeteilt werden, die der idealen Linie am nächsten kommen. Wer jetzt denkt: „Es geht hier doch um Vektorgrafik, warum muss da eine Linie gerastert werden?“, der hat theoretisch recht – doch in der Praxis macht hier wie beim Linienzeichnen die Massenträgheit der Galvos der schönen mathematischen Theorie einen Strich durch die Rechnung. Denn soll eine Linie gezeichnet werden, bei der beide Galvos unterschiedlich weit geschwenkt werden müssen – etwa eine flach ansteigende Schräge – dann braucht der eine länger bis zur Endposition und der andere kürzer. Das Ergebnis wäre keine Linie, sondern würde einen deutlichen Knick zeigen. Aus diesem Grund müssen für unsere Lasershow schräge Linien gerastert, sprich: in kurze Stücke aufgeteilt werden. Auf dem Oszilloskop hingegen ist das kein Thema.

Die einfachste Möglichkeit der Rasterung ist die direkte Umsetzung der Geradengleichung, die die Linie definiert:

wobei der Index a die x- und y-Koordinaten des Anfangspunkts der Linie markiert und e jene des Endpunktes. Diese Formel ist jedoch bei Berechnungen sehr langsam, da sie mit Divisionen und damit Gleitkommazahlen arbeitet.

1963 veröffentlichte der amerikanische Informatiker Jack Bresenham einen Algorithmus, der nur ganzzahlige Berechnungen enthält. Durch eine geringfügige Erweiterung lässt sich der ursprüngliche Algorithmus, der für gerade Linien entworfen wurde, auch für die Rasterung von Kreisen verwenden. Beide Varianten des Bresenham-Algorithmus haben wir in den Zeichenroutinen dieses Projekts verwendet.

Der Algorithmus schreitet beim Rastern von Linien immer in der „schnellen“ Richtung einen Schritt (ein Pixel) voran und fügt je nach Steigung hin und wieder zusätzlich einen Schritt in die „langsamere“ Richtung ein.

Der prinzipielle Programmablauf sieht nun folgendermaßen aus:

Voraussetzung für das Ausführen meines „LaserGambling-Frameworks“ sind die Libraries TimerOne.h, Time.h und WiiNunchuck. Diese müssen vorher heruntergeladen und in die Arduino IDE eingebunden werden.

Im setup()-Teil des Arduino-Codes wird mit init_DAC(25) das R2R-Netzwerk vorbereitet und das Timer-Intervall eingestellt. Je kleiner der Wert in der Klammer, desto höher ist die Scanner-Geschwindigkeit. Meine Galvos waren mit einer Geschwindigkeit von 20 Kpps angegeben. Dafür erwies sich ein Timer-Intervall von 22 bis 25 Mikrosekunden als recht gut passend.

Auf beginFrame() folgen Zeichenanweisungen, wie sie in der Tabelle aufgelistet sind. Den Abschluss eines Frames löst der Aufruf von endFrame() aus.

Zeichenbefehle
Befehl Beschreibung
blanking(x, y) Laser positionieren
DrawLine(x, y, color) Linie von der momentanen Position zu den angegebenen Koordinaten zeichnen
DrawCircle(xm, ym, radius, color) Kreis zeichnen aus Mittelpunkt und Radius
DrawSquare(left, top, right, botton, color) Rechteck zeichnen
draw_letter(letter, x, y, color) einzelnen Buchstaben letter schreiben
draw_string(text, x, y, color) Zeichenkette text schreiben
marquee(text, x, y, x_length, color) Lauftext text schreiben; dabei werden x_length Zeichen gleichzeitig angezeigt
drawInt(z, x, y, color) Integer-Zahl z schreiben

Schon während der Stream mit Daten gefüllt wird, bekommen die Galvo-Scanner Timer-gesteuert Anzeigedaten geliefert. Wurde ein Frame komplett angezeigt, wird der nächste abgespielt, sofern der in der Zwischenzeit berechnet wurde. Soll – für ein stehendes Bild – immer wieder der gleiche Frame wiedergegeben werden, so setzt man einfach PointerSet= -1. Damit wird dem Anzeigezeiger vorgegaukelt, dass sich der Befüllzeiger hinter ihm befindet und damit Daten zum Anzeigen vorliegen.

Die Struktur des Streams mit den zwei Zeigern erlaubt einen Trick, um die Berechnung einzelner Frames deutlich zu verkürzen, wenn sich nur Teile des Bildes ändern sollen. Denn der Stream muss nicht jedes Mal komplett neu gefüllt werden.

Als Beispiel habe ich eine analoge Uhr in den Sketch eingebaut. Dabei wird das Zifferblatt nur einmal berechnet und in den Stream gefüllt. Die Zeigerposition vom Ende des Ziffernblattes speichere ich und positioniere den Befüllzeiger (PointerSet) zum Berechnen der Zeiger jedes Mal an diese Position. Dadurch wird viel Rechenzeit eingespart und das Bild flüssiger dargestellt. Soll die Uhr wirklich die korrekte Uhrzeit anzeigen, braucht der Arduino natürlich noch eine DCF- oder RTC-Uhr.

Eine funktionierende analoge Uhr als Hingucker

Um die Grafiken für die Lasershow nicht mühsam aus Linien, Rechtecken und Kreisen zusammenprogrammieren zu müssen, habe ich noch ein kleines Windows-Vektorzeichenprogramm namens VectorEdit geschrieben, das als Ergebnis fertigen Arduino-Code bereitstellt. Dort hinein kann man BMP- und JPG-Grafiken als Hintergrundbild laden, die man dann einfach durch Linien nachzeichnet. Das Programm speichert die Vektordaten als TXT-Dateien oder gibt sie als PROGMEM-Arrays aus. Diese nutzen den üppigen Programmspeicher des Arduino Mega und belegen damit keinen Platz im Speicher für die Variablen, den ich ja für den Stream reserviert habe.

Das selbstgeschriebene Zeichenprogramm VectorEdit wandelt den Make-Schriftzug in Laservektoren um.

Die Enterprise – nach einer Vorlage aus VectorEdit mit dem Laser gezeichnet

Alle in diesem Artikel dargestellten und weitere Laserbilder sind im Arduino-Sketch im Download-Paket zu diesem Artikel integriert. Wie immer freuen wir uns aber auf Ihre eigenen Lasergrafiken und Spiele – wenn Sie also Ihre eigene Lasershow zum Laufen gebracht haben und selbst kreativ geworden sind, freuen wir uns über Bild- und Codezuschriften an mail@make-magazin.de oder einen Kommentar im Artikelforum. (pek)