As I can distinguish different data from Serial? - python

I trying to read by serial differents values, but i dont know hoy to split that, because the two values are numbers but from different source
First i have a PICAXE sending converted data by ADC of light sensor by serial to python.
Second i have a PICAXE sending data of temperature sensor by serial to python.
Light code PICAXE
symbol puerto = B.5
main: readadc10 puerto,w1 ; read value into w1
sertxd(#w1,cr,lf)
goto main ; loop back to start
Temp code PICAXE
symbol temp = B.4
readtemp temp, w0 ; read value into w1
debug
sertxd(#w0,cr,lf)
goto main
Python code
import pygame
import sys, serial
from pygame.locals import *
ser = serial.Serial()
ser.port = 3
ser.baudrate = 4800
while True:
datos = ser.readline()
grados = float(datos)
print grados
The problem is that picaxe send simultaneus data from light and temp, but when python receive data, i dont know how to recognized each data.
Anyone can help me??
Thank!

If you have a temperature reading and a light level reading to send at the same time, you could put them on one line separated by a space.
PICAXE:
sertxd(#w0," ",#w1,cr,lf)
Python:
readings = ser.readline()
[reading1, reading2] = readings.split()
temperature = float(reading1)
lightlevel = float(reading2)
If the two types of reading are produced irregularly, you could transmit a character before each one to identify what type it is.
PICAXE:
sertxd("T ",#w0,cr,lf)
...
sertxd("L ",#w1,cr,lf)
Python:
reading = ser.readline()
[readingtype, readingvalue] = reading.split()
if readingtype == "T":
temperature = float(readingvalue)
elif readingtype == "L":
lightlevel = float(readingvalue)

Related

How to extract certain data from list of serial port data using python

i am beginner. i have connected my arduino to my raspberry pi and get data from serial monitor. Below is the code that i used.
import serial
import numpy as np
ser = serial.Serial('/dev/ttyACM0',9600)
s = [0,1]
while True:
b = ser.readline()[:-5]
str_rn = b.decode()
string = str_rn.rstrip()
print(string)
The ouput on each line consist of: mac address,data,time. How can i get just data (-83, -85, -89) from specific mac address (let say 40:49:0f) and pass into a variable in array? Can anyone assists? Thanks for help.
The output at the moment like this:
40:49:0f,-83,1412
56:ab:27,-87,1416
f4:c5:6f,-80,1417
40:49:0f,-85,1417
56:ab:27,-88,1417
56:ab:27,-86,1417
0f:b9:b6,-48,1417
40:49:0f,-89,1721

How to properly read most recent value from serial?

I am reading values from a pressure sensing mat which has 32x32 individual pressure points. It outputs the readings on serial as 1024 bytes between 1 and 250 + 1 'end token' byte which is always 255 (or xFF).
I thought the function bellow would flush/reset the input buffer and then take a 'fresh' reading and return the max pressure value from that reading whenever I call it.
However, none of the ser.reset_input_buffer() and similar methods seem to actually empty the buffer. When I press down on the mat, run the program and immediately release the pressure, I don't see the max value drop immediately. Instead, it seems to be going through the buffer one by one.
import serial
import numpy as np
import time
def read_serial():
ser_bytes = bytearray([0])
# none of these seem to make a differece
ser.reset_input_buffer()
ser.flushInput()
ser.flush()
# 2050 bytes should always contain a whole chunk of 1025 bytes ending with 255 (xFF)
while len(ser_bytes) <= 2050:
ser_bytes = ser_bytes + ser.read_until(b'\xFF')
ser_ints = np.array(ser_bytes, dtype='int32') #bytes to ints
last_end_byte_index = np.max( np.where(ser_ints == 255) ) #find the last end byte
# get only the 1024 sensor readings as 32x32 np array
mat_reading = np.array( ser_ints[last_end_byte_index-1024: last_end_byte_index]).reshape(32,32)
return np.amax(mat_reading)
ser = serial.Serial('/dev/tty.usbmodem14201', 115200, timeout=1)
while True:
print(read_serial())
time.sleep(1)
The best solution I found so far is having a designated thread which keeps reading the buffer and updating a global variable. It works but seems a bit unresourceful if I only want to read the value about every 60 seconds. Is there a better way?
Also... is there a better way to read the 1025-byte chunk representing the entire mat? There are no line breaks, so ser.readline() won't work.
Thanks! Not sure how to make an MWE with serial, sorry about that ;)

how to read multiple values from com port using pyserial with python?

I have an STM32 connected to a thermal sensor which indicate the temperature of the room and i worte this program to read this temperatur from my com port. Now i need a program to read multiple value from my com port.
thank you for helping me to solve this problem.
import serial
serport = 'COM3'
serbaudrate = 38400
ser = serial.Serial(port = serport, baudrate = serbaudrate, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, timeout=2)
try:
ser.isOpen()
except:
print("Error")
exit()
if ser.isOpen():
try:
while 1:
if ser.inWaiting() > 0:
#print(ser.readline())
response = ser.readline()
print(response.decode("utf-8"))
else:
ser.write(b"1")
except Exception as e:
print(e)
#Tarmo thank you for answering my question. This is the code i wrote for programming th microcontroller:
while (1)
{
// Test: Set GPIO pin high
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
// Get ADC value
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
raw = HAL_ADC_GetValue(&hadc1);
raw = ((raw*0.000244*3.3) - 0.25)/0.028;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);
// Convert to string and print
sprintf(msg, "%hu\r\n", raw);
HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
// Pretend we have to do something else for a while
HAL_Delay(100);
}
in this case i am reading just one value because the thermal sensor gives only one value. if i have more than one value how can i delimit them with a semicolon?
If you've already gone the way of sending a numeric value as text, you can extend that. Assuming you want to send 3 integer values at the same time, just delimit them with a semicolon. E.g. 123;456;789\n.
Your microcontroller should then output data in this format and your Python program can read the entire line just like it does now. The you can parse this line into individual values using regex:
import re
...
response = ser.readline()
needles = re.match("(\d+);(\d+);(\d+)", response)
if needles:
print("Got: {} {} {}".format(needles[0], needles[1], needles[2]))
Let's assume you have 3 values from the ADC, in the variables raw1, raw2, and raw3. Then you can use sprintf() to format a message with all of them, and use Tarmo's suggestion to read them.
sprintf(msg, "%hu;%hu;%hu\r\n", raw1, raw2, raw3);
Please provide enough memory in the variable msg.

How to parse data from a NMEA GPS through serial connection in python?

I am very new to python and I am trying to implement a serial communication with a GPS. There is 4 lines repeating periodically in each sample and I just want those which starts as GPGGA to be saved. The GPS is sampling on 5 Hz as default. I have the code below so far.
import serial
import csv
gps = serial.Serial('COM3', 56700, timeout=1) # opening COM port
gps.flushInput() # clears the serial port so there is no data overlaping
gps_bytes = gps.readline()
try:
while gps_bytes:
line = gps.readline()
if line.find('$GPGGA') != -1:
#else:
# time, LAT, dir1, LONG, dir2 = line.split(",")[1:5]
print(line)
input('Press Enter to stop\n')
except (Exception, KeyboardInterrupt):
pass
gps.close()
#with open("gps_data.csv","a") as f:
# writer = csv.writer(f,delimiter=",")
# writer.writerow([time.time(),gps_data])
The GPS signal lines are coma separated. Where I want to use only the GPGGA, time (hhmmss.), LON (XX), N, LAT (YY), E line and only need these 3 numeric values (time, LONG, LAT).
$GPGGA,070611.00, XXXX.XX, N, YYY.Y, E,2,12,0.9,15.147,M,39.586,M,,*50
$PNVGBLS,070611.00,,,,,,,N*33
$GPRMC,070611.00,A,XXXX.X, N,YYY.Y, E,0.07,0.00,211020,,,D*5E
$GPVTG,0.00,T,,,0.07,N,0.13,K,D*70
$GPHDT,,T*1B
What I want, is to open the serial and start firing me data until I hit enter to stop and then save it in a .csv file. Can anybody help me with how to do that? Any help will be highly appreciated.
Thank you in advance

Interpret serialdata in python

I'm currently struggling with an issue. I have an arduino sending serialdata to my raspberry pi. The raspberry pi reads the data and stores it in a database. What i'm struggling with is to get data in the correct order. If i start the script at the correct time, the values get read properly. If i don't they get mixed up.
I have a headerByte sent from the arduino, this value is 999 and it is the first value to be sent each time. Is there a way in python to make 999 the marker for the beginning of every read? My variables will never exceed 999 so this will not be a problem.
Python code:
import serial
import time
values = []
serialArduino = serial.Serial('/dev/ttyACM0', baudrate=9600, timeout=1)
voltageRead = serialArduino.readline()
currentRead = serialArduino.readline()
while True:
voltageRead = serialArduino.readline()
currentRead = serialArduino.readline()
print"V=", voltageRead, "A=", currentRead
Arduino Code:
void loop() {
float voltageRead = analogRead(A0);
float ampsRead = analogRead(A1);
float calculatedVoltage = voltageRead / 103;
float calculatedCurrent = ampsRead / 1;
int headerByte = 999;
Serial.println(headerByte);
Serial.println(calculatedVoltage);
Serial.println(calculatedCurrent);
delay(1000);
}
Your method isn't particularly efficient; you could send everything as a struct from the Arduino (header + data) and parse it on the RPi side with the struct module though your way does have the advantage of simplicity. But, if 999 is the highest value you expect in your readings, then it makes more sense to use a number greater than 999 like 1000. And 999 isn't really a byte.
That said, if "1000" is your header, you can simply check for the header's presence like this:
HEADER = "1000"
serialArduino = serial.Serial('/dev/ttyACM0', baudrate=9600, timeout=1)
while True:
if serialArduino.readline().rstrip() == HEADER: # check for header
voltageRead = serialArduino.readline() # read two lines
currentRead = serialArduino.readline()
print"V=", voltageRead, "A=", currentRead

Categories