I am reading values from a Battery Management System using two, serial USB-RS485 adaptors (ftdi). I am doing this over MODBUS using the minimal modbus library and python:
# Bank A
# port name, slave address (in decimal)
instrument_A = minimalmodbus.Instrument('/dev/ttyUSB0', 1)
# Bank B
instrument_B = minimalmodbus.Instrument('/dev/ttyUSB1', 1)
# Port on which to send via serial to CAN Shield Arduino
port = '/dev/ttyACM0'
# Initialize CAN Shield Arduino Serial Line
ard = serial.Serial(port, 115200, timeout=5)
// Read something from BMS
socA = instrument_A.read_register(40008)
See picture below
I am reading these values repeatedly, and then sending them over another serial/UART to an arduino which is then controlling some things..
Now this all works absolutely fine on my laptop, which runs ubuntu - but it only works on the Pi for a few reads, after which it fails.
Is the raspberry pi not capable of doing this many serial concurrent processes at once?
Edit:
I have now included the whole python file, as it has been pointed out that the question was not as clear in terms of what is running concurrently etc.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import minimalmodbus
import serial
import syslog
import time
import math
# Some constants which are decided by us, and are sent to the inverter - not coming from the BMS
CONST_BAT_CHARGE_VOLTAGE = 585 # 58,5V
CONST_BAT_DISCHARGE_VOLTAGE = 44 * 10
CONST_BAT_CHRGE_CURR_LIM = 50*10 # Battery Rack DC Charge Current Limitation, integer
VAR_BAT_DCHRG_CURR_LIM = 200*10 # Battery Rack DC Discharge Current Limitation, integer
# Looping constants
running = 1
counter = 0
# Some constants which are decided by us, and are sent to the inverter - not coming from the BMS
# Voltage at which battery need be charged. 58,5V
CONST_BAT_CHARGE_VOLTAGE = 585
# Voltage at which the battery stops discharging
CONST_BAT_DISCHARGE_VOLTAGE = 44 * 10
# Battery Rack DC Charge Current Limitation, integer
VAR_BAT_CHRGE_CURR_LIM = 0 * 10
# Battery Rack DC Discharge Current Limitation, integer
CONST_BAT_DCHRG_CURR_LIM = 200 * 10
CONST_BAT_RCK_AVG_SOC = 75 # Battery Rack, average module SOC Value, integer
CONST_BAT_RCK_AVG_SOH = 98 # Battery Rack, average module SOH Value, integer
# Bank A
# port name, slave address (in decimal)
# instrument_A = minimalmodbus.Instrument('/dev/ttyUSB0', 1)
instrument_A = minimalmodbus.Instrument('/dev/cu.lpss-serial1', 1)
# Bank B
instrument_B = minimalmodbus.Instrument('/dev/cu.lpss-serial2', 1)
# Port on which to send via serial to CAN Shield Arduino
# port = '/dev/ttyACM0'
port = '/dev/cu.usbmodem14421'
# Initialize CAN Shield Arduino Serial Line
ard = serial.Serial(port, 115200, timeout=5)
################### FUNCTIONS ###################
# Convert integer to binary string
def int2bin(i):
if i == 0:
return '0'
s = ''
while i:
if i & 1 == 1:
s = '1' + s
else:
s = '0' + s
i /= 2
return s
# Rounds up to the the ceiling
def ceiling(x):
n = int(x)
return (n if n - 1 < x <= n else n + 1)
# To determine the number of bits within a type of object
def bitLen(int_type):
length = 0
while int_type:
int_type >>= 1
length += 1
return length
# Convert an integer into the parts of its most and least significant bits
def toHex(x):
LSB = x & 0x00FF
MSB = x >> 8
return (LSB, MSB)
# Get battery data
def getBatteryData(InverterAddress):
# Initializing send buffer, this buffer is populated with integers - ready for transformation into a byte array
sendBuffer = []
if InverterAddress == 0x351:
sendBuffer.append(1)
sendBuffer.append(CONST_BAT_CHARGE_VOLTAGE)
sendBuffer.append(VAR_BAT_CHRGE_CURR_LIM)
sendBuffer.append(CONST_BAT_DCHRG_CURR_LIM)
sendBuffer.append(CONST_BAT_DISCHARGE_VOLTAGE)
elif InverterAddress == 0x355:
sendBuffer.append(5)
# Battery Rack A, Average module SOC Value, integer
socA = instrument_A.read_register(40008)
socB = instrument_B.read_register(40008)
soc = ceiling((socA + socB) / 2 / 10)
sendBuffer.append(soc)
# print "SOC For Bank A"
# print socA
# print "SOC For Bank B"
# print socB
# Battery Rack, average module SOH Value, integer
# print "Average SOC Value, both banks"
# print soc
sohA = instrument_A.read_register(40009)
sohB = instrument_B.read_register(40009)
soh = ceiling((sohA + sohB) / 2 / 10)
# print "Average SOH Value, both banks"
# print soh
sendBuffer.append(soh)
elif InverterAddress == 0x35A:
sendBuffer.append(0x65)
sendBuffer.append(0)
sendBuffer.append(0)
else:
sendBuffer.append(0)
byteSendBuffer = bytearray()
for i in sendBuffer:
(LSB, MSB) = toHex(i)
byteSendBuffer.append(LSB)
byteSendBuffer.append(MSB)
# print "The following is the byte array to be sent to the Inverter"
for byte in byteSendBuffer:
print byte
return byteSendBuffer
while running:
print 'Starting read and serial write cycle'
time.sleep(0.3)
ard.write(getBatteryData(0x351))
ard.write(getBatteryData(0x355))
ard.write(getBatteryData(0x35A))
# try:
# print "Attempting read and send..."
# ard.write(getBatteryData(0x351))
# ard.write(getBatteryData(0x355))
# ard.write(getBatteryData(0x35A))
# except:
# print "Failure..."
# pass
time.sleep(0.3)
print 'Ending read and serial write cycle'
"{0:b}".format(an_int_value)