minimalmodbus-list Mailing List for minimalmodbus (Page 3)
Status: Beta
Brought to you by:
pyhys
This list is closed, nobody may subscribe to it.
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2012 |
Jan
(3) |
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
(1) |
Jul
(6) |
Aug
(1) |
Sep
(2) |
Oct
(3) |
Nov
(1) |
Dec
(4) |
2013 |
Jan
(7) |
Feb
(1) |
Mar
|
Apr
(1) |
May
(2) |
Jun
(2) |
Jul
|
Aug
(9) |
Sep
|
Oct
|
Nov
(5) |
Dec
(3) |
2014 |
Jan
(11) |
Feb
(2) |
Mar
(1) |
Apr
(3) |
May
(6) |
Jun
(1) |
Jul
|
Aug
(2) |
Sep
(2) |
Oct
(7) |
Nov
(3) |
Dec
|
2015 |
Jan
(2) |
Feb
(6) |
Mar
|
Apr
(2) |
May
(5) |
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
(3) |
Dec
(3) |
2016 |
Jan
|
Feb
|
Mar
(1) |
Apr
(5) |
May
|
Jun
|
Jul
(1) |
Aug
(11) |
Sep
|
Oct
(2) |
Nov
(3) |
Dec
(2) |
2017 |
Jan
|
Feb
(4) |
Mar
(5) |
Apr
(2) |
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Áron M. <mol...@gm...> - 2015-04-28 21:41:21
|
Dear minimalmodbus team! Im about to design a home control system: the brain is a RaspberryPi V1 ModelB, using modbus, the slaves are PIC16F887 chips. In the future all devices will use RS485 on CAT5 wires, but for now direct connection from PiTx-to PICRx.. At the moment I stucked by using minimalmodbus: The communication works properly, everything I send from the Pi is arriving to the receive buffer of the uController ( I can see all the buffer entrys in debug mode in MPLAB)! Currently its only one way communication, so no respond from the PIC, the Pi's RX wire is not installed because of the 5V-3.3V issue...The PIC is happy with the 3.3V signal) The problem is, that after sending 8 characters /for example: read_register(x,y)/ the first 6 bytes of the 8 are arriving properly. the 7th and the 8th are arriving as well these should contain the CRC_high and CRC_low bytes! There is something arriving in the 7th and 8th, so not empty buffer entrys but the content is incorrect! For example after receiving a modbus message from the Pi -> the first 6 bytes: 0x01\0x03\0x00\0x01\0x00\0x01 then the crc is 0xA5\0x9A! This is incorrect, this should be 0xD5\0xCA! I tried two different method of CRC calculation: - lookup table as it is in the project https://github.com/danjperron/NoContact ... er/CRC16.c <https://github.com/danjperron/NoContactWaterDetect/blob/master/CRC16.c> - cyclic calculation as in the project https://github.com/EmbeddedSam/Modbus-S ... r/modbus.c <https://github.com/EmbeddedSam/Modbus-Slave-for-PIC18F/blob/master/modbus.c> - PLUS just to make sure I also checked by using online excel tool at http://www.simplymodbus.ca/crc.xls The result is always 0xD5\0xCA! I have to say: considering the fact that the first bytes are arriving without any problem, the communication is OK. The problem should be in the minimalmodbus SW in the Pi! The way to calculate CRC is not OK, or not CRC16... Is there any configuration in minimalmodbus, or any setting or anything I was not aware of? Is there anything can solve this problem? Many thanks in advance! Best Regards, BlueSquirrel Here is the result of the minimalmodbus._getDiagnosticString(): ## Diagnostic output from minimalmodbus ## Minimalmodbus version: 0.6 Minimalmodbus status: Beta Revision: $Rev: 200 $ Revision date: $Date: 2014-06-22 01:29:19 +0200 (Sun, 22 Jun 2014) $ File name (with relative path): /usr/local/lib/python2.7/dist-packages/minimalmodbus.pyc Full file path: /usr/local/lib/python2.7/dist-packages/minimalmodbus.pyc pySerial version: 2.7 pySerial full file path: /usr/local/lib/python2.7/dist-packages/serial/__init__.pyc Platform: linux2 Filesystem encoding: 'UTF-8' Byteorder: little Python version: 2.7.3 (default, Mar 18 2014, 05:13:23) [GCC 4.6.3] Python version info: sys.version_info(major=2, minor=7, micro=3, releaselevel='final', serial=0) Python flags: sys.flags(debug=0, py3k_warning=0, division_warning=0, division_new=0, inspect=0, interactive=0, optimize=0, dont_write_bytecode=0, no_user_site=0, no_site=0, ignore_environment=0, tabcheck=0, verbose=0, unicode=0, bytes_warning=0, hash_randomization=0) Python argv: [''] Python prefix: '/usr' Python exec prefix: '/usr' Python executable: '/usr/bin/python' Long info: sys.long_info(bits_per_digit=15, sizeof_digit=2) Float repr style: 'short' Variable __name__: minimalmodbus Current directory: /home/pi Python path: /usr/lib/python2.7 /usr/lib/python2.7/plat-linux2 /usr/lib/python2.7/lib-tk /usr/lib/python2.7/lib-old /usr/lib/python2.7/lib-dynload /usr/local/lib/python2.7/dist-packages /usr/lib/python2.7/dist-packages /usr/lib/pymodules/python2.7 ## End of diagnostic output ## |
From: Greene, W. B. <Wal...@fs...> - 2015-04-01 23:51:50
|
I'm new to Python programming - please forgive my ignorance. How do I trap the exception generated when the instrument fails to answer? I've tried: Import minimalmodbus as mdi mdi.BAUDRATE = 57600 mdi.PARITY = 'N' mdi.BYTESIZE = 8 mdi.STOPBITS = 1 mdi.TIMEOUT = 3.0 COM_PORT = 'COM1' SLAVE_ADR = 2 MODE = 'rtu' IO_open = False print 'Entering Exception Loop' while (IO_open == False): try: PIM = mdi.Instrument(COM_PORT, SLAVE_ADR, MODE) print 'Returned from Instrument Port Open" IO_open = True except IOError: print "Port Open Failure" Results: Entering Exception loop Returned from Instrument Port Open <delay - I think it's my timeout delay of 3 seconds> Traceback.....IOError: No communications with the instrument Now when I have the instrument (Slave) ready and execute the script, it works (ie the communications is established and transactions function). In order to make this script 'user friendly' I need to have the program wait for a valid slave connection. I'm using minimalmodbus with Tkinter to provide a windowed low level instrument control interface for developing an Modbus controlled device. Help/guidance would be greatly appreciated. Walter Greene Kidde-Fenwal 508-231-2740 wal...@ki... |
From: 张礼勇 <liy...@ye...> - 2015-02-26 07:43:28
|
Dear Pyhys! Very glade to hear that you take this patch. I'm very much looking forward to the next release! With best regards, Peter 在 2015-02-18 05:10:52,"Jonas Berg" <jon...@ho...> 写道: Best Peter! Thanks for your patch. I will improve the CRC calculation in next release with your method. Best Regards Jonas <-----Ursprungligt Meddelande-----> | | | From: ??? [liy...@ye...] Sent: 4/2/2015 4:02:46 AM To: py...@us... Subject: A Patch to MinimalModbus (Computation of cyclic redundancy checks) Pyhys: Many thanks for your excellent project MinimalModbus which has contribute a lot to my program running on a embedded arm board! MinimalModbus is easy to use and has a very elegant API. However, a pretty high CPU load occur when my program read 60 registers every 500ms. My arm board has a Samsung S5PV210 Cortex A8 CPU(1GH) and a 512M DDR2 memeory. Then I read the source code of minimalModbus and I find that the library use compute method to get checksum rather than lookup table. So, I make a patch which use lookup table method to get checksum. In my program, CPU load drop to 9 percent from 33 percent. Peter | |
From: Edwin v. d. O. <oet...@gm...> - 2015-02-20 12:13:26
|
I modified the code and removed most cut and paste. Here is the new main file : The config.py ########################### Adresse1 = 9 Adresse2 = 10 Adresse3 = 11 Adresse4 = 12 Adresse5 = 13 Adresse6 = 14 Adresse7 = 15 Adresse8 = 16 Port = '/dev/ttyUSB0' sensorcount = 16 # Anzahl der Sensoren sensorname1 = 'TEST1' sensorname2 = 'TEST2' sensorname3 = 'TEST3' sensorname4 = 'TEST4' sensorname5 = 'TEST5' sensorname6 = 'TEST6' sensorname7 = 'TEST7' sensorname8 = 'TEST8' ############################ And the main program #!/usr/bin/env python # modified heavily by Edwin van den Oetelaar # 20 Feb 2015 # Open source, no warranties of any sort import datetime from os import path import os import os.path import shutil import fnmatch import time from ftplib import FTP from glob import glob from os.path import join from socket import gaierror import minimalmodbus # HOLEN DER ADRESSEN AUS CONFIG FILE (config.py muss im selben Verzeichnis liegen) from config import * # list of modbus device numbers of each sensor # you could be more flexible when adding the list directly into the config file instead of make the list here sensorlist = (Adresse1, Adresse2, Adresse3, Adresse4, Adresse5, Adresse6, Adresse7, Adresse8) sensornames = (sensorname1, sensorname2, sensorname3, sensorname4, sensorname5, sensorname6, sensorname7, sensorname8) # MODBUS-ADAPTER AN COM PORT KONFIGURIEREN minimalmodbus.BAUDRATE = 19200 minimalmodbus.PARITY = 'E' minimalmodbus.BYTESIZE = 8 minimalmodbus.stopbits = 1 minimalmodbus.TIMEOUT = 0.31 instrumentlist = [] # list of instruments pressure_list = {} # hash of pressures temp_list = {} # hash of temperatures # make a list of instruments try: for sensor in sensorlist: instrumentlist.append(minimalmodbus.Instrument(port=Port, slaveaddress=sensor)) except OSError as ex: print ">> FATAL :: The serial device could not be opened, please check name or connections in config.py" raise # the instruments all use these registers register_pressure = 0 # modbus register for pressure value register_temp = 4 # modbus register for temp value # loop until end of time while True: # try read all the pressure values from the sensors # fill in a 'disconnect'/'invalid' value if value can not be read from sensor count = 1 for i in instrumentlist: try: pressure_list[count] = i.read_register(register_pressure, numberOfDecimals=3, functioncode=4, signed=True) except IOError as ex: pressure_list[count] = 'disconnected' except ValueError as ex: pressure_list[count] = 'invalid' count += 1 # try read all the temp values count = 1 for i in instrumentlist: try: temp_list[count] = i.read_register(register_temp, numberOfDecimals=1, functioncode=4, signed=True) except IOError as ex: temp_list[count] = 'disconnected' except ValueError as ex: temp_list[count] = 'invalid' count += 1 # output all the values to a file output_path = path.join('/', 'Logger_Test') filename = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M.txt") print "writing file {f} into directory {d}".format(f=filename, d=output_path) output_file_name = path.join(output_path, filename) # send the file to a remote location using FTP heute = datetime.date.today() Zeit = datetime.datetime.now().strftime("%H:%M:%S.%f") Zeit2 = datetime.datetime.now().strftime("%H:%M:%S") date_string = datetime.date.today().strftime('%d-%b-%Y') time_string = datetime.datetime.now().strftime("%H:%M:%S.%f") with open(output_file_name, "w") as myfile: myfile.write("Date: {d} {t}\n\nSensor Count: {sc}\n\n".format(d=date_string, t=time_string, sc=sensorcount)) for sn in sensornames: myfile.write('Name: {sn}\n'.format(sn=sn)) for sn in sensornames: myfile.write('Name: {sn}t\n'.format(sn=sn)) # note the extra 't' myfile.write('Timestamp') for sn in sensornames: myfile.write('\t{sn}'.format(sn=sn)) for sn in sensornames: myfile.write('\t{sn}t'.format(sn=sn)) # note the extra 't' for temp sensors myfile.write('\n\n{d} {t}'.format(d=heute.strftime('%d-%b-%Y'), t=Zeit2)) for sv in pressure_list: myfile.write('\t{val}'.format(val=sv)) for sv in temp_list: myfile.write('\t{val}'.format(val=sv)) myfile.close() # print values to screen also print 'Pressure sensors\n' count = 1 for sn in sensornames: print '{sn}\t{i}\t{pv}\t{d}\t{t}'.format(sn=sn, i=count, pv=pressure_list[count], d=heute.strftime('%d.%m.%Y'), t=datetime.datetime.now().strftime("%H:%M:%S")) count += 1 print "\nTemperature sensors\n" count = 1 for sn in sensornames: print '{sn}\t{i}\t{pv}\t{d}\t{t}'.format(sn=sn, i=count, pv=temp_list[count], d=heute.strftime('%d.%m.%Y'), t=datetime.datetime.now().strftime("%H:%M:%S")) count += 1 # FTP stuff I did not change print 'FTP-UPLOAD' dir_name = "/Logger_Test" filterx = "*.txt" url, user_name, password = "XXXXXXXXX", "XXXXXXXXXXXXXX", "XXXXXXXXXXXXXX" try: session = FTP(url, user_name, password) for file_name in glob(join(dir_name, filterx)): with open(file_name, "rb") as file_handler: session.storbinary("STOR %s" % file_name, file_handler) session.quit() except gaierror: print("error: maybe no connection") print 'FTP-TRANSFER BEENDET' # BACKUP DER GESENDETEN FILES print 'FILES-BACKUP START' list_of_dirs_to_copy = ['/Logger_Test'] # List of source dirs excluded_subdirs = ['backup'] # subdir to exclude from copy dest_dir = '/Logger_Test/backup' # folder for the destination of the copy files_patterns = ['*.txt', '*.doc'] for root_path in list_of_dirs_to_copy: for root, dirs, files in os.walk(root_path): # recurse walking for dir in excluded_subdirs: if dir in dirs: dirs.remove(dir) # remove the dir from the subdirs to visit if not os.path.exists(dest_dir): os.makedirs(dest_dir) # create the dir if not exists for pattern in files_patterns: for thefile in fnmatch.filter(files, pattern): # filter the files to copy shutil.move(os.path.join(root, thefile), dest_dir) # copy file print 'FILES-BACKUP BEENDET' # Wait for X seconds time.sleep(60) On Wed, Feb 18, 2015 at 8:36 AM, <fr...@in...> wrote: > > Hello Edwin, > > here is my (beginners) Script i wrote to read from 8 different devices: |
From: <fr...@in...> - 2015-02-18 07:36:53
|
Hello Edwin, here is my (beginners) Script i wrote to read from 8 different devices: modbus4.py: ################################################################# #!/usr/bin/env python import minimalmodbus import datetime from os import path, chdir # Import fuer FTP from socket import gaierror from ftplib import FTP from glob import glob from os.path import join from socket import gaierror #IMPORT VON DATUM UND UHRZEIT datum = [] heute = datetime.date.today() datum.append(heute) # HOLEN DER ADRESSEN AUS CONFIG FILE (config.py muss im selben Verzeichnis liegen) from config import * # MODBUS-ADAPTER AN COM PORT KONFIGURIEREN minimalmodbus.BAUDRATE = 19200 minimalmodbus.PARITY = 'E' minimalmodbus.BYTESIZE = 8 minimalmodbus.stopbits = 1 minimalmodbus.TIMEOUT = 0.31 while True: #DEFINITION VON HARDWARE UND SLAVE-ADRESSE instrument1 = minimalmodbus.Instrument(str(Port), + Adresse1) instrument2 = minimalmodbus.Instrument(str(Port), + Adresse2) instrument3 = minimalmodbus.Instrument(str(Port), + Adresse3) instrument4 = minimalmodbus.Instrument(str(Port), + Adresse4) instrument5 = minimalmodbus.Instrument(str(Port), + Adresse5) instrument6 = minimalmodbus.Instrument(str(Port), + Adresse6) instrument7 = minimalmodbus.Instrument(str(Port), + Adresse7) instrument8 = minimalmodbus.Instrument(str(Port), + Adresse8) #Definition von Temperaturmodulen (Nicht noetig) instrument1t = minimalmodbus.Instrument(str(Port), + Adresse1) instrument2t = minimalmodbus.Instrument(str(Port), + Adresse2) instrument3t = minimalmodbus.Instrument(str(Port), + Adresse3) instrument4t = minimalmodbus.Instrument(str(Port), + Adresse4) instrument5t = minimalmodbus.Instrument(str(Port), + Adresse5) instrument6t = minimalmodbus.Instrument(str(Port), + Adresse6) instrument7t = minimalmodbus.Instrument(str(Port), + Adresse7) instrument8t = minimalmodbus.Instrument(str(Port), + Adresse8) #AUSLESEN VON REGISTER 1 ( ACHTUNG: REGISTER 1 IST 0) UND DEFINITION VON preassure1 = instrument1.read_register(0, numberOfDecimals=3, functioncode=4, signed=True) preassure2 = instrument2.read_register(0, numberOfDecimals=3, functioncode=4, signed=True) preassure3 = instrument3.read_register(0, numberOfDecimals=3, functioncode=4, signed=True) preassure4 = instrument4.read_register(0, numberOfDecimals=3, functioncode=4, signed=True) preassure5 = instrument5.read_register(0, numberOfDecimals=3, functioncode=4, signed=True) preassure6 = instrument6.read_register(0, numberOfDecimals=3, functioncode=4, signed=True) preassure7 = instrument7.read_register(0, numberOfDecimals=3, functioncode=4, signed=True) preassure8 = instrument8.read_register(0, numberOfDecimals=3, functioncode=4, signed=True) temperature1 = instrument1.read_register(4, numberOfDecimals=1, functioncode=4, signed=True) temperature2 = instrument2.read_register(4, numberOfDecimals=1, functioncode=4, signed=True) temperature3 = instrument3.read_register(4, numberOfDecimals=1, functioncode=4, signed=True) temperature4 = instrument4.read_register(4, numberOfDecimals=1, functioncode=4, signed=True) temperature5 = instrument5.read_register(4, numberOfDecimals=1, functioncode=4, signed=True) temperature6 = instrument6.read_register(4, numberOfDecimals=1, functioncode=4, signed=True) temperature7 = instrument7.read_register(4, numberOfDecimals=1, functioncode=4, signed=True) temperature8 = instrument8.read_register(4, numberOfDecimals=1, functioncode=4, signed=True) #Ausgabe definieren und formatieren Datum = heute.strftime('%d-%b-%Y') Zeit = datetime.datetime.now().strftime("%H:%M:%S.%f") Zeit2 = datetime.datetime.now().strftime("%H:%M:%S") test1 = heute.strftime('%Y-%m-%d'),datetime.datetime.now().strftime("-%H-%M") datei = "".join(str(x) for x in test1) print datei # Verzeichnis zum Schreiben der Werte wechseln myfile = path.join('/', 'Logger_Test') chdir(myfile) # Datei oeffnen, schreiben, schliessen with open(datei + ".txt", "w") as myfile: myfile.write("Date: ") myfile.write(str(Datum)) myfile.write(" ") myfile.write(str(Zeit)) myfile.write("\n") myfile.write("\n") myfile.write("Sensor Count: ") myfile.write(str(sensorcount)) myfile.write("\n") myfile.write("\n") # Sensornamen Auflistung myfile.write("Name: ") myfile.write(str(sensorname1)) myfile.write("\n") myfile.write("Name: ") myfile.write(str(sensorname2)) myfile.write("\n") myfile.write("Name: ") myfile.write(str(sensorname3)) myfile.write("\n") myfile.write("Name: ") myfile.write(str(sensorname4)) myfile.write("\n") myfile.write("Name: ") myfile.write(str(sensorname5)) myfile.write("\n") myfile.write("Name: ") myfile.write(str(sensorname6)) myfile.write("\n") myfile.write("Name: ") myfile.write(str(sensorname7)) myfile.write("\n") myfile.write("Name: ") myfile.write(str(sensorname8)) myfile.write("\n") #Sensornamen Teperatur myfile.write("Name: ") myfile.write(str(sensorname1)) myfile.write("t\n") myfile.write("Name: ") myfile.write(str(sensorname2)) myfile.write("t\n") myfile.write("Name: ") myfile.write(str(sensorname3)) myfile.write("t\n") myfile.write("Name: ") myfile.write(str(sensorname4)) myfile.write("t\n") myfile.write("Name: ") myfile.write(str(sensorname5)) myfile.write("t\n") myfile.write("Name: ") myfile.write(str(sensorname6)) myfile.write("t\n") myfile.write("Name: ") myfile.write(str(sensorname7)) myfile.write("t\n") myfile.write("Name: ") myfile.write(str(sensorname8)) myfile.write("t\n") myfile.write("\n") # Sensornamen myfile.write("Timestamp\t") myfile.write(str(sensorname1)) myfile.write("\t") myfile.write(str(sensorname2)) myfile.write("\t") myfile.write(str(sensorname3)) myfile.write("\t") myfile.write(str(sensorname4)) myfile.write("\t") myfile.write(str(sensorname5)) myfile.write("\t") myfile.write(str(sensorname6)) myfile.write("\t") myfile.write(str(sensorname7)) myfile.write("\t") myfile.write(str(sensorname8)) myfile.write("\t") # Sensornamen Temperatur myfile.write(str(sensorname1)) myfile.write("t\t") myfile.write(str(sensorname2)) myfile.write("t\t") myfile.write(str(sensorname3)) myfile.write("t\t") myfile.write(str(sensorname4)) myfile.write("t\t") myfile.write(str(sensorname5)) myfile.write("t\t") myfile.write(str(sensorname6)) myfile.write("t\t") myfile.write(str(sensorname7)) myfile.write("t\t") myfile.write(str(sensorname8)) myfile.write("t\n") # Zeile fuer Messwerte myfile.write(str(Datum)) myfile.write(" ") myfile.write(str(Zeit2)) myfile.write("\t") myfile.write(str(preassure1)) myfile.write("\t") myfile.write(str(preassure2)) myfile.write("\t") myfile.write(str(preassure3)) myfile.write("\t") myfile.write(str(preassure4)) myfile.write("\t") myfile.write(str(preassure5)) myfile.write("\t") myfile.write(str(preassure6)) myfile.write("\t") myfile.write(str(preassure7)) myfile.write("\t") myfile.write(str(preassure8)) myfile.write("\t") # Temperaturmesswerte myfile.write(str(temperature1)) myfile.write("\t") myfile.write(str(temperature2)) myfile.write("\t") myfile.write(str(temperature3)) myfile.write("\t") myfile.write(str(temperature4)) myfile.write("\t") myfile.write(str(temperature5)) myfile.write("\t") myfile.write(str(temperature6)) myfile.write("\t") myfile.write(str(temperature7)) myfile.write("\t") myfile.write(str(temperature8)) myfile.write("\t") myfile.close() #AUSGABE VON PREASSURE print "SENSOR1\t","1\t",preassure1,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR2\t","2\t",preassure2,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR3\t","3\t",preassure3,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR4\t","4\t",preassure4,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR5\t","5\t",preassure5,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR6\t","6\t",preassure6,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR7\t","7\t",preassure7,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR8\t","8\t",preassure8,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "TEMPERATUR" print "SENSOR1\t","t1\t",temperature1,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR2\t","t2\t",temperature2,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR3\t","t3\t",temperature3,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR4\t","t4\t",temperature4,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR5\t","t5\t",temperature5,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR6\t","t6\t",temperature6,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR7\t","t7\t",temperature7,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") print "SENSOR8\t","t8\t",temperature8,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%H:%M:%S") # FTP-TRANSFER print 'FTP-UPLOAD' dir_name = "/Logger_Test" filter = "*.txt" url, user_name, password = "XXXXXXXXX", "XXXXXXXXXXXXXX", "XXXXXXXXXXXXXX" try: session = FTP(url, user_name, password) for file_name in glob(join(dir_name, filter)): with open(file_name, "rb") as file_handler: session.storbinary("STOR %s" % file_name, file_handler) session.quit() except gaierror: print("error: maybe no connection") print 'FTP-TRANSFER BEENDET' # BACKUP DER GESENDETEN FILES print 'FILES-BACKUP START' import os import os.path import shutil import fnmatch list_of_dirs_to_copy = ['/Logger_Test'] # List of source dirs excluded_subdirs = ['backup'] # subdir to exclude from copy dest_dir = '/Logger_Test/backup' # folder for the destination of the copy files_patterns = ['*.txt', '*.doc'] for root_path in list_of_dirs_to_copy: for root, dirs, files in os.walk(root_path): # recurse walking for dir in excluded_subdirs: if dir in dirs: dirs.remove(dir) # remove the dir from the subdirs to visit if not os.path.exists(dest_dir): os.makedirs(dest_dir) # create the dir if not exists for pattern in files_patterns: for thefile in fnmatch.filter(files, pattern): # filter the files to copy shutil.move(os.path.join(root, thefile), dest_dir) #copy file print 'FILES-BACKUP BEENDET' import time # Wait for X seconds time.sleep(60) ################################################################# config.py ########################### Adresse1=9 Adresse2=10 Adresse3=11 Adresse4=12 Adresse5=13 Adresse6=14 Adresse7=15 Adresse8=16 Port='/dev/ttyUSB0' sensorcount=16 #Anzahl der Sensoren sensorname1='TEST1' sensorname2='TEST2' sensorname3='TEST3' sensorname4='TEST4' sensorname5='TEST5' sensorname6='TEST6' sensorname7='TEST7' sensorname8='TEST8' ############################ I hope, anybody can help me (and as you see, it is really a script from a beginner ;-)) Regards Franz Zitat von Edwin van den Oetelaar <oet...@gm...>: > On Mon, Feb 16, 2015 at 9:36 PM, Franz Löseke <fr...@in...> wrote: >> >> >> Hello, >> >> i want to create a datalogger with minimalmodbus.. until now it works >> great buut i have one problem. At the moment i have 8 devices on 8 >> different adresses. If someone is not reachable (maybe broken or >> maintenace) then the script crashes. I have not much experiences in >> python and so i have no idea how i can handle this problem. I want >> that minimalmodbus ignore the missing adress after a specified timeout >> (maybe 2 seconds) and collect the other adresses. Now it crashes and >> did not collect any data. Does it need a modification in my "learning >> by doing" script or in minimalmodbus? Maybe it is possible to modify >> minimalmodbus in case of not reachable adress send as answer "XXXX" >> for example. >> >> Can anyone help me in this case? > > Can you post a minimal script? > You can most likely detect a missing device and prevent a crash. > Just show your approach as you are using now. try/except or what? > >> >> >> Regards >> >> Franz > > Greetings, > Edwin |
From: Jonas B. <jon...@ho...> - 2015-02-17 21:28:17
|
Best Peter! Thanks for your patch. I will improve the CRC calculation in next release with your method. Best Regards Jonas <-----Ursprungligt Meddelande-----> From: ??? [liy...@ye...] Sent: 4/2/2015 4:02:46 AM To: py...@us... Subject: A Patch to MinimalModbus (Computation of cyclic redundancy checks) Pyhys: Many thanks for your excellent project MinimalModbus which has contribute a lot to my program running on a embedded arm board! MinimalModbus is easy to use and has a very elegant API. However, a pretty high CPU load occur when my program read 60 registers every 500ms. My arm board has a Samsung S5PV210 Cortex A8 CPU(1GH) and a 512M DDR2 memeory. Then I read the source code of minimalModbus and I find that the library use compute method to get checksum rather than lookup table. So, I make a patch which use lookup table method to get checksum. In my program, CPU load drop to 9 percent from 33 percent. Peter |
From: Edwin v. d. O. <oet...@gm...> - 2015-02-16 20:44:14
|
On Mon, Feb 16, 2015 at 9:36 PM, Franz Löseke <fr...@in...> wrote: > > > Hello, > > i want to create a datalogger with minimalmodbus.. until now it works > great buut i have one problem. At the moment i have 8 devices on 8 > different adresses. If someone is not reachable (maybe broken or > maintenace) then the script crashes. I have not much experiences in > python and so i have no idea how i can handle this problem. I want > that minimalmodbus ignore the missing adress after a specified timeout > (maybe 2 seconds) and collect the other adresses. Now it crashes and > did not collect any data. Does it need a modification in my "learning > by doing" script or in minimalmodbus? Maybe it is possible to modify > minimalmodbus in case of not reachable adress send as answer "XXXX" > for example. > > Can anyone help me in this case? Can you post a minimal script? You can most likely detect a missing device and prevent a crash. Just show your approach as you are using now. try/except or what? > > > Regards > > Franz Greetings, Edwin |
From: Franz L. <fr...@in...> - 2015-02-16 20:36:32
|
Hello, i want to create a datalogger with minimalmodbus.. until now it works great buut i have one problem. At the moment i have 8 devices on 8 different adresses. If someone is not reachable (maybe broken or maintenace) then the script crashes. I have not much experiences in python and so i have no idea how i can handle this problem. I want that minimalmodbus ignore the missing adress after a specified timeout (maybe 2 seconds) and collect the other adresses. Now it crashes and did not collect any data. Does it need a modification in my "learning by doing" script or in minimalmodbus? Maybe it is possible to modify minimalmodbus in case of not reachable adress send as answer "XXXX" for example. Can anyone help me in this case? Regards Franz Von meinem Samsung Gerät gesendet. |
From: Jonas B. <jon...@ho...> - 2015-01-12 19:47:37
|
Hi Thomas, great! I will include this in next release. Thanks! /Jonas <-----Ursprungligt Meddelande-----> From: Thomas Speckert [tho...@om...] Sent: 5/1/2015 5:49:58 PM To: min...@li... Subject: [Minimalmodbus-list] UnicodeEncodeError in debug mode (Windows,Python 3.4) Hi, While debugging a Python 3.4 application on Window using MinimalModbus, I would get a UnicodeEncodeError with debug mode enabled when I ran my application using the Windows command prompt. Here's a partial Traceback: File "C:\Python34\lib\site-packages\minimalmodbus.py", line 494, in read_registers numberOfRegisters=numberOfRegisters, payloadformat='registers') File "C:\Python34\lib\site-packages\minimalmodbus.py", line 693, in _genericCommand payloadFromSlave = self._performCommand(functioncode, payloadToSlave) File "C:\Python34\lib\site-packages\minimalmodbus.py", line 791, in _performCommand response = self._communicate(message, number_of_bytes_to_read) File "C:\Python34\lib\site-packages\minimalmodbus.py", line 848, in _communicate format(number_of_bytes_to_read, message)) File "C:\Python34\lib\site-packages\minimalmodbus.py", line 2329, in _print_out sys.stdout.write(inputstring + '\n') File "C:\Python34\lib\encodings\cp437.py", line 19, in encode return codecs.charmap_encode(input,self.errors,encoding_map)[0] UnicodeEncodeError: 'charmap' codec can't encode character '\xc8' in position 89: character maps to <undefined> It seems the problem was a combination of the default encoding in the Windows shell being code page 437 (IBM437), and Python trying to interpret the "raw" Modbus frame data as a proper string. The value 0xc8 apparently couldn't be encoded using code page 437, and so an exception was thrown. The simplest solution to this problem was to change the encoding of the console with the command 'chcp 65001' to use UTF-8 encoding. But I would suggest a solution where the raw frame data is instead converted to string representation (i.e. the char 0xc8 is converted to the 4-char string "\xc8") before being sent to stdout. In addition to solving the problem, this has the nice side effect of clearer debugging output :) My solution was to add the following function to the module: > def _rawframe_to_hexstring(string, prefix='\\x'): > if len(string) < 1: > return '' > return prefix + prefix.join('{:02x}'.format(ord(char)) for char in string) and then change Instrument._communicate in two places: > if self.debug: > _print_out('\nMinimalModbus debug mode. Writing to instrument (expecting {} bytes back): {!r}'. \ > format(number_of_bytes_to_read, message)) becomes > if self.debug: > _print_out('\nMinimalModbus debug mode. Writing to instrument (expecting {} bytes back): {}'. \ > format(number_of_bytes_to_read, _rawframe_to_hexstring(message))) and > if self.debug: > template = 'MinimalModbus debug mode. Response from instrument: {!r} ({} bytes), ' + \ > 'roundtrip time: {:.1f} ms. Timeout setting: {:.1f} ms.\n' > text = template.format( > answer, > ...omitted... becomes > if self.debug: > template = 'MinimalModbus debug mode. Response from instrument: {} ({} bytes), ' + \ > 'roundtrip time: {:.1f} ms. Timeout setting: {:.1f} ms.\n' > text = template.format( > _rawframe_to_hexstring(answer), > ...omitted... The debug output is then more consistent - and no UnicodeEncodingError with the default console encoding: MinimalModbus debug mode. Writing to instrument (expecting 9 bytes back): \x05\x03\x03\x8f\x00\x02\xf4\x20 MinimalModbus debug mode. No sleep required before write. Time since previous read: 9.0 ms, minimum silent period: 1.00 ms. MinimalModbus debug mode. Response from instrument: \x05\x03\x04\x03\x66\xc7\xc8\x0c\x0e (9 bytes), roundtrip time: 21.0 ms. Timeout setting: 2000000.0 ms. Best Regards, Thomas Speckert ------------------------------------------------------------------------ ------ Dive into the World of Parallel Programming! The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net _______________________________________________ Minimalmodbus-list mailing list Min...@li... https://lists.sourceforge.net/lists/listinfo/minimalmodbus-list . |
From: Thomas S. <tho...@om...> - 2015-01-05 16:50:18
|
Hi, While debugging a Python 3.4 application on Window using MinimalModbus, I would get a UnicodeEncodeError with debug mode enabled when I ran my application using the Windows command prompt. Here's a partial Traceback: File "C:\Python34\lib\site-packages\minimalmodbus.py", line 494, in read_registers numberOfRegisters=numberOfRegisters, payloadformat='registers') File "C:\Python34\lib\site-packages\minimalmodbus.py", line 693, in _genericCommand payloadFromSlave = self._performCommand(functioncode, payloadToSlave) File "C:\Python34\lib\site-packages\minimalmodbus.py", line 791, in _performCommand response = self._communicate(message, number_of_bytes_to_read) File "C:\Python34\lib\site-packages\minimalmodbus.py", line 848, in _communicate format(number_of_bytes_to_read, message)) File "C:\Python34\lib\site-packages\minimalmodbus.py", line 2329, in _print_out sys.stdout.write(inputstring + '\n') File "C:\Python34\lib\encodings\cp437.py", line 19, in encode return codecs.charmap_encode(input,self.errors,encoding_map)[0] UnicodeEncodeError: 'charmap' codec can't encode character '\xc8' in position 89: character maps to <undefined> It seems the problem was a combination of the default encoding in the Windows shell being code page 437 (IBM437), and Python trying to interpret the "raw" Modbus frame data as a proper string. The value 0xc8 apparently couldn't be encoded using code page 437, and so an exception was thrown. The simplest solution to this problem was to change the encoding of the console with the command 'chcp 65001' to use UTF-8 encoding. But I would suggest a solution where the raw frame data is instead converted to string representation (i.e. the char 0xc8 is converted to the 4-char string "\xc8") before being sent to stdout. In addition to solving the problem, this has the nice side effect of clearer debugging output :) My solution was to add the following function to the module: > def _rawframe_to_hexstring(string, prefix='\\x'): > if len(string) < 1: > return '' > return prefix + prefix.join('{:02x}'.format(ord(char)) for char in string) and then change Instrument._communicate in two places: > if self.debug: > _print_out('\nMinimalModbus debug mode. Writing to instrument (expecting {} bytes back): {!r}'. \ > format(number_of_bytes_to_read, message)) becomes > if self.debug: > _print_out('\nMinimalModbus debug mode. Writing to instrument (expecting {} bytes back): {}'. \ > format(number_of_bytes_to_read, _rawframe_to_hexstring(message))) and > if self.debug: > template = 'MinimalModbus debug mode. Response from instrument: {!r} ({} bytes), ' + \ > 'roundtrip time: {:.1f} ms. Timeout setting: {:.1f} ms.\n' > text = template.format( > answer, > ...omitted... becomes > if self.debug: > template = 'MinimalModbus debug mode. Response from instrument: {} ({} bytes), ' + \ > 'roundtrip time: {:.1f} ms. Timeout setting: {:.1f} ms.\n' > text = template.format( > _rawframe_to_hexstring(answer), > ...omitted... The debug output is then more consistent - and no UnicodeEncodingError with the default console encoding: MinimalModbus debug mode. Writing to instrument (expecting 9 bytes back): \x05\x03\x03\x8f\x00\x02\xf4\x20 MinimalModbus debug mode. No sleep required before write. Time since previous read: 9.0 ms, minimum silent period: 1.00 ms. MinimalModbus debug mode. Response from instrument: \x05\x03\x04\x03\x66\xc7\xc8\x0c\x0e (9 bytes), roundtrip time: 21.0 ms. Timeout setting: 2000000.0 ms. Best Regards, Thomas Speckert |
From: Jonas B. <jon...@ho...> - 2014-11-13 21:10:16
|
Hej! Your data is this: Request \x04\x01\x00\x00\x00\x01\xfd\x9f Read one bit from address 0 in slave 4. Response \x04 Slave 4 \x01 Function 1 (read bits) \x01 Byte count = 1 \x01 Value = 1 \x90\x84 CRC This seems correct (i have not checked whether the CRC is valid). Then you have the zeros in the beginning and the end of the message. My guess is actually that this is hardware related problems, with your RS-485 adapter. Maybe you should try another one. Nevertheless, if you need to fix it, follow the ideas outlined here: http://minimalmodbus.sourceforge.net/usage.html#handling-extra-0xfe-byte -after-some-messages The code is here: http://minimalmodbus.sourceforge.net/_modules/minimalmodbus.html#_extrac tPayload Please come back if you need more help. Best regards Jonas <-----Ursprungligt Meddelande-----> From: and...@gm... [and...@gm...] Sent: 7/11/2014 4:36:49 PM To: min...@li... Subject: [Minimalmodbus-list] Device implementation Hello I have a device with a funny problem. I't consistently gives me a empty byte in the end and beginning of each message. Tried to fix every angle of hardware aspects including using termination resistors, but with no luck. It leeds me to believe developers of the device might taken a shortcut or two in implementing modbus protocol. I need some way to strip my response from the first and last byte of the response, but how? I don't know how and where to edit your code, but the functions should do basically the same thing as when one is working with ascii messages, but in my case removing /x00 instead. See the end of the diagnostic and you'll realize the answer is much so correct, when removing first and last byte. It is tested with several registers and they all give "correct" responses. Writing to the device is working like a charm! ## Diagnostic output from minimalmodbus ## Minimalmodbus version: 0.6 Minimalmodbus status: Beta Revision: $Rev: 200 $ Revision date: $Date: 2014-06-22 01:29:19 +0200 (Sun, 22 Jun 2014) $ File name (with relative path): /usr/local/lib/python2.7/dist-packages/minimalmodbus.pyc Full file path: /usr/local/lib/python2.7/dist-packages/minimalmodbus.pyc pySerial version: 2.5 pySerial full file path: /usr/lib/python2.7/dist-packages/serial/__init__.pyc Platform: linux2 Filesystem encoding: 'UTF-8' Byteorder: little Python version: 2.7.3 (default, Mar 18 2014, 05:13:23) [GCC 4.6.3] Python version info: sys.version_info(major=2, minor=7, micro=3, releaselevel='final', serial=0) Python flags: sys.flags(debug=0, py3k_warning=0, division_warning=0, division_new=0, inspect=0, interactive=0, optimize=0, dont_write_bytecode=0, no_user_site=0, no_site=0, ignore_environment=0, tabcheck=0, verbose=0, unicode=0, bytes_warning=0, hash_randomization=0) Python argv: ['./rstest.py'] Python prefix: '/usr' Python exec prefix: '/usr' Python executable: '/usr/bin/python' Long info: sys.long_info(bits_per_digit=15, sizeof_digit=2) Float repr style: 'short' Variable __name__: minimalmodbus Current directory: /home/pi/bin/test Python path: /home/pi/bin/test /usr/lib/python2.7 /usr/lib/python2.7/plat-linux2 /usr/lib/python2.7/lib-tk /usr/lib/python2.7/lib-old /usr/lib/python2.7/lib-dynload /usr/local/lib/python2.7/dist-packages /usr/lib/python2.7/dist-packages /usr/lib/pymodules/python2.7 ## End of diagnostic output ## minimalmodbus.Instrument<id=0xb6d09508, address=4, mode=rtu, close_port_after_each_call=True, precalculate_read_size=False, debug=True, serial=Serial<id=0xb6d0b210, open=False>(port='/dev/ttyUSB0', baudrate=19200, bytesize=8, parity='N', stopbits=1, timeout=0.5, xonxoff=False, rtscts=False, dsrdtr=False)> MinimalModbus debug mode. Writing to instrument (expecting 1000 bytes back): '\x04\x01\x00\x00\x00\x01\xfd\x9f' MinimalModbus debug mode. No sleep required before write. Time since previous read: 1415374511529.1 ms, minimum silent period: 2.01 ms. MinimalModbus debug mode. Response from instrument: '\x00\x04\x01\x01\x01\x90\x84\x00' (8 bytes), roundtrip time: 527.5 ms. Timeout setting: 500.0 ms. Value error |
From: <and...@gm...> - 2014-11-07 15:38:01
|
Hello I have a device with a funny problem. I’t consistently gives me a empty byte in the end and beginning of each message. Tried to fix every angle of hardware aspects including using termination resistors, but with no luck. It leeds me to believe developers of the device might taken a shortcut or two in implementing modbus protocol. I need some way to strip my response from the first and last byte of the response, but how? I don’t know how and where to edit your code, but the functions should do basically the same thing as when one is working with ascii messages, but in my case removing /x00 instead. See the end of the diagnostic and you’ll realize the answer is much so correct, when removing first and last byte. It is tested with several registers and they all give “correct” responses. Writing to the device is working like a charm! ## Diagnostic output from minimalmodbus ## Minimalmodbus version: 0.6 Minimalmodbus status: Beta Revision: $Rev: 200 $ Revision date: $Date: 2014-06-22 01:29:19 +0200 (Sun, 22 Jun 2014) $ File name (with relative path): /usr/local/lib/python2.7/dist-packages/minimalmodbus.pyc Full file path: /usr/local/lib/python2.7/dist-packages/minimalmodbus.pyc pySerial version: 2.5 pySerial full file path: /usr/lib/python2.7/dist-packages/serial/__init__.pyc Platform: linux2 Filesystem encoding: 'UTF-8' Byteorder: little Python version: 2.7.3 (default, Mar 18 2014, 05:13:23) [GCC 4.6.3] Python version info: sys.version_info(major=2, minor=7, micro=3, releaselevel='final', serial=0) Python flags: sys.flags(debug=0, py3k_warning=0, division_warning=0, division_new=0, inspect=0, interactive=0, optimize=0, dont_write_bytecode=0, no_user_site=0, no_site=0, ignore_environment=0, tabcheck=0, verbose=0, unicode=0, bytes_warning=0, hash_randomization=0) Python argv: ['./rstest.py'] Python prefix: '/usr' Python exec prefix: '/usr' Python executable: '/usr/bin/python' Long info: sys.long_info(bits_per_digit=15, sizeof_digit=2) Float repr style: 'short' Variable __name__: minimalmodbus Current directory: /home/pi/bin/test Python path: /home/pi/bin/test /usr/lib/python2.7 /usr/lib/python2.7/plat-linux2 /usr/lib/python2.7/lib-tk /usr/lib/python2.7/lib-old /usr/lib/python2.7/lib-dynload /usr/local/lib/python2.7/dist-packages /usr/lib/python2.7/dist-packages /usr/lib/pymodules/python2.7 ## End of diagnostic output ## minimalmodbus.Instrument<id=0xb6d09508, address=4, mode=rtu, close_port_after_each_call=True, precalculate_read_size=False, debug=True, serial=Serial<id=0xb6d0b210, open=False>(port='/dev/ttyUSB0', baudrate=19200, bytesize=8, parity='N', stopbits=1, timeout=0.5, xonxoff=False, rtscts=False, dsrdtr=False)> MinimalModbus debug mode. Writing to instrument (expecting 1000 bytes back): '\x04\x01\x00\x00\x00\x01\xfd\x9f' MinimalModbus debug mode. No sleep required before write. Time since previous read: 1415374511529.1 ms, minimum silent period: 2.01 ms. MinimalModbus debug mode. Response from instrument: '\x00\x04\x01\x01\x01\x90\x84\x00' (8 bytes), roundtrip time: 527.5 ms. Timeout setting: 500.0 ms. Value error |
From: Jonas B. <jon...@ho...> - 2014-11-03 20:33:50
|
Great, thanks Edwin! It will be included in next release. Best regards Jonas <-----Ursprungligt Meddelande-----> From: Edwin van den Oetelaar [ed...@oe...] Sent: 31/10/2014 2:45:09 PM To: min...@li... Subject: [Minimalmodbus-list] patch for running with python 2.6 Hello everyone, I tried running on python Python 2.6.6 (r266:84292, Dec 27 2010, 21:57:32) on a iMx233 board and that did not work.. Format strings must have position indicators. So : '{}'.format(77) will not work but '{0}'.format(777) will work fine I made a patch to fix my problems and you can add it without risk. Hope this is useful, Edwin van den Oetelaar |
From: Edwin v. d. O. <ed...@oe...> - 2014-10-31 13:45:22
|
--- /home/oetelaar/.virtualenvs/nuts-nomad/lib/python2.7/site-packages/minimalmodbus.py 2014-10-05 13:12:45.000000000 +0200 +++ ownCloud/workspace_BertHofstede/TestExperiments/PythonModbus/minimalmodbus.py 2014-10-31 14:28:15.507757958 +0100 @@ -154,7 +154,7 @@ def __repr__(self): """String representation of the :class:`.Instrument` object.""" - return "{}.{}<id=0x{:x}, address={}, mode={}, close_port_after_each_call={}, precalculate_read_size={}, debug={}, serial={}>".format( + return "{0}.{1}<id=0x{2:x}, address={3}, mode={4}, close_port_after_each_call={5}, precalculate_read_size={6}, debug={7}, serial={8}>".format( self.__module__, self.__class__.__name__, id(self), @@ -783,8 +783,8 @@ number_of_bytes_to_read = _predictResponseSize(self.mode, functioncode, payloadToSlave) except: if self.debug: - template = 'MinimalModbus debug mode. Could not precalculate response size for Modbus {} mode. ' + \ - 'Will read {} bytes. Message: {!r}' + template = 'MinimalModbus debug mode. Could not precalculate response size for Modbus {0} mode. ' + \ + 'Will read {1} bytes. Message: {2!r}' _print_out(template.format(self.mode, number_of_bytes_to_read, message)) # Communicate @@ -844,7 +844,7 @@ _checkInt(number_of_bytes_to_read) if self.debug: - _print_out('\nMinimalModbus debug mode. Writing to instrument (expecting {} bytes back): {!r}'. \ + _print_out('\nMinimalModbus debug mode. Writing to instrument (expecting {0} bytes back): {1!r}'. \ format(number_of_bytes_to_read, message)) if self.close_port_after_each_call: @@ -863,8 +863,8 @@ sleep_time = minimum_silent_period - time_since_read if self.debug: - template = 'MinimalModbus debug mode. Sleeping for {:.1f} ms. ' + \ - 'Minimum silent period: {:.1f} ms, time since read: {:.1f} ms.' + template = 'MinimalModbus debug mode. Sleeping for {0:.1f} ms. ' + \ + 'Minimum silent period: {1:.1f} ms, time since read: {2:.1f} ms.' text = template.format( sleep_time * _SECONDS_TO_MILLISECONDS, minimum_silent_period * _SECONDS_TO_MILLISECONDS, @@ -875,7 +875,7 @@ elif self.debug: template = 'MinimalModbus debug mode. No sleep required before write. ' + \ - 'Time since previous read: {:.1f} ms, minimum silent period: {:.2f} ms.' + 'Time since previous read: {0:.1f} ms, minimum silent period: {1:.2f} ms.' text = template.format( time_since_read * _SECONDS_TO_MILLISECONDS, minimum_silent_period * _SECONDS_TO_MILLISECONDS) @@ -896,8 +896,8 @@ answer = str(answer, encoding='latin1') # Convert types to make it Python3 compatible if self.debug: - template = 'MinimalModbus debug mode. Response from instrument: {!r} ({} bytes), ' + \ - 'roundtrip time: {:.1f} ms. Timeout setting: {:.1f} ms.\n' + template = 'MinimalModbus debug mode. Response from instrument: {0!r} ({1} bytes), ' + \ + 'roundtrip time: {2:.1f} ms. Timeout setting: {3:.1f} ms.\n' text = template.format( answer, len(answer), @@ -1002,22 +1002,22 @@ # Validate response length if mode == MODE_ASCII: if len(response) < MINIMAL_RESPONSE_LENGTH_ASCII: - raise ValueError('Too short Modbus ASCII response (minimum length {} bytes). Response: {!r}'.format( \ + raise ValueError('Too short Modbus ASCII response (minimum length {0} bytes). Response: {1!r}'.format( \ MINIMAL_RESPONSE_LENGTH_ASCII, response)) elif len(response) < MINIMAL_RESPONSE_LENGTH_RTU: - raise ValueError('Too short Modbus RTU response (minimum length {} bytes). Response: {!r}'.format( \ + raise ValueError('Too short Modbus RTU response (minimum length {0} bytes). Response: {1!r}'.format( \ MINIMAL_RESPONSE_LENGTH_RTU, response)) # Validate the ASCII header and footer. if mode == MODE_ASCII: if response[BYTEPOSITION_FOR_ASCII_HEADER] != _ASCII_HEADER: - raise ValueError('Did not find header ({!r}) as start of ASCII response. The plain response is: {!r}'.format( \ + raise ValueError('Did not find header ({0:!r}) as start of ASCII response. The plain response is: {1!r}'.format( \ _ASCII_HEADER, response)) elif response[-len(_ASCII_FOOTER):] != _ASCII_FOOTER: - raise ValueError('Did not find footer ({!r}) as end of ASCII response. The plain response is: {!r}'.format( \ + raise ValueError('Did not find footer ({0:!r}) as end of ASCII response. The plain response is: {1!r}'.format( \ _ASCII_FOOTER, response)) @@ -1025,8 +1025,8 @@ response = response[1:-2] if len(response) % 2 != 0: - template = 'Stripped ASCII frames should have an even number of bytes, but is {} bytes. ' + \ - 'The stripped response is: {!r} (plain response: {!r})' + template = 'Stripped ASCII frames should have an even number of bytes, but is {0} bytes. ' + \ + 'The stripped response is: {1!r} (plain response: {2!r})' raise ValueError(template.format(len(response), response, plainresponse)) # Convert the ASCII (stripped) response string to RTU-like response string @@ -1045,7 +1045,7 @@ calculatedChecksum = calculateChecksum(responseWithoutChecksum) if receivedChecksum != calculatedChecksum: - template = 'Checksum error in {} mode: {!r} instead of {!r} . The response is: {!r} (plain response: {!r})' + template = 'Checksum error in {0} mode: {1!r} instead of {2!r} . The response is: {3!r} (plain response: {4!r})' text = template.format( mode, receivedChecksum, @@ -1057,17 +1057,17 @@ responseaddress = ord(response[BYTEPOSITION_FOR_SLAVEADDRESS]) if responseaddress != slaveaddress: - raise ValueError('Wrong return slave address: {} instead of {}. The response is: {!r}'.format( \ + raise ValueError('Wrong return slave address: {0} instead of {1}. The response is: {2!r}'.format( \ responseaddress, slaveaddress, response)) # Check function code receivedFunctioncode = ord(response[BYTEPOSITION_FOR_FUNCTIONCODE]) if receivedFunctioncode == _setBitOn(functioncode, BITNUMBER_FUNCTIONCODE_ERRORINDICATION): - raise ValueError('The slave is indicating an error. The response is: {!r}'.format(response)) + raise ValueError('The slave is indicating an error. The response is: {0!r}'.format(response)) elif receivedFunctioncode != functioncode: - raise ValueError('Wrong functioncode: {} instead of {}. The response is: {!r}'.format( \ + raise ValueError('Wrong functioncode: {0} instead of {1}. The response is: {2!r}'.format( \ receivedFunctioncode, functioncode, response)) # Read data payload @@ -1137,7 +1137,7 @@ number_of_registers * _NUMBER_OF_BYTES_PER_REGISTER else: - raise ValueError('Wrong functioncode: {}. The payload is: {!r}'.format( \ + raise ValueError('Wrong functioncode: {0}. The payload is: {1!r}'.format( \ functioncode, payloadToSlave)) # Calculate number of bytes to read @@ -1691,21 +1691,21 @@ _checkString(hexstring, description='hexstring') if len(hexstring) % 2 != 0: - raise ValueError('The input hexstring must be of even length. Given: {!r}'.format(hexstring)) + raise ValueError('The input hexstring must be of even length. Given: {0!r}'.format(hexstring)) if sys.version_info[0] > 2: by = bytes(hexstring, 'latin1') try: return str(binascii.unhexlify(by), encoding='latin1') except binascii.Error as err: - new_error_message = 'Hexdecode reported an error: {!s}. Input hexstring: {}'.format(err.args[0], hexstring) + new_error_message = 'Hexdecode reported an error: {0!s}. Input hexstring: {1}'.format(err.args[0], hexstring) raise TypeError(new_error_message) else: try: return hexstring.decode('hex') except TypeError as err: - raise TypeError('Hexdecode reported an error: {}. Input hexstring: {}'.format(err.message, hexstring)) + raise TypeError('Hexdecode reported an error: {0}. Input hexstring: {1}'.format(err.message, hexstring)) def _bitResponseToValue(bytestring): |
From: Russell N. <rus...@gm...> - 2014-10-20 20:59:17
|
Ahhhh, I see the problem: It was 6 in 0.4 and you've since changed it to 5 in 0.6. All is right with the world; thanks for your attention! On Mon, Oct 20, 2014 at 4:03 PM, Jonas Berg <jon...@ho...> wrote: > Hi again Russel! > That is very strange. If you look at the code for write_bit: > > http://minimalmodbus.sourceforge.net/_modules/minimalmodbus.html#Instrument.write_bit > it contains: > > _checkFunctioncode(functioncode, [5, 15]) > > Please check again with unmodified MinimalModbus code. > I might have made some mistake when commiting it. > > Best regards > Jonas > > <-----Ursprungligt Meddelande-----> > *From: Russell Nelson [rus...@gm... <rus...@gm...>]* > Sent: 20/10/2014 7:12:05 AM > To: jon...@ho... > Cc: min...@li... > Subject: Re: [Minimalmodbus-list] Morningstar SunSaver MPPT > > > Indeed that works, but only if I've modified minimalmodbus to include > function code 5 in the call to _checkFunctioncode that currently only lists > 6 and 16. > > On Sun, Oct 19, 2014 at 4:33 PM, Jonas Berg <jon...@ho...> wrote: > >> Best Russel, >> sorry for the late reply. >> >> I was looking into the documentation for your battery charging regulator: >> >> http://support.morningstarcorp.com/wp-content/uploads/2014/07/SSMPPT.APP_.Modbus.EN_.10.pdf >> >> On page 5, it says Write Single Coil (0x05). The address for reset is >> 0x00F. >> >> "Single Coil" is in practical terms a bit. So I guess you should use the >> command: >> write_bit(0xff, 1, >> >> >> >> *functioncode=5) See >> http://minimalmodbus.sourceforge.net/#implemented-functions >> <http://minimalmodbus.sourceforge.net/#implemented-functions> *Please >> give it a try, and report back. >> >> Best regards >> Jonas >> >> <-----Ursprungligt Meddelande-----> >> *From: Russell Nelson [rus...@gm... <rus...@gm...>]* >> Sent: 30/9/2014 3:34:06 PM >> To: min...@li... >> Subject: [Minimalmodbus-list] Morningstar SunSaver MPPT >> >> Hi. I'm trying to command the Morningstar SunSaver MPPT to reset. >> That's register 0xff, writing a 1. Trouble is that they only support >> using function 5 to do that, and write_register() rejects all but 6 >> and 10. I got it to work by adding 5 to the list. I don't know if this >> is the right thing to do in general, but it works for me. Hope this is >> helpful. Like this: >> >> >> >> _checkFunctioncode(functioncode, [5, 6, 16]) >> >> >> and then like this: >> instrument.write_register(0xff,1, functioncode=5) >> >> ------------------------------------------------------------------------------ >> >> Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer >> Achieve PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports >> Are you Audit-Ready for PCI DSS 3.0 Compliance? Download White paper >> Comply to PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer >> >> http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.clktrk >> _______________________________________________ >> Minimalmodbus-list mailing list >> Min...@li... >> https://lists.sourceforge.net/lists/listinfo/minimalmodbus-list >> . >> > > |
From: Jonas B. <jon...@ho...> - 2014-10-20 20:03:33
|
Hi again Russel! That is very strange. If you look at the code for write_bit: http://minimalmodbus.sourceforge.net/_modules/minimalmodbus.html#Instrum ent.write_bit it contains: _checkFunctioncode(functioncode, [5, 15]) Please check again with unmodified MinimalModbus code. I might have made some mistake when commiting it. Best regards Jonas <-----Ursprungligt Meddelande-----> From: Russell Nelson [rus...@gm...] Sent: 20/10/2014 7:12:05 AM To: jon...@ho... Cc: min...@li... Subject: Re: [Minimalmodbus-list] Morningstar SunSaver MPPT Indeed that works, but only if I've modified minimalmodbus to include function code 5 in the call to _checkFunctioncode that currently only lists 6 and 16. On Sun, Oct 19, 2014 at 4:33 PM, Jonas Berg < jon...@ho... <mailto:jon...@ho...> > wrote: Best Russel, sorry for the late reply. I was looking into the documentation for your battery charging regulator: http://support.morningstarcorp.com/wp-content/uploads/2014/07/SSMPPT.APP _.Modbus.EN_.10.pdf On page 5, it says Write Single Coil (0x05). The address for reset is 0x00F. "Single Coil" is in practical terms a bit. So I guess you should use the command: write_bit(0xff, 1, functioncode=5) See http://minimalmodbus.sourceforge.net/#implemented-functions Please give it a try, and report back. Best regards Jonas <-----Ursprungligt Meddelande-----> From: Russell Nelson [ rus...@gm... <mailto:rus...@gm...> ] Sent: 30/9/2014 3:34:06 PM To: min...@li... <mailto:min...@li...> Subject: [Minimalmodbus-list] Morningstar SunSaver MPPT Hi. I'm trying to command the Morningstar SunSaver MPPT to reset. That's register 0xff, writing a 1. Trouble is that they only support using function 5 to do that, and write_register() rejects all but 6 and 10. I got it to work by adding 5 to the list. I don't know if this is the right thing to do in general, but it works for me. Hope this is helpful. Like this: _checkFunctioncode(functioncode, [5, 6, 16]) and then like this: instrument.write_register(0xff,1, functioncode=5) ------------------------------------------------------------------------ ------ Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer Achieve PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports Are you Audit-Ready for PCI DSS 3.0 Compliance? Download White paper Comply to PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.cl ktrk <http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.c lktrk> _______________________________________________ Minimalmodbus-list mailing list Min...@li... <mailto:Min...@li...> https://lists.sourceforge.net/lists/listinfo/minimalmodbus-list . |
From: Russell N. <rus...@gm...> - 2014-10-20 05:12:14
|
Indeed that works, but only if I've modified minimalmodbus to include function code 5 in the call to _checkFunctioncode that currently only lists 6 and 16. On Sun, Oct 19, 2014 at 4:33 PM, Jonas Berg <jon...@ho...> wrote: > Best Russel, > sorry for the late reply. > > I was looking into the documentation for your battery charging regulator: > > http://support.morningstarcorp.com/wp-content/uploads/2014/07/SSMPPT.APP_.Modbus.EN_.10.pdf > > On page 5, it says Write Single Coil (0x05). The address for reset is > 0x00F. > > "Single Coil" is in practical terms a bit. So I guess you should use the > command: > write_bit(0xff, 1, > > > > *functioncode=5) See > http://minimalmodbus.sourceforge.net/#implemented-functions > <http://minimalmodbus.sourceforge.net/#implemented-functions> *Please > give it a try, and report back. > > Best regards > Jonas > > <-----Ursprungligt Meddelande-----> > *From: Russell Nelson [rus...@gm... <rus...@gm...>]* > Sent: 30/9/2014 3:34:06 PM > To: min...@li... > Subject: [Minimalmodbus-list] Morningstar SunSaver MPPT > > Hi. I'm trying to command the Morningstar SunSaver MPPT to reset. > That's register 0xff, writing a 1. Trouble is that they only support > using function 5 to do that, and write_register() rejects all but 6 > and 10. I got it to work by adding 5 to the list. I don't know if this > is the right thing to do in general, but it works for me. Hope this is > helpful. Like this: > > > > _checkFunctioncode(functioncode, [5, 6, 16]) > > > and then like this: > instrument.write_register(0xff,1, functioncode=5) > > ------------------------------------------------------------------------------ > > Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer > Achieve PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports > Are you Audit-Ready for PCI DSS 3.0 Compliance? Download White paper > Comply to PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer > > http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.clktrk > _______________________________________________ > Minimalmodbus-list mailing list > Min...@li... > https://lists.sourceforge.net/lists/listinfo/minimalmodbus-list > . > |
From: Jonas B. <jon...@ho...> - 2014-10-19 20:34:04
|
Best Russel, sorry for the late reply. I was looking into the documentation for your battery charging regulator: http://support.morningstarcorp.com/wp-content/uploads/2014/07/SSMPPT.APP _.Modbus.EN_.10.pdf On page 5, it says Write Single Coil (0x05). The address for reset is 0x00F. "Single Coil" is in practical terms a bit. So I guess you should use the command: write_bit(0xff, 1, functioncode=5) See http://minimalmodbus.sourceforge.net/#implemented-functions Please give it a try, and report back. Best regards Jonas <-----Ursprungligt Meddelande-----> From: Russell Nelson [rus...@gm...] Sent: 30/9/2014 3:34:06 PM To: min...@li... Subject: [Minimalmodbus-list] Morningstar SunSaver MPPT Hi. I'm trying to command the Morningstar SunSaver MPPT to reset. That's register 0xff, writing a 1. Trouble is that they only support using function 5 to do that, and write_register() rejects all but 6 and 10. I got it to work by adding 5 to the list. I don't know if this is the right thing to do in general, but it works for me. Hope this is helpful. Like this: _checkFunctioncode(functioncode, [5, 6, 16]) and then like this: instrument.write_register(0xff,1, functioncode=5) ------------------------------------------------------------------------ ------ Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer Achieve PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports Are you Audit-Ready for PCI DSS 3.0 Compliance? Download White paper Comply to PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.cl ktrk _______________________________________________ Minimalmodbus-list mailing list Min...@li... https://lists.sourceforge.net/lists/listinfo/minimalmodbus-list . |
From: Jonas B. <jon...@ho...> - 2014-10-19 20:29:21
|
Best Andreas! The MinimalModbus module itself should not be any problem. But it depends on the PySerial module. I do not know if it possible to instal PySerial on it, but as also that is pure Python it should probably be possible. As MinimalModbus is a single file, you should be able just to copy it to your device. So again, try to install PySerial, then MinimalModbus should work fine. Best regards Jonas <-----Ursprungligt Meddelande-----> From: Andreas Feiler [and...@ps...] Sent: 15/10/2014 11:15:18 PM To: min...@li... Subject: [Minimalmodbus-list] MinimlaModbus Hi Jonas, i am interested in your code. I am Using a controller (picture below) which enables wireless communication and on the field side, there is a RS232 port. The code on the Module is written in Python. The module uses a TELIT (perhaps you know this chip) and supports: Python script interpreter engine v. 2.7.2 multi thread Can you help me: How can I check if it is possible to use your library with this controller? Are there any challenges to use the minimalmodbus on a wireless board? If yes, how can I check if my serial port matches with your minimalmodbus application..Can I see it on the library I use for the serial port ..please for help. Thnaks Best regards Andreas Round Solutions HSPA+ Terminal - Aarlogic® (TER-HN910) Mit freundlichen Grüßen / Best regards Andreas Feiler Dipl. Ing. (TU) Logo-PS-sytec_Sig PSsystec Andreas Feiler Jochstr.7 86 356 Augsburg Tel: +49 (0) 821 - 56 75 94 92 Fax: +49 (0) 821 - 56 75 94 96 Mobil: +49 (0) 163 - 86 99 320 and...@ps... <mailto:and...@ps...> www.pssystec.de <http://www.pssystec-gmbh.de/> Der Inhalt dieser E-Mail ist ausschließlich für den Adressaten bestimmt. Sollten Sie diese E-Mail irrtümlich erhalten haben, so beachten Sie bitte, dass jede Form der Veröffentlichung, Vervielfältigung oder Weitergabe des Inhalts unzulässig ist. Bitte setzen Sie sich in diesem Fall umgehend mit uns in Verbindung. |
From: Russell N. <rus...@gm...> - 2014-09-30 13:34:16
|
Hi. I'm trying to command the Morningstar SunSaver MPPT to reset. That's register 0xff, writing a 1. Trouble is that they only support using function 5 to do that, and write_register() rejects all but 6 and 10. I got it to work by adding 5 to the list. I don't know if this is the right thing to do in general, but it works for me. Hope this is helpful. Like this: _checkFunctioncode(functioncode, [5, 6, 16]) and then like this: instrument.write_register(0xff,1, functioncode=5) |
From: Jonas B. <jon...@ho...> - 2014-09-03 20:27:09
|
Best Andreas! Sorry for my late answer. You are right, it seems that your Modbus slave is behaving little strange. We ask for a single bit, but your device seems to respond on more than one. In the document it says "The LSB of the first data byte contains the input addressed in the query". So when we ask for a single bit, only the LSB should be affected. I guess I prefer MinimalModbus to complain when something out-of-spec is received, but I plan to put your patch on the homepage for others with the same problem. This will happen when I update it later this year. Thanks a lot /Jonas <-----Ursprungligt Meddelande-----> From: Andreas Treutler [and...@t-...] Sent: 14/8/2014 11:31:39 PM To: min...@li... Subject: [Minimalmodbus-list] Fehlermeldung function _bitRespondToValue Dear Jonas, thanks for your software. I will try to use it to read my modbus devices. But there is a error in bit-read (1,2). If I want to read a bit, I use >>>instrument.read_bit(0,2) If there are more then one bit set, I get an error. i.e. Writing: \x1e\x02\x00\x00\x00\x01 +CRC Response \x1e\x02\x01\x03 +CRC These answer contains InputBit 0 and InputBit 1 set. The function _bitResponseToValue go to error. It is possible, that this is a wrong implementation of the modbus protocoll in the client device. In the "MODBUS Application Protocol Specification V1.1b3" (Site 13) is written: >If the returned input quantity is not a multiple of eight, the remaining bits in the final data byte >will be padded with zeros (toward the high order end of the byte). The Byte Count field >specifies the quantity of complete bytes of data. My client do not fill with zero - it fills with following bits. But these are don't care. To solve the problem, please change (line 1729ff): > if bytestring == RESPONSE_ON: > return 1 > elif bytestring == RESPONSE_OFF: > return 0 > else: > raise ValueError('Could not convert bit response to a value. Input: {0!r}'.format(bytestring)) to this line > return ord(bytestring) & 1 In my example, now it works. And it will work with both kind of client. Please check the changes. Thanks Andreas Treutler p.s. Cubietruck with RS485-USB-Dongle Modbus 2DI/2DO ordered by aliexpress.com http://www.aliexpress.com/item/Modbus-RTU-protocol-2-relay-outputs-2-dig ital-inputs-RS485-acquisition-module/968729687.html Arch Linux Python 3.4.1 Pyserial 2.7 MinimalModbus 0.6 ------------------------------------------------------------------------ ------ _______________________________________________ Minimalmodbus-list mailing list Min...@li... https://lists.sourceforge.net/lists/listinfo/minimalmodbus-list . |
From: Andreas T. <and...@t-...> - 2014-08-14 21:31:49
|
Dear Jonas, thanks for your software. I will try to use it to read my modbus devices. But there is a error in bit-read (1,2). If I want to read a bit, I use >>>instrument.read_bit(0,2) If there are more then one bit set, I get an error. i.e. Writing: \x1e\x02\x00\x00\x00\x01 +CRC Response \x1e\x02\x01\x03 +CRC These answer contains InputBit 0 and InputBit 1 set. The function _bitResponseToValue go to error. It is possible, that this is a wrong implementation of the modbus protocoll in the client device. In the "MODBUS Application Protocol Specification V1.1b3" (Site 13) is written: >If the returned input quantity is not a multiple of eight, the remaining bits in the final data byte >will be padded with zeros (toward the high order end of the byte). The Byte Count field >specifies the quantity of complete bytes of data. My client do not fill with zero - it fills with following bits. But these are don't care. To solve the problem, please change (line 1729ff): > if bytestring == RESPONSE_ON: > return 1 > elif bytestring == RESPONSE_OFF: > return 0 > else: > raise ValueError('Could not convert bit response to a value. Input: {0!r}'.format(bytestring)) to this line > return ord(bytestring) & 1 In my example, now it works. And it will work with both kind of client. Please check the changes. Thanks Andreas Treutler p.s. Cubietruck with RS485-USB-Dongle Modbus 2DI/2DO ordered by aliexpress.com http://www.aliexpress.com/item/Modbus-RTU-protocol-2-relay-outputs-2-digital-inputs-RS485-acquisition-module/968729687.html Arch Linux Python 3.4.1 Pyserial 2.7 MinimalModbus 0.6 |
From: Jonas B. <jon...@ho...> - 2014-08-03 20:33:57
|
Best Dino, thanks for your input. I will definitely improve the debug output to include HEX printout. I also like your idea of passing a serial port object to the constructor. Best regards Jonas <-----Ursprungligt Meddelande-----> From: di...@do... [di...@do...] Sent: 24/7/2014 12:22:49 PM To: py...@us... Subject: MinimalModbus 06 Hi Jonas i like to thank you for this very handy implementation of modbus. I used this to verify my embedded modbusimplmentation and i also based my gui to read data from the device on it. I did 2 small tweaks to it: 1) i dont generate the com port object inside the minmodbus constructor. i generate the com port object within my application and i give it to the mod bus instrument as already opened com object. giving me the advantage that i can run multiple modbus instruments on a single com port without the need to open and close it between calls. Very small change to your consttructor: def __init__(self, port, slaveaddress, mode=MODE_RTU): if port not in _SERIALPORTS or not _SERIALPORTS[port]: self.serial = port #self.serial = _SERIALPORTS[port] = serial.Serial(port=port, baudrate=BAUDRATE, parity=PARITY, bytesize=BYTESIZE, stopbits=STOPBITS, timeout=TIMEOUT) 2) i am using the debug console output a lot, but i could see that it does not translate all my binary data to nice hex strings. not sure why. but i added this work around: def AsciToStr(msg): string="" for c in msg: string += hex(ord(c)) + "; " return string if self.debug: messageStr = AsciToStr(message) _print_out('\nMinimalModbus debug mode. Writing to instrument (expecting {} bytes back): {!r}'. \ format(number_of_bytes_to_read, messageStr)) answerStr = AsciToStr(answer) template = 'MinimalModbus debug mode. Response from instrument: {!r} ({} bytes), ' + \ 'roundtrip time: {:.1f} ms. Timeout setting: {:.1f} ms.\n' text = template.format( answerStr, len(answer), (_LATEST_READ_TIMES.get(self.serial.port, 0) - latest_write_time) * _SECONDS_TO_MILLISECONDS, self.serial.timeout * _SECONDS_TO_MILLISECONDS) _print_out(text) Thank you very much for your great work, i saved me a lot of time. kind regards DINO |
From: Jonas B. <jon...@ho...> - 2014-06-20 14:42:50
|
Hi Luca, thanks for your input! I will add it to the documentation. Best regards Jonas <-----Ursprungligt Meddelande-----> From: Luca Di Gregorio [lu...@gm...] Sent: 20/6/2014 9:03:03 AM To: py...@us... Subject: minimalmodbus - TODO - ? Handle RS485 adapters with echo functionality enabled ? Good morning Jonas, I've read the doc of your library (thank you very much, easy to use, well documented, never fails) and, since a friend and I use a MAX3082 (similar to MAX485) connected to the UART of a Raspberry Pi, we faced with the problem of setting the right voltage to DE and RE at the right time. We've read your considerations about RS-485, maybe the most elegant solution is the patch in the linux kernel, but practically there is an easier and immediate solution: - DE always at high voltage --> transmission always enabled - RE alvays at low voltage --> reception always enabled When the UART transmits, it immediately receives the echo, and then the response from the modbus slave. So we added the line in red in your library, that suppress this echo, to obtain the "clear" response from the slave: ... self.serial.write(message) echo_to_be_discarded = self.serial.read(len(message)) answer = self.serial.read(number_of_bytes_to_read) ... We don't know if with "Handle RS485 adapters with echo functionality enabled" you meant exactly what we did with the line in red, anyway it works perfectly with our stuff, and maybe it can be added in your library with a parameter such like "suppress_rs485_echo" or something similar. It could be really useful for all who try to use integrated circuits like the MAX485, without installing real time patches in the kernel and without getting fools trying to use the RTS in the Raspberry Pi UART. Regards, have a nice day Luca |
From: Jonas B. <jon...@ho...> - 2014-05-29 21:26:52
|
Hi Pawel! Unfortunately MinimalModbus can not be used for implementing a Modbus slave. I guess that the other Python Modbus libraries mentioned on the home page might be useful. See http://minimalmodbus.sourceforge.net/#related-software Best regards Jonas <-----Ursprungligt Meddelande-----> From: Pawel Jablonski [jab...@po...] Sent: 24/5/2014 9:43:00 AM To: min...@li... Subject: [Minimalmodbus-list] Using computer as slave Hello, is it possible to use computer as a slave with minimalmodbus library? In a documentation is only how to use as a master, but I will connect computer with text panel SH-300 which is running only as a master via RS-485 (modbus RTU). Best regards Pawel |