Cannot unpack noniterable bool object - python

I'm new to Python and posting on SO.
I'm doing a class project on trying to create an automated climate control system with a Raspberry pi(Pi4 4GB) and a DHT.
Here is my current error and code and I'm not sure what's causing the fail in the loop. It works for a while then errors out. It seems to error when it gets a bad read from the sensor, but until then it works fine.
Traceback (most recent call last):
File "/home/pi/raphael-kit/python/Climatecontrol.py", line 156, in <module>
main()
File "/home/pi/raphael-kit/python/Climatecontrol.py", line 118, in main
humidity, temperature = readDht11()
TypeError: cannot unpack non-iterable bool object
import RPi.GPIO as GPIO
import time
import LCD1602
dhtPin = 17
relayPin = 23 # Set GPIO23 as control pin
set_temp = 25 # this is the required temperature
GPIO.setmode(GPIO.BCM)
# Set relayPin's mode to output,
# and initial level to High(3.3v)
GPIO.setup(relayPin, GPIO.OUT, initial=GPIO.HIGH)
MAX_UNCHANGE_COUNT = 100
STATE_INIT_PULL_DOWN = 1
STATE_INIT_PULL_UP = 2
STATE_DATA_FIRST_PULL_DOWN = 3
STATE_DATA_PULL_UP = 4
STATE_DATA_PULL_DOWN = 5
def readDht11():
GPIO.setup(dhtPin, GPIO.OUT)
GPIO.output(dhtPin, GPIO.HIGH)
time.sleep(0.05)
GPIO.output(dhtPin, GPIO.LOW)
time.sleep(0.02)
GPIO.setup(dhtPin, GPIO.IN, GPIO.PUD_UP)
unchanged_count = 0
last = -1
data = []
while True:
current = GPIO.input(dhtPin)
data.append(current)
if last != current:
unchanged_count = 0
last = current
else:
unchanged_count += 1
if unchanged_count > MAX_UNCHANGE_COUNT:
break
state = STATE_INIT_PULL_DOWN
lengths = []
current_length = 0
for current in data:
current_length += 1
if state == STATE_INIT_PULL_DOWN:
if current == GPIO.LOW:
state = STATE_INIT_PULL_UP
else:
continue
if state == STATE_INIT_PULL_UP:
if current == GPIO.HIGH:
state = STATE_DATA_FIRST_PULL_DOWN
else:
continue
if state == STATE_DATA_FIRST_PULL_DOWN:
if current == GPIO.LOW:
state = STATE_DATA_PULL_UP
else:
continue
if state == STATE_DATA_PULL_UP:
if current == GPIO.HIGH:
current_length = 0
state = STATE_DATA_PULL_DOWN
else:
continue
if state == STATE_DATA_PULL_DOWN:
if current == GPIO.LOW:
lengths.append(current_length)
state = STATE_DATA_PULL_UP
else:
continue
if len(lengths) != 40:
#print ("Data not good, skip")
return False
shortest_pull_up = min(lengths)
longest_pull_up = max(lengths)
halfway = (longest_pull_up + shortest_pull_up) / 2
bits = []
the_bytes = []
byte = 0
for length in lengths:
bit = 0
if length > halfway:
bit = 1
bits.append(bit)
#print ("bits: %s, length: %d" % (bits, len(bits)))
for i in range(0, len(bits)):
byte = byte << 1
if (bits[i]):
byte = byte | 1
else:
byte = byte | 0
if ((i + 1) % 8 == 0):
the_bytes.append(byte)
byte = 0
#print (the_bytes)
checksum = (the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3]) & 0xFF
#if the_bytes[4] != checksum:
#print ("Data not good, skip")
#return False
return the_bytes[0], the_bytes[2]
def main():
while True:
humidity, temperature = readDht11()
if humidity is not None and temperature is not None:
print("Temp={0:0.1f}*C Humidity={1:0.1f}%".format(temperature, humidity))
# test for low temperature
if temperature < set_temp:
print(GPIO.output(relayPin, GPIO.LOW))
# test for high temperature
if temperature > (set_temp + 1):
print(GPIO.output(relayPin, GPIO.HIGH))
else:
print("Failed to retrieve data from humidity sensor")
time.sleep(5) #this is the time between taking readings and acting on them you can reduce it but not below 5 seconds
# Define a destroy function for clean up everything after
# the script finished
def setup():
LCD1602.init(0x27, 1) # init(slave address, background light)
LCD1602.write(0, 0, 'Temperature: %s C')
LCD1602.write(1, 1, 'humidity: %s %%')
time.sleep(2)
def destroy():
# set relay to off
GPIO.output(relayPin, GPIO.LOW)
# Release resource
GPIO.cleanup()
if __name__ == '__main__':
try:
setup()
except KeyboardInterrupt:
destroy()
as a note I haven't managed to get the LCD working in tandem but im more worried about the main functionality

Related

Error - Takes 1 positional argument but 2 were given

