Modbus mit minimalmodbus

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
puba
User
Beiträge: 13
Registriert: Dienstag 22. Juli 2008, 18:53

hallo,
ich versuche mit dem Modul minimalmodbus.py aus einem Messgerät Werte zu lesen.
Dazu gibt es auch gute Dokumentationen unter:
http://minimalmodbus.sourceforge.net/index.html
Leider bekomme ich keine Verbindung mit dem Beispielscript:

Code: Alles auswählen

#!/usr/bin/env python
import minimalmodbus

instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 10) # port name, slave address (in decimal)

## Read temperature (PV = ProcessValue) ##
drehzahl = instrument.read_register(17696, 1) # Registernumber, number of decimals
print drehzahl

## Change temperature setpoint (SP) ##
#NEW_TEMPERATURE = 95
#instrument.write_register(24, NEW_TEMPERATURE, 1) # Registernumber, value, number of decimals for storage
weil die Baudrate standardgemäß auf 19800 steht und die Parität auf NO

Für meine Anwendung benötige ich
BAUDRATE: 38000
PARYTY: EVEN

Setze ich nun nach der Zeile --> import minimalmodbus

Code: Alles auswählen

instrument.serial.baudrate = 38000   # Baud
instrument.serial.parity   = serial.PARITY_EVEN
so bekomme ich die Fehlermeldung, dass "instrument nicht erkannt wird"

setze ich diese Zeilen nach der Zeile
--> instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 10)

so bekomme ich als Fehlermeldung, dass die BAUDRATE nicht geändert werden kann

Weiss jemand wass ich hier falsch mache?

Gruß
Armin
puba
User
Beiträge: 13
Registriert: Dienstag 22. Juli 2008, 18:53

Hallo, einen Teilerfog konnte ich erreichen.
Das setzen der Baudrate muss natürelich wie folgt erfolgen:

Code: Alles auswählen

instrument.serial.baudrate = 38400   # Baud
Denn 38000 ist nicht definiert :idea:

Und richtiger Weiese nach der Zeile:

Code: Alles auswählen

instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 10)

Aber beim setzen der Parität -- gemäß Dokumentationen
mit

Code: Alles auswählen

instrument.serial.parity = serial.PARITY_EVEN
bekomme ich immer folgender Fehlermeldung:
-----------
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
instrument.serial.parity = serial.PARITY_EVEN
NameError: name 'serial' is not defined
------------

Kann hier jemand helfen?

Gruß
Armin
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@puba
Bevor Du 'PARITY_EVEN' aus dem 'serial'-Modul verwenden kannst, musst Du natürlich erst einen import des 'serial'-Moduls machen.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
puba
User
Beiträge: 13
Registriert: Dienstag 22. Juli 2008, 18:53

@mutetella

o.k. - danke für den Hinweis, so hat es geklappt.
Ich hatte angenommen, dass 'serial' mir zur Verfügung steht, da es bereits von 'minimalmodbus' mit importiert wird.
Da ich es aber als Wertzuweisenug noch mals verwende, ist das auch einleuchtend.

Danke
Armin
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

puba hat geschrieben:Ich hatte angenommen, dass 'serial' mir zur Verfügung steht, da es bereits von 'minimalmodbus' mit importiert wird.
Deine Annahme ist auch korrekt. Wenn 'serial' innerhalb des 'minimalmodbus' importiert wird, dann steht es auch innerhalb des Namensraumes von 'minimalmodbus' zur Verfügung. Aber eben nicht außerhalb.
puba hat geschrieben:Da ich es aber als Wertzuweisenug noch mals verwende, ist das auch einleuchtend.
Ich bin mir nicht sicher, ob ich Dich richtig verstehe...
Wenn Du einen Wert aus einem Modul irgendwo zuweist, dann heisst das nicht, dass dieser Wert danach nicht mehr existieren würde. Im Sinne eines "Einwegobjektes"...
Anstatt 'serial' in den Namensraum, in dem die Zuweisung stattfindet, zu importieren könntest Du 'PARITY_EVEN' auch über

Code: Alles auswählen

instrument.serial.parity = minimalmodbus.serial.PARITY_EVEN
erreichen.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
puba
User
Beiträge: 13
Registriert: Dienstag 22. Juli 2008, 18:53

@mutetella
Danke für deine Hilfe. Da war meine obige Interpretation nicht richtig.
Dank deiner Erklärung habe ich es jetzt verstanden.
Und es klappt auch gut.

