Search code examples
jsonpython-2.7raspberry-pimodbus

how to handle value errors in while 1 loop with scheduling it with a Timer class


i have written a code to read registers of a modbus communication protocol. i have attached the code below as well.. am able to overcome the i/o errors by exception handling method where as the value error that i get , am not able throw that error and move on. Basically what i am doing is am reading the data in the registers and sending up to the server. but my requirement is i have to read the values every second and for 24 hours. so i need to build a robust system that will overcome these value errors and continue executing the threads i have created. the code to read registers is given below :

import minimalmodbus
import serial
from ctypes import *
import struct
import time

minimalmodbus.BAUDRATE = 9600
minimalmodbus.PARITY = serial.PARITY_NONE
minimalmodbus.BYTESIZE = 8
minimalmodbus.TIMEOUT=5
minimalmodbus.CLOSE_PORT_AFTER_EACH_CALL = True
energy_meter = serial.Serial("/dev/ttyUSB0", baudrate=9600,
                            parity=serial.PARITY_NONE,
                            stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=5)
energy_meter = minimalmodbus.Instrument('/dev/ttyUSB0', 2, mode='rtu')
#energy_meter.debug = True


def convert_in_float(value1, value2):
    raw = struct.pack('>HH',value1,value2)
    ans = struct.unpack('>f', raw)[0]
    return ans

def sdm630():
    parameter_list1 = [ 0 ] * 0x12
    parameter_list2 = [ 0 ] * 3
    parameter_list3 = [ 0 ] * 6
    #print energy_meter
    error = 0
    try:
            index = 0
            read_values1  = energy_meter.read_registers( 0 , 0x24, 4)
            for i in range ( 0, 0x24, 2):
                    parameter_list1[index] = convert_in_float( read_values1[i], read_values1[i+1])
                    #print "Parameter read from register : ", hex(index), "is : ", parameter_list1[index] ,"\n"
                    index = index + 1
   #read parameter list 2 & 3 in a similar way
            error = 0
            return error, parameter_list1, parameter_list2, parameter_list3, int(time.time())
    except IOError or ValueError:
            print "got error"
            error = 1
            return error, parameter_list1, parameter_list2, parameter_list3, int(time.time())

also, i have written a separate code to dump all data to server and is shown below :

import time
from pymongo import MongoClient

client = MongoClient('mongodb://10.32.36.40:27017')
db = client.clytics
collection = db['raspberry_pi']



 def pushData(error, value1, value2, value3, value4):
    if error == 0 :
            temp_js = {
            #variable assignment
            }
            temp_js_id = collection.insert(temp_js)

using the above two codes i have created threads for each function. and i only execute this code and after 20 minutes of execution , i get value errors and the program doesnt execute anymore. the main program is given below :

  import time
  from threading import Thread
  from threading import Timer
  from Queue import Queue
  from modbus import sdm630
  from dumpInDB import pushData
  from processData import process_the_data

  DELAY_SEC = 1
  DELAY_MIN = 60
  LOOP_LIMIT = 60


  def getData(q):
    error, parameter_list1, parameter_list2 , parameter_list3, parameter_list4= sdm630()
    print "In getData - data:", parameter_list1, parameter_list2
    q.put([error, parameter_list1, parameter_list2, parameter_list3, parameter_list4])

  def processData(q1,q2):
    sec_data = q1.get()
    min_data =  process_the_data(sec_data)
    print "In processData - data:", sec_data, min_data
    q2.put(min_data)
    print "queue:", q2.qsize()

 def putData(q):
    #print "In putData - data:", value[0], value[1], value[2]
    for i in range(0, q.qsize()):
            value = q.get()
            print "In putData - data:", value[0], value[1], value[2], value[3]
            pushData( value[0], value[1] , value[2], value[3] , value[4])

 def thread1(threadName, q):
    i = 0
    while 1:
            t = Timer( DELAY_SEC, getData, args = (q,))
            t.start()
            time.sleep(DELAY_SEC)

 def thread2( threadName, q1,q2):
    i = 0
    print "in thread2"
    while 1:
    t = Timer( DELAY_SEC, processData,  args = (q1,q2,))
            t.start()
            time.sleep(DELAY_SEC)

 def thread3( threadName, q):
    i = 0
    print "in thread3"
    while 1:
            t = Timer( DELAY_MIN, putData, args =  (q,))
            t.start()
            print "schedule time - min"
            time.sleep(DELAY_MIN)


  queue_second = Queue()
  queue_minute = Queue()
  thread1 = Thread( target=thread1, args=("Thread-1", queue_second) )
  thread2 = Thread( target=thread2, args=("Thread-2", queue_second,      queue_minute) )
  thread3 = Thread( target=thread3, args=("Thread-3", queue_minute) )

  thread1.start()
  thread2.start()
  thread3.start()
  thread1.join()
  thread2.join()
  thread3.join()

am stuck with this error. shown below :

  minimalmodbus.Instrument<id=0xb6b2d9b8, address=2, mode=rtu,          close_port_after_each_call=True, precalculate_read_size=True, debug=False, serial=Serial<id=0xb6b482f0, open=False>(port='/dev/ttyUSB0', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=5, xonxoff=False, rtscts=False, dsrdtr=False)>
  Traceback (most recent call last):
  File "topScript.py", line 7, in <module>
  from modbus import sdm630
  File "/home/pi/scripts/modbus.py", line 60, in <module>
sdm630()
 File "/home/pi/scripts/modbus.py", line 32, in sdm630
 read_values1  = energy_meter.read_registers( 0 , 0x24, 4)
   File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 498, in read_registers
   numberOfRegisters=numberOfRegisters, payloadformat='registers')
    File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 697, in _genericCommand
    payloadFromSlave = self._performCommand(functioncode, payloadToSlave)
    File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 798, in _performCommand
    payloadFromSlave = _extractPayload(response, self.address, self.mode, functioncode)
   File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 1075, in _extractPayload
   raise ValueError(text)
   ValueError: Checksum error in rtu mode: '\xa6\xe6' instead of '\xf7[' .    The response is: '\xff\xf7HCeN\xce\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\x80\x00\x00?\x80\x00\x00?\x80\x00\x00\xa6\xe6' (plain response: '\xff\xf7HCeN\xce\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\

sometimes value error keeps popping up for sometime and finally fails and gives a message saying no more threads can be created.(reached to maximum level)


Solution

  • Your syntax to handle multiple exceptions is wrong. Use something like:

    except (ValueError, IOError):

    For more details see the Python tutorial https://docs.python.org/2/tutorial/errors.html