I'm getting an error message saying 'Traceback (most recent call last): File "C:\Users\SUL-I\fatest2.py", line 42, in leftsensor = fa.ReadLine(0) File "C:\Users\SUL-I\FA.py", line 180, in ReadLine self._flush(self) TypeError: _flush() takes 1 positional argument but 2 were given' when I run a bit of Python code I've written.
Here is the code:
#brings in external references
import FA
import time
#defines some constants
black = 0
white = 200
correction = 10
w = 0
#controls the first robot, remember to update the com port number
fa = FA.Create()
comport = 7
fa.ComOpen(comport)
time.sleep(5)
fa.PlayNote(294,800)
fa.PlayNote(330,800)
fa.PlayNote(262,800)
fa.LEDWrite(24)
time.sleep(0.25)
fa.LEDWrite(60)
time.sleep(0.25)
fa.LEDWrite(36)
time.sleep(0.25)
fa.LEDWrite(102)
time.sleep(0.25)
fa.LEDWrite(66)
time.sleep(0.25)
fa.LEDWrite(195)
time.sleep(0.25)
fa.LEDWrite(129)
time.sleep(0.25)
fa.LEDWrite(195)
time.sleep(0.25)
fa.LEDWrite(66)
time.sleep(0.25)
fa.LEDWrite(102)
time.sleep(0.25)
fa.LEDWrite(36)
time.sleep(0.25)
fa.LEDWrite(60)
leftsensor = fa.ReadLine(0)
rightsensor = fa.ReadLine(1)
while w < 100:
if leftsensor >= white:
fa.SetMotors(20,10)
elif rightsensor >= white:
fa.SetMotors(10,20)
else:
fa.Forwards(10)
w = w+1
ComClose(comport)
Here is ReadLine in the FA module:
def ReadLine(self, index):
"""Read the line sensor value
Args:
index: Line sensor to query (0 to 1)
Returns:
int: Value of Line sensor (0 to 4095)
"""
self._flush(self)
s = 'ReadLine {0}\n'.format(int(index))
self.__ser.write(s.encode())
r = self._readval("ReadLine", 1, 1)
return(r);
definition of readval:
def _readval(self, cmd, loop_max):
r = -1
loop = 0
while (loop < loop_max):
try:
r = int(self.__ser.readline().rstrip())
if (self.__verbose != 0):
msg = '{0}: {1}'.format(cmd, r)
print(msg)
loop = loop_max + 1 #break out of loop
except ValueError:
if (self.__verbose != 0):
msg = '{0}: No return({1})'.format(cmd,loop)
print(msg)
loop = loop + 1
return(r);
Having resolved the error involving _flush_, your second error occurs for similar reasons.
Compare the definition of _readval:
def _readval(self, cmd, loop_max):
to your call:
r = self._readval("ReadLine", 1, 1)
"Readline" is assigned to cmd, and the first 1 is assigned to loop_max. There are no parameter left for the second 1 to be assigned to, so you get the observed error.

Python - Thread copied duplicate

Am trying to do multithreading in my python app. I got main thread which creates sub-threads. However, for testing am only using 1 thread. The task that the thread must do is collect data and then store it in DB. But, I can see it stores it twice, after debugging I found that I get 2 threads instead of 1.
main program :
app = webApp.app
def main_program():
sleep(3)
while True:
Sensor.sensors.items()
def start_webApp():
bottle.run(app=app, host='0.0.0.0', port=8080, reloader=True, debug=True)
if __name__ == '__main__':
app_thread = threading.Thread(target=start_webApp).start()
s1_thread = threading.Thread(target=sensor_thread.start_sensor_reading, args=(14, SL.bedroom_1,), name="Sensor_1")
s1_thread.start()
main_program()
thread file
def start_sensor_reading(sensor_pin, sensor_location):
sleep(3)
global sensor, current, pulses, sensor_status
sensor = DigitalInputDevice(sensor_pin)
current = WFS.isIdle
pulses = 0
valve_open_time = 0
valve_close_time = 0
Sensor.sensors[sensor_location] = False
doc_ref = db.collection(sensor_location.value).document()
while True:
if current == WFS.isIdle:
print("idle")
if sensor.value == 1:
print("S IS OPENED")
current = WFS.isOpened
if pulses == 0:
valve_open_time = datetime.datetime.now()
if current == WFS.isOpened:
m, s = get_time_diff(valve_open_time)
if s > 30:
Sensor.sensors[sensor_location] = True
while sensor.value == 1:
print("S IS OPENED - Counting pulses")
pulses += sensor.value
current = WFS.isNoisy
if current == WFS.isNoisy:
print("S IN NOISE")
valve_close_time = datetime.datetime.now()
while sensor.value == 0:
print("S IN NOISE - checking if will close")
minutes, seconds = get_time_diff(valve_close_time)
if seconds > 3:
current = WFS.isClosed
break
if current == WFS.isClosed:
current = WFS.isIdle
sleep(10) <<< HERE IS THE PROBLEM - I do sleep 10 secs to see how many times it prints <<<<<<
print("S IS CLOSED - SAVING IN DB - SENSOR PIN : " + str(sensor_pin))
sleep(10)
m, s = get_time_diff(valve_open_time)
duration = str(m) + ":" + str(s)
liters = pulses / 450
doc_ref.set({
'Liters': liters,
'Started_At': valve_open_time,
'Stopped_At': valve_close_time,
'Duration': duration
})
pulses = 0
console output
S IN NOISE - checking if will close
S IN NOISE - checking if will close
S IS CLOSED - SAVING IN DB - SENSOR PIN : 14
S IS CLOSED - SAVING IN DB - SENSOR PIN : 14
idle
idle
idle
idle
As you can see I must get IS CLOSED printed once but it appears twice
Regards
I found that it was flask thread cousing the coping of the threads so I removed it then evrything was working fine.

Let the GUI continue working after crashing without having to reset device

