Problem 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
chris8
User
Beiträge: 6
Registriert: Mittwoch 15. Februar 2023, 16:51

Hallo zusammen,

hänge jetzt schon seit tagen an einem Problem wo ich nicht mehr weiter komme.
Ich habe mir ein Skript zur Steuerung eines Triac geschrieben welcher Serial angesprochen wird.
Soweit so gut.
Jetzt habe ich das Phänomen das das Skript in unregelmäßigen Abständen (mal 5 min oder 30min) hängen bleibt und die CPU auf 100 Prozent geht.
Ich kann es mit Strg+C noch abbrechen und das Skript durchläuft noch den except.

Also, es hängt immer am ser.write(serial.to_bytes(cw))
Als wenn pyserial ein Problem hätte.
Im Syslog usw konnte ich keine Fehler finden die auf Hardware deuten.


Hier ein Ausschnitt:

Code: Alles auswählen

        elif mqttwatt < -35 and Verbraucher == 1:
#            print("Start Verbraucher zum zweiten..")
#            print("Leistung:", mqttwatt)
#            print("Letzer Winkel:", angle)
            verbaktuell = wattinwinkel[angle]
#            print("Aktueller Verbrauch in Watt:", verbaktuell)
            while i <= 98:
                #watt_rechnung = mqttwatt - wattinwinkel[angle]
                watt_gesammt = mqttwatt - verbaktuell
                watt_rechnung = watt_gesammt + wattinwinkel[i]
                if watt_rechnung < -35:
                    i += 1
#                    print("Da geht noch was. Die zweite", i)

                if watt_rechnung >= -35 and watt_rechnung <= -15:
                    angle = i
                    cw = [255,0,129,angle]
                    print(cw)
                    time.sleep(0.5)
                    
                    
                    #########   Hier bleibt es mit 100% CPU Last hängen
                    
                    ser.write(serial.to_bytes(cw))

                    time.sleep(3)
                    break
                if i == 99:
                    print("Volle Pulle.")
                    cw = [255,0,129,99]
                    ser.write(serial.to_bytes(cw))
                    i = 98
                    time.sleep(3)
                    break
Gibt es noch einen anderen Weg ein Serial Device an zusprecht?
Ich würde es gern über os.system probieren. Da kommen ich mit der Hochkomma Aktion nicht weiter.

Code: Alles auswählen

import os
test = 'echo -en "\xFF\x00\x80\x00" > /dev/ttyUSB0'
os.system(test)
Ich hoffe ihr könnt mir helfen....

Gruß
Chris
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ueber os.system zu probieren ist quatsch. pyserial selbst ist nur eine sehr duenne schicht ueber die eigentlichen Systemaufrufe, hier write. Wenn das nicht klappt, klappt das auch nicht durch Dateiumleitung mit os.system. Das man eh nicht benutzen sollte. Sondern wen subprocess. Aber wie gesagt, das kann keinen Unterschied machen.

Das hier ist die Zeile in pyserial: https://github.com/pyserial/pyserial/bl ... ix.py#L628 - das ist ein simples write. Die timeout-Geschichten sehen eigentlich ok aus. Das du da wirklich 100% CPU in dem Call siehst, kann ich mir fast nicht vorstellen. Ich denke da ist eher was anderes faul.
chris8
User
Beiträge: 6
Registriert: Mittwoch 15. Februar 2023, 16:51

Ja, im erstem Moment könnte man denken das eine Schleife läuft.
Kann ich von der Ausführung eine Dump o. Trace ziehen?

Hatte es um die Hardware auszuschließen auch schon auf einer anderen Maschine laufen lassen.

Willst du das Script mal durchschauen?

Gruß
Chris
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ganze Skript kann nicht schaden. Und du kannst mal atrace laufen lassen, damit man mal sieht, ob’s da Muster gibt. Die logs umleiten und zb auf pastebin hochladen.
chris8
User
Beiträge: 6
Registriert: Mittwoch 15. Februar 2023, 16:51

Sorry, hatte in der Zwischenzeit noch was zu tun.

Habe mein Fehler gefunden. Mir geht eine Schleife durch. Kann aber nicht feststellen warum:


Hier der Trace:

Code: Alles auswählen

