我使用Python 3.4程序来控制Raspberry Pi的测量设置。该计划的作用如下: - 通过COM端口向微控制器发送命令 - 接收数据包并解析它们 - 将收到的数据和一些统计信息写入文件 - 重复进行下一次测量
整个程序有点像弗兰肯斯坦,因为在我尝试创建之前我对Python一无所知:D所以有很多小的不一致。请不要判断。
#!/usr/bin/python3
import serial
import io
import binascii
import crcmod.predefined
import sys
import struct
import time
import signal
import random
import os
from subprocess import call
REVERSE_BYTE_TABLE = [
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
]
def reverse_byte(x):
return REVERSE_BYTE_TABLE[x]
def signal_handler(signal, frame):
global signalcount
if(signalcount == 0):
print("Broke loop")
signalcount = 1
raise KeyboardInterrupt()
elif(signalcount == 1):
print("\nProgram terminated by user")
try:
mean.close()
except Exception as e:
print(e)
sys.exit()
def recovery(cc430):
call(["gpio", "-g", "write", "24", "1"])
cc430.flushInput()
cc430.close()
cc430.open()
#cc430.flushOutput()
cc430.flushInput()
input = bytearray()
time.sleep(2)
call(["gpio", "-g", "write", "24", "0"])
time.sleep(1)
cc430.close()
cc430.open()
time.sleep(5)
cc430.write(b'\xd3')
cc430.write(b'\x01')
cc430.write(rfset.to_bytes(1, 'big'))
cc430.write(b'\x00')
cc430.write(b'\x00')
cc430.write(b'\x00')
cc430.write(b'\x30')
print("Recovery maneuver executed")
return
rfrange = (14,15,16)
#rfrange = (0,1,2,3,4,5,6,7,8)
#rfrange = (9,10)
rfrange25k = (1,2,3,4)
rfrange10k = (5,6,7,8)
rfrange2k = (9,10,11,12)
rfrangeinfinite = (-1,3,4,7,8,13,14,15,16)
call(["gpio", "export", "24", "out"])
signal.signal(signal.SIGINT, signal_handler)
global signalcount
signalcount = 0
#cc430 = serial.Serial(port='/dev/ttyAMA0', baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=0.05)
#cc430.write(b'\xaa') #acknowledge proper receiption 0xAA, without, MSP430 will be stuck
#cc430.close()
##sys.exit()
for rfset in rfrange:
try:
#rfset = rfset + 1
cc430 = serial.Serial(port='/dev/ttyAMA0', baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=0.05)
cc430.close()
cc430.open()
input = bytearray()
beginpaket = bytearray(b"\x4d\xe2\xf8\xe0\x6d\x4e\xb5\x54")
newline = bytearray(b"\x8a\x8a\x36\x36\x36\x66\xfb\x51")
crc = 0x0000
crc2 = 0x0000
makecrc = crcmod.predefined.mkCrcFun('crc-16-mcrf4xx')
color = ''
templist = []
timelist = []
timelistint = []
timelistext = []
rssilistint = []
rssilistext = []
printlist = []
lastidle = 0
crcfail = False
wronginit = False
dbm = ''
meter = ''
with open("dbm", "r+") as f:
dbm = str(f.readline())[:-1]
meter = str(f.readline())[:-1]
measname = str(f.readline())[:-1]
if(int(dbm) < -81 and (rfset in rfrange25k or rfset == 0)):
print("dBm kleiner -81, keine messung für rfset " + str(rfset))
time.sleep(1)
raise(OSError)
try:
os.mkdir("./datasertest/")
except OSError as err:
print(err)
try:
os.mkdir("./datasertest/" + measname + "/")
except OSError as err:
print(err)
try:
os.mkdir("./datasertest/" + measname + "/" + meter + "/")
except OSError as err:
print(err)
try:
os.mkdir("./datasertest/" + measname + "/" + meter + "/" + dbm + "dBm/")
except OSError as err:
print(err)
try:
os.mkdir("./datasertest/" + measname + "/" + meter + "/" + dbm + "dBm/" + "RF_setting_" + str(rfset).zfill(2) + "/")
except OSError as err:
print(err)
path = measname + "/" + meter + "/" + dbm + "dBm/" + "RF_setting_" + str(rfset).zfill(2) + "/"
filename = "Reference_Measurement_Signal_Generator_" + meter + "_" + dbm + "dBm_time"
filename2 = "Reference_Measurement_Signal_Generator_" + meter + "_" + dbm + "dBm_mean"
avgtime = 0
laufend = 0
timestamp1 = time.time()
timestamp2 = time.time()
#rfset = 1
mean = open("./datasertest/" + path + time.strftime('%Y%m%d_%H%M%S_') + filename2 + "_rfsetting_" + str(rfset) + ".log", 'w+')
run1 = True
run2 = False
timestamp1 = time.time()
rssiOffset = 74
if(rfset == 0):
mnumsfortest = 495
if(rfset in rfrange25k):
mnumsfortest = 490#200 #was 475
if(rfset in rfrange10k):
mnumsfortest = 490#200 #was 490
if(rfset in rfrange2k):
mnumsfortest = 498#450 #was 498
if (rfset in rfrangeinfinite):
mnumsfortest = -4000
cyclesfortest = 2502
cc430.write(b'\xd3')
cc430.write(b'\x01')
cc430.write(rfset.to_bytes(1, 'big'))
cc430.write(b'\x00')
cc430.write(b'\x00')
cc430.write(b'\x00')
cc430.write(b'\x30')
timebegin = time.time()
while(cc430.isOpen()):
if((timestamp1 - time.time()) <= -80 or wronginit):
if(wronginit):
print("Wrong initialization")
else:
print("Timeout occured")
recovery(cc430)
run1 = True
timestamp1 = time.time()
input = bytearray()
wronginit = False
input.extend(cc430.read(16))
if newline in input: #Search for newline
print("Input Read: " + str(timestamp1 - time.time()))
timestamp1 = time.time()
while beginpaket in input: #As long as there is begin packet in input, but doesn't start at byte 0
if (beginpaket in input[:8]) and (beginpaket not in input[1:]): #If begin packet is once in input
del input[-8:] # truncate begin and end of packet
del input[:8]
crc = int.from_bytes([reverse_byte(x) for x in input[-2:]], 'little')
print(crc)
crc2 = makecrc(input[:-2])
#print(crc2)
#crc2 = makecrc(input[:-2])
#print(crc2)
#crc2 = makecrc(input[:int(len(input)/2)])
#crc2 = makecrc(input[int(len(input)/2):-2], crc2)
#print(crc2)
if not (crc == crc2): #CRC OK?
print("CRC Fail") #inform user anyhow
recovery(cc430)
run1 = True
crcfail = True
break
cc430.write(b'\xaa') #acknowledge proper receiption 0xAA, without, MSP430 will be stuck
del input[-2:] #remove CRC from end of packet
break
else:
del input[0] #Delete byte zero, because not part of begin paket
if not(crcfail):
while len(input) > 0: #Keep parsing while there is packet left
if input[0] == 0x00: #MNUM
print("Measurement number %d" % int.from_bytes(input[1:3], 'big'))
# print(int.from_bytes(input[1:3], 'big'))
del input[0:3]
if len(input) == 0:
break
if input[0] == 0x01: #CLK_INT
# print(int.from_bytes(input[1:3], 'big'))
tmpClkInt = int.from_bytes(input[1:5], 'big')
timelistint.append(tmpClkInt)
del input[0:5]
if len(input) == 0:
break
if input[0] == 0x02: #CLK_EXT
# print(int.from_bytes(input[1:3], 'big'))
tmpClkExt = int.from_bytes(input[1:5], 'big')
timelistext.append(tmpClkExt)
del input[0:5]
if len(input) == 0:
break
if input[0] == 0x03: #RSSI_INT
# print("Last RSSI value: %d" % int.from_bytes(input[1:2], 'big'))
# print(int.from_bytes(input[1:2], 'big'))
tmpRSSIint = int.from_bytes(input[1:2], 'big')
if(tmpRSSIint >= 128):
tmpRSSIint = ((tmpRSSIint - 256) / 2) - rssiOffset
else:
tmpRSSIint = (tmpRSSIint / 2) - rssiOffset
rssilistint.append(tmpRSSIint)
del input[0:2]
if len(input) == 0:
break
if input[0] == 0x04: #RSSI_EXT
# print(int.from_bytes(input[1:2], 'big'))
tmpRSSIext = int.from_bytes(input[1:2], 'big')
if(tmpRSSIext >= 128):
tmpRSSIext = ((tmpRSSIext - 256) / 2) - rssiOffset
else:
tmpRSSIext = (tmpRSSIext / 2) - rssiOffset
rssilistext.append(tmpRSSIext)
del input[0:2]
if len(input) == 0:
break
if input[0] == 0x05: #TEMP_INT
print(int.from_bytes(input[1:3], 'big'))
templist.append(int.from_bytes(input[1:3], 'big'))
del input[0:3]
if len(input) == 0:
break
if input[0] == 0x06: #TEMP_EXT
print(int.from_bytes(input[1:3], 'big'))
del input[0:3]
if len(input) == 0:
break
if input[0] == 0x07: #AVG_CLK_INT
print(int.from_bytes(input[1:5], 'big'))
del input[0:5]
if len(input) == 0:
break
if input[0] == 0x08: #AVG_CLK_EXT
print(struct.unpack_from("f", input[1:5]))
print(':'.join(hex(x) for x in input[1:5]))
print(':'.join(bin(x) for x in input[1:5]))
del input[0:5]
if len(input) == 0:
break
if input[0] == 0x09:
print(input[2:(input[1] + 1)].decode('cp1252')) #decode String with Windows encoding
if input[2] == 0x00:
color = 'error'
if input[2] == 0x01:
color = 'warning'
if input[2] == 0x02:
color = 'data'
if input[2] == 0x03:
color = 'success'
if input[2] == 0x04:
color = 'boring'
del input[0:(input[1] + 2)]
if len(input) == 0: #leave parser @ end of packet
break
if input[0] == 0x0A: #PI_RFSTATUS
#print(int.from_bytes(input[1:2], 'big'))
#print(':'.join(bin(x) for x in input[1:2]))
print(':'.join(hex(x) for x in input[1:2]))
del input[0:2]
if len(input) == 0:
break
if input[0] == 0x0B: #PKT_LOSS
# print("Number of lost packeges in last measurement: %d" % int.from_bytes(input[1:3], 'big'))
# print(int.from_bytes(input[1:3], 'big'))
del input[0:3]
if len(input) == 0:
break
if input[0] == 0x0C: #CRC_ERR
# print("Number of CRC errors in last measurement: %d" % int.from_bytes(input[1:3], 'big'))
# print(int.from_bytes(input[1:3], 'big'))
del input[0:3]
if len(input) == 0:
break
if input[0] == 0x0D: #IDLE_COUNT
thisidle = int.from_bytes(input[1:5], 'big')
# print("Idle Count: %d calculated from this idle %d and lastidle %d" % (thisidle - lastidle, thisidle, lastidle))
# print(int.from_bytes(input[1:5], 'big'))
lastidle = thisidle
del input[0:5]
if len(input) == 0:
break
if input[0] > 0x0D:
print(str(input[0]) + " is invalid packet identifier: break parsing")
break
input = bytearray()
avgtemp = 0
for i in range(len(templist)):
avgtemp += templist[i]
if len(templist) > 0:
lol = 1
# print(avgtemp/len(templist))
# random.seed(avgtime)
avgtime = 0
# randomlist = list(timelistext)
# random.shuffle(randomlist, random.random)
# print(randomlist)
for i in range(len(timelistint)):
if (i == 0):
offset = -1
else:
offset = i - 1
timelist.append(timelistint[i]-timelistext[i])
printlist.append(str(timelistint[i]-timelistext[i]) + ";" + str(timelistint[i]) + ";" + str(timelistext[i]) + ";" + str(rssilistint[i]) + ";" + str(rssilistext[i]))# + ";" + str(timelistext[offset]) + ";" + str(randomlist[i]))
# for i in timelist:
# print(i)
print("Länge Timelist: " + str(len(timelist)))
timelistdel = []
for i in range(len(timelist)):
if (timelistint[i] == 0 or timelistext[i] == 0):
# print("Timelist item bigger then 1000 or <= 0, Abort, Abort: %d No: %d" % (timelist[i], i))
timelistdel.append(i)
else:
avgtime += timelist[i]
for i in timelistdel[::-1]:
del timelist[i]
# del printlist[i]
print("Länge Timelist: " + str(len(timelist)))
print("Länge Printlist: " + str(len(printlist)))
print("Messung " + str(laufend) + " von rfset " + str(rfset))
if not (len(printlist) == 0):
with open("./datasertest/" + path + time.strftime('%Y%m%d_%H%M%S_') + filename + '_' + str(laufend) + '_rfsetting_' + str(rfset) + ".log", 'w+') as f:
for string in printlist:
f.write(str(string) + '\r\n')
# print(i)
laufend = laufend + 1
avgmean = 0
if len(timelist) > 0:
lol = 2
avgmean = avgtime/len(timelist)
print(avgmean)
mean.write(str(avgmean) + '\r\n')
if not (run1 or run2):
if((avgmean > 600 and avgmean < 640) or (avgmean > 2800 and avgmean < 3200)):
wronginit = True
timelist = []
timelistint = []
timelistext = []
rssilistint = []
rssilistext = []
printlist = []
mnumsfortest += 1
# mnumsfortest = 27
if (mnumsfortest > 500):
mean.close()
print("\nFertig\n")
break
time.sleep(3)
if(run2):
run2 = False
if(run1):
print("Run 1 - Sleep 20 s")
run1 = False
run2 = True
time.sleep(20)
cc430.write(b'\xd3')
cc430.write(b'\x01')
# cc430.write(b'\x07')
cc430.write(rfset.to_bytes(1, 'big'))
# cc430.write(int(mnumsfortest/3).to_bytes(1, 'big'))
#for by in mnumsfortest.to_bytes(2, 'big'):
# cc430.write(y)
absmnumsfortest = abs(mnumsfortest)
cc430.write(absmnumsfortest.to_bytes(2, 'big'))
# cyclesfortest = 1000
#for by in cyclesfortest.to_bytes(2, 'big'):
# cc430.write(by)
cc430.write(cyclesfortest.to_bytes(2, 'big'))
else:
crcfail = False
if(time.time() - timebegin > 54000):
print("Time up! Next RF-Set")
break
if(time.time() - timebegin > 38160 and rfset == 14):
print("Time up for RF 14! Next RF-Set")
break
except KeyboardInterrupt as keyi:
print("Loop: " + str(rfset) + " interrupted")
time.sleep(1) #Delay to hit CTRL + C two times
signalcount = 0
except OSError as oeri:
print(oeri)
pass
现在的问题是,虽然程序大部分时间都运行良好(连续几个小时到几天)但它有时会停止。程序中出现的位置每次都不同,但似乎总是在BufferedWriter操作期间发生。当我看到程序没有执行更多测量时,我按Ctrl + C退出。我收到以下三条错误消息:
Messung 1901 von rfset 3
-282499.4179164167
^C^CBroke loop
Traceback (most recent call last):
File "./autosertest.py", line 177, in <module>
input.extend(cc430.read(16))
File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 442, in read
ready,_,_ = select.select([self.fd],[],[], self._timeout)
File "./autosertest.py", line 57, in signal_handler
print("Broke loop")
File "./autosertest.py", line 57, in signal_handler
print("Broke loop")
RuntimeError: reentrant call inside <_io.BufferedWriter name='<stdout>'>
--
Messung 364 von rfset 3
615.0213957208558
Input Read: -29.404370069503784
39232
Länge Timelist: 5002
Länge Timelist: 5000
Länge Printlist: 5002^C
Traceback (most recent call last):
File "./autosertest.py", line 396, in <module>
print("Länge Printlist: " + str(len(printlist)))
File "./autosertest.py", line 57, in signal_handler
print("Broke loop")
RuntimeError: reentrant call inside <_io.BufferedWriter name='<stdout>'>
--
1
Länge Timelist: 2500
Länge Printlist: 2502
Messung 640 von rfset 14
517.8528
^CInput Read: -15.271323919296265
Traceback (most recent call last):
File "./autosertest.py", line 220, in <module>
print("Input Read: " + str(timestamp1 - time.time()))
File "./autosertest.py", line 57, in signal_handler
print("Broke loop")
RuntimeError: reentrant call inside <_io.BufferedWriter name='<stdout>'>
我知道,可重入调用来自信号处理程序,它试图写入已经在使用的资源(stdout),并且应该避免在信号处理程序中执行I / O.但我认为,这不是问题,而是程序不会从写操作返回。
您可能想知道的参数: