I use Arduino to receive data from sensors (4 types of data : humidity, temperature, photocell and milliseconds)
Datas comes like this : xx xx xx xxxx in the serial buffer. (data space data space etc...)
I split this line in order to isolate each data because I want to make individual calculations for each sensor.
Calculation for each sensor consist on : ((latest_data) - (data_of_previous_line), latest_data) in order to get a tuple for each sensor. I want all the sensors tuples appearing in the same line.
Doing this with 1 sensor and 1 method (calculate()) is working fine but it doesn't work if I add a second sensor in sensors() object !
QUESTION : how to make all this working with at least 2 sensors data ?
(the code below is working perfectly with 1 "splited" sensor data).
Thanks in advance.
class _share:
def __init__(self):
self.last_val = [0 for i in range(2)]
def calculate(self, val):
self.last_data = val
self.last_val = [self.last_data] + self.last_val[:-1]
diff = reduce(operator.__sub__, self.last_val)
print (diff, val)
return (diff, val)
share = _share()
ser = serial.Serial('/dev/ttyS1', 9600, timeout=0.1)
def sensors():
while True:
try:
time.sleep(0.01)
ser.flushInput()
reception = ser.readline()
receptionsplit = reception.split()
sensor_milli = receptionsplit[3]
sensor_pho_1 = receptionsplit[2]
sensor_tem_1 = receptionsplit[1]
sensor_hum_1 = receptionsplit[0]
int_sensor_milli = int(sensor_milli)
int_sensor_pho_1 = int(sensor_pho_1)
int_sensor_tem_1 = int(sensor_tem_1)
int_sensor_hum_1 = int(sensor_hum_1)
a = int_sensor_milli
b = int_sensor_pho_1
c = int_sensor_tem_1
d = int_sensor_hum_1
return str(share.calculate(b))
except:
pass
time.sleep(0.1)
f = open('da.txt', 'ab')
while 1:
arduino_sensor = sensors()
f.write(arduino_sensor)
f.close()
f = open('da.txt', 'ab')
You need to use different share instance for each sensor otherwise the calculations will be wrong. So use share_a, share_b, share_c and share_d for a, b, c and d respectively for example. Now if I understand this correctly, you can return all the sensors at once by changing your return to:
return [ str(share_a.calculate(a)), str(share_b.calculate(b)), str(share_c.calculate(c)), str(share_d.calculate(d)) ]
The above would return a list containing all 4 sensors and then in your main method you can change to:
arduino_sensor = sensors()
sensor_string ="a:%s b:%s c:%s d:%s"%( arduino_sensor[0], arduino_sensor[1], arduino_sensor[2], arduino_sensor[3] )
print sensor_string # single line screen print of all sensor data
f.write( sensor_string )
I hope that is helpful.
Related
I have tried my luck with these codes to read the data from the DDSU666-H and it seems that I am able to read data, but I don't know what to do with it. In theory it is a list of data, but I am not able to understand what I am receiving or how to translate it into something I can use
import serial # import the module
def banner_bottom():
print(' +-------------------------------------------+')
print(' | SPACE |')
print(' +-------------------------------------------+')
COM_Port = serial.Serial('COM3')
COM_Port.baudrate = 9600 # set Baud rate
COM_Port.bytesize = 8 # Number of data bits = 8
COM_Port.parity = 'N' # No parity
COM_Port.stopbits = 1 # Number of Stop bits = 1
COM_Port.setRTS(1) #RTS=1,~RTS=0 so ~RE=0,Receive mode enabled for MAX485
COM_Port.setDTR(1) #DTR=1,~DTR=0 so DE=0,(In FT232 RTS and DTR pins are inverted)
#~RE and DE LED's on USB2SERIAL board will be off
RxedData = COM_Port.readline()
print(' ',RxedData, '\n')
COM_Port.close() # Close the Serial port
banner_bottom()# Display the bottom banner
Output:
b'\x7f~\xbb\xff\xfb\xe3=\x7f~_cuI_\x0e\x7f~\xbb\xff\xfb\xe3=\x7f~_]\xd3V\'\t\x7f~\xbb\xff\xfb\xe3=\x7f~__\x07\xf5tU\x7f~\xbb\xff\xfb\xe3=\x7f~_[y\x8d\xba\x00\x7f~\xbb\xff\xfb\xe3=\x7f~_YsGe\x18\x7f~\xbb\xff\xfb\xe3=\x7f~_Y\xe3\x06n\x16\x7f~\xbb\xff\xfb\xe3=\x7f~__O]I\x1d\x7f~\xbb\xff\xfb\xe3=\x7f~_ao\xff\xf0\x05\x7f~\xbb\xff\xfb\xe3=\x7f~_co-O\x10\x7f~\xbb\xff\xfb\xe3=\x7f~__\x15\x117\x03\x7f~\xbb\xff\xfb\xe3=\x7f~__!-\xc9/\x7f~\xbb\xff\xfb\xe3=\x7f~__}\xed|\x00\x7f~\xbb\xff\xfb\xe3=\x7f~_c\xb7+\xda\x00\x7f~\xbb\xff\xfb\xe3=\x7f~_e\x8f"U\x01\x7f~\xfd\xff\xfb]\x1a\x7f~_W\xaf\x08\x975\x00\x7f~\xfd\xff\xfb]\x1a\x7f~_W\xaf\x08\x975\x00\x7f~\xfd\xff\xfb]\x1a\x7f~_W\xaf\x08\x975\x00\x7f~\xbb\xff\xfb\xe3=\x7f~_]\xd3V\'\t\x7f~\xbb\xff\xfb\xe3=\x7f~__\xd9\xadb\x08\x7f~\xbb\xff\xfb\xe3=\x7f~__\xc5[P\x05\x7f~\xbb\xff\xfb\xe3=\x7f~__\x91\xfef\x00\x7f~\xbb\xff\xfb\xe3=\x7f~_c3\xb3T\x0f\x7f~\xbb\xff\xfb\xe3=\x7f~_e\xbd\x01\xb0\x03\x7f~\xbb\xff\xfb\xe3=\x7f~_e?y\x84\x19\x7f~\xbb\xff\xfb\xe3=\x7f~_\xe349\xac\n'
Code 2:
#!/usr/bin/env python3
import serial
port = 'COM3'
ComPort = serial.Serial(port)
ComPort.baudrate = 9600
ComPort.bitesize = 8
ComPort.parity = 'N'
ComPort.stopbits = 1
dataIn=ComPort.read(6)
print(dataIn)
ComPort.close()
Ouput:
b'\x7f~\xbb\xff\xfb\xe3'
I've tried to translate the output into something I can understand, but I haven't been able to see anything either.
binary_data = b'\x7f~\xbb\xff\xfb\xe3'
aa = binary_data.hex()
print(aa)
#OUT: 7f7ebbfffbe3
bb = ''.join(['%02x' % b for b in binary_data])
print(bb)
#OUT: 7f7ebbfffbe3
s = binary_data.decode('cp855')
print(s)
#OUT:~╗ чÑ
What can I try to resolve this?
I'm having success reading in and printing some Serial Port data in a python script. I'm having difficulty with what tools/functions to use to change the Serial port data into a table or continuously append to a .csv. So after spending many hours researching everything about Serial Ports and python on stack overflow and other sites I'm reaching out for a hand as I don't know what steps to take next and I can't find information that helps answer my question.
Here is my script so far:
ser = serial.Serial('com4',
baudrate=38400,
timeout=1,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS)
while True:
rawdata = (ser.readline().decode('ascii'))
print(rawdata)
Ok....great we have the Sensor data printing in the console looking like this:
$PDLMA,+11.91,+20.7,-0.1,-0.4*6C
$PDLMH,134829.844,+2644.8,+81.46,+3094.7,+21.99*6F
$PDLM1,134829.844,+1824.1,+127.69,+3276.7,+36.82*26
Now here's how the data from the sensor is structured:
$PDLMH 134829.844 2644.8 81.46 3094.7 21.99 *6F
Hhmmss.sss HCP05 HCPI PRP05 PRP05I Checksum
$PDLM1 134829.844 1824.1 127.69 3727.7 36.82 *26
Hhmmss.sss HCP10 HCP10I PRP10 PRP10I Checksum
$PDLMA 11.91 20.7 -0.1 -0.4
Voltage Temperature Pitch Roll
Now my goal is to get the final output to look like this:
Time HCP05 HCP05I PRP05 PRP05I HCP10 HCP10I PRP10 PRP10I Voltage Temp Pitch
(now) data data data data data data data data Data Data Data
So what should I do to take the serial data and transform it to what I need above as well as continuously reading in the data? I have tried dataframes, lists, etc but clearly I'm missing something here. In the .csv output file I would expect there to be about 120000 lines of data on average in our use case.
The Newbie of the day.
I achieved my desired output with the following code:
while dser.inWaiting() == 0:
pass
NMEA1 = dser.readline().decode("ascii")
while dser.inWaiting() == 0:
pass
NMEA2 = dser.readline().decode("ascii")
while dser.inWaiting() == 0:
pass
NMEA3 = dser.readline().decode("ascii")
while dser.inWaiting() == 0:
pass
NMEA4 = dser.readline().decode("ascii")
while dser.inWaiting() == 0:
pass
NMEA1_array = NMEA1.split(',')
NMEA2_array = NMEA2.split(',')
NMEA3_array = NMEA3.split(',')
NMEA4_array = NMEA4.split(',')
if NMEA1_array[0] == '$PDLMH':
HCP05 = NMEA1_array[2]
PRP05 = NMEA1_array[4]
if NMEA1_array[0] == '$PDLM1':
HCP10 = NMEA1_array[2]
PRP10 = NMEA1_array[4]
if NMEA1_array[0] == '$PDLM2':
HCP20 = NMEA1_array[2]
PRP20 = NMEA1_array[4]
if NMEA1_array[0] == '$PDLMA':
Voltage = NMEA1_array[1]
Temperature = NMEA1_array[2]
Pitch = NMEA1_array[3]
Roll = NMEA1_array[4].partition("*")[0]
if NMEA2_array[0] == '$PDLMH':
HCP05 = NMEA2_array[2]
PRP05 = NMEA2_array[4]
if NMEA2_array[0] == '$PDLM1':
HCP10 = NMEA2_array[2]
PRP10 = NMEA2_array[4]
if NMEA2_array[0] == '$PDLM2':
HCP20 = NMEA2_array[2]
PRP20 = NMEA2_array[4]
if NMEA2_array[0] == '$PDLMA':
Voltage = NMEA2_array[1]
Temperature = NMEA2_array[2]
Pitch = NMEA2_array[3]
Roll = NMEA2_array[4].partition("*")[0]
if NMEA3_array[0] == '$PDLMH':
HCP05 = NMEA3_array[2]
PRP05 = NMEA3_array[4]
if NMEA3_array[0] == '$PDLM1':
HCP10 = NMEA3_array[2]
PRP10 = NMEA3_array[4]
if NMEA3_array[0] == '$PDLM2':
HCP20 = NMEA3_array[2]
PRP20 = NMEA3_array[4]
if NMEA3_array[0] == '$PDLMA':
Voltage = NMEA3_array[1]
Temperature = NMEA3_array[2]
Pitch = NMEA3_array[3]
Roll = NMEA3_array[4].partition("*")[0]
if NMEA4_array[0] == '$PDLMH':
HCP05 = NMEA4_array[2]
PRP05 = NMEA4_array[4]
if NMEA4_array[0] == '$PDLM1':
HCP10 = NMEA4_array[2]
PRP10 = NMEA4_array[4]
if NMEA4_array[0] == '$PDLM2':
HCP20 = NMEA4_array[2]
PRP20 = NMEA4_array[4]
if NMEA4_array[0] == '$PDLMA':
Voltage = NMEA4_array[1]
Temperature = NMEA4_array[2]
Pitch = NMEA4_array[3]
Roll = NMEA4_array[4].partition("*")[0]
if () is not None:
return (float(HCP05), float(PRP05), float(HCP10),
float(PRP10), float(HCP20), float(PRP20),
float(Voltage), float(Temperature), float(Pitch),
float(Roll))
Not to sure if this is the best result but it is now working.
i am using Python to import a csv file with coordinates in it, passing it to a list and using the contained data to calculate the area of each irregular figure. The data within the csv file looks like this.
ID Name DE1 DN1 DE2 DN2 DE3 DN3
88637 Zack Fay -0.026841782 -0.071375637 0.160878583 -0.231788845 0.191811833 0.396593863
88687 Victory Greenfelder 0.219394372 -0.081932907 0.053054879 -0.048356016
88737 Lynnette Gorczany 0.043632299 0.118916157 0.005488698 -0.268612073
88787 Odelia Tremblay PhD 0.083147337 0.152277791 -0.039216388 0.469656787 -0.21725977 0.073797219
The code i am using is below - however it brings up an IndexError: as the first line doesn't have data in all columns. Is there a way to write the csv file so it only uses the colums with data in them ?
import csv
import math
def main():
try:
# ask user to open a file with coordinates for 4 points
my_file = raw_input('Enter the Irregular Differences file name and location: ')
file_list = []
with open(my_file, 'r') as my_csv_file:
reader = csv.reader(my_csv_file)
print 'my_csv_file: ', (my_csv_file)
reader.next()
for row in reader:
print row
file_list.append(row)
all = calculate(file_list)
save_write_file(all)
except IOError:
print 'File reading error, Goodbye!'
except IndexError:
print 'Index Error, Check Data'
# now do your calculations on the 'data' in the file.
def calculate(my_file):
return_list = []
for row in my_file:
de1 = float(row[2])
dn1 = float(row[3])
de2 = float(row[4])
dn2 = float(row[5])
de3 = float(row[6])
dn3 = float(row[7])
de4 = float(row[8])
dn4 = float(row[9])
de5 = float(row[10])
dn5 = float(row[11])
de6 = float(row[12])
dn6 = float(row[13])
de7 = float(row[14])
dn7 = float(row[15])
de8 = float(row[16])
dn8 = float(row[17])
de9 = float(row[18])
dn9 = float(row[19])
area_squared = abs((dn1 * de2) - (dn2 * de1)) + ((de3 * dn4) - (dn3 * de4)) + ((de5 * dn6) - (de6 * dn5)) + ((de7 * dn8) - (dn7 * de8)) + ((dn9 * de1) - (de9 * dn1))
area = area_squared / 2
row.append(area)
return_list.append(row)
return return_list
def save_write_file(all):
with open('output_task4B.csv', 'w') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(["ID", "Name", "de1", "dn1", "de2", "dn2", "de3", "dn3", "de4", "dn4", "de5", "dn5", "de6", "dn6", "de7", "dn7", "de8", "dn8", "de9", "dn9", "Area"])
writer.writerows(all)
if __name__ == '__main__':
main()
Any suggestions
Your problem appears to be in the calculate function.
You are trying to access various indexes of row without first confirming they exist. One naive approach might be to consider the values to be zero if they are not present, except that:
+ ((dn9 * de1) - (de9 * dn1)
is an attempt to wrap around, and this might invalidate your math since they would go to zero.
A better approach is probably to use a slice of the row, and use the sequence-iterating approach instead of trying to require a certain number of points. This lets your code fit the data.
coords = row[2:] # skip id and name
assert len(coords) % 2 == 0, "Coordinates must come in pairs!"
prev_de = coords[-2]
prev_dn = coords[-1]
area_squared = 0.0
for de, dn in zip(coords[:-1:2], coords[1::2]):
area_squared += (de * prev_dn) - (dn * prev_de)
prev_de, prev_dn = de, dn
area = abs(area_squared) / 2
The next problem will be dealing with variable length output. I'd suggest putting the area before the coordinates. That way you know it's always column 3 (or whatever).
A month ago, i asked this about multiplexing a string of numbers with 4 7-segment displays. But now, I'm trying to update the code to multiplex a string of letters using 7 7-segment displays in python.
This is the new circuit. When i send data using the parallel port, the Latch Enable receives the most significant bit (pin 9). In the second latch, the Latch Enable receives it also but negated, that is the reason of the 7404.
That is either address is set (/LE==False) or data is set (/LE=True).
This is what I'm trying to do. The 'X' represents that the 7-segment display is off. But can't archive it.
XXXXXXX
XXXXXXS
XXXXXST
XXXXSTA
XXXSTAC
XXSTACK
XSTACKX
STACKX0
TACKX0V
ACKX0V3
CKX0V3R
KX0V3RF
X0VERFL
0VERFL0
VERFL0W
ERFL0WX
RFL0WXX
FL0WXXX
L0WXXXX
0WXXXXX
WXXXXXX
XXXXXXX
That would be the output for the string "STACK 0V3RFL0W".
Also the past code:
import sys
import parallel
class Display(object):
def __init__(self):
'''Init and blank the "display".'''
self.display = [' '] * 4
self._update()
def setData(self,data):
'''Bits 0-3 are the "value".
Bits 4-7 are positions 0-3 (first-to-last).
'''
self.display = [' '] * 4
value = data & 0xF
if data & 0x10:
self.display[0] = str(value)
if data & 0x20:
self.display[1] = str(value)
if data & 0x40:
self.display[2] = str(value)
if data & 0x80:
self.display[3] = str(value)
self._update()
def _update(self):
'''Write over the same four terminal positions each time.'''
sys.stdout.write(''.join(self.display) + '\r')
if __name__ == '__main__':
p = Display()
pp=parallel.Parallel()
nums = raw_input("Enter a string of numbers: ")
# Shift over the steam four-at-a-time.
stream = 'XXXX' + nums + 'XXXX'
data = [0] * 4
for i in range(len(stream)-3):
# Precompute data
for pos in range(4):
value = stream[i+pos]
data[pos] = 0 if value == 'X' else (1<<(pos+4)) + int(value)
# "Flicker" the display...
for delay in xrange(1000):
# Display each position briefly.
for d in data:
pp.setData(d)
# Clear the display when done
p.setData(0)
Algorithm outline:
string = "07831505"
while True:
for i in range(7):
# switch display `i` on
notlatch.set(True)
data.set(1 << i)
notlatch.set(False)
time.sleep(<very little>)
notlatch.set(True)
# display character on display `i`
data.set(char_to_7segment(string[i]))
time.sleep(0.01)
I have a for loop which references a dictionary and prints out the value associated with the key. Code is below:
for i in data:
if i in dict:
print dict[i],
How would i format the output so a new line is created every 60 characters? and with the character count along the side for example:
0001
MRQLLLISDLDNTWVGDQQALEHLQEYLGDRRGNFYLAYATGRSYHSARELQKQVGLMEP
0061
DYWLTAVGSEIYHPEGLDQHWADYLSEHWQRDILQAIADGFEALKPQSPLEQNPWKISYH
0121 LDPQACPTVIDQLTEMLKETGIPVQVIFSSGKDVDLLPQRSNKGNATQYLQQHLAMEPSQ
It's a finicky formatting problem, but I think the following code:
import sys
class EveryN(object):
def __init__(self, n, outs):
self.n = n # chars/line
self.outs = outs # output stream
self.numo = 1 # next tag to write
self.tll = 0 # tot chars on this line
def write(self, s):
while True:
if self.tll == 0: # start of line: emit tag
self.outs.write('%4.4d ' % self.numo)
self.numo += self.n
# wite up to N chars/line, no more
numw = min(len(s), self.n - self.tll)
self.outs.write(s[:numw])
self.tll += numw
if self.tll >= self.n:
self.tll = 0
self.outs.write('\n')
s = s[numw:]
if not s: break
if __name__ == '__main__':
sys.stdout = EveryN(60, sys.stdout)
for i, a in enumerate('abcdefgh'):
print a*(5+ i*5),
shows how to do it -- the output when running for demonstration purposes as the main script (five a's, ten b's, etc, with spaces in-between) is:
0001 aaaaa bbbbbbbbbb ccccccccccccccc dddddddddddddddddddd eeeeee
0061 eeeeeeeeeeeeeeeeeee ffffffffffffffffffffffffffffff ggggggggg
0121 gggggggggggggggggggggggggg hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
0181 hhhhhhh
# test data
data = range(10)
the_dict = dict((i, str(i)*200) for i in range( 10 ))
# your loops as a generator
lines = ( the_dict[i] for i in data if i in the_dict )
def format( line ):
def splitter():
k = 0
while True:
r = line[k:k+60] # take a 60 char block
if r: # if there are any chars left
yield "%04d %s" % (k+1, r) # format them
else:
break
k += 60
return '\n'.join(splitter()) # join all the numbered blocks
for line in lines:
print format(line)
I haven't tested it on actual data, but I believe the code below would do the job. It first builds up the whole string, then outputs it a 60-character line at a time. It uses the three-argument version of range() to count by 60.
s = ''.join(dict[i] for i in data if i in dict)
for i in range(0, len(s), 60):
print '%04d %s' % (i+1, s[i:i+60])
It seems like you're looking for textwrap
The textwrap module provides two convenience functions, wrap() and
fill(), as well as TextWrapper, the class that does all the work, and
a utility function dedent(). If you’re just wrapping or filling one or
two text strings, the convenience functions should be good enough;
otherwise, you should use an instance of TextWrapper for efficiency.