Seite 1 von 1

SR830 Lock-in Amplifier

Verfasst: Donnerstag 19. August 2021, 15:15
von Bartolomeo85
Moin zusammen,
ich bin gerade etwas am verzweifeln, ich hoffe ihr könnt mir helfen.
Ich arbeite mit einem SR830 Lock-in Amplifier von Stanford Research Systems.
Mit folgendem Code kann ich den LockIn wunderbar vom Raspberry Pi auslesen:

#####################
import serial

def toBytes(string):
return bytes(string, 'utf-8')

def make_lockin_connection(port):
return serial.Serial(port, 9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout = 2)

if __name__ == "__main__":
port = "/dev/ttyUSB0"
con = make_lockin_connection(port)
con.write(toBytes('OUTX0\n')) #Set Output to RS232
con.write(toBytes('*IDN?\n')) # Get the IDN of the connected LockIn
answer = con.readline().decode("utf-8")
con.close()
print(answer)
#####################

Momentan schreibe ich das Programm so um, dass ich von einem Windows Rechner den LockIn auslesen kann, der Code dafür ist folgender:


#####################
import serial

def toBytes(string):
return bytes(string, 'utf-8')

def make_lockin_connection(port):
return serial.Serial(port, 9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout = 2)

if __name__ == "__main__":
port = "CPM5"
con = make_lockin_connection(port)
con.write(toBytes('OUTX0')) #Set Output to RS232
con.write(toBytes('*IDN?')) # Get the IDN of the connected LockIn
answer = con.readline().decode("utf-8")
con.close()
print(answer)
#####################

Das Problem ist aber, dass ich keine Antwort bekomme. Auf dem Raspi bekomme ich die ID vom LockIn wieder, hier nichts.
Könnte ihr mir vielleicht helfen? wo ist mein Fehler? habe ich schlicht einfach noch was vergessen?

Ich freue mich auf eure Antworten!

Re: SR830 Lock-in Amplifier

Verfasst: Donnerstag 19. August 2021, 15:20
von __deets__
Die fehlen die Zeilenendezeichen. Hast du von Hand abgetippt statt zu kopieren?

Re: SR830 Lock-in Amplifier

Verfasst: Donnerstag 19. August 2021, 15:31
von Bartolomeo85
Hi, danke für die schnelle Antwort.
Meinst du die "\n"?
Ich habe die beim Code für Windows extra weg gelassen, soweit ich weis, sind die nur für Linux gedacht. Jedoch habe ich beide Varianten ausprobiert und ich bekomme nichts zurück. Wenn ich bei der Windows-Variante "\n" benutze, meldet mir der LockIn, am Gerät, einen Fehler.

Re: SR830 Lock-in Amplifier

Verfasst: Donnerstag 19. August 2021, 16:37
von __deets__
Das hat nichts mit Linux zu tun. Sondern damit, wie dein Gerät funktioniert. Ohne die wird es nicht gehen. Steht hier https://research.ece.cmu.edu/~mems/reso ... SR830m.pdf

Zu dem Fehler kann ich nix sagen. Ich sehe ihn ja nicht.

Re: SR830 Lock-in Amplifier

Verfasst: Donnerstag 19. August 2021, 18:18
von Bartolomeo85
Den Fehler sehe ich auch nicht, das einzige was ich sehe ist, das eine Lampe für Error aufleuchtet, wenn ich "\n" mit sende.
Trotzdem bekomme ich bei beiden Varianten nichts zurück.
Mich wundert halt, dass es übers Raspi geht und mit dem "selben" code, nur mit halt für windows anderen Port, funktioniert es nicht.

kann es noch an was anderem liegen?

Re: SR830 Lock-in Amplifier

Verfasst: Donnerstag 19. August 2021, 18:30
von __deets__
Ich würde ein Terminal Programm benutzen & es mal damit probieren. Denn das liest auch irgendwelche Ausgaben aus. Und das verlinkte Handbuch durchlesen, ob und wie genau Fehler kommuniziert werden.

Aber um das nochmal ganz klar zu machen: ohne newline geht es nicht. Das du keinen Fehler bekommen hast, war kein Zeichen von alles super. Sondern wie eine unversandte Kündigung. Passiert halt nix.

Re: SR830 Lock-in Amplifier

Verfasst: Freitag 27. August 2021, 11:36
von Bartolomeo85
Moin, schon etwas her, aber ich habe ein wenig rum probiert.
Hier der Code mit dem ich den SR830 wunderbar auslesen kann:

