Ich habe Probleme mit pyserial

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
askhille
User
Beiträge: 7
Registriert: Freitag 3. März 2006, 13:34

Hallo,

ich habe folgendes Problem:

ich möchte ein Siemens LOGO! (Kleinsteuerung) von Python aus steuern und Werte auslesen.

Ich habe hierzu die Original Siemens Software mit einem Portmonitor "belauscht" und
die Steuercodes notiert. Mit einem Terminalprogramm funktioniert die Verbindung zur LOGO einwandfrei.

Ich habe pyserial installiert um auf die RS232 zuzugreifen.

Folgendes kleines Testprogramm habe ich geschrieben.

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

ser = serial.Serial(0, 9600, timeout=1, parity=seria.PARITY_EVEN)

# Logo Status

ser.write(str(02))
ser.write(str(1F))
ser.write(str(02))
print ser.read(5)

ser.write(str(0x55))
ser.write(str(0x23))
ser.write(str(0x23))
ser.write(str(0xAA))
print ser.read(2)

ser.close()
###########################################################

Mit dem Portmonitor habe ich dann beobachtet, das die Hex Zahlenwerte in ASCII Werte umgewandelt werden (Durch den Befehl write ?).

Meine Frage:
Wie gelingt es mir, HEX Zahlenwerte, die außerhalb des ASCII Code liegen,
über die Schnittstelle zu bekommen.
Ich bin Programmieranfänger und habe bisher nur Kleinigkeiten mit VB6
realisiert.

MfG

Achim
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

askhille hat geschrieben:Mit dem Portmonitor habe ich dann beobachtet, das die Hex Zahlenwerte in ASCII Werte umgewandelt werden (Durch den Befehl write?).
Hi Achim!

Nein, nicht durch "write()" sondern durch "str()".

Versuchs mal mit "chr(0x02)" und Hex-Zahlen müssen in Python immer mit "0x" beginnen.

Vielleicht hilft dir das ja schon.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BlackJack

askhille hat geschrieben:

Code: Alles auswählen

import serial

ser = serial.Serial(0, 9600, timeout=1, parity=seria.PARITY_EVEN)

# Logo Status

ser.write(str(02))
ser.write(str(1F))
ser.write(str(02))
print ser.read(5)

ser.write(str(0x55))
ser.write(str(0x23))
ser.write(str(0x23))
ser.write(str(0xAA))
print ser.read(2)

ser.close()
Meine Frage:
Wie gelingt es mir, HEX Zahlenwerte, die außerhalb des ASCII Code liegen, über die Schnittstelle zu bekommen.
Man kann Hex-Zeichen auch in literalen Zeichenketten angeben wenn man ein '\x' voranstellt:

Code: Alles auswählen

import serial

ser = serial.Serial(0, 9600, timeout=1, parity=serial.PARITY_EVEN)

# Logo Status

ser.write('\x02\x1f\x02')
print ser.read(5)

ser.write('\x55\x23\x23\xaa')
print ser.read(2)

ser.close()
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

askhille hat geschrieben:Hallo,

ich habe folgendes Problem:

ich möchte ein Siemens LOGO! (Kleinsteuerung) von Python aus steuern und Werte auslesen.

Ich habe hierzu die Original Siemens Software mit einem Portmonitor "belauscht" und
die Steuercodes notiert. Mit einem Terminalprogramm funktioniert die Verbindung zur LOGO einwandfrei.

Ich habe pyserial installiert um auf die RS232 zuzugreifen.

Folgendes kleines Testprogramm habe ich geschrieben.

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

ser = serial.Serial(0, 9600, timeout=1, parity=seria.PARITY_EVEN)

# Logo Status

ser.write(str(02))
ser.write(str(1F))
ser.write(str(02))
print ser.read(5)

ser.write(str(0x55))
ser.write(str(0x23))
ser.write(str(0x23))
ser.write(str(0xAA))
print ser.read(2)

ser.close()
###########################################################

Mit dem Portmonitor habe ich dann beobachtet, das die Hex Zahlenwerte in ASCII Werte umgewandelt werden (Durch den Befehl write ?).

Meine Frage:
Wie gelingt es mir, HEX Zahlenwerte, die außerhalb des ASCII Code liegen,
über die Schnittstelle zu bekommen.
Ich bin Programmieranfänger und habe bisher nur Kleinigkeiten mit VB6
realisiert.

MfG

Achim

Du könntest es so machen :
(wie die anderen schon erklärt haben )

Code: Alles auswählen

ser.write(0x02)
ser.write(0x1F)
ser.write(0x02)
BlackJack

Mad-Marty hat geschrieben: Du könntest es so machen :
(wie die anderen schon erklärt haben )

Code: Alles auswählen

ser.write(0x02)
ser.write(0x1F)
ser.write(0x02)
`write()` erwartet Zeichenketten, Du gibst da Zahlen an. Dat jeht nich.
askhille
User
Beiträge: 7
Registriert: Freitag 3. März 2006, 13:34

Hallo,

vielen Dank für die Hilfe, die Übertragung zur LOGO hat funktioniert.

Wie verarbeite ich die Steuercodes, die von der Logo zurückkommen.

Code: Alles auswählen

def Logo_Stop():

    ser.write('\x55\x17\x17\xAA') #Logo Status
    status1 = ser.read(2)

    a = repr(status1)
    
    c = string.replace(a,'\\x',"")
    
    print c
    
    if c == ("\'1504\'")or c == ("\'1505\'"):
        print "LOGO ist im Stop Mode"
    
    if c == ("\' \'"):
        print "LOGO ist im Run Mode"
        
    ser.close()