My current GUI is to show target tracking from a TI processor to PC via UART. Sometimes, GUI crashes due to UART performance. But everytime I want to reset GUI, I also have to reset my TI device. So I want to modify python code so as to only re-open GUI, enter COM port without having to reset device whenever GUI crashes.
Currently, each time GUI crashes, even though I re-opened GUI but didn't reset device (power off & on), I can not continue tracking.
I put python code for GUI below.In this GUI python program, we have 2 blanks & button to enter UART COM port, 2 buttons to select & send configuration to device. Then it can begin tracking.
I'm considering to modify the part of sendCfg(self), but still not sure how to make it work as my purpose due to my lack of experience in Python & GUI design. Please help me with sample code for this task.
class Window(QDialog):
def __init__(self, parent=None, size=[]):
super(Window, self).__init__(parent)
#when running Gree Demo
self.Gree = 1
# set window toolbar options, and title. #deb_gp
self.setWindowFlags(
Qt.Window |
Qt.CustomizeWindowHint |
Qt.WindowTitleHint |
Qt.WindowMinimizeButtonHint |
Qt.WindowMaximizeButtonHint |
Qt.WindowCloseButtonHint
)
self.setWindowTitle("mmWave People Counting")
print('Python is ', struct.calcsize("P")*8, ' bit')
print('Python version: ', sys.version_info)
gridlay = QGridLayout()
gridlay.addWidget(self.comBox, 0,0,1,1)
gridlay.addWidget(self.statBox, 1,0,1,1)
gridlay.addWidget(self.configBox,2,0,1,1)
gridlay.addWidget(self.plotControlBox,3,0,1,1)
gridlay.addWidget(self.boxTab,4,0,1,1)
gridlay.addWidget(self.spBox,5,0,1,1)
gridlay.addWidget(self.graphTabs,0,1,6,1)
gridlay.addWidget(self.gw, 0, 2, 6, 1)
#gridlay.addWidget(self.demoData, 0,3,1,2)
#gridlay.addWidget(self.hPlot,1,3,4,2)
gridlay.setColumnStretch(0,1)
gridlay.setColumnStretch(1,3)
self.setLayout(gridlay)
#
# left side pane layout
#
def setConnectionLayout(self):
self.comBox = QGroupBox('Connect to Com Ports')
self.uartCom = QLineEdit('') #deb_gp
self.dataCom = QLineEdit('') #deb_gp
self.uartLabel = QLabel('UART COM:')
self.dataLabel = QLabel('DATA COM:')
self.connectStatus = QLabel('Not Connected')
self.connectButton = QPushButton('Connect')
self.connectButton.clicked.connect(self.connectCom)
self.configLabel = QLabel('Config Type:')
self.configType = QComboBox()
self.configType.addItems(["3D People Counting", "SDK Out of Box Demo", "Long Range People Detection", "Indoor False Detection Mitigation", "(Legacy) 2D People Counting", "(Legacy): Overhead People Counting"])
self.comLayout = QGridLayout()
self.comLayout.addWidget(self.uartLabel,0,0)
self.comLayout.addWidget(self.uartCom,0,1)
self.comLayout.addWidget(self.dataLabel,1,0)
self.comLayout.addWidget(self.dataCom,1,1)
self.comLayout.addWidget(self.configLabel,2,0)
self.comLayout.addWidget(self.configType,2,1)
self.comLayout.addWidget(self.connectButton,3,0)
self.comLayout.addWidget(self.connectStatus,3,1)
self.comBox.setLayout(self.comLayout)
def setConfigLayout(self):
self.configBox = QGroupBox('Configuration')
self.selectConfig = QPushButton('Select Configuration')
self.sendConfig = QPushButton('Send Configuration')
self.selectConfig.clicked.connect(self.selectCfg)
self.sendConfig.clicked.connect(self.sendCfg)
self.configTable = QTableWidget(5,2)
#set parameter names
self.configTable.setItem(0,0,QTableWidgetItem('Radar Parameter'))
self.configTable.setItem(0,1,QTableWidgetItem('Value'))
self.configTable.setItem(1,0,QTableWidgetItem('Max Range'))
self.configTable.setItem(2,0,QTableWidgetItem('Range Resolution'))
self.configTable.setItem(3,0,QTableWidgetItem('Max Velocity'))
self.configTable.setItem(4,0,QTableWidgetItem('Velcoity Resolution'))
self.configLayout = QVBoxLayout()
self.configLayout.addWidget(self.selectConfig)
self.configLayout.addWidget(self.sendConfig)
self.configLayout.addWidget(self.configTable)
#self.configLayout.addStretch(1)
self.configBox.setLayout(self.configLayout)
def updateGraph(self, parsedData):
updateStart = int(round(time.time()*1000))
self.useFilter = 0
classifierOutput = []
pointCloud = parsedData[0]
targets = parsedData[1]
indexes = parsedData[2]
numPoints = parsedData[3]
numTargets = parsedData[4]
self.frameNum = parsedData[5]
fail = parsedData[6]
classifierOutput = parsedData[7]
fallDetEn = 0
indicesIn = []
if (fail != 1):
#left side
pointstr = 'Points: '+str(numPoints)
targetstr = 'Targets: '+str(numTargets)
self.numPointsDisplay.setText(pointstr)
self.numTargetsDisplay.setText(targetstr)
#right side fall detection
peopleStr = 'Number of Detected People: '+str(numTargets)
if (numTargets == 0):
fdestr = 'Fall Detection Disabled - No People Detected'
elif (numTargets == 1):
fdestr = 'Fall Detection Enabled'
fallDetEn = 1
elif (numTargets > 1):
fdestr = 'Fall Detected Disabled - Too Many People'
#self.numDetPeople.setText(peopleStr)
#self.fallDetEnabled.setText(fdestr)
if (len(targets) < 13):
targets = []
classifierOutput = []
if (fail):
return
#remove static points
if (self.configType.currentText() == '3D People Counting'):
if (not self.staticclutter.isChecked()):
statics = np.where(pointCloud[3,:] == 0)
try:
firstZ = statics[0][0]
numPoints = firstZ
pointCloud = pointCloud[:,:firstZ]
indexes = indexes[:,:self.previousFirstZ]
self.previousFirstZ = firstZ
except:
firstZ = -1
#point cloud persistence
fNum = self.frameNum%10
if (numPoints):
self.previousCloud[:5,:numPoints,fNum] = pointCloud[:5,:numPoints]
self.previousCloud[5,:len(indexes),fNum] = indexes
self.previousPointCount[fNum]=numPoints
#plotting 3D - get correct point cloud (persistent points and synchronize the frame)
if (self.configType.currentText() == 'SDK3xPeopleCount'):
pointIn = pointCloud
else:
totalPoints = 0
persistentFrames = int(self.persistentFramesInput.currentText())
#allocate new array for all the points
for i in range(1,persistentFrames+1):
totalPoints += self.previousPointCount[fNum-i]
pointIn = np.zeros((5,int(totalPoints)))
indicesIn = np.ones((1, int(totalPoints)))*255
totalPoints = 0
#fill array
for i in range(1,persistentFrames+1):
prevCount = int(self.previousPointCount[fNum-i])
pointIn[:,totalPoints:totalPoints+prevCount] = self.previousCloud[:5,:prevCount,fNum-i]
if (numTargets > 0):
indicesIn[0,totalPoints:totalPoints+prevCount] = self.previousCloud[5,:prevCount,fNum-i]
totalPoints+=prevCount
if (self.graphFin):
self.plotstart = int(round(time.time()*1000))
self.graphFin = 0
if (self.threeD):
try:
indicesIn = indicesIn[0,:]
except:
indicesIn = []
self.get_thread = updateQTTargetThread3D(pointIn, targets, indicesIn, self.scatter, self.pcplot, numTargets, self.ellipsoids, self.coordStr, classifierOutput, self.zRange, self.gw, self.plotByIndex.isChecked(), self.plotTracks.isChecked(), self.bbox,self.boundaryBoxes[0]['checkEnable'].isChecked())
self.get_thread.done.connect(self.graphDone)
self.get_thread.start(priority=QThread.HighestPriority-1)
else:
npc = pointIn[0:2,:]
print (np.shape(npc))
self.legacyThread = update2DQTGraphThread(npc, targets, numTargets, indexes, numPoints, self.trailData, self.activeTrail, self.trails, self.scatter2D, self.gatingScatter)
self.legacyThread.done.connect(self.graphDone)
self.legacyThread.start(priority=QThread.HighestPriority-1)
else:
return
#pointIn = self.previousCloud[:,:int(self.previousPointCount[fNum-1]),fNum-1]
#state tracking
if (numTargets > 0):
self.lastFrameHadTargets = True
else:
self.lastFrameHadTargets = False
if (numTargets):
self.lastTID = targets[0,:]
else:
self.lastTID = []
def graphDone(self):
plotend = int(round(time.time()*1000))
plotime = plotend - self.plotstart
try:
if (self.frameNum > 1):
self.averagePlot = (plotime*1/self.frameNum) + (self.averagePlot*(self.frameNum-1)/(self.frameNum))
else:
self.averagePlot = plotime
except:
self.averagePlot = plotime
self.graphFin = 1
pltstr = 'Average Plot time: '+str(plotime)[:5] + ' ms'
fnstr = 'Frame: '+str(self.frameNum)
self.frameNumDisplay.setText(fnstr)
self.plotTimeDisplay.setText(pltstr)
def resetFallText(self):
self.fallAlert.setText('Standing')
self.fallPic.setPixmap(self.standingPicture)
self.fallResetTimerOn = 0
def updateFallThresh(self):
try:
newThresh = float(self.fallThreshInput.text())
self.fallThresh = newThresh
self.fallThreshMarker.setPos(self.fallThresh)
except:
print('No numberical threshold')
def connectCom(self):
#get parser
self.parser = uartParserSDK(type=self.configType.currentText())
self.parser.frameTime = self.frameTime
print('Parser type: ',self.configType.currentText())
#init threads and timers
self.uart_thread = parseUartThread(self.parser)
if (self.configType.currentText() != 'Replay'):
self.uart_thread.fin.connect(self.parseData)
self.uart_thread.fin.connect(self.updateGraph)
self.parseTimer = QTimer()
self.parseTimer.setSingleShot(False)
self.parseTimer.timeout.connect(self.parseData)
try:
uart = "COM"+ self.uartCom.text() #deb_gp
data = "COM"+ self.dataCom.text() #deb_gp
#TODO: find the serial ports automatically.
self.parser.connectComPorts(uart, data)
self.connectStatus.setText('Connected') #deb_gp
self.connectButton.setText('Disconnect') #deb_gp
#TODO: create the disconnect button action
except:
self.connectStatus.setText('Unable to Connect')
if (self.configType.currentText() == "Replay"):
self.connectStatus.setText('Replay')
if (self.configType.currentText() == "Long Range People Detection"):
self.frameTime = 400
#
# Select and parse the configuration file
# TODO select the cfgfile automatically based on the profile.
def selectCfg(self):
try:
self.parseCfg(self.selectFile())
except:
print('No cfg file selected!')
def selectFile(self):
fd = QFileDialog()
filt = "cfg(*.cfg)"
filename = fd.getOpenFileName(directory='./../chirp_configs',filter=filt) #deb_gp - added folder name
return filename[0]
def parseCfg(self, fname):
cfg_file = open(fname, 'r')
self.cfg = cfg_file.readlines()
counter = 0
chirpCount = 0
for line in self.cfg:
args = line.split()
if (len(args) > 0):
if (args[0] == 'cfarCfg'):
zy = 4
#self.cfarConfig = {args[10], args[11], '1'}
elif (args[0] == 'AllocationParam'):
zy=3
#self.allocConfig = tuple(args[1:6])
elif (args[0] == 'GatingParam'):
zy=2
#self.gatingConfig = tuple(args[1:4])
elif (args[0] == 'SceneryParam' or args[0] == 'boundaryBox'):
self.boundaryLine = counter
self.profile['leftX'] = float(args[1])
self.profile['rightX'] = float(args[2])
self.profile['nearY'] = float(args[3])
self.profile['farY'] = float(args[4])
self.setBoundaryTextVals(self.profile)
self.boundaryBoxes[0]['checkEnable'].setChecked(True)
elif (args[0] == 'staticBoundaryBox'):
self.staticLine = counter
elif (args[0] == 'profileCfg'):
self.profile['startFreq'] = float(args[2])
self.profile['idle'] = float(args[3])
self.profile['adcStart'] = float(args[4])
self.profile['rampEnd'] = float(args[5])
self.profile['slope'] = float(args[8])
self.profile['samples'] = float(args[10])
self.profile['sampleRate'] = float(args[11])
print(self.profile)
elif (args[0] == 'frameCfg'):
self.profile['numLoops'] = float(args[3])
self.profile['numTx'] = float(args[2])+1
elif (args[0] == 'chirpCfg'):
chirpCount += 1
elif (args[0] == 'sensorPosition'):
self.profile['sensorHeight'] = float(args[1])
self.profile['az_tilt'] = float(args[2])
self.profile['elev_tilt'] = float(args[3])
counter += 1
maxRange = self.profile['sampleRate']*1e3*0.9*3e8/(2*self.profile['slope']*1e12)
#update boundary box
self.drawBoundaryGrid(maxRange)
#update chirp table values
bw = self.profile['samples']/(self.profile['sampleRate']*1e3)*self.profile['slope']*1e12
rangeRes = 3e8/(2*bw)
Tc = (self.profile['idle']*1e-6 + self.profile['rampEnd']*1e-6)*chirpCount
lda = 3e8/(self.profile['startFreq']*1e9)
maxVelocity = lda/(4*Tc)
velocityRes = lda/(2*Tc*self.profile['numLoops']*self.profile['numTx'])
self.configTable.setItem(1,1,QTableWidgetItem(str(maxRange)[:5]))
self.configTable.setItem(2,1,QTableWidgetItem(str(rangeRes)[:5]))
self.configTable.setItem(3,1,QTableWidgetItem(str(maxVelocity)[:5]))
self.configTable.setItem(4,1,QTableWidgetItem(str(velocityRes)[:5]))
#update sensor position
self.az_tilt.setText(str(self.profile['az_tilt']))
self.elev_tilt.setText(str(self.profile['elev_tilt']))
self.s_height.setText(str(self.profile['sensorHeight']))
def sendCfg(self):
try:
if (self.configType.currentText() != "Replay"):
self.parser.sendCfg(self.cfg)
self.configSent = 1
self.parseTimer.start(self.frameTime)
except:
print ('No cfg file selected!')
# Needed ?? deb_gp
# def setParser(self, uParser):
# self.parser = uParser
def parseData(self):
self.uart_thread.start(priority=QThread.HighestPriority)
def whoVisible(self):
if (self.threeD):
self.threeD = 0
else:
self.threeD = 1
print('3d: ', self.threeD)
if __name__ == '__main__':
if (compileGui):
appctxt = ApplicationContext()
app = QApplication(sys.argv)
screen = app.primaryScreen()
size = screen.size()
main = Window(size=size)
main.show()
exit_code = appctxt.app.exec_()
sys.exit(exit_code)
else:
app = QApplication(sys.argv)
screen = app.primaryScreen()
size = screen.size()
main = Window(size=size)
main.show()
sys.exit(app.exec_())

