Make Magazin 5/2017
S. 16
Retro-Display
Aufmacherbild

Vektorgrafik auf dem Oszilloskop

Auf einem analogen Vektor-Display erscheint die Retro-Liniengrafik stilecht in grün auf schwarz. Ein solcher Bildschirm schlummert schon in Ihrer Werkstatt – wenn Sie ein analoges X-Y-Oszilloskop besitzen.

Oszilloskope sind wichtige Messgeräte in der Elektronik, die Spannungsänderungen über der Zeit anzeigen. Bei einem modernen digitalen Oszilloskop erscheinen die Messwerte auf einem LCD, also mit fester Pixel-Auflösung, wie auf einem Computermonitor. Auf älteren Oszilloskopen zeichnet dagegen ein analog angesteuerter Elektronenstrahl die Spannungsverläufe auf einen nachleuchtenden Phosphorschirm. Beim Messen fährt üblicherweise der Strahl die X-Achse entlang, in einer per Elektronik einstellbaren Zeit, und die zu messende Spannung ergibt dann einen Ausschlag entlang der Y-Achse. Bei Oszilloskopen mit zwei Messkanälen kann man aber auch einen X-Y-Modus benutzen, bei dem ein Messkanal die Y-Achse steuert und der andere die X-Achse. Legt man nun variable Spannungen an die beiden Messkanäle, so kann man den Elektronenstrahl zu jedem Punkt auf dem Bildschirm steuern. Gerade zu Beginn der Computertechnik wurde das Prinzip für Displays benutzt, da der für Pixel-Bildschirme erforderliche Videospeicher (RAM) zu dieser Zeit knapp und teuer war.

Wer schon einmal ein Vectrex-Spielsystem gesehen oder gar in den Genuss der YouScope-Demo auf einem Oszilloskop kam (siehe auch unser Video), ist schnell vom Retro-Charme eines Vektor-Displays eingenommen. Einen kompletten Vintage-Analogrechner mit Vektorausgabe ersetzt dies zwar nicht, bedingt durch die Wandlung von digital zu analog im Computer – aber die Wirkung kommt dem schon nahe und die Speicher- und Geschwindigkeitslimits der alten Maschinen spielen erfreulicherweise auch keine Rolle mehr.

Einstiegsdroge

Wenn Sie ein passendes analoges Oszilloskop mit X-Y-Modus besitzen, können Sie schnell einmal testen, wie die Grafik auf Ihrem Vektor-Display wirkt. Laden Sie dazu einfach die Audiodatei von YouScope herunter (alle Downloads erreichen Sie über den Link in der Kurzinfo) und spielen Sie sie auf einem Computer oder Smartphone ab (letzteres funktioniert meiner Erfahrung nach oft besser). Der Open-Source-Player VLC kommt garantiert mit dessen Flac-Audioformat klar.

Für einen ersten Test kann man den Kopfhörerausgang eines Smartphones simpel mit den Messeingängen und GND des Oszilloskops verbinden.
Auswahl des Boards in der Arduino-Entwicklungsumgebung (IDE)

Wie verdrahtet wird, zeigt die Abbildung; etwas isolierter Draht reicht bei Frequenzen im Audio-Bereich. Verwendet man normale Tastköpfe, die mit kleinen Hakenklammern oder nur Spitzen versehen sind, so passen diese oft nicht recht an einen 3,5-mm-Klinkenstecker. In diesem Fall basteln Sie etwas selbst, etwa aus Krokoklemmen, einer 3,5-mm-Klinkenbuchse oder Sie schrauben den Stecker auf, um an die kleineren Kontakte zu gelangen. Angst vor Kurzschlüssen oder falschen Verbindungen müssen Sie nicht haben, im schlimmsten Fall sehen Sie nur kein Bild auf dem Oszilloskop. Auch die Soundkarte oder Ihr Smartphone sind nicht gefährdet.

Der Lohn der Mühen: Animierte Vektorgrafik auf dem Oszilloskop

