Raspberry Oszilloskop      

Elektronik-Labor  Projekte  Mikrocontroller  Raspberry     




Übliche Oszilloskope im Elektronik-Labor können schnelle Änderungen bis in den MHz-Bereich aufzeichnen und haben Empfindlichkeiten bis hinunter zu wenigen mV. Solche Daten sind mit dem einfachen AD-Wandler für den Raspberry natürlich nicht zu erreichen. Aber es ist eine interessante Aufgabe, das Beste herauszuholen.



Grundlage des Oszilloskops ist der einfache AD-Wandler. Allerdings muss die Messung möglichst schnell durchgeführt werden, damit eine brauchbare zeitliche Auflösung entsteht. Das in Python programmierte Oszilloskop hat 25 mal 10 Kästchen mit einer Auflösung von einer Sekunde in x-Richtung und einem Volt in y-Richtung. In jeder Sekunde werden 20 Einzelmessungen durchgeführt auf aufgezeichnet. Die Null-Linie liegt in der Mitte. Damit wird der volle Messbereich von -5 V bis + 5V dargestellt.  Die Anzeige erfolgt in Echtzeit, sodass man beobachten kann, wie sich das Oszillogramm in 25 Sekunden aufbaut.

Für die Ausgabe wird ein Canvas-Element mit einem Rechteck von 500 mal 200 Pixeln verwendet. Beim Start werden alle Hilfslinien und die grüne Nulllinie eingezeichnet. Dann werden 500 Messwerte erfasst und dargestellt. Für jeden Messpunkt wird eine AD-Wandlung mit 10.000 Vergleichen durchgeführt, was etwa 50 ms dauert. Das Oszillogramm wird aus Linienelementen aufgebaut. Der jeweilige Anfangspunkt  muss in den globalen Variablen x1 und y1 geführt werden, damit er beim jeweils folgenden Aufruf der Funktion scope(cv) bekannt ist.

Die Funktion scope(cv) zeichnet 500 Linienelemente und ruft sich jeweils mit einer Verzögerung von nur einer Millisekunde wieder auf. Fast die gesamte Rechenzeit wird für die AD-Wandlung gebraucht. Damit ergibt sich die erforderliche Verzögerung von 50 ms/Messpunkt. Nur am Ende der Messung wartet das Programm 2000 ms, damit man genügend Zeit hat, das gesamte Oszillogramm zu sehen. Der AD-Wandler kann kalibriert werden indem man die konstanten Spannungen 0 V und 3,3 V misst.

Das Programm stammt aus dem Franzis-Lernpaket Raspberry Pi Maker Kit Elektronik. Es wurde ursprünglich für den Raspberry Pi 2 entwickelt, läuft aber auch auf dem Zero. Ein Test mit dem Raspberry Pi 3 zeigte dann, dass es da noch glatter läuft, einfacher weil der Rpi3 noch schneller ist. Im Moment ist mein Rpi3 allerdings meist mit einer anderen Aufgabe belegt: Als Kurzwellensender für WSPR-Signale. Deshalb ist der Rpi2 weiterhin als Messlabor aktiv.



#Tk_ADC9_11oszi1.py   Oszilloskop 1s/Skt, 1V/Skt
from Tkinter import *
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(9, GPIO.OUT)
GPIO.setup(11, GPIO.IN)
global x1
x1=0
global y1

def scope(cv):
global x1
global y1
if x1==0:
cv.create_rectangle(1, 1, 500, 200, fill="white")
for n in range (10):
cv.create_line(1, n*20, 500, n*20, fill = "grey")
for n in range (25):
cv.create_line( n*20, 1, n*20, 200, fill = "grey")
cv.create_line(1, 100, 500, 100, fill = "green")
while not GPIO.input(11):
GPIO.output(9, 1)
u1=0
u2=0
for i in range(10000):
if GPIO.input(11):
GPIO.output(9, 0)
u1=u1+1
else:
GPIO.output(9, 1)
u2=u2+1
GPIO.output(9, 0)
u=u1-u2
u=u*1000 #Endwert kalibrieren
u=u/100000
u=u+1 #Nullpunkt kalibrieren
u=u+100
y2=u
x2=x1+1
if x1>0:
cv.create_line(x1, 200-y1, x2, 200-y2, fill = "black")
y1=y2
x1=x1+1

if x1<500:
cv.after(1, scope, cv)
if x1>499:
x1=0
cv.after(2000, scope, cv)

root = Tk()
root.title("Oszilloskop GPIO 9/11")
cv = Canvas(root, width=502, height=202)
cv.pack()
cv.create_rectangle(1, 1, 500, 200, fill="white")
cv.create_line(1, 100, 500, 100, fill = "green")
w = Label(root, text="1V/Skt 1s/Skt")
w.pack()
scope(cv)
mainloop()


Verbesserungsvorschlag von Frank Behlich

Es geht darum, die Systembelastung zu verringern. Falls jemand Problem mit dem Oszilloskop beobachtet, sollte er diese Version testen, bei der Linien nicht nur erzeugt sondern auch wieder gelöscht werden.

#Tk_ADC9_11oszi1.py   Oszilloskop 1s/Skt, 1V/Skt
import Tkinter as tk
from random import randint

#import RPi.GPIO as GPIO
#GPIO.setwarnings(False)
#GPIO.setmode(GPIO.BCM)
#GPIO.setup(9, GPIO.OUT)
step_x = 5
def scope(cv, x, step_x, id):

def measure_point():
#while not GPIO.input(11):
# GPIO.output(9, 1)
#u1=0
#u2=0
#for i in range(10000):
#if GPIO.input(11):
#GPIO.output(9, 0)
#u1=u1+1
#else:
#GPIO.output(9, 1)
#u2=u2+1
#GPIO.output(9,0)
u1 = randint(0, 5000)
u2 = randint(0, 5000)
u = 200 - (((u1 - u2) * 1000 / 100000) + 100)
return u

if x < 500:
if id:
last_y = cv.coords(id)[-1]
else:
cv.delete("line_point")
last_y = 100
x += step_x
id = cv.create_line(x-step_x, last_y , x, measure_point(), fill = "black", tag="line_point", width=2)
else:
x = 0
id = None
cv.after(10, scope, cv, x, step_x, id)

root = tk.Tk()
root.title("Oszilloskop GPIO 9/11")
cv = tk.Canvas(root, width=500, height=200, bg="white")
cv.pack(padx=5, pady=5)
for n in xrange (10):
cv.create_line(1, n*20, 500, n*20, fill = "lightblue")
for n in xrange (25):
cv.create_line( n*20, 1, n*20, 200, fill = "lightblue")
cv.create_line(1, 100, 500, 100, fill = "lightgreen")
tk.Label(root, text="1V/Skt 1s/Skt").pack()
scope(cv, 0, step_x, None)
tk.mainloop()



Elektronik-Labor  Projekte  Mikrocontroller  Raspberry