ArduinoScopePaint


Auf einer Kurzreise nach Dublin sah ich im Schaufenster des Makeshops https://dublin.sciencegallery.com/makeshop ein Oszilloskop, das nicht wie üblich ein Signal über einen Zeitverlauf anzeigte, sondern eine Vektorgrafik.
Das musste ich gleich auf meinem guten analogen Hameg 204-2 ausprobieren.
Mit minimalem Aufwand erreicht man ein mittelmäßiges Ergebnis wie dieses hier:

Bild "ArduinoScopePaint_Scope.jpg"  
C-Hack ist übrigens unser lokaler Hackerspace: c-hack.de

Was man so braucht

  1. Ein analoges 2-Kanal Oszilloskop, das einen x-y-Modus hat (haben eigentlich alle) und einen Z-Eingang, mit dem man das Signal dunkel schalten kann
  2. Einen Arduino (egal welchen)
  3. Zwei Kondensatoren 68nF und zwei Widerstände 4.7kOhm als Tiefpassfilter
  4. Ein bisschen Lochrasterplatine oder ein Steckbrett um die Schaltung aufzubauen

Die Schaltung


Bild "ArduinoScopePaint_Schaltung.png"

Um verschiedene Punkte anfahren zu können auf dem Oszilloskop, müssen die Ausgänge analoge Spannungswerte ausgeben können. Abhängig von der jeweiligen Spannung wird dann der Leuchtpunkt nach rechts (X-Kanal) bzw, nach oben (Y-Kanal) ausgelenkt. Lässt man das den Mikrocontroller vielen Male pro Sekunde wiederholen, dann erhält man ein stehenden Bild.
Wichtig: Hierzu muss man Pins des Arduino verwenden, die PWM Funktion haben und somit mit dem Befehl analogWrite() benutzt werden können. Bei mir waren das Pin 9 und 10.

Wozu die Widerstände und Kondensatoren?

Damit man auf dem Bildschirm eine Linie sieht, muss der sich Leuchtstrahl in endlicher Geschwindigkeit bewegen. Schaltet man von einer Spannung zur anderen um, so passiert das viel zu schnell. Man würde nur jeweils bei Start und Ziel einen Punkt sehen und keine Linie. Durch den Tiefpassfilter verlangsamt sich der Übergang.

Hier kann man den Effekt der Tiefpassfilter ganz gut sehen. Hier ist dazu das Scope von X-Y-Modus zurück auf den Zweikanalmodus umgeschaltet um die beiden Kanäle bezogen auf eine Zeitbasis zu zeigen:

Bild "ArduinoScopePaint_Signale.jpg"
  

PWM

Die üblichen Mikrocontroller (so auch der Arduino ATMEGA) können keine analogen Spannungen ausgeben. Stattdessen wird ein digitale Output-Pin zwischen 0V und 5V gepulst. Dadurch das das Verhältnis von Ein- und Ausschaltzeit variiert wird, ergibt sich im Mittel eine analoge Spannung zwischen 0 und 5V. Die beiden Tiefpässe sind auch notwendig, um diese Mittelung vorzunehmen. Ohne diese Filter würde sich ein wildes Gespringe zwischen den digitalen Spannungswerten auf dem Scope-Bildschirm abspielen.

Da wir sehr schnell springen müssen, damit sich für das Auge ein stehendes Bild ergibt, muss die PWM-Frequenz viel höher sein als die Frequenz der Umschaltvorgänge in unserem Bild. Ist sie aber nicht beim Arduino. Abhängig vom Modell liegt sie bei etwas 1kHz, was viel zu niedrig ist.
Mit ein paar Low Level Befehlen kann man aber den Timer umprogrammieren und so bis auf 62kHz hochtunen, was ausreicht.

void setPwmFrequency(int pin, int divisor) {
  byte mode;
  if(pin == 9 || pin == 10) {
    switch(divisor) {
      case 1: mode = 0x01; break;
      case 8: mode = 0x02; break;
      case 64: mode = 0x03; break;
      case 256: mode = 0x04; break;
      case 1024: mode = 0x05; break;
      default: return;
    }
    TCCR1B = TCCR1B & 0b11111000 | mode;
  }
}

Verwendet man den kleinsten Teiler, so ergibt das die höchste PWM-Frequenz.

Hier sieht man die große Zeitkonstante des Filters, und darauf die Schaltzyklen der PWM Pulse:

Bild "ArduinoScopePaint_TPSignal.jpg"

Bei den verwendeten Bauteilen ergibt sich eine Zeitkonstante von T = 68nF * 4.7kOhm = 0.32ms
Eine Skaleneinheit auf dem Bild oben entspricht 0.2ms. Nach der Zeit T wird ca. 63% der Maximalamplitude erreicht. Man sieht, dass die Theorie zu stimmen scheint.  :)

Der Z-Eingang

Mit X- und Y-Eingang kann man schon schöne Bilder zeichnen. Allerdings müssen alle Linien in einem Zug gemalt werden. Das "Haus vom Nikolaus" geht also zum Beispiel. Ein Schriftzug geht nicht, weil ja immer man wieder der Stahl unsichtbar von einem zum nächsten Buchstaben bewegt werden muss. Hierzu habe ich den Z-Eingang des Hameg 204-2 benutzt, der den Strahl ein- und ausschalten kann. 5V an dem Eingang schaltet ihn ein, 0V sorgt dafür, dass er dunkel ist. Das erledigt ein weiterer Pin des Arduino. Das kann ein digitaler Pin sein. Bei mir Pin 12.
Die BNC-Buchse für das Z-Signal ist übrigens auf der Rückseite des Geräts.

Der Aufbau

Ich habe mich für Lochstreifen entschieden, weil ich gerade einen Rest davon rumliegen hatte und man keine Drähte ziehen muss für die Verbindungen. Es geht natürlich auch ein simples Steckbrett oder ein fliegender Aufbau.

Bild "ArduinoScopePaint_Filter.jpg"

Bild "ArduinoScopePaint_Kabel2.jpg"

Was man besser machen könnte

Das simple RC Tiefpassfilter hat einen e-funktionsförmigen Verlauf. Das führt dazu, dass sich der Strahl am Anfang sehr schnell bewegt und dann immer langsamer wird. Somit ist die Linie in der Nähe des Startpunktes ziemlich dunkel, während sie zum Ziel hin immer heller wird. Man muss mit der Wartezeit etwas herumspielen. Wartet man zu lange, dann wird der Leuchtpunkt am Ende zu hell und das Bild flackert, weil sich die Wartezeiten zu einer sehr langsamen Wiederholrate addieren.
Sind die Wartezeiten zu kurz, dann erreicht der Strahl jeweils das Ziel nicht, die Ecken werden rund und das Bild wird nicht mehr richtig dargestellt.

Besser wäre ein linearer Verlauf der Flanken des Signals (constant slew rate). Das könnte man z.B. mit einer Integratorschaltung machen. Das werde ich demnächst mal probieren...

Bild "ArduinoScopePaint_Scope2.jpg"

Und hier noch der ganz simple Source-Code - definitv ausbaufähig... :)
ArduinoScopePaint.ino