Starten Sie nun das Abspielen der YouScope-Audiodatei und vergessen Sie nicht, die Lautstärke aufzudrehen. Das Oszilloskop sollte bereits angeschaltet sein, denn die Bildröhre benötigt etwas Zeit, um warm zu werden. Die meisten Knöpfe stehen in ihrer Normalstellung, nur der X-Y-Knopf muss gedrückt und die DC-(Gleichstrom-)Koppelung auf den Eingängen aktiv sein.

Am Anfang der YouScope-Datei sieht man eine etwas unscharfe Linie, gefolgt von einer Sinuskurve. Sobald Sie etwas Bewegung sehen, können Sie mit den Volts/DIV-Knöpfen für beide Kanäle die Breite und Höhe einstellen. Mittels der Y-POS-I- und X-POS-Regler lässt sich die Bildlage korrigieren. Durch die eingebauten Filter in den Ausgabeschaltungen von Smartphones oder PC-Soundkarten erhält man allerdings kein absolut scharfes Bild. Man könnte eine PC-Soundkarte für ein klareres Bild modifizieren, allerdings ist man so immer noch auf die Frequenzen beschränkt, die eine Soundkarte generieren kann, und die klingt außerdem nach der Modifikation nicht mehr so gut. Wer jetzt mehr Vektorgrafik auf sein Gerät bringen will, dem empfehle ich die Lösung, die darzustellenden Grafiken digital vom Computer liefern zu lassen und dann per Digital- zu Analog-Wandler (DAC, Digital Analog Converter) an das Oszilloskop auszugeben. Mehr zu DAC allgemein lesen Sie auf Seite 40.

Teensy statt Arduino

Es hat sich als sehr flexibel erwiesen, einen Microcontroller für die Ansteuerung des DAC zu verwenden. Leider ist ein einfacher Arduino nicht schnell genug, um komplexe Grafiken zu erzeugen. Neuere Arduinos laufen zwar flotter, sind aber oft 3,3-V-Boards, was die periphere Beschaltung verkompliziert. Meine Wahl fiel daher auf ein Teensy 3.2 Board, das einen 32-Bit-ARM-Prozessor mit 96 MHz bietet, nicht zu teuer ist und wie ein Arduino programmiert werden kann.

Die DACs werden per SPI (Serial Peripheral Interface) angebunden und die Grafikbefehle dann per USB an das Board geschickt. Dabei emulieren die Teensy Boards eine serielle Schnittstelle, damit sie kompatibel zum Arduino sind. Tatsächlich ist das Board aber per USB angebunden – dazu gleich mehr. Noch leichter fiel die Entscheidung für das Teensy 3.2 Board durch die hervorragende Arbeit von Trammell Hudson und sein V.st-Projekt, das ein gutes Framework für die Darstellung von Vektorgrafik auf dem Oszilloskop bereitstellt (siehe Link in der Kurzinfo).

Umsteigerfreundlich

Neben Geschwindigkeit und Speichergröße hat das Teensy 3.x Board noch weitere Vorteile gegenüber der Arduino-Familie: zwei separate AD-Wandler, ein echter 12-Bit-DA-Wandler (leider nicht gut genug für unsere Zwecke), volle USB-Unterstützung, integrierte 3,3-V-Wandler und 5-V-Toleranz der Eingänge. Für Arduino-Umsteiger ist besonders vorteilhaft, dass man die Arduino-Entwicklungsumgebung weiter nutzen kann – inklusive praktisch aller der Libraries, die das Arbeiten mit dem Arduino so angenehm machen. Falls auch der Arduino für Sie Neuland ist: Über den Link in der Kurzinfo finden Sie dazu eine einsteigerfreundliche Anleitung.

Die Unterstützung der Teensy Boards rüstet ein spezieller Installer nach. Danach integrieren sich die Teensy Boards genauso in die Arduino-IDE wie andere Platinen auch – inklusive Beispielen, unter anderem auch dem „HelloWorld“-Programm der Mikrocontrollerwelt: Blink.ino, das eine LED auf dem Board blinken lässt.