def reflectivity(COMport1, COMport2, detector_const, readouts):
ser = serial.Serial(COMport1, 9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout = 0.05)
ser1 = serial.Serial(COMport2, 9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout = 0.05)
summe = 0
summe1 = 0
ser.write('OUTX0\n'.encode('utf-8'))
ser1.write('OUTX0\n'.encode('utf-8'))
for i in range(0,readouts):
try:
ser.write('OUTP?3\n'.encode('utf-8'))
response = float(ser.readline())
summe += response
print("first try res:", response)
except ValueError:
ser.write('OUTP?3\n'.encode('utf-8'))
response = float(ser.readline())
summe += response
print("second try res:", response)
try:
ser1.write('OUTP?3\n'.encode('utf-8'))
response1 = float(ser1.readline())
summe1 += response1
print("first try res1:", response1)
except ValueError:
ser1.write('OUTP?3\n'.encode('utf-8'))
response1 = float(ser1.readline())
summe1 += response1
print("second try res1:", response1)
S1 = summe/readouts
S2 = summe1/readouts
divide = S2/S1
reflectivity = (1-divide*detector_const)/(1+divide*detector_const)
ser.close()
ser1.close()
return reflectivity

Ja ich weis, in den except's wird das Gleiche probiert wie im try's, fragt mich nicht warum, ich habe den Code aus einem fast 10 Jahre alten Programm.
Als Ergebnis bekomme ich immer:
frist try res: ....
first try res1: ....
usw.

Sobald ich die try's und except's entferne, bekomme ich bei "response1 = float(ser1.readline())" immer den Fehler, dass readline() Nichts zurück bekommt. Selbst wenn ich die Port's tausche, also die Reihenfolge, des Auslesens, der LockIn's wechsle, bekomme ich immer den Fehler bei "response1 = ...".

Hat jemand einen Hilfreichen Tipp, warum, wieso, weshalb?

Re: SR830 Lock-in Amplifier

Verfasst: Freitag 27. August 2021, 12:30
von __deets__
Bei deinem absurd kleinen timeout ist es kein Wunder, das nix zurück kommt.

Und Code bitte in Code Tags setzen. Der ist sonst nahezu unlesbar.

Statt des permanenten "encode('UTF-8')" einfach ein b vor das Literal schreiben, dann hast du gleich Bytes.

Re: SR830 Lock-in Amplifier

Verfasst: Freitag 27. August 2021, 12:37
von Bartolomeo85
Sry für die Unleserlichkeit.
Egal auf was ich die Timeouts ändere (außer unter 0.03), das Problem bleibt.

Re: SR830 Lock-in Amplifier

Verfasst: Freitag 27. August 2021, 12:42
von __deets__
Warum *hast* du einen Timeout? Weisst du, was der Timeout macht, und wie es sich aeussert, dass er "zugeschlagen" hat? Und hast du meine Tipp mit dem Terminal mal ausprobiert? Was dabei ist rumgekommen?

Programmierung (und den Umgang mit System, die Programmiert sind, wie dein Geraet) ist systematische Arbeit. Nicht eine Piniata, auf der man rumkloppt, bis die Belohnung rauskommt.

Re: SR830 Lock-in Amplifier

Verfasst: Freitag 27. August 2021, 12:46
von __deets__
Und noch eine Frage: warum ploetzlich zwei serielle Ports?

Re: SR830 Lock-in Amplifier

Verfasst: Freitag 27. August 2021, 13:01
von Bartolomeo85
Ein Timeout legt die Zeit fest, wie lange gewartet wird, auf empfangende Daten.
Ja ich weiß, wie es aussieht, wenn er "zuschlägt". Den Tip mit dem Terminal habe ich ausprobiert und es hatte damit geklappt, also der SR830 hat mir sowohl seine ID, als auch die Werte für Ref ausgegeben.

Für das endgültige Programm benutze ich 2 SR800, um die Reflektivität von z.b. Spiegeln zu ermitteln.

Re: SR830 Lock-in Amplifier

Verfasst: Freitag 27. August 2021, 13:43
von __deets__
Und wie sieht das aus? Denn das erklaert doch, warum du Leerstrings bekommst. Warum hast du den Timeout eingebaut? Die Frage hast du nicht beantwortet.

Dann solltest du dein Programm neu aufbauen. Man schreibt sich Funktionen oder Klassen, die mit *einem* Geraet umgehen. Und wenn man dann mehrere braucht, dann benutzt man die eben zweimal, jeweils mit anderen COM-Ports. Denn das vereinfacht den Code massiv, und verhindert dieses verschachteln, das keiner mehr durchblickt.