sunflower1.py(224):             while i <= 98:
sunflower1.py(225):                 print("while 1", i)
while 1 73
sunflower1.py(227):                 watt_gesammt = mqttwatt - verbaktuell
sunflower1.py(228):                 watt_rechnung = watt_gesammt + wattinwinkel[i]
sunflower1.py(229):                 if watt_rechnung < -35:
sunflower1.py(230):                     i += 1
sunflower1.py(233):                     print("IF 1", i)
IF 1 74
sunflower1.py(235):                 if watt_rechnung >= -35 and watt_rechnung <= -15:
sunflower1.py(247):                 if i == 99:
sunflower1.py(255):                 print("Schleifenzähler", i)
Schleifenzähler 74
sunflower1.py(224):             while i <= 98:
sunflower1.py(225):                 print("while 1", i)
while 1 74
sunflower1.py(227):                 watt_gesammt = mqttwatt - verbaktuell
sunflower1.py(228):                 watt_rechnung = watt_gesammt + wattinwinkel[i]
sunflower1.py(229):                 if watt_rechnung < -35:
sunflower1.py(230):                     i += 1
sunflower1.py(233):                     print("IF 1", i)
IF 1 75
sunflower1.py(235):                 if watt_rechnung >= -35 and watt_rechnung <= -15:
sunflower1.py(247):                 if i == 99:
sunflower1.py(255):                 print("Schleifenzähler", i)
Schleifenzähler 75
sunflower1.py(224):             while i <= 98:
sunflower1.py(225):                 print("while 1", i)
while 1 75
sunflower1.py(227):                 watt_gesammt = mqttwatt - verbaktuell
sunflower1.py(228):                 watt_rechnung = watt_gesammt + wattinwinkel[i]
sunflower1.py(229):                 if watt_rechnung < -35:
sunflower1.py(230):                     i += 1
sunflower1.py(233):                     print("IF 1", i)
IF 1 76
sunflower1.py(235):                 if watt_rechnung >= -35 and watt_rechnung <= -15:
sunflower1.py(247):                 if i == 99:
sunflower1.py(255):                 print("Schleifenzähler", i)
Schleifenzähler 76
sunflower1.py(224):             while i <= 98:
sunflower1.py(225):                 print("while 1", i)
while 1 76
sunflower1.py(227):                 watt_gesammt = mqttwatt - verbaktuell
sunflower1.py(228):                 watt_rechnung = watt_gesammt + wattinwinkel[i]
sunflower1.py(229):                 if watt_rechnung < -35:
sunflower1.py(230):                     i += 1
sunflower1.py(233):                     print("IF 1", i)
IF 1 77
sunflower1.py(235):                 if watt_rechnung >= -35 and watt_rechnung <= -15:
sunflower1.py(247):                 if i == 99:
sunflower1.py(255):                 print("Schleifenzähler", i)
Schleifenzähler 77
sunflower1.py(224):             while i <= 98:
sunflower1.py(225):                 print("while 1", i)
while 1 77
sunflower1.py(227):                 watt_gesammt = mqttwatt - verbaktuell
sunflower1.py(228):                 watt_rechnung = watt_gesammt + wattinwinkel[i]
sunflower1.py(229):                 if watt_rechnung < -35:
sunflower1.py(235):                 if watt_rechnung >= -35 and watt_rechnung <= -15:
sunflower1.py(247):                 if i == 99:
sunflower1.py(255):                 print("Schleifenzähler", i)
Schleifenzähler 77
sunflower1.py(224):             while i <= 98:
sunflower1.py(225):                 print("while 1", i)
while 1 77
sunflower1.py(227):                 watt_gesammt = mqttwatt - verbaktuell
sunflower1.py(228):                 watt_rechnung = watt_gesammt + wattinwinkel[i]
sunflower1.py(229):                 if watt_rechnung < -35:
sunflower1.py(235):                 if watt_rechnung >= -35 and watt_rechnung <= -15:
sunflower1.py(247):                 if i == 99:
sunflower1.py(255):                 print("Schleifenzähler", i)
Schleifenzähler 77
sunflower1.py(224):             while i <= 98:
sunflower1.py(225):                 print("while 1", i)
while 1 77
sunflower1.py(227):                 watt_gesammt = mqttwatt - verbaktuell
sunflower1.py(228):                 watt_rechnung = watt_gesammt + wattinwinkel[i]
sunflower1.py(229):                 if watt_rechnung < -35:
sunflower1.py(235):                 if watt_rechnung >= -35 and watt_rechnung <= -15:
sunflower1.py(247):                 if i == 99:
sunflower1.py(255):                 print("Schleifenzähler", i)
Schleifenzähler 77
sunflower1.py(224):             while i <= 98:
sunflower1.py(225):                 print("while 1", i)
while 1 77
sunflower1.py(227):                 watt_gesammt = mqttwatt - verbaktuell
sunflower1.py(228):                 watt_rechnung = watt_gesammt + wattinwinkel[i]
sunflower1.py(229):                 if watt_rechnung < -35:
sunflower1.py(235):                 if watt_rechnung >= -35 and watt_rechnung <= -15:
sunflower1.py(247):                 if i == 99:
sunflower1.py(255):                 print("Schleifenzähler", i)
Schleifenzähler 77
sunflower1.py(224):             while i <= 98:
sunflower1.py(225):                 print("while 1", i)
while 1 77
sunflower1.py(227):                 watt_gesammt = mqttwatt - verbaktuell
sunflower1.py(228):                 watt_rechnung = watt_gesammt + wattinwinkel[i]
sunflower1.py(229):                 if watt_rechnung < -35:
sunflower1.py(235):                 if watt_rechnung >= -35 and watt_rechnung <= -15:
sunflower1.py(247):                 if i == 99:
sunflower1.py(255):                 print("Schleifenzähler", i)
Schleifenzähler 77


