I have got a simple program running in the uno that measures the distance using ping sensor and now i am trying to control some servos based on the distance in python but the conditional thingy is not working even in a simple code like this
import serial
data = serial.Serial('COM7',9600)
while(1):
if(data.inWaiting()>0):
dist = data.readline()
if(dist>100):
print("dist is greater than 100")
else:
print("this shit does not work")
It is always the if that works, I am a noob please help me!
Data from serial port type is str
You are trying to read the data and use if .... > 100 this will never work.
You need to read the data to a buffer and then check it, Also you need some sync frame to know you have got all the data(it's not a must but its much eaiser)
for example let say the read data is 100! and ! is your sync frame.
import serial
my_serial = serial.Serial('COM7',9600)
my_data = ""
while(1):
if(my_serial.inWaiting()>0):
my_data = my_serial.readline()
if '!' in my_data:
break
my_data = [:my_data.find("!")]
if int(my_data) > 100:
print("dist is greater than 100")
else:
print("this shit does not work")
Related
I am trying to extract sensor data from Arduino. Arduino code sends sensor data using serial communication every 1 second. My goal is to display this data and plot it in real-time in a GUI using Tkinter. But where I seem to be stuck is retrieving data from Arduino. In my code, I tried to extract the data and save them in multiple variables. But when Arduino is sending only 5 seconds worth of data which is 5 sensor measurements, my python code is saving more than 60 measurements in the variable. I don't have any idea how to solve this. I have been stuck here for some time. Here is my python code.
In the given pictures I ran the code for 5 seconds. That is 5 measurements will be sent from Arduino. I am recieving the data correctly, but when I process them and seperate them in individual variables I have analog_voltage containing:80 , current:70, voltage:75 and temperature:65 measurements as they should only contain 5. What should I do, is there any way to go around this problem?
This is the same issue when I am trying to save the file. For the 5 seconds of data the program saves a million rows of data in csv. Any help is much appreciated. Thank you for reading.
The image for arduino data is just for reference as it is not possible to run both the programs in a same time due to the serial communication protocols hence the data looks different.
data_to_sort =[]
analog_voltage = []
Voltage= []
Current=[]
Temperature=[]
def arduino_read_serialdata():
global ser
ser = serial.Serial('COM4', 9600, timeout=1)
time.sleep(1.0)
ser.flushInput()
while True:
global analog_voltage, Voltage, Temperature, Current, yp, cleaned_data, anvol
incoming_data = ser.inWaiting()
incoming_data = ser.readline()
incoming_data = incoming_data.decode()
cleaned_data = incoming_data.strip("/n")
data_to_sort.append(cleaned_data)
for everyrow in data_to_sort:
if everyrow.startswith("Measuring voltage and current with INA219 ..."):
pass
elif everyrow.startswith("MAX31855 test"):
pass
elif everyrow.startswith("Initializing sensor...DONE checking reading the values now."):
pass
elif everyrow.startswith("The Analog Voltage is:"):
anvol = everyrow[-8:]
anvol = float(anvol)
analog_voltage.append(anvol)
elif everyrow.startswith("Bus Voltage............:"):
vol = everyrow[-8:]
Voltage.append(float(vol))
elif everyrow.startswith("Current..............:"):
cur = everyrow[-8:]
Current.append(float(cur))
elif everyrow.startswith("Temperature in celcius:"):
temp = everyrow[-7:]
Temperature.append(float(temp))
else:
pass
with open("Sensor_data.csv", 'w+', newline='') as output_file:
output_file.flush()
output_file = csv.writer(output_file)
fields = ['Analog Voltage V', 'Voltage V', 'Current mA', 'Temperature °C']
output_file.writerow(fields)
for idx in range(0, len(analog_voltage)):
output_file.writerow([analog_voltage[idx]])
if keyboard.is_pressed("q"):
print("Manually interrupted by user")
ser.close()
# output_file.close()
print("Serial port closed")
file.close()
print("File closed, Writing done")
You have an array
data_to_sort =[]
and you append each incoming line to it
data_to_sort.append(cleaned_data)
And with each incoming data, you process the whole data
for everyrow in data_to_sort:
and add the values to these four lists:
analog_voltage = []
Voltage= []
Current=[]
Temperature=[]
and these lists are never cleared.
What should be done instead:
either clear these four lists with each incoming data or
process only the incoming line
My personal preference would be the latter. Instead of always writing the whole output file, append only the last line to the output file using "a" instead of "w+".
I'm trying to read incoming data from a weight scale (Lexus Matrix One). I want the code to start reading the 8 characters after = appears.
The problem is that sometimes the code does that, and other times it starts reading the data at the middle of the measurement sent by the scale, making it impossible to read properly. I'm using the pyserial module on python 3 on windows.
import serial
ser=serial.Serial("COM4", baudrate=9600)
a=0
while a<10:
b=ser.read(8)
a=a+1
print(b)
the expected result is: b'= 0004.0'
but sometimes I get: b'4.0= 000'
I think we would need a little more information on the format of data coming from your weight scale to provide a complete answer. But your current code only reads the first 80 bytes from the stream, 8 bytes at a time.
If you want to read the next 8 bytes following any equals sign, you could try something like this:
import serial
ser = serial.Serial("COM4", baudrate=9600)
readings = []
done = False
while not done:
current_char = ser.read()
# check for equals sign
if current_char == b'=':
reading = ser.read(8)
readings.append(reading)
# this part will depend on your specific needs.
# in this example, we stop after 10 readings
# check for stopping condition and set done = True
if len(readings) >= 10:
done = True
Been trying to fix this. The barometer data on the Adruino looks like this:
1008.94
1008.95
1008.94
Which I'm happy with. These get "read" every 10 second for now.
The problem is with my python script. I can read and write all the data to my mySQLdb. But the the data is not always good. It will go like something like:
1008.94
108.95
108.94
1008.96
The "lost zero" or other value always appears on the Adruino's serial monitor.
How can I get the python script to read the whole xxxx.xx line? Just thought even at times of low pressure xxx.xx.
Here is my python code:
import MySQLdb
import serial
import time
ser = serial.Serial('/dev/ttyACM0', 9600)
db = MySQLdb.connect("localhost", "root", "pword","weather")
cursor = db.cursor()
while 1:
# print ("Waiting for data...")
# print("")
x = ser.readline()
clock = (time.strftime("%H:%M:%S"))
print x
# print ("Collecting data...")
x = x
# print ("Inserting to database...")
# print ("")
sql = ("""INSERT INTO WeatherP (pres, Time) VALUES (%s, %s)""", (x, clock,))
cursor.execute(*sql)
db.commit()
#
Thank you.
Tinus
I found the following here:
ser.read(ser.inWaiting())
According to the pySerial documentation inWaiting() does return the size of the received data in the buffer. This could solve your problem because the read function has a size of data it takes given by a parameter (in your case 1 byte since you haven't specified) if the received data is larger it might cause such problems.
My controller is receiving data from a radio module through a serial port, it's recording temperature and humidity to two decimal places every 1 second, using 'a' as a signal to time stamp it. For example:
a21.12 65.43
a21.13 65.40
Here is the code I'm using:
import serial
import datetime
connected = False
locations=['/dev/ttyUSB0','/dev/ttyUSB1','/dev/ttyUSB2','/dev/ttyUSB3']
for device in locations:
try:
print "Trying...",device
ser = serial.Serial(device, 9600)
break
except:
print "Failed to connect on",device
while not connected:
serin = ser.read()
connected = True
with open('tempdata.txt', 'w') as text_file:
while 1:
if ser.read() is 'a':
text_file.write(datetime.datetime.now().strftime('%d/%m/%Y %H:%M:%S'))
text_file.write(" ")
x = ser.read()
text_file.write(x)
text_file.flush()
ser.close()
When I check my text file afterwards the result seems to be different every time. If I let it run for just 2 or 3 seconds I sometimes get a correct result, sometimes I only get the humidity, sometimes I get the time stamp with a number that is half temperature, half humidity (like 2.16.3). If I let it run for more than a few seconds the file is just completely blank.
The basis for my code is from a question previously asked on here and it worked fine until I added the time stamp part. I tried changing the radio transfer rate from 9600 to 4800 but that just turned the numbers into garbage characters.
I'm running this on a Raspberry Pi 2 model B so I could be demanding too much from it in a short time.
You are calling read() twice and writing only the output of the second call. I don't imagine that is your intent.
You can change this section:
with open('tempdata.txt', 'a') as text_file:
while 1:
content = ser.read()
if content is 'a':
text_file.write(datetime.datetime.now().strftime('%d/%m/%Y %H:%M:%S'))
text_file.write(" ")
text_file.write(content)
text_file.flush()
I am writing a python script that will communicate to a Fluke meter over a COM port. I am able to receive the data but want to parse it into a usable float. The code looks like this:
import serial
ser = serial.Serial('COM3', 115200, timeout=1)
#Decalring some variables
FlukeID = b'ID\r'
FlukeQM = b'QM\r'
#Requesting the meters ID to verify connection on terminal
ser.writelines(FlukeID)
line = ser.readline()
print(line)
#Declaring variables for my while loop
thermdata = 0
t=1
ser.writelines(FlukeQM)
thermdata = ser.readline()
while(t < 5):
ser.writelines(FlukeQM)
#thermdata = (thermdata + ser.readline()) /2
thermdata = ser.readline()
print(thermdata)
t+=1
The data returned by the device looks like this on the console:
8.597E3,OHM,NORMAL,NONE INCORRECT
EDIT: The data actually appears like this over the terminal:
b'0\r8.597E3,OHM,NORMAL,NONE\r'
I just want to be able to use the numerical value at the beginning so I can do some calculations over time. I also need to be able to use the scientific notion portion in my number as I will not know the range of my measurements before hand. I know there must be a simple way to do this and would greatly appreciate any help.
On a side note, I would also like to be able to graph these values or place them into some kind of .csv file. If you have any comments on where to look to learn how to do this also that would be great, but I am mostly concerned with the handling of the bytearray.
Use split() to break your string into the comma separated parts. Then the first part is the string '8.597E3', which you convert using the float() function.
s = '8.597E3,OHM,NORMAL,NONE'.split(',')
value = float(s[0])
How about something like:
def atof(text):
try:
return float(text)
except ValueError:
return text
thermdata = b'0\r8.597E3,OHM,NORMAL,NONE\r'
for line in thermdata.strip().split(b'\r'):
print(list(map(atof, line.split(b','))))
# [0.0]
# [8597.0, b'OHM', b'NORMAL', b'NONE']