Fritzing-Schema und real aufgebaute Breadboard-Schaltung für die Oszilloskop-Ansteuerung.

Nach der Installation (für Linux beachten Sie die Anleitungen und die Troubleshooting-Seite) werden die Teensy Boards erkannt und auch eine serielle Schnittstelle bereitgestellt. Tatsächlich kommuniziert ein Teensy Board aber immer über den USB-Port, die serielle Schnittstelle ist nur für die Kompatibilität mit dem Arduino gedacht. Teensys können auch als MIDI, Maus, generelles HID (Human Interface Device) oder Flugsimulator-Steuerungen verwendet werden. Wählen Sie als Board in der Arduino IDE „Teensy 3.2/3.1“ aus und setzen Sie den USB-Typ auf „Serial“ (wichtig, damit wir später mit dem Board kommunizieren können), die Taktfrequenz können Sie auf der Vorgabe lassen oder auf 96 MHz (overclock) setzen. Ich habe dabei bisher keine Erwärmung oder andere negative Effekte bemerkt. Bei Anwendungen, die per Batterie oder Akku laufen sollen, mag die Stromaufnahme bei overclock hingegen ein beachtenswerter Punkt sein.

Wenn Sie nun etwa den Blink.ino-Sketch kompilieren und wie vom Arduino gewohnt hochladen, so erscheint ein kleines Hilfsprogramm, das für den nötigen Reset des Teensy Boards sorgt, damit der Bootloader das neue Programm annimmt. Je nach Konfiguration des Boards und je nachdem, ob es gerade frisch eingesteckt wurde, muss eventuell einmal der Reset-Knopf auf dem Board gedrückt werden, danach funktioniert es dann automatisch. Der Upload sollte ohne Fehlermeldungen ablaufen. Verändern Sie zum Test doch einmal die delay()-Zeiten im Blink-Sketch, um sicher zu sein, dass nicht das in der Fabrik aufgespielte Blink-Programm läuft.

Die Teensy Loader Application lädt die Firmware unkompliziert auf das Teensy Board.
Schaltplan für die Oszilloskop-Ansteuerung

Digital nach analog

Als DACs für unsere Oszilloskop-Ansteuerung kommt der Chip MCP 4922-E/P zum Einsatz, der im DIL-Gehäuse (Dual In-Line, mit zwei Reihen Pins) auch prima auf einem Breadboard eingesetzt werden kann und per SPI performant und simpel angebunden wird. Auf einem von Trammell Hudson eigens entworfenen Board sind noch Spannungsreferenzen und Blockkondensatoren vorgesehen, die die Ausgabe noch weiter verbessern. Für unsere ersten Experimente reicht aber erst mal die einfache Breadboard-Schaltung, wie in der Abbildung zu sehen.

Als Anschlusspunkt für das Oszilloskop kommt in meinem realen Aufbau eine doppelreihige Header-Leiste zum Einsatz, bei der in der oberen Reihe die beiden äußeren Pins komplett in das Breadboard gedrückt wurden und in der unteren Reihe der mittlere Pin. Dies schafft mehr Platz, um die Oszilloskop-Tastköpfe bequem anzuklemmen, und sorgt für einen sicheren Sitz der Steckerleiste im Breadboard. In Maker-Manier tut es aber stattdessen auch ein Klecks Heißkleber. Alternativ können Sie auch die Tastköpfe weglassen, die Masse über einen 4-mm-Stecker an der GND-Buchse des Oszilloskops und die Kanäle mit 1,2-mm Lötstiften direkt per einfachem Kabel anschließen.

Software on Board

Jetzt geht es darum, eine Software auf das Teensy Board zu spielen, welche auf Grafik-Befehle per emulierter serieller Schnittstelle wartet und diese dann auf dem Oszilloskop per DA-Wandler ausgibt.

Demo und Einstellhilfe der V.st-Firmware