Und hier der Scriptausschnitt:

Code: Alles auswählen

            while i <= 98:
                print("while 1", i)
                #watt_rechnung = mqttwatt - wattinwinkel[angle]
                watt_gesammt = mqttwatt - verbaktuell
                watt_rechnung = watt_gesammt + wattinwinkel[i]
                if watt_rechnung < -35:
                    i += 1
#                    print("Da geht noch was. Die zweite", i)
                    # time.sleep(0.2)
                    print("IF 1", i)

                if watt_rechnung >= -35 and watt_rechnung <= -15:
                    angle = i
                    cw = [255,0,129,angle]
                    print(cw)
                    time.sleep(0.5)
                    ser.write(serial.to_bytes(cw))

                    i = 255   ###################### Was ist das
                    time.sleep(3)
                    print("IF 2", i)
                    break
                    
                if i == 99:
                    print("Volle Pulle.")
                    cw = [255,0,129,99]
                    ser.write(serial.to_bytes(cw))
                    i = 98
                    time.sleep(3)
                    print("IF 3", i)
                    break
                print("Schleifenzähler", i)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Also das ist ziemlich gruselig, aber der entscheidende Punkt ist: mit pyserial hat es nichs zu tun. Die Logik ist einfach verquer, und tritt nicht ein in deine gewuenschte Bedingung. Also wird auch nix geschickt. Der Code muss eben richtig sein. Warum er das nicht ist, laesst sich aus dem Code nicht ersehen, weil er nicht vollstaendig ist. Was nur auffaellt: wenn das die gesamte Shcleife ist, dann gibt's da nichts, was watt_gesammt (mit einem m uebrigens) noch wattinwinkel veraendert, also kann da auch nichts passieren, ausser hoch zu zaehlen.
chris8
User
Beiträge: 6
Registriert: Mittwoch 15. Februar 2023, 16:51

Hier der volle Code:

Code: Alles auswählen

import requests 
import sys
import time
import os
import logging
import serial


### Variablen

Verbraucher  = 0


### Winkle des Triac mit Verbrauch
### Wir hier im Dictonary hinterlegt
wattinwinkel =  {1: 20,
                 2: 20,
                 3: 20,
                 4: 20,
                 5: 20,
                 6: 20,
                 7: 20,
                 8: 20,
                 9: 20,
                10: 20,
                11: 20,
                12: 20,
                13: 20,
                14: 20,
                15: 20,
                16: 20,
                17: 20,
                18: 20,
                19: 20,
                20: 20,
                21: 20,
                22: 20,
                23: 20,
                24: 20,
                25: 20,
                26: 20,
                27: 20,
                28: 20,
                29: 25,
                30: 25,
                31: 31,
                32: 32,
                33: 32,
                34: 39,
                35: 39,
                36: 39,
                37: 47,
                38: 47,
                39: 55,
                40: 55,
                41: 65,
                42: 65,
                43: 65,
                44: 75,
                45: 75,
                46: 75,
                47: 88,
                48: 88,
                49: 100,
                50: 100,
                51: 100,
                52: 116,
                53: 116,
                54: 130,
                55: 130,
                56: 130,
                57: 148,
                58: 148,
                59: 166,
                60: 166,
                61: 166,
                62: 186,
                63: 186,
                64: 186,
                65: 207,
                66: 207,
                67: 228,
                68: 228,
                69: 228,
                70: 250,
                71: 250,
                72: 274,
                73: 274,
                74: 274,
                75: 299,
                76: 299,
                77: 326,
                78: 326,
                79: 326,
                80: 352,
                81: 352,
                82: 383,
                83: 383,
                84: 383,
                85: 411,
                86: 411,
                87: 411,
                88: 446,
                89: 446,
                90: 478,
                91: 478,
                92: 478,
                93: 512,
                94: 512,
                95: 549,
                96: 549,
                97: 549,
                98: 582
                         }


###### Hier wird der Triac initialiesiert.
ser = serial.Serial(
        # Serial Port to read the data from
        #port='/dev/serial0',
        port='/dev/ttyUSB0',
 
        #Rate at which the information is shared to the communication channel
        baudrate = 9600,
   
        #Applying Parity Checking (none in this case)
        parity=serial.PARITY_NONE,
 
       # Pattern of Bits to be read
        stopbits=serial.STOPBITS_ONE,
     
        # Total number of bits to be read
        bytesize=serial.EIGHTBITS,
        write_timeout=1,
 
        # Number of serial commands to accept before timing out
        timeout=0
)