Testing multiple DS18B20 sensor cables

I'm really new to python and coding in general so i turn here for help. At work we need to test many cables with up to five DS18B20 sensors attached to them. We got this program and we've been using it for a while now to test cables with raspberry Pi. But there are few problems with it.
The program needs to detect the number of sensors attached and see if they're working, then list them by serial number lowest>highest (so we can warm them up, see which one gets highlighted, one by one and physically number them) and repeat.
It feels generally slow and crashes pretty often.
With the cables that have 5 sensors attached to them, it can find the sensors on max 2 cables(more if lucky), and when you attach 3rd cable it won't find them anymore or it will keep saying that there's 10 sensors attached. Rebooting the Pi fixes it but it takes time. Hot-swapping the cables is probably the main culprit here, but its the fastest way.
With 3 sensor cables you can check 4-5 of them until it hangs.
Any hints where the problem could be or how i could make things more efficient and faster are welcome.
Code:
import os,sys,time
import curses
stdscr = curses.initscr()
begin_x = 5; begin_y = 5
height = 40; width = 40
def temp_raw(sensor_str):
f = open(sensor_str, 'r')
lines = f.readlines()
f.close()
return lines
def read_temp(sensor_str):
lines = temp_raw(sensor_str)
while lines[0].strip()[-3:] != 'YES':
lines = temp_raw(sensor_str)
temp_output = lines[1].find('t')
if temp_output != -1:
temp_string = lines[1].strip()[temp_output+2:]
temp_c = float(temp_string) / 1000.0
return temp_c
init = 1
timer = 0
search = 1
curses.noecho()
curses.curs_set(0)
subdirectories = []
old_nbr_of_subdirs = 1
nbr_of_subdirs = 1
old_subdirectories = []
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
while (1):
timer = timer + 1
while search == 1:
stdscr.addstr(10,30, "Searching for sensors");
subdirectories = os.listdir("/sys/bus/w1/devices/");
nbr_of_subdirs = len(subdirectories);
time.sleep(3)
if nbr_of_subdirs > old_nbr_of_subdirs:
stdscr.addstr(10,30, "Found %d new sensors " % (nbr_of_subdirs-old_nbr_of_subdirs));
stdscr.addstr(11,30, "Is this all sensors? (y/n)?");
stdscr.refresh()
c = -1;
while(c == -1):
c = stdscr.getch();
if c == ord('y'):
stdscr.addstr(10,30, " ");
stdscr.addstr(11,30, " ");
stdscr.refresh()
old_nbr_of_subdirs = nbr_of_subdirs;
init = 1;
search = 0;
timer = 0;
else:
stdscr.addstr(10,51 + timer, ". ");
timer = timer + 1;
timer = timer % 4;
stdscr.refresh()
if init == 1:
init = 0
alive_ticker = 0;
temp_list = [];
sensor_oldtemp = [0,0,0,0,0,0];
sensor_temp = [0,0,0,0,0,0];
active_sensor = [0,0,0,0,0,0];
sensors = 0;
alive_ticker = 0;
active = 2;
confirm = 0;
stdscr.addstr(17,0, "Number of subdirectories %d" % (len(subdirectories)));
removed = 0;
index = 0;
length_old_subdirs = len(old_subdirectories);
while (index < length_old_subdirs):
length_old_subdirs = len(old_subdirectories);
if old_subdirectories[index] in subdirectories:
subdirectories.remove(old_subdirectories[index]);
removed += 1;
index += 1;
else:
old_subdirectories.remove(old_subdirectories[index]);
index = 0;
stdscr.addstr(30,20, "Removed %d" % (removed))
stdscr.addstr(18,0, "Number of CUT subdirectories %d" % (len(subdirectories)));
stdscr.addstr(19,0, "Number of old_subdirectories %d" % (len(old_subdirectories)));
stdscr.addstr(13,20, "Press space to confirm active sensor!");
stdscr.addstr(14,20, "Press r to reset!");
for index in range(len(subdirectories)):
if subdirectories[index].find("28") != -1:
temp_list.append("/sys/bus/w1/devices/"+subdirectories[index]+"/w1_slave");
sensor_temp[sensors] = 0;
sensors = sensors + 1;
old_subdirectories = old_subdirectories + subdirectories;
temp_list.sort();
if confirm == 1:
stdscr.addstr(13,20, "Press space to confirm active sensor!");
stdscr.addstr(14,20, "Press r to restart!");
curses.halfdelay(1);
c = stdscr.getch();
if c == 32:
confirm = 0;
timer = 10
for z in range(sensors):
if active_sensor[z] > active:
stdscr.addstr(z+5,20, " " , curses.A_DIM)
active_sensor[z] = 100
stdscr.refresh()
elif c == ord('n'):
init = 1
continue
elif c == ord('r'):
for z in range(sensors):
active_sensor[z] = 1;
if (timer > 9):
timer = 0
nbr_active_sensors = 0
for y in range(sensors):
if 99 > active_sensor[y]:
nbr_active_sensors = nbr_active_sensors + 1;
sensor_temp[y] = read_temp(temp_list[y]);
if ((sensor_oldtemp[y] + 0.1) < sensor_temp[y]):
active_sensor[y] = active_sensor[y] + 1;
sensor_oldtemp[y] = sensor_temp[y]
stdscr.addstr(3,5, "nbr_active_sensors=%d" % (nbr_active_sensors))
stdscr.addstr(4,5, "sensors=%d" % (sensors))
if nbr_active_sensors == 0:
search = 1
timer = 0;
continue
for x in range(sensors):
if (99 > active_sensor[x] and active_sensor[x] > active):
confirm = 1
stdscr.addstr(x+5,20, "Sensor %d value %4.2f ID:%s : %d " % (x+1, sensor_temp[x], temp_list[x][20:-9], active_sensor[x]), curses.A_STANDOUT)
elif active_sensor[x] <= active:
stdscr.addstr(x+5,20, "Sensor %d value %4.2f ID:%s : %d " % (x+1, sensor_temp[x], temp_list[x][20:-9], active_sensor[x]))
stdscr.refresh()
alive_ticker = alive_ticker + 1
stdscr.addstr(2, 55, "Alive ticker: %6d" % (alive_ticker))
Question: when you insert the 3rd cable (with 2-3 temp sensor on them) it just won't find any new sensors anymore.
If I recall properly there is a Limit of 2 Cable. Have you verified your Hardware supports more Cable?
I suggest to rewrite the Code and separate the Code into UI, Sensor and Wire Parts.
For instance:
class DS18B20(object):
...
def read(self):
...
class One_Wire(object):
def search(self):
print("Searching sensors")
...
def read(self):
print('Reading sensors')
for key in self.sensors:
self.sensors[key].read()
def refresh(self):
print("Refreshing sensors")
...
def history(self, alive=True):
print('Reading History')
...
Usage:
if __name__ == '__main__':
oWire = One_Wire()
oWire.search()
print(oWire)
oWire.refresh()
print(oWire)
oWire.read()
print(oWire)
history = oWire.history()
print(history)
Output:
Searching sensors
Sensors:5, active:5
id:i2c-0 CONNECT temp:None, id:i2c-3 CONNECT temp:None, id:i2c-1 CONNECT temp:None, id:i2c-5 CONNECT temp:None, id:i2c-6 CONNECT temp:None
Refreshing sensors
NEW Sensor:i2c-2
NEW Sensor:i2c-4
Sensors:7, active:6
id:i2c-0 CONNECT temp:None, id:i2c-2 CONNECT temp:None, id:i2c-3 CONNECT temp:None, id:i2c-1 disconnect temp:None, id:i2c-5 CONNECT temp:None, id:i2c-6 CONNECT temp:None, id:i2c-4 CONNECT temp:None
Reading sensors
Reading sensors
Reading sensors
Sensors:7, active:6
id:i2c-0 CONNECT temp:19, id:i2c-2 CONNECT temp:25, id:i2c-3 CONNECT temp:26, id:i2c-1 disconnect temp:None, id:i2c-5 CONNECT temp:25, id:i2c-6 CONNECT temp:18, id:i2c-4 CONNECT temp:30
Reading History
[{'i2c-0': [20, 27, 19]}, {'i2c-2': [30, 21, 25]}, {'i2c-3': [23, 29, 26]}, {'i2c-5': [30, 18, 25]}, {'i2c-6': [30, 21, 18]}, {'i2c-4': [24, 18, 30]}]