Gruß
Armin
pybus
User
Beiträge: 6
Registriert: Montag 8. September 2014, 16:32

Hallo zusammen, da meine Frage in die gleiche Richtung geht, knüpfe ich mal an das Thema an. Ich möchte gerne einen Temperatursensor über Modbus auslesen. Zur Verfügung steht ein RS485 -> USB Adapter (http://www.dx.com/de/p/usb-to-rs485-ada ... A3QChDN3YQ), genutzt wird ein Windows-System. Der Sensor hat standardmäßig folgende Einstellungen:
Slave Adresse: 1
Baudrate: 19200
keine Parität
2 Stoppbits
Der Temperaturwert befindet sich in Register 2, Länge 2 Wörter. Function Code müsste 4 für read input register sein. Nach Anschließen des USB Sticks erscheint er als COM-Port15. Folgendes Skript habe ich aus dem Tutorial zusammengestellt:

Code: Alles auswählen

import minimalmodbus
import serial

instrument = minimalmodbus.Instrument('COM15', 1) # port name, slave address (in decimal)
instrument.serial.stopbits = 2 # aendern der stopbits
instrument.debug = True
temperature = instrument.read_register(2, 2) # Registernumber, number of decimals
print (temperature)
Mit dem aktivierten Debuging ergibt sich folgende Meldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Python33\Lib\site-packages\test.py", line 79, in <module>
    temperature = instrument.read_register(2, 2) # Registernumber, number of decimals
  File "C:\Python33\Lib\site-packages\minimalmodbus.py", line 254, in read_register
    return self._genericCommand(functioncode, registeraddress, numberOfDecimals=numberOfDecimals, signed=signed)
  File "C:\Python33\Lib\site-packages\minimalmodbus.py", line 693, in _genericCommand
    payloadFromSlave = self._performCommand(functioncode, payloadToSlave)
  File "C:\Python33\Lib\site-packages\minimalmodbus.py", line 791, in _performCommand
    response = self._communicate(message, number_of_bytes_to_read)
  File "C:\Python33\Lib\site-packages\minimalmodbus.py", line 848, in _communicate
    format(number_of_bytes_to_read, message))
ValueError: zero length field name in format
Leider werd ich daraus nicht wirklich schlau. Den COM-Port habe ich auch schon über den Geräte Manager mit den Parametern belegt. Kann mir jemand auf die Sprünge helfen?

Vielen Dank und liebe Grüße

edit: Danke fürs Setzen des Quelltextes in Python Code. Ein Fehler ist mir selbst grade aufgefallen: Ich habe das Skript mit der 2.7 Version von Python ausgeführt. Wechsel ich in die Konsole und führe das ganze mit Python 3.3 aus, kommt die folgende Meldung:
Traceback (most recent call last):
File "C:\Python33\Lib\site-packages\test.py", line 76, in <module>
instrument = minimalmodbus.Instrument('COM15', 1) # port name, slave address
(in decimal)
File "C:\Python33\Lib\site-packages\minimalmodbus.py", line 108, in __init__
self.serial = _SERIALPORTS[port] = serial.Serial(port=port, baudrate=BAUDRAT
E, parity=PARITY, bytesize=BYTESIZE, stopbits=STOPBITS, timeout=TIMEOUT)
File "C:\Python33\Lib\site-packages\serial\serialwin32.py", line 38, in __init
__
SerialBase.__init__(self, *args, **kwargs)
File "C:\Python33\Lib\site-packages\serial\serialutil.py", line 282, in __init
__
self.open()
File "C:\Python33\Lib\site-packages\serial\serialwin32.py", line 66, in open
raise SerialException("could not open port %r: %r" % (self.portstr, ctypes.W
inError()))
serial.serialutil.SerialException: could not open port 'COM15': PermissionError(
13, 'Zugriff verweigert', None, 5)
Hab die CMD als Administrator ausgeführt, aber das war noch nicht der richtige Schritt.
Zuletzt geändert von Anonymous am Montag 8. September 2014, 16:54, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@pybus: An der Stelle ist ein Programmfehler in `minimalmodbus`. Könntest Du dem/den Entwickler(n) melden. Der Fehler ist im Code zur Debugausgabe, Du könntest also versuchen den zu vermeiden in dem Du das Debug-Flag nicht setzt.
pybus
User
Beiträge: 6
Registriert: Montag 8. September 2014, 16:32