Zu guter Letzt wuerde ich auch auf readline erstmal verzichten, und stattdessen die Daten einfach mal so lange einlesen, bis ein "\n" kommt. Denn es koennte sein, dass der unter Windows fuer readline ein \r\n will. Nur das du das nicht bekommst.

Re: SR830 Lock-in Amplifier

Verfasst: Freitag 27. August 2021, 14:35
von rogerb
Ich habe keine Praxiserfahrung mit pySerial zwei Punkte sind mir aber aufgefallen

Code: Alles auswählen

def reflectivity(COMport1, COMport2, detector_const, readouts):
    ser = serial.Serial(COMport1, 9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=0.05)
    ser1 = serial.Serial(COMport2, 9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=0.05)
    summe = 0
    summe1 = 0
    ser.write("OUTX0\n".encode("utf-8"))
    ser1.write("OUTX0\n".encode("utf-8"))
    for i in range(0, readouts):
        ser.write("OUTP?3\n".encode("utf-8"))
        # ser.flush()  <-------- u.U. nötig um zu warten bis alles gesendet wurde
        response = float(ser.readline())
        summe += response
        print("first try res:", response)

        ser1.write("OUTP?3\n".encode("utf-8"))
        # ser.flush()  <-------- u.U. nötig um zu warten bis alles gesendet wurde
        response1 = float(ser1.readline())
        summe1 += response1
        print("first try res1:", response1)

        S1 = summe / readouts
        S2 = summe1 / readouts
        divide = S2 / S1
        reflectivity = (1 - divide * detector_const) / (1 + divide * detector_const)
        # ^^^^^ das ist der Funktionsname - keine gute Idee, hat aber nichts mit dem Problem zu tun
        ser.close()
        ser1.close()

    return reflectivity

Re: SR830 Lock-in Amplifier

Verfasst: Freitag 27. August 2021, 15:57
von __deets__
Da sind noch deutlich mehr Fehler drin. Wenn das wirklich so der Code ist, dann ist natuerlich das ser.close() auf der gleichen Ebene wie der Schleifencode ein Problem. Ich wuerde das wenn so machen:

Code: Alles auswählen

def read_value(ser):
    ser.write(b"OUTX0\nOUTP?3\n")
    return float(ser.readline())


def reflectivity(amplifier_a, amplifier_b, detector_const, readouts):
    average_a = sum([read_value(amplifier_a) for _ in range(readouts)]) / readouts
    average_b = sum([read_value(amplifier_b) for _ in range(readouts)]) / readouts
    h = average_b / average_a
    return (1 - h * detector_const) / (1 + h * detector_const)
    

def main():
    amplifier_a = serial.Serial(COMport1, 9600) # das andere sollte alles der default sein
    amplifier_b = serial.Serial(COMport2, 9600) # das andere sollte alles der default sein
    print(reflectivity(amplifier_a, amplifier_b, whatever, 10))
Es gibt auch keinen Grund, andauernd die Ports wieder zu schliessen. Und wenn das wirklich so falsch eingerueckt ist beim TE, dann ist das natuerlich auch der Grund fuer Fehler beim lesen nach dem ersten mal.

Ggf. muss dbas OUTX0 nur einmal am Anfang in der main gemacht werden, dazu kenne ich das Protokoll jetzt nicht gut genug.

Re: SR830 Lock-in Amplifier

Verfasst: Freitag 27. August 2021, 15:59
von rogerb

Code: Alles auswählen

Wenn das wirklich so der Code ist, dann ist natuerlich das ser.close() auf der gleichen Ebene wie der Schleifencode ein Problem
Da der ursprüngliche Code nicht formatiert war, kann das auch meine Fehlinterpretation gewesen sein.

Re: SR830 Lock-in Amplifier

Verfasst: Freitag 27. August 2021, 16:06
von __deets__
rogerb hat geschrieben: Freitag 27. August 2021, 15:59 Da der ursprüngliche Code nicht formatiert war, kann das auch meine Fehlinterpretation gewesen sein.
Ich habe mir den mal mit meinen "Privilegien" im Editor angeschaut, da ist es tatsaechlich richtig(er). Das ist natuerlich fast schade, weil es dann ein einfach zu behebender Fehler waere.

Re: SR830 Lock-in Amplifier

Verfasst: Samstag 28. August 2021, 00:29
von __blackjack__
Privilegien braucht man dafür doch gar nicht, einfach auf „mit Zitat antworten“ klicken, dann kommt man auch als normaler Benutzer an den Quelltext des Beitrags mit den Einrückungen wie sie eingegeben wurden.