while True:
    i = 1
    
    ##############################################
    # Hier wird der vzlogger ausgelesen 
    param = requests.get('http://192.168.23.28:8081')
    # print(param.text)

    # Aufsplitten der Eingabe in Listen damit gepased werden kann
    Textsplit = param.text.split()

    #for a in Textsplit:
    #    count += 1
    #    print(a)
    #    print(count)

    # Umstellung von String auf Float

    Leistung = round(float(Textsplit[54]))
    mqttwatt = Leistung
    print(mqttwatt)
    ##############################################

#    try:
        # Hier wird zum erstem mal gestartet. Es muss mehr als 35 Watt übrig sein.
    if mqttwatt < -35 and Verbraucher == 0:
#            print("Start Verbrauchen zum ersten...")
#            print(mqttwatt)
            while i <= 98:
                watt_rechnung = mqttwatt + wattinwinkel[i]
                if watt_rechnung < -35:
#                    print("Da geht noch was", i)
                    i += 1
                    
                if watt_rechnung >= -35 and watt_rechnung <= -15:
                    angle = i
                    #####################################
                    cw = [255,0,129,angle]
                    time.sleep(0.5)
                    ser.write(serial.to_bytes(cw))
                    
                    ######################################
                    Verbraucher = 1
                    time.sleep(3)
                    break
                if i == 99:
                    print("Volle Pulle.")
                    Verbraucher = 1
                    cw = [255,0,129,98]
                    ser.write(serial.to_bytes(cw))
                    angle = 98
                    break

    elif mqttwatt < -36 and Verbraucher == 1:
#            print("Start Verbraucher zum zweiten..")
#            print("Leistung:", mqttwatt)
#            print("Letzer Winkel:", angle)
            verbaktuell = wattinwinkel[angle]
#            print("Aktueller Verbrauch in Watt:", verbaktuell)
            while i <= 98:
                print("while 1", i)
                #watt_rechnung = mqttwatt - wattinwinkel[angle]
                watt_gesammt = mqttwatt - verbaktuell
                watt_rechnung = watt_gesammt + wattinwinkel[i]
                if watt_rechnung < -35:
                    i += 1
#                    print("Da geht noch was. Die zweite", i)
                    # time.sleep(0.2)
                    print("IF 1", i)

                if watt_rechnung >= -35 and watt_rechnung <= -15:
                    angle = i
                    cw = [255,0,129,angle]
                    print(cw)
                    time.sleep(0.5)
                    ser.write(serial.to_bytes(cw))

                    i = 255   ###################### Was ist das
                    time.sleep(3)
                    print("IF 2", i)
                    break
                    
                if i == 99:
                    print("Volle Pulle.")
                    cw = [255,0,129,99]
                    ser.write(serial.to_bytes(cw))
                    i = 98
                    time.sleep(3)
                    print("IF 3", i)
                    break
                print("Schleifenzähler", i)


    elif mqttwatt >= -35 and Verbraucher == 1:
#            print("Verbraucher regulierung nach unten...")
#            print("Leistung:", mqttwatt)
#            print("Letzer Winkel:", angle)
            verbaktuell = wattinwinkel[angle]
#            print("Aktueller Verbrauch in Watt:", verbaktuell)
            i = 98
            while i >= 1:
                watt_gesammt = mqttwatt - verbaktuell
                watt_rechnung = watt_gesammt + wattinwinkel[i]
                #print(watt_rechnung)
                if watt_rechnung > -40:
                    print("Winkel runter", i)
                    i -= 1
                if watt_rechnung <= -40:
                    angle = i
                    cw = [255,0,129,angle]
                    time.sleep(0.5)
                    ser.write(serial.to_bytes(cw))

                    i = 0
                    time.sleep(3)
                    break
                if i == 0:
                    print("Verbraucher auf 0. im else")
                    cw = [255,0,129,0]
                    ser.write(serial.to_bytes(cw))
                    Verbraucher = 0
                    break
    time.sleep(1)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist viel zu konfus, mit globalem Zustand, und sehr sehr kompliziert ausgedrueckt. Es gibt da auch in meinen Augen ungueltige Programmzustaende: wenn der Verbraucher aus ist, aber mqttwatt < -36, kann es sein, dass es die Variable angle noch ueberhaupt nicht gibt.

Das muss deutlich aufgeraumt werden, und dazu wuerde ich dich mal bitten zu erklaeren, was da eigentlich warum passieren soll.

Um es aber auch nochmal klar zu sagen: dein Problem ist *nicht* pyserial. Die Logik ist verquer.
Antworten