Hallo in die Runde,
ich bin neu hier, und eigentlich auch neu im Thema Python, aber ein paar Snipsel laufen doch.
Mein Problem:
Ich habe Code vom Notebook auf eine Ordid C4 / Ubuntu portiert und alles ist sehr seltsam.
Auf einem anderen C4 laufen die Progs schon, aber nicht auf dem "Neuen"
C4-Neu:
Python 3.10.12
pymodbus 3.11.3
Auf meinem Notebook:
Python 3.8.12
pymodbus 3.0.2
Auf dem Notebook , unter eclipse , läuft es wie erwartet.
Was ich beim Port auf den C4 machen muste: in den pymodbuscall: unit= durch device_id= ersetzen, ansonsten bekam ich immer eine Exception.
Aber das wird scheinbar nicht richtig verarbeitet.
Daher habe ich "versucht" das Logging der RTU Connection einzuschalten.
Obwohl der Code auf dem Nodebook incl. einen verständlichem Logging läuft, bekomme ich ich auf dem C4 für read_holding_registers gar kein Logging. Wieso ?
Und für client.write_register:
2025-11-23 20:16:22,301 MainThread DEBUG base :72 Processing: 0xc9 0x6 0x0 0xc 0x0 0x0 0x59 0x81
2025-11-23 20:16:22,302 MainThread DEBUG decoders :79 decoded PDU function_code(6 sub -1) -> WriteSingleRegisterResponse(dev_id=0, transaction_id=0, address=12, count=0, bits
Wobei in der ersten Zeile die Adresse noch richtig geloggt wird. In der zweiten Zeile ist die Adresse "0" -- Verstehe ich nicht!
Hier der Code: des write:
def qxdo24_setDuty ( client, io, wert ):
lunit = int(config_tempctl.ADDR_QXDO24)
val = int(wert * 10)
reg = 0x0
reg += io -1
print( "Set Unit= " + str(lunit) + " Reg: " + str(reg) + " Val: " + str(val) )
client.write_register(reg, val, device_id=lunit)
return()
Das Main sieht aus wie folgt:
#!/usr/bin/env python3
# coding=utf-8
from pymodbus.client import ModbusSerialClient as ModbusClient
from qxdo24 import qxdo24_readConfig1, qxdo24_setAddr, qxdo24_setDuty, qxdo24_setFreq, qxdo24_setCtrl
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s '
'%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
print ( "Vorr RTU Connection" )
baudrate = 9600
client = ModbusClient(
# method = 'rtu'
#,
port=config_tempctl.port
,baudrate=baudrate
,parity = 'N'
,bytesize = 8
,stopbits = 1
,timeout=2
# war 2 Sek
)
connection = client.connect()
if connection is None:
print ( "Fehler RTU Connection" )
log_msg( "E","0", "0", "Fehler RTU Connect" )
exit ()
if connection == False:
print ( "Fehler RTU Connection" )
log_msg( "E","0", "0", "Fehler RTU Connect" )
exit ()
print ( "Nach RTU Connection" )
config_tempctl.client = client
#QX-DO24 PWM Outout
qxdo24_readConfig1 ( config_tempctl.client )
# qxdo24_setAddr ( config_tempctl.client )
qxdo24_setDuty ( config_tempctl.client , 1, 0 )
Soweit die Fragmente
Meine Fragen:
Wieso verhält sich das Logging so anders?
Und wie übergebe ich unter 3.11.3 die Adresse den nun richtig ?
Ich weiss, das der Write keine Fehlerbearbeitung hat........
Für mich sieht es aus, als wenn hier Versionen massiv NICHT zusammen passen.
Aber wie erkennen ...und dann beheben.
Vielen Dank für jeden Hinweis
JR
pymodbus 3.11.3 Logging der RTU Frames / Änderungen zu 3.02
- __blackjack__
- User
- Beiträge: 14230
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Das Modul hat eine Dokumentation die unter anderem einen „API changes“-Abschnitt enthält. Wo man auch sieht wie verdammt weit die beiden Versionen bei Dir auseinander sind.
Anmerkungen zum Quelltext: Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).
Man schreibt nicht den Modulnamen als Prefix für alle Funktionen. Das Modul ist doch schon der Namensraum. Es macht keinen Sinn diese Information noch mal zu wiederholen.
Namen sollten keine kryptischen Pre- oder Postfixe enthalten. Und auch keine angehängten nichtssagenden Nummern.
Es wird in dem bisschen Code `logging`, `print()`, *und* dann auch noch eine `log_msg()`-Funktion verwendet.
Auf Modulebene sollte nur Code stehen, der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
`ModbusClient`-Objekte sind Kontextmanager, die sollte man mit der ``with``-Anweisung verwenden.
`connection` wäre ein Name für eine Verbindung, nicht für einen Wahrheitswert. Der auch nicht `None` werden kann. Selbst wenn er es könnte machen die *zwei* Prüfungen die dann jeweils den gleichen Code im ``if``-Zweig stehen haben keinen Sinn. Das ist einfach ``if not client.connect():``.
Wurde `exit()` explizit aus dem `sys`-Modul importiert? Denn sonst verlässt man sich auf eine andere Funktion die so heisst und die es nicht zwingend ”einfach so” geben muss. Zudem sollte man da auch einen Rückgabecode angeben, denn *das* ist der Zweck dieser Funktion. Sonst hätte man nämlich die Hauptfunktion an der Stelle auch einfach per ``return`` verlassen können.
Der Client sollte nicht als globale Variable im Konfigurationsmodul gesetzt werden!
Bei der `set_duty()`-Funktion herrscht ziemliches Namenschaos. Im Konfigurationsmodul heisst das was an `lunit` gebunden wird `ADDR_*`, ist aber gar keine Adresse, das ist `reg`, und wird als `device_id` übergeben. Und `value` auszuschreiben bringt einen auch nicht um. Was auch immer das `l` in `lunit` bedeuten soll. `reg` wird auch komisch gebildet. Klar kann man was auf 0 addieren. Man kann aber auch einfach gleich den Wert zuweisen den man da addiert.
Eine Funktion die Grundsätzlich ein leeres Tupel zurück gibt, mit dem der Aufrufer dann auch überhaupt gar nichts anfängt, macht keinen Sinn.
Die `set_duty()`-Funktion würde eher so aussehen:
Und das Hauptprogramm so:
Anmerkungen zum Quelltext: Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).
Man schreibt nicht den Modulnamen als Prefix für alle Funktionen. Das Modul ist doch schon der Namensraum. Es macht keinen Sinn diese Information noch mal zu wiederholen.
Namen sollten keine kryptischen Pre- oder Postfixe enthalten. Und auch keine angehängten nichtssagenden Nummern.
Es wird in dem bisschen Code `logging`, `print()`, *und* dann auch noch eine `log_msg()`-Funktion verwendet.
Auf Modulebene sollte nur Code stehen, der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
`ModbusClient`-Objekte sind Kontextmanager, die sollte man mit der ``with``-Anweisung verwenden.
`connection` wäre ein Name für eine Verbindung, nicht für einen Wahrheitswert. Der auch nicht `None` werden kann. Selbst wenn er es könnte machen die *zwei* Prüfungen die dann jeweils den gleichen Code im ``if``-Zweig stehen haben keinen Sinn. Das ist einfach ``if not client.connect():``.
Wurde `exit()` explizit aus dem `sys`-Modul importiert? Denn sonst verlässt man sich auf eine andere Funktion die so heisst und die es nicht zwingend ”einfach so” geben muss. Zudem sollte man da auch einen Rückgabecode angeben, denn *das* ist der Zweck dieser Funktion. Sonst hätte man nämlich die Hauptfunktion an der Stelle auch einfach per ``return`` verlassen können.
Der Client sollte nicht als globale Variable im Konfigurationsmodul gesetzt werden!
Bei der `set_duty()`-Funktion herrscht ziemliches Namenschaos. Im Konfigurationsmodul heisst das was an `lunit` gebunden wird `ADDR_*`, ist aber gar keine Adresse, das ist `reg`, und wird als `device_id` übergeben. Und `value` auszuschreiben bringt einen auch nicht um. Was auch immer das `l` in `lunit` bedeuten soll. `reg` wird auch komisch gebildet. Klar kann man was auf 0 addieren. Man kann aber auch einfach gleich den Wert zuweisen den man da addiert.
Eine Funktion die Grundsätzlich ein leeres Tupel zurück gibt, mit dem der Aufrufer dann auch überhaupt gar nichts anfängt, macht keinen Sinn.
Die `set_duty()`-Funktion würde eher so aussehen:
Code: Alles auswählen
def set_duty(client, io, value):
address = io - 1
value = int(value * 10)
device_id = config.ADDR_QXDO24
log.debug("Set Unit=%r Reg: %r Val: %r", device_id, address, value)
client.write_register(address, value, device_id=device_id)Code: Alles auswählen
#!/usr/bin/env python3
import logging
import sys
import config
import qxdo24
from pymodbus.client import ModbusSerialClient as ModbusClient
BAUDRATE = 9600
logging.basicConfig(
format=(
"%(asctime)-15s %(threadName)-15s "
"%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s"
)
)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
def main():
log.debug("Vor RTU Connection")
with ModbusClient(
port=config.PORT,
baudrate=BAUDRATE,
parity="N",
bytesize=8,
stopbits=1,
timeout=2,
) as client:
if not client.connect():
log.fatal("Fehler RTU Connection")
sys.exit(1)
log.debug("Nach RTU Connection")
qxdo24.read_config(client)
# qxdo24.set_addr(client)
qxdo24.set_duty(client, 1, 0)
if __name__ == "__main__":
main()“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002
Hallo _blackjock_
Danke für die Hinweise.
Werde das Prog. überarbeiten, bzw Deine Korrekturen übernehmen.
Das Prog. ist nunmehr schon ziemlich verbastelt, weil ich auch versuchte, den Fehler einzugrenzen.
Zum Thema Modbus:
Ok, die Vers. liegen auseinder.
Die API Docu habe ich gelesen .
Da habe ich ja auch die "devide_id " Änderung her
Was mich so ersaunt: Das der Code mit dem 3.1 nicht mehr läuft und das ohne , für mich, erkennbaren Grund.
Ich habe doch ...nur .. das OS geupdated.
Da hätte ich mehr erwartet, auch in den Change.logs
der Lesebefehl wird gar nicht mehr geloggt
Der Schreibbefehl erzeugt nur noch 2 Zeilen, statt den gewohnten 10-15 Zeilen.
Und dann in den Zeilen ist die Ausgabe mehr als verwirrend:
2025-11-23 20:16:22,301 MainThread DEBUG base :72 Processing: 0xc9 0x6 0x0 0xc 0x0 0x0 0x59 0x81
2025-11-23 20:16:22,302 MainThread DEBUG decoders :79 decoded PDU function_code(6 sub -1) -> WriteSingleRegisterResponse(dev_id=0, transaction_id=0, address=12, count=0, bits
In der ersten Zeile ist die Client Adresse mit 0xc9 erkennbar
in der zweiten Zeile ist dann "(dev_id=0, " Das widerspricht sich enorm. Aber so strubbelig kann doch die pymodbus nicht sein! Das kann ich mir nicht vorstellen !!!!
Ich bin ziemlich "verwirrt" ganz vorsichtig ausgedrückt
Hat schon jemand Erfahrung mit der pymodbus 3.11.3
Für mich sieht es aus, als wenn die Debug Lines etwas anderes als RTU verarbeiten wollen ...?
Danke für jeden Hinweis
JR
Danke für die Hinweise.
Werde das Prog. überarbeiten, bzw Deine Korrekturen übernehmen.
Das Prog. ist nunmehr schon ziemlich verbastelt, weil ich auch versuchte, den Fehler einzugrenzen.
Zum Thema Modbus:
Ok, die Vers. liegen auseinder.
Die API Docu habe ich gelesen .
Da habe ich ja auch die "devide_id " Änderung her
Was mich so ersaunt: Das der Code mit dem 3.1 nicht mehr läuft und das ohne , für mich, erkennbaren Grund.
Ich habe doch ...nur .. das OS geupdated.
Da hätte ich mehr erwartet, auch in den Change.logs
der Lesebefehl wird gar nicht mehr geloggt
Der Schreibbefehl erzeugt nur noch 2 Zeilen, statt den gewohnten 10-15 Zeilen.
Und dann in den Zeilen ist die Ausgabe mehr als verwirrend:
2025-11-23 20:16:22,301 MainThread DEBUG base :72 Processing: 0xc9 0x6 0x0 0xc 0x0 0x0 0x59 0x81
2025-11-23 20:16:22,302 MainThread DEBUG decoders :79 decoded PDU function_code(6 sub -1) -> WriteSingleRegisterResponse(dev_id=0, transaction_id=0, address=12, count=0, bits
In der ersten Zeile ist die Client Adresse mit 0xc9 erkennbar
in der zweiten Zeile ist dann "(dev_id=0, " Das widerspricht sich enorm. Aber so strubbelig kann doch die pymodbus nicht sein! Das kann ich mir nicht vorstellen !!!!
Ich bin ziemlich "verwirrt" ganz vorsichtig ausgedrückt
Hat schon jemand Erfahrung mit der pymodbus 3.11.3
Für mich sieht es aus, als wenn die Debug Lines etwas anderes als RTU verarbeiten wollen ...?
Danke für jeden Hinweis
JR
- __blackjack__
- User
- Beiträge: 14230
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@jr1: Bei der langen Liste an Änderungen zwischen den Bibliotheksversionen wundert mich nicht dass man da was umschreiben muss. Die haben da einiges geändert in den grob 11 Versionen mit API-Änderungen, die dazwischen liegen. Die haben da ja streckenweise in den letzten 3 Jahren monatlich eine Version mit API-Änderungen raus gehauen.
Hast Du das Logging für `pymodbus` denn konfiguriert? Vielleicht waren denen oder den Nutzern das früher auch einfach zu viele Logausgaben.
Hast Du das Logging für `pymodbus` denn konfiguriert? Vielleicht waren denen oder den Nutzern das früher auch einfach zu viele Logausgaben.
“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002