Im Prinzip kann man durch die zwei Kanäle den Elektronenstrahl an beliebige Stellen des Schirms lenken. Durch das Nachleuchten der Phosphorbeschichtung erscheint eine Linie, wenn man den Strahl von einem Punkt zum anderen lenkt. Die Geschwindigkeit bestimmt, wie hell diese Linie erscheint. Bewegt man den Elektronenstrahl sehr schnell, so wird der Phosphor kaum aufgeladen und man kann den Strahl ohne offensichtliche Linien bewegen. Erweitert man sein Oszilloskop um einen Z-Eingang, so kann man den Strahl auch abschalten oder sogar in der Helligkeit steuern und bekommt ein noch besseres Bild. Die Voraussetzungen dazu sind im Sketch bereits vorhanden und die Schaltung kann man einfach um ein zweiten DAC ergänzen.

Ein solches Programm ist nicht schwierig zu schreiben: Man lauscht auf der seriellen Schnittstelle auf Linienkoordinaten und zeichnet diese dann. Aber wie so oft steckt der Teufel im Detail und man muss das Programm gut optimieren, um eine annehmbare Geschwindigkeit zu erzielen.

Dankenswerterweise hat Trammell Hudson uns hier schon fast alle Arbeit abgenommen: Er stellt eine optimierte Datenübertragung und Direct Memory Access (DMA) bereit, um die Daten per SPI-Schnittstelle an den DAC auszugeben. Auch viele Funktionen wie die Textdarstellung und das Handling von Vektoren sind schon vorgefertigt. Ich habe sein Sketch benutzt und für diesen Artikel etwas entschlackt. Insbesondere habe ich die enthaltene Oszilloskop-Analoguhr wegen Library-Problemen nie zum Laufen bekommen und daher entfernt, sowie einige Vorgaben an unser Projekt angepasst, damit es leichter nachzuvollziehen ist.

Was dem Linuxer sein „dmesg“, ist dem Windows-Nutzer sein Gerätemanager. Hier erfahren Sie die COM-Schnittstelle des Teensy.

Testbild

Laden Sie den Sketch und einige Beigaben über den Link in der Kurzinfo herunter oder schauen sich das dort ebenfalls verlinkte Repository an und entpacken Sie das Archiv auf Ihrer Festplatte. Im Ordner teensyv_cw-master/teensyv finden Sie den Sketch teensyv.ino, den Sie in der Arduino-IDE öffnen. Wenn Sie das Teensy Board wie oben beschrieben erfolgreich mit dem Blink.ino bespielen konnten und die Schaltung aufgebaut ist, können Sie den Sketch auf das Board hochladen und das Oszilloskop anschließen. Dazu klemmen Sie eine der GND-Krokoklemmen an den mittleren Pin des Headers, an den rechten Pin klemmen Sie Kanal 1 des Oszilloskops, an den linken Kanal 2.

Am Oszilloskop muss der X-Y-Modus angeschaltet sein, die Eingänge sollten auf DC-Koppelung stehen. Die Empfindlichkeit müssen Sie für Ihr Gerät experimentell ermitteln: Bei meinem Hameg 205-2 steht die Empfindlichkeit an Kanal 1 (X) auf 1 V/DIV und auf 0,5 V/DIV für Kanal 2 (Y), allerdings muss ich für eine bildschirmfüllende Darstellung Kanal 1 mit dem Feinregler einstellen, 0,5 V/DIV ist hier leider schon zu viel. Mit X-POS und Y-POS 1 stellen Sie die Bildlage ein, mit der Verstärkung (V/DIV) regeln Sie die Skalierung, gegebenenfalls passen Sie diese mit den Feinreglern genau an. Feintuning geschieht mit den Focus- und Intensity-Reglern (Schärfe und Helligkeit des Elektronenstrahls).

Es sollte jetzt ungefähr ein Bild wie in der Abbildung erscheinen. Erscheint es um 90 Grad gekippt, so tauschen Sie einfach die Kanäle. Je nach Oszilloskop können auch mal ein paar Linien schief oder gar ein Flimmern wahrnehmbar sein, weil das Oszilloskop eine kurze Nachleuchtdauer hat. Ansonsten sollte das Bild aber ruhig stehen und die kleine Schrift lesbar sein. Herzlichen Glückwunsch, Sie haben ein funktionierendes Vektordisplay-System!