Issue with Python garbage collector?

I have a simple program which reads a large file containing few million rows, parses each row (numpy array) and converts into an array of doubles (python array) and later writes into an hdf5 file. I repeat this loop for multiple days. After reading each file, i delete all the objects and call garbage collector. When I run the program, First day is parsed without any error but on the second day i get MemoryError. I monitored the memory usage of my program, during first day of parsing, memory usage is around 1.5 GB. When the first day parsing is finished, memory usage goes down to 50 MB. Now when 2nd day starts and i try to read the lines from the file I get MemoryError. Following is the output of the program.
source file extracted at C:\rfadump\au\2012.08.07.txt
parsing started
current time: 2012-09-16 22:40:16.829000
500000 lines parsed
1000000 lines parsed
1500000 lines parsed
2000000 lines parsed
2500000 lines parsed
3000000 lines parsed
3500000 lines parsed
4000000 lines parsed
4500000 lines parsed
5000000 lines parsed
parsing done.
end time is 2012-09-16 23:34:19.931000
total time elapsed 0:54:03.102000
repacking file
done
> s:\users\aaj\projects\pythonhf\rfadumptohdf.py(132)generateFiles()
-> while single_date <= self.end_date:
(Pdb) c
*** 2012-08-08 ***
source file extracted at C:\rfadump\au\2012.08.08.txt
cought an exception while generating file for day 2012-08-08.
Traceback (most recent call last):
File "rfaDumpToHDF.py", line 175, in generateFile
lines = self.rawfile.read().split('|\n')
MemoryError
I am very sure that windows system task manager shows the memory usage as 50 MB for this process. It looks like the garbage collector or memory manager for Python is not calculating the free memory correcly. There should be lot of free memory but it thinks there is not enough.
Any idea?
EDIT
Adding my code here
I will put parts of my code. I am new to python, please pardon my python coding style.
module 1
def generateFile(self, current_date):
try:
print "*** %s ***" % current_date.strftime("%Y-%m-%d")
weekday=current_date.weekday()
if weekday >= 5:
print "skipping weekend"
return
self.taqdb = taqDB(self.index, self.offset)
cache_filename = os.path.join(self.cache_dir,current_date.strftime("%Y.%m.%d.h5"))
outputFile = config.hdf5.filePath(self.index, date=current_date)
print "cache file: ", cache_filename
print "output file: ", outputFile
tempdir = "C:\\rfadump\\"+self.region+"\\"
input_filename = tempdir + filename
print "source file extracted at %s " % input_filename
## universe
reader = rfaTextToTAQ.rfaTextToTAQ(self.tickobj) ## PARSER
count = 0
self.rawfile = open(input_filename, 'r')
lines = self.rawfile.read().split('|\n')
total_lines = len(lines)
self.rawfile.close()
del self.rawfile
print "parsing started"
start_time = dt.datetime.now()
print "current time: %s" % start_time
#while(len(lines) > 0):
while(count < total_lines):
#line = lines.pop(0) ## This slows down processing
result = reader.parseline(lines[count]+"|")
count += 1
if(count % 500000 == 0):
print "%d lines parsed" %(count)
if(result == None):
continue
ric, timestamp, quotes, trades, levelsUpdated, tradeupdate = result
if(len(levelsUpdated) == 0 and tradeupdate == False):
continue
self.taqdb.insert(result)
## write to hdf5 TODO
writer = h5Writer.h5Writer(cache_filename, self.tickobj)
writer.write(self.taqdb.groups)
writer.close()
del lines
del self.taqdb, self.tickobj
##########################################################
print "parsing done."
end_time = dt.datetime.now()
print "end time is %s" % end_time
print "total time elapsed %s" % (end_time - start_time)
defragger = hdf.HDF5Defragmenter()
defragger.Defrag(cache_filename,outputFile)
del defragger
print "done"
gc.collect(2)
except:
print "cought an exception while generating file for day %s." % current_date.strftime("%Y-%m-%d")
tb = traceback.format_exc()
print tb
module 2 - taqdb - to store parsed data in an array
class taqDB:
def __init__(self, index, offset):
self.index = index
self.tickcfg = config.hdf5.getTickConfig(index)
self.offset = offset
self.groups = {}
def getGroup(self,ric):
if (self.groups.has_key(ric) == False):
self.groups[ric] = {}
return self.groups[ric]
def getOrderbookArray(self, ric, group):
datasetname = orderBookName
prodtype = self.tickcfg.getProdType(ric)
if(prodtype == ProdType.INDEX):
return
orderbookArrayShape = self.tickcfg.getOrderBookArrayShape(prodtype)
if(group.has_key(datasetname) == False):
group[datasetname] = array.array("d")
orderbookArray = self.tickcfg.getOrderBookArray(prodtype)
return orderbookArray
else:
orderbookArray = group[datasetname]
if(len(orderbookArray) == 0):
return self.tickcfg.getOrderBookArray(prodtype)
lastOrderbook = orderbookArray[-orderbookArrayShape[1]:]
return np.array([lastOrderbook])
def addToDataset(self, group, datasetname, timestamp, arr):
if(group.has_key(datasetname) == False):
group[datasetname] = array.array("d")
arr[0,0]=timestamp
a1 = group[datasetname]
a1.extend(arr[0])
def addToOrderBook(self, group, timestamp, arr):
self.addToDataset(self, group, orderBookName, timestamp, arr)
def insert(self, data):
ric, timestamp, quotes, trades, levelsUpdated, tradeupdate = data
delta = dt.timedelta(hours=timestamp.hour,minutes=timestamp.minute, seconds=timestamp.second, microseconds=(timestamp.microsecond/1000))
timestamp = float(str(delta.seconds)+'.'+str(delta.microseconds)) + self.offset
## write to array
group = self.getGroup(ric)
orderbookUpdate = False
orderbookArray = self.getOrderbookArray(ric, group)
nonzero = quotes.nonzero()
orderbookArray[nonzero] = quotes[nonzero]
if(np.any(nonzero)):
self.addToDataset(group, orderBookName, timestamp, orderbookArray)
if(tradeupdate == True):
self.addToDataset(group, tradeName, timestamp, trades)
Module 3- Parser
class rfaTextToTAQ:
"""RFA Raw dump file reader. Readers single line (record) and returns an array or array of fid value pairs."""
def __init__(self,tickconfig):
self.tickconfig = tickconfig
self.token = ''
self.state = ReadState.SEQ_NUM
self.fvstate = fvstate.FID
self.quotes = np.array([]) # read from tickconfig
self.trades = np.array([]) # read from tickconfig
self.prodtype = ProdType.STOCK
self.allquotes = {}
self.alltrades = {}
self.acvol = 0
self.levelsUpdated = []
self.quoteUpdate = False
self.tradeUpdate = False
self.depth = 0
def updateLevel(self, index):
if(self.levelsUpdated.__contains__(index) == False):
self.levelsUpdated.append(index)
def updateQuote(self, fidindex, field):
self.value = float(self.value)
if(self.depth == 1):
index = fidindex[0]+(len(self.tickconfig.stkQuotes)*(self.depth - 1))
self.quotes[index[0]][fidindex[1][0]] = self.value
self.updateLevel(index[0])
else:
self.quotes[fidindex] = self.value
self.updateLevel(fidindex[0][0])
self.quoteUpdate = True
def updateTrade(self, fidindex, field):
#self.value = float(self.value)
if(self.tickconfig.tradeUpdate(self.depth) == False):
return
newacvol = float(self.value)
if(field == acvol):
if(self.value > self.acvol):
tradesize = newacvol - self.acvol
self.acvol = newacvol
self.trades[fidindex] = tradesize
if(self.trades.__contains__(0) == False):
self.tradeUpdate = True
else:
self.trades[fidindex] = self.value
if(not (self.trades[0,1]==0 or self.trades[0,2]==0)):
self.tradeUpdate = True
def updateResult(self):
field = ''
valid, field = field_dict.FIDToField(int(self.fid), field)
if(valid == False):
return
if(self.value == '0'):
return
if(self.prodtype == ProdType.STOCK):
fidindex = np.where(self.tickconfig.stkQuotes == field)
if(len(fidindex[0]) == 0):
fidindex = np.where(self.tickconfig.stkTrades == field)
if(len(fidindex[0]) == 0):
return
else:
self.updateTrade(fidindex, field)
else:
self.updateQuote(fidindex, field)
else:
fidindex = np.where(self.tickconfig.futQuotes == field)
if(len(fidindex[0]) == 0):
fidindex = np.where(self.tickconfig.futTrades == field)
if(len(fidindex[0]) == 0):
return
else:
self.updateTrade(fidindex, field)
else:
self.updateQuote(fidindex, field)
def getOrderBookTrade(self):
if (self.allquotes.has_key(self.ric) == False):
acvol = 0
self.allquotes[self.ric] = self.tickconfig.getOrderBookArray(self.prodtype)
trades = self.tickconfig.getTradesArray()
self.alltrades[self.ric] = [trades, acvol]
return self.allquotes[self.ric], self.alltrades[self.ric]
def parseline(self, line):
self.tradeUpdate = False
self.levelsUpdated = []
pos = 0
length = len(line)
self.state = ReadState.SEQ_NUM
self.fvstate = fvstate.FID
self.token = ''
ch = ''
while(pos < length):
prevChar = ch
ch = line[pos]
pos += 1
#SEQ_NUM
if(self.state == ReadState.SEQ_NUM):
if(ch != ','):
self.token += ch
else:
self.seq_num = int(self.token)
self.state = ReadState.TIMESTAMP
self.token = ''
# TIMESTAMP
elif(self.state == ReadState.TIMESTAMP):
if(ch == ' '):
self.token = ''
elif(ch != ','):
self.token += ch
else:
if(len(self.token) != 12):
print "Invalid timestamp format. %s. skipping line.\n", self.token
self.state = ReadState.SKIPLINE
else:
self.timestamp = datetime.strptime(self.token,'%H:%M:%S.%f')
self.state = ReadState.RIC
self.token = ''
# RIC
elif(self.state == ReadState.RIC):
if(ch != ','):
self.token += ch
else:
self.ric = self.token
self.token = ''
self.ric, self.depth = self.tickconfig.replaceRic(self.ric)
self.prodtype = self.tickconfig.getProdType(self.ric)
if(self.tickconfig.subscribed(self.ric)):
self.state = ReadState.UPDATE_TYPE
self.quotes, trades = self.getOrderBookTrade()
self.trades = trades[0]
self.acvol = trades[1]
else:
self.state = ReadState.SKIPLINE
# UPDATE_TYPE
elif(self.state == ReadState.UPDATE_TYPE):
if(ch != '|'):
self.token += ch
else:
self.update_type = self.token
self.token = ''
self.state = ReadState.FVPAIRS
#SKIPLINE
elif(self.state == ReadState.SKIPLINE):
return None
# FV PAIRS
elif(self.state == ReadState.FVPAIRS):
# FID
if(self.fvstate == fvstate.FID):
if(ch != ','):
if(ch.isdigit() == False):
self.token = self.value+ch
self.fvstate = fvstate.FIDVALUE
self.state = ReadState.FVPAIRS
else:
self.token += ch
else:
self.fid = self.token
self.token = ''
self.fvstate = fvstate.FIDVALUE
self.state = ReadState.FVPAIRS
# FIDVALUE
elif(self.fvstate == fvstate.FIDVALUE):
if(ch != '|'):
self.token += ch
else:
self.value = self.token
self.token = ''
self.state = ReadState.FVPAIRS
self.fvstate = fvstate.FID
# TODO set value
self.updateResult()
return self.ric, self.timestamp, self.quotes, self.trades, self.levelsUpdated, self.tradeUpdate
Thanks.
The only reliable way to free memory is to terminate the process.
So, if your main program spawns a worker process to do most of the work (the stuff that is done in one day) then when that worker process completes, the memory used will be freed:
import multiprocessing as mp
def work(date):
# Do most of the memory-intensive work here
...
while single_date <= self.end_date:
proc = mp.Process(target = work, args = (single_date,))
proc.start()
proc.join()

Categories

Resources