ich bekomme den Wert der Logo über ser.read in die Variable status1.
Dort erhalte ich einen String mit Hex Wert + 1fache Anführungszeichen.
Das x vom Hexwert bekomme ich mit replace weg, die Anführungszeichen nicht.

die Zeile if c == ("\'1504\''") muß doch auch anders zu lösen sein.

Im Idealfall hätte ich einen reinen Zahlenwert zum weiterverarbeiten,
krieges es aber einfach nicht hin.

Welches Einsteigerbuch könnt ihr mir empfehlen. Die Python Kurse im
Internet helfen auch nur bedingt weiter. Ich weiß nicht, warum ich mich mit dieser Sprache so schwer tue. Aber ich muß es mit Python programmieren, damit es nacher als cgi script auf meinem Webserver läuft.



Gruß

Achim

Edit (BlackJack): Code in Python-Tags gesetzt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

...bitte schreibe Code in "code"-Tags. Siehe Codehighlighting.
Du kannst deinen Beitrag ändern, indem du auf den "Edit"-Button klickst.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BlackJack

askhille hat geschrieben:

Code: Alles auswählen

def Logo_Stop():

    ser.write('\x55\x17\x17\xAA') #Logo Status
    status1 = ser.read(2)

    a = repr(status1)
    
    c = string.replace(a,'\\x',"")
    
    print c
    
    if c == ("\'1504\'")or c == ("\'1505\'"):
        print "LOGO ist im Stop Mode"
    
    if c == ("\' \'"):
        print "LOGO ist im Run Mode"
        
    ser.close()
ich bekomme den Wert der Logo über ser.read in die Variable status1.
Dort erhalte ich einen String mit Hex Wert + 1fache Anführungszeichen.
Das x vom Hexwert bekomme ich mit replace weg, die Anführungszeichen nicht.

Du bekommst in `status1` keine Zeichenkette mit Anführungszeichen zurück und auch keinen Hexwert sondern eine Zeichenkette oder besser gesagt eine Bytekette mit Werten die sich nicht als ASCII-Zeichen darstellen lassen. Beispiel:

Code: Alles auswählen

In [5]:status = '\x15\x04'

In [6]:print status


In [7]:print repr(status)
'\x15\x04'

In [8]:len(status)
Out[8]:2
Wie man sieht gibt ``print`` "nichts" aus. Von `repr()` bekommt man eine Representation der Zeichenkette in der nicht druckbare Zeichen als Hexadezimale Escape-Sequenz dargestellt werden. `len()` zeigt aber, das es sich nicht um eine Zeichenkette mit 10 Zeichen sondern nur um zwei Zeichen bzw. Bytes handelt.
die Zeile if c == ("\'1504\''") muß doch auch anders zu lösen sein.
Ja klar:

Code: Alles auswählen

if status in ('\x15\x04', '\x15\x05'):
        print "LOGO ist im Stop Mode"
    
    if status == '\x20':
        print "LOGO ist im Run Mode"
Im Idealfall hätte ich einen reinen Zahlenwert zum weiterverarbeiten,
krieges es aber einfach nicht hin.
Den Wert eines einzelnen Zeichens bekommst Du mit der `ord()` Funktion. Wenn Du längere Zeichenketten zerlegen willst, die mehrere Zahlen enthalten, dann ist das `struct` Modul angesagt.
askhille
User
Beiträge: 7
Registriert: Freitag 3. März 2006, 13:34

wieder ein Problem, diesmal mit Tk

Ich möchte die Logo mit Hilfe von Tkinter (1 Button Start, 1 Button Stop)
bedienen.

Hier das Programm

Code: Alles auswählen

import serial
import string


def Logo_Start():

    ser = serial.Serial(0, 9600, timeout=1, parity=serial.PARITY_EVEN)
    ser.write('\x55\x17\x17\xAA') #Logo Status
    status = ser.read(2)
    a = repr(status)

    byte1 = a[3:5]
    byte2 = a[7:9]

    print byte1, byte2
    ser.write('\x55\x18\x18\xAA') #Logo START
    status = ser.read(2)
    ser.close()

def Logo_Stop():

    ser = serial.Serial(0, 9600, timeout=1, parity=serial.PARITY_EVEN)
    ser.write('\x55\x17\x17\xAA') #Logo Status
    status = ser.read(2)
    a = repr(status)

    byte1 = a[3:5]
    byte2 = a[7:9]

    print byte1, byte2
    ser.write('\x55\x12\x12\xAA') #Logo STOP
    status = ser.read(2)
    ser.close()


from Tkinter import *

master=Tk()
b=Button(master, text='LOGO Run', command=Logo_Start())
b.pack()
c=Button(master, text='LOGO Stop', command=Logo_Stop())
c.pack()

master.mainloop()

Ohne Tkinter funktioniert das Programm einwandfrei:
Aufruf Logo_Start() --> Logo geht in Run
Aufruf Logo_Stop() --> Logo Stopt.

Mit Tkinter wird (habe ich mit dem Portmonitor beobachtet)
sofort bei Programmstart
1. command=Logo_Start()
2. command=Logo_Stop()
aufgerufen, und das ohne einen Button angeklickt zu haben !

Die Buttons kann ich danach anklicken, es werden keine
Daten über die RS232 gesendet. Das Programm hängt irgendwie ?

Bitte um Hilfe


Gruß

Achim
Antworten