Steuersoftware auf dem PC

Nun gilt es das Display mit eigenen Grafiken zu füttern. Im heruntergeladenen Archiv gibt es den Ordner processing, dort befinden sich Demos für die Processing-Programmierumgebung. Processing wurde ursprünglich als vereinfachte Java-Version speziell für Designer, Künstler und andere Programmier-Quereinsteiger entworfen, die mit wenigen Codezeilen zu schicken Visualisierungen kommen sollten, ist aber auch eng mit der Arduino-Welt verbunden. Laden Sie sich die kostenlose Processing-IDE über den Link in der Kurzinfo herunter und installieren Sie diese.

Im Unterordner processing/basic unseres Projektarchivs befindet sich die Datei basic.pde, die Sie in den gestarteten Processing-Editor laden. Als Nächstes gilt es den seriellen Port herauszufinden, auf dem das Teensy Board auf Befehle lauscht.

Ausgabe des Processing-Programms basic.pde auf dem PC als Vorschau und auf dem Oszilloskop. Mit der Maus verschiebt man das kleine Quadrat.

Unter Windows finden Sie den Port im Geräte-Manager unter Anschlüsse (COM & LPT), in meinem Fall ist es COM10. Unter Linux schauen Sie mit dmesg auf der Kommandozeile nach dem Port. Achten Sie darauf, dass beim Hochladen der Firmware (also des kompilierten Sketches) auf das Teensy Board in der Arduino-IDE im Werkzeuge-Menü USB Type: Serial ausgewählt ist, sonst ist per seriellem Port keine Kommunikation möglich und der Port erscheint auch beim Anschließen des Teensy nicht. In so einem Fall muss die Firmware erneut mit korrekten Einstellungen hochgeladen werden.

Ist basic.pde geöffnet, so wechseln Sie in den Tab „VSE“. Dort findet sich in Zeile 9 der zu verwendende Port:

if (match(port, "COM10|usbmode|ACM") == null) { 

Tatsächlich durchsucht dieser Code alle verfügbaren seriellen Ports und verwendet den ersten (!), der in das Namensschema passt, der also entweder „COM10“, „usbmode“ oder „ACM“ im Namen enthält. Im Fehlerfall erscheint im Ausgabefenster eine Liste mit verfügbaren Ports und so erhält man immerhin einen Hinweis, welche denn noch sinnvoll zu testen wären. Ändern Sie also im Sketch COM10 auf den von Ihnen verwendeten Port, unter Linux dann analog ttyACM00 oder ähnlich. Weitere Suchterme können Sie mit | getrennt eingeben.

basic.pde

01  Vst vst;
02  
03  void settings() {
04    size(500, 500, P3D);
05    pixelDensity(displayDensity());
06  }
07  
08  void setup() {
09    vst = new Vst(this, createSerial());
10    frameRate(50);
11  }
12  
13  void draw() {
14    background(0);
15    vst.line(128, 125, 125, 375, 375);
16    vst.line(128, 125, 375, 375, 125);
17    rectMode(CORNER);
18    vst.rect(128, 0, 0, width - 1, height - 1);
19    rectMode(CENTER);
20    vst.rect(128, width / 2.0, height / 2.0, 250, 250);
21    vst.rect(255, mouseX, mouseY, 20, 20);
22    vst.display();
23  }

Wenn Sie den Sketch mit Klick auf den runden Button mit Pfeil starten, so öffnet sich ein neues Fenster mit der Ausgabe, wie sie auf dem Oszilloskop erscheinen sollte. Wenn Sie die Maus über diesem Fenster bewegen, erscheint ein kleines Quadrat am Mauscursor, und auch auf dem Oszilloskop sollten damit die Mausbewegungen sichtbar sein.

Der Code von basic.pde ist sehr simpel, kann aber als Rahmen fürs Programmieren von eigenen Grafiken in Processing dienen. Versuchen Sie doch einmal ein paar Änderungen einzubauen oder schwelgen Sie in 2D-Retro-Programming, Linie für Linie. Im processing-Ordner sind noch weitere und spektakulärere Demos vorhanden – versehen Sie auch hier die VSE.pde mit der korrekten Portnummer und lassen Sie sich überraschen!

3D-Grafik mit Blender

Noch schicker als die Darstellung von Linie für Linie programmierter 2D-Grafiken sind natürlich 3D-Grafiken in Drahtgitter-Optik. Auch wenn ich durch meine intensive Beschäftigung mit der 3D-Software Blender ein Fachmann fürs Erstellen von 3D-Grafik bin, so habe ich doch in der dafür grundlegenden Mathematik Nachholbedarf. Aber irgendwie wäre es doch trotzdem cool, Grafiken im Stile von alten Vectrex-Spielen auf dem eigenen Oszilloskop zu erzeugen. Auch ein kleiner Film im Stile des Videos für die Kickstarter-Kampagne zum Projekt „Oscilloscope Music“ wäre nett (siehe Link in der Kurzinfo).

Suzanne, das Blender-Maskottchen, auf dem Oszilloskop

Der naheliegende Weg – die 3D-Grafik als Vektorgrafik zu exportieren, in Quellcode umzuwandeln und an das Teensy Board zu schicken – erschien mir zu eingeschränkt. Warum die ganzen Möglichkeiten, die man in Blender zum Modellieren und Animieren hat, entweder verlieren oder mühevoll auf einem Microcontroller nachbauen müssen? Nach kurzem Studium der Python-API-Dokumentation (Programmierschnittstelle) von Blender (siehe Link in der Kurzinfo) keimte in mir die Hoffnung, dass es möglich sein müsse. Python-Handler, die pro Update der Blender-3D-Fenster ausgeführt werden, hatte ich schon verwendet, Kommunikation per Python über die serielle Schnittstelle auch.

Das Sende-Skript

Das Skript zum Senden von Grafiken ans Oszilloskop und eine Blender-Datei mit Demos finden Sie über den Link in der Kurzinfo zum Download. Laden und starten Sie es, wie im Kasten beschrieben und im Video gezeigt.

Die 3D-Szene nach polygonalen (Mesh-)Objekten zu durchsuchen und die 3D-Punkte (Vertices) und Kanten (Edges) abzufragen, war eine recht einfache Übung, denn das habe ich nicht das erste Mal gemacht. Ein zu knackendes Problem war die hochoptimierte Byte-weise Übertragung aus der Dokumentation von V.st nach Python zu übertragen – Bits schubst ein Python-Programmierer nicht alle Tage. Nach ein paar Google-Irrwegen bin ich bei einem Code herausgekommen, der jenem der Processing-Sketches sehr ähnlich sieht, und tatsächlich erschienen dann auch recht schnell die ersten Linien auf dem Oszilloskop.

Von 3D allerdings noch keine Spur, denn um an die perspektivisch umgerechneten Koordinaten heranzukommen, müsste man wohl das OpenGL-Rendering abfangen. Das wird zwar auch bei der Quake-Version für Oszilloskope und für das MAME-Retro-Game-System so ähnlich gemacht, geht aber weit über meinen Horizont. Nach ein paar Experimenten mit einfacher Projektion und den ersten nach 3D aussehenden, sich drehenden Würfeln, habe ich mich dann doch in Blender versucht, um die Weltkoordinaten der Objekte in projizierte Koordinaten umzurechnen. Im Prinzip sind viele der nötigen (Vektor- oder Matritzen-)Funktionen in Blender schon vorhanden, nur hat es doch gedauert, das wenigstens so gut zu verstehen, damit auch etwas Sinnvolles an das Teensy Board gesendet wurde.

In Blender können Sie die Layer mit den Ziffern auf der Haupttastatur oder über die Layer-Buttons im 3D-Fenster umschalten.
Sieht zweidimensional aus, ist es aber nicht: Der hungrige Pac-Man läuft in Blender als 3D-Animation, die rotierenden Würfel als Futter deuten es an.

Ein weiteres Problem war das im Microcontroller-Sketch nicht implementierte Clipping von Linien, die über den Darstellungsbereich herausgehen, aber das konnte zügig durch etwas googlen und kopieren (die Herkunft ist in dem ungekürzten Quellcode der Blender-Datei natürlich vermerkt) eines Codes für ein „Cohen-Sutherland Clipping“ behoben werden. Leider habe ich nicht herausfinden können, wie man den Handler in Blender wieder stoppt und damit auch den seriellen Port wieder schließt. Mit meinem Code muss man also Blender beenden (und gegebenenfalls vorher die Szene speichern), dann Blender neu starten und die Szene laden, was allerdings schnell geht. Für Tipps von Python/Blender-Gurus zur Abhilfe bin ich dankbar!

Vektorzauber

Jetzt aber erst mal zum praktischen Einsatz: Tragen Sie die korrekte serielle Schnittstelle in das Skript ein (Zeile 6). Das Oszilloskop sollte angeschaltet und das Teensy Board mit dem PC per USB verbunden sein. Sobald Sie nun Alt+P drücken, wenn der Mauszeiger über dem Skript-Fenster in Blender schwebt, oder Sie den Knopf „Run Script“ anklicken, wird die aktuelle Kameraansicht in Blender an das Vektor-Display geschickt und dort solange angezeigt, bis Sie ein neues Bild schicken.

In Zeile 11 des Skripts können Sie nun den Handler aktivieren, indem Sie die Zeile

HAND = false
Eine unserer Blender-Demos nutzt die Physik-Engine von Blender, um die Würfel live berechnet fallen zu lassen.
Die Feuerwerks-Demo wird mit Processing-Code erzeugt und ist über den Download-Link zu erreichen.
Das Oszilloskop eignet sich hervorragend als Display für die Reanimation von 3D-Wireframe-Spieleklassikern wie BattleZone.

durch das Voranstellen eines # auskommentieren. Jetzt führt das erneute Starten des Skripts dazu, dass jede Änderung in der 3D-Ansicht, sei es per Animation oder manuelles Transformieren von Objekten, an das Vektor-Display geschickt wird. Aktivieren Sie doch einmal die Animation per Alt+A (Mauszeiger über der 3D-Ansicht) oder mit dem Play-Button ganz unten im Blender-Fenster. Auf den Layern 1–10 der Blender-Beispieldatei sind noch weitere Demos zu finden, die meisten mit Animation.

Modellieren können Sie übrigens auf Ihrem Vektor-Display nicht: Das Skript unterstützt den dazu verwendeten Edit Mode von Blender nicht. Weiterhin werden nur polygonale (Mesh-)Objekte aus der Blender-Datei dargestellt, (siehe Zeile 67 im Listing). Ansonsten zeigt das Oszilloskop aber so ziemlich alles an, was man in Blender mit Meshes und Animation machen kann, etwa physikalische Simulationen, Character Animation oder Modifier, so dass man im Prinzip einen ganzen Film für Vektor Displays produzieren kann.

13  import serial
14  import bpy
15  import bpy_extras
16  from mathutils import Vector,Matrix
17  import math

Möchte man in Blenders Python auf die Interna von Blender zugreifen, so muss das Modul bpy (steht für Blender Python) importiert werden. Die übrigen Zeilen importieren auch noch andere Module für mathematische Funktionen und Strukturen sowie den Zugriff auf die serielle Schnittstelle.

25          self.cam = bpy.data.objects.get("Camera")
26          if self.cam == None:
27              print("Keine Kamera!")
28              self.sock.close()
29              exit

Damit das Skript funktioniert, muss eine Blender-Kamera in der Szene vorhanden sein, die auch exakt „Camera“ heisst (in meiner Datei befindet sie sich auf Layer 11).

51      def send2v(self):
52          vbytes = bytearray(4)   # vier 0-bytes als Header
53  
54          # Undo-Problematik Crash umschiffen
55          self.scene = bpy.context.scene
56          self.cam = bpy.data.objects.get("Camera")
...
66              if (obj.type in ['MESH']):       # Nur Meshes
67                  # Modifier anwenden
68                  me = obj.to_mesh(self.scene, apply_modifiers=True,:
                         .settings='PREVIEW')
69                  wx = obj.location.x
70                  wy = obj.location.y
71                  mat = obj.matrix_world
72                  verts = me.vertices
73                  edges = me.edges

Hier geht es ans Eingemachte: Nachdem ein paar Informationen über die Szene und die verwendete Kamera abgefragt wurden, wird über alle sichtbaren Mesh-Objekte in Blender iteriert. Pro Objekt werden dann die Position und Orientierung abgefragt.

74                  for ed in edges:
75                      v0_2d = bpy_extras.object_utils.:
                                .world_to_camera_view(
76                                 self.scene, self.cam,:
                                         .mat*verts[ed.vertices[0]].co)
77                      v1_2d = bpy_extras.object_utils.:
                                .world_to_camera_view(
78                                 self.scene, self.cam,:
                                         .mat*verts[ed.vertices[1]].co)

Weiter wird jede Kante (Edge) des Objekts ausgelesen und die Koordinaten mit den Informationen über die Kamera und die Szene in eine perspektivische 2D-Ansicht umgerechnet.

81                      x0=(v0_2d.x * render_size[0])
82                      y0=(v0_2d.y * render_size[1])
83                      x1=(v1_2d.x * render_size[0])
84                      y1=(v1_2d.y * render_size[1])
85  
86                      # Clipping
87                      x0,y0,x1,y1=self.cohensutherland:
                                    .(0,0,render_size[0]-1,
88                                        render_size[1]-1,x0,y0,x1,y1)
89                      # Bytes schubsen und shiften
90                      if (x0!=None):
91                          v = (1) << 30 | (0 & 63) << 24 | (round(x0):
                                . & 4095) << 12 | (round(y0) & 4095) << 0
92                          vbytes.append((v >> 24) & 0xFF)
93                          vbytes.append((v >> 16) & 0xFF)
94                          vbytes.append((v >>  8) & 0xFF)
95                          vbytes.append((v >>  0) & 0xFF)
96                          v = (1) << 30 | (1 & 63) << 24 | (round(x1) :
                                 . & 4095) << 12 | (round(y1) & 4095) << 0
97                          vbytes.append((v >> 24) & 0xFF)
98                          vbytes.append((v >> 16) & 0xFF)
99                          vbytes.append((v >>  8) & 0xFF)
100                         vbytes.append((v >>  0) & 0xFF)

Hier werden diese Werte dann noch auf den Ausgabebereich 4096 × 4096 zugeschnitten und in ein Byte-Array geschrieben.

Dies ist im Prinzip nur eine Adaption des Codes der Processing-Demos – die Koordinaten und Helligkeiten werden platzsparend in möglichst wenig Bytes gepackt. Die Beschreibung des Protokolls finden Sie über die Links.

Nach Ende der for-Schleife werden dann noch vier 1er-Bytes als Abschluss geschrieben.

109          if (self.sock!=None):
110              self.sock.write(vbytes)

Das ganze Byte-Paket wird gesendet.

Ausblick

Ich hoffe, Sie haben nun Lust bekommen, auch einmal mit einem vorhandenen Oszilloskop zu experimentieren oder kaufen sich vielleicht sogar ein gebrauchtes analoges Gerät eigens für diesen Zweck. Von Ideen, Anregungen und eigenen Projekten würden wir natürlich gerne hören! Schreiben Sie einfach eine Mail an mail@make-magazin.de.

Im zweiten und abschließenden Artikel zu diesem Projekt geht es voraussichtlich in der kommenden regulären Make-Ausgabe 6/17 mit der direkten Programmierung auf dem Teensy weiter, sei es nun für Spiele, interaktive Anzeigen und andere Anwendungen. Natürlich wird dann auch wieder Blender eingesetzt, um Grafik für unser Vektor-Display zu erstellen. pek