Hallo BlackJack,
vielen Dank für deine schnelle Antwort. Kannst du mir sagen wo genau der Fehler ist, so direkt sehe ich das nicht? Ich bin nicht mehr am Arbeitsplatz, aber hatte es vorhin auch ohne die Debug-Aktivierung probiert. Kann mich erinnern das dabei auch eine Fehlermeldung auftrat, diese reiche ich morgen früh direkt nach!
pybus
User
Beiträge: 6
Registriert: Montag 8. September 2014, 16:32

Hallo, habs grade noch mal mit deaktiviertem Logging probiert. Wenn ich das Script über die CMD ausführe kommt folgende Fehlermeldung:
Traceback (most recent call last):
File "C:\Python33\Lib\site-packages\test.py", line 76, in <module>
instrument = minimalmodbus.Instrument('COM15', 1) # port name, slave address
(in decimal)
File "C:\Python33\Lib\site-packages\minimalmodbus.py", line 108, in __init__
self.serial = _SERIALPORTS[port] = serial.Serial(port=port, baudrate=BAUDRAT
E, parity=PARITY, bytesize=BYTESIZE, stopbits=STOPBITS, timeout=TIMEOUT)
File "C:\Python33\Lib\site-packages\serial\serialwin32.py", line 38, in __init
__
SerialBase.__init__(self, *args, **kwargs)
File "C:\Python33\Lib\site-packages\serial\serialutil.py", line 282, in __init
__
self.open()
File "C:\Python33\Lib\site-packages\serial\serialwin32.py", line 66, in open
raise SerialException("could not open port %r: %r" % (self.portstr, ctypes.W
inError()))
serial.serialutil.SerialException: could not open port 'COM15': PermissionError(
13, 'Zugriff verweigert', None, 5)
Über die Python Shell hingegen:
Traceback (most recent call last):
File "C:\Python33\Lib\site-packages\test.py", line 79, in <module>
temperature = instrument.read_register(2, 2) # Registernumber, number of decimals
File "C:\Python33\Lib\site-packages\minimalmodbus.py", line 254, in read_register
return self._genericCommand(functioncode, registeraddress, numberOfDecimals=numberOfDecimals, signed=signed)
File "C:\Python33\Lib\site-packages\minimalmodbus.py", line 693, in _genericCommand
payloadFromSlave = self._performCommand(functioncode, payloadToSlave)
File "C:\Python33\Lib\site-packages\minimalmodbus.py", line 791, in _performCommand
response = self._communicate(message, number_of_bytes_to_read)
File "C:\Python33\Lib\site-packages\minimalmodbus.py", line 909, in _communicate
raise IOError('No communication with the instrument (no answer)')
IOError: No communication with the instrument (no answer)
Der IOError sagt ja anscheinend, dass kein Gerät gefunden wird, wohingegen über das Ausführen in der CMD der COM-Port nicht geöffnet werden kann!?
pybus
User
Beiträge: 6
Registriert: Montag 8. September 2014, 16:32

Hallo,

mal ein kurzes Update. Es schien tatsächlich etwas an der Hardware nicht zu stimmen, beim Betrachten mit einem Oszilloskop wurde weder beim Senden noch möglichen Empfangen etwas angezeigt. Hab infolge dessen mal einen Adapter mit einem Ft232 Chip bestellt. Dieser funktioniert unter Windows ohne Probleme. Man kann beliebit Anfragen absenden, und diese werden mit dem richtigen Messwert beantwortet. Unter Linux funktioniert das prinzipiell auch. Jedoch erscheint meistens die Fehlermeldung "IOError('No communication wirh the instrument(no aswer)'). Hin und wieder funktioniert das aber. Mein Verdacht war daher, dass vielleicht der Port noch offen ist. Daher habe ich mal den Parameter "CLOSE_PORT_AFTER_EACH_CALL" auf true gesetzt. Einen wirklichen Erfolg brachte das aber auch nicht. Auch die Zeit zwischen zwei Abfragen war nicht zwingend ein Indikator für die Fehlermeldung. Hatte vielleicht schon mal jemand das Problem oder weiß, ob man noch weitere Parameter setzen muss?

Danke und beste Grüße

edit: Was anscheinend etwas bringt, ist den Timeout etwas hochzusetzen. Dieser ist defaultmäßig auf 0,05 Sekunden gesetzt. Hab dem ganzen Ding jetzt mal eine Sekunde verpasst, und dabei wird jedes Telegramm gesendet und beantwortet.
Antworten