How to read the serial port with a arduino over python? - python

import serial
ser= serial.Serial('com5',9600)
while 1:
Value_from_arduino = ser.readline()
Zustand = float(Value_from_arduino)
print(Zustand)
if Zustand == 1:
ser.write(0)
print('off')
elif Zustand == 0:
ser.write(1)
print(on)
This was the Python code, now here the arduino code.
char serialData;
int pin=12;
int pin2 = 5;
int Value;
void setup(){
pinMode(pin,OUTPUT);
pinMode(pin2,INPUT);
Serial.begin(9600);
}
void loop(){
Value = digitalRead(pin2);
Serial.println(Value);
delay(250);
while(Serial.available()){
serialData = Serial.read();
Serial.print(serialData);
if(serialData = '1'){
digitalWrite(pin,HIGH);
}
else if(serialData = '0'){
digitalWrite(pin,LOW);
}
}
}
My problem is, when i run my python code, it stops when he gets the Value 0 from my arduino.
Here is the report from python:
Zustand = float(Value_from_Arduino)
ValueError: could not convert string to float: b'\x000\r\n'
Python immediatly stops, but he puts the LED on.
The LED should be on if Python gets the value of 0, he do but then he just end run.
The LED should go on if value is 0 and of if value is 1.

You need to decode the serial bytes from the serial port.
Replace the Zustand = line in your code
Value_from_arduino = ser.readline()
Zustand = float(ser_bytes[0:len(Value_from_arduino )-2].decode("utf-8"))
Please check here https://makersportal.com/blog/2018/2/25/python-datalogger-reading-the-serial-output-from-arduino-to-analyze-data-using-pyserial
also try, if encodings doesn't work well
import struct
Zustand, = struct.unpack('<f',Value_from_arduino )

Finally i have found out please replace these lines of code
Steps -> Read,Decode to string, Strip /n and /r, Convert to float
please check here https://problemsolvingwithpython.com/11-Python-and-External-Hardware/11.04-Reading-a-Sensor-with-Python/
Value_from_arduino = ser.readline()
Value_from_arduino = Value_from_arduino.decode()
Value_from_arduino = Value_from_arduino.rstrip()
Zustand = float(Value_from_arduino)
Hope this Works..

Related

Arduino MLX90614 to Pyserial error converting String to Float

Good Day! I was struggling about my arduino MLX90614 code my pyserial cant read the data it show's
Here's my arduino MLX90614 code:
#include <Wire.h>
#include <Adafruit_MLX90614.h>
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
void setup() {
Serial.begin(9600);
mlx.begin();
}
void loop() {
Serial.print("Ambient = "); Serial.print(mlx.readAmbientTempC());
Serial.print("*C\tObject = "); Serial.print(mlx.readObjectTempC()); Serial.println("*C");
Serial.print("Ambient = "); Serial.print(mlx.readAmbientTempF());
Serial.print("*F\tObject = "); Serial.print(mlx.readObjectTempF()); Serial.println("*F");
Serial.println();
delay(500);
}
And heres my python code "Pyserial" to read the data from my arduino
import csv
from time import time
import serial
# Your serial port might be different!
ser = serial.Serial('COM5', timeout=1)
f = open("df.csv", "a+")
writer = csv.writer(f, delimiter=',')
while True:
s = ser.readline().decode()
if s != "":
rows = [float(x) for x in s.split(',')]
# Insert local time to list's first position
rows.insert(0, int(time()))
print(rows)
writer.writerow(rows)
f.flush()
But in result it show's this
"rows = [float(x) for x in s.split(',')]
ValueError: could not convert string to float: 'Ambient 30c /n'"
Someone please help me with this I am really struggling with connecting my Arduino MLX90614 to my Arduino. Thanks in advance
If s != '' is not a space, add the whitespace between the quotes, this is returning values that cannot be passed to the int constructor.
Comment the list comprehension out and print instead to see the current values your code is storing.

Serial communication between python + arduino and parsing string

I'm trying to send a set of [x, y] coordinates from python to arduino in order to control servo motors on a robot drivetrain. I'm taking the approach of sending a string in the format "x,y". On the arduino side, I'm trying to parse this string to get the x and y substrings. However the indexOf function doesn't return the proper index. Here is my code:
arduino = serial.Serial(port='COM3', baudrate=9600, timeout=.1)
def write_read(x):
arduino.write(bytes(x, 'utf-8'))
time.sleep(0.05)
data = arduino.readline()
return data
for coordinate in coordinates:
c = str(coordinate[0]) + ", " + str(coordinate[1])
print(write_read(c))
#include <Servo.h>
void setup() {
Serial.begin(9600);
Serial.setTimeout(1);
}
void loop() {
while (!Serial.available());
String coordinates = "" + Serial.readString();
// Serial.print(coordinates); //this prints normally as the string value
int i = coordinates.indexOf(',');
Serial.print(i);
}
When I send something like "-9.45, -16.3". The output is b'-1-1-1-1-10-1-1-1-1-1-1'. I'm not sure what's going on here or how to get the actual index (in this case it would be 5).

Python I2C communication TTP229

I need to read 2 different bytes from TTP229 (16 keys or 8 keys touch pad detector).
I use I2C In Python. TTP229 datasheet PDF.
I can't read the second byte, but I can get the first byte.
Python code:
import smbus
bus = smbus.SMBus(1)
adressTTP229 = 0x57 #0xAF>>1
byte1 = bus.read_byte(adressTTP229)
byte2 = bus.read_byte(adressTTP229)
byte1 is always equal to byte2.
This Arduino code, works ok:
#include <Wire.h>
#define ttp229 (0xAF>>1)
void setup() {
Serial.begin(9600); // start serial for output
Wire.begin();
}
void loop() {
delay(50);
bool isNewData = false;
Wire.requestFrom(ttp229,2,true);
while (Wire.available()) {
uint16_t b1 = Wire.read(); // receive a first byte
uint16_t b2 = Wire.read(); // receive a second byte
if (b1==b2 && b2==0) {break;}
//...
}
}
How do I use Arduino's requestFrom() function in Python?
try:
import smbus, time
bus = smbus.SMBus(1)
while True:
print bus.read_word(0xAF)
time.sleep(0.1)
dont change address, bus doe the conversion, and if you read byte you will always get the same first byte. you want to read a word = 2 bytes at once
not tested, but might work, have it ordered and will test

Windows pipes: Write from C - read in Python

I'd like to transmit a few bytes of data though a pipe to plot it from python.
I started with some snippets I found here but I cant get them working.
I've created the pipe like this:
int main(void){
HANDLE hPipe;
char buffer[24];
DWORD dwRead;
hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\Pipe"),
PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
PIPE_WAIT,
1,
24 * 16,
24 * 16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
while (hPipe != INVALID_HANDLE_VALUE)
{
if (ConnectNamedPipe(hPipe, NULL) != FALSE) // wait for someone to connect to the pipe
{
while (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &dwRead, NULL) != FALSE)
{
/* add terminating zero */
buffer[dwRead] = '\0';
/* do something with data in buffer */
printf("%s", buffer);
}
}
DisconnectNamedPipe(hPipe);
}
return 0;}
If I execute the following code it writes but the read part blocks:
import time
import struct
f = open(r'\\.\\pipe\\Pipe', 'r+b', 0)
i = 1
sss='ccccc'
while True:
s = sss.format(i)
i += 1
f.write(struct.pack('I', len(s)) + s) # Write str length and str
f.seek(0) # EDIT: This is also necessary
print 'Wrote:', s
n = struct.unpack('I', f.read(4))[0] # Read str length
s = f.read(n) # Read str
f.seek(0) # Important!!!
print 'Read:', s
time.sleep(2)
I tried commenting the ReadFile part in the C code but It did not work. Is there any other way to achieve this? I want to write from C and read from python. I tried writing into the pipe with CreateFile (from C) and it worked as expected. I only need the read part with python.
On most systems pipe is one-directional and you use two pipes to get two-directional (bidirectional) connection.
In your Python code you can open two connections
and then you don't need seek
import time
import struct
wf = open(r'Pipe', 'wb', 0)
rf = open(r'Pipe', 'rb', 0)
i = 0
template = 'Hello World {}'
while True:
i += 1
text = template.format(i)
# write text length and text
wf.write(struct.pack('I', len(text)))
wf.write(text)
print 'Wrote:', text
# read text length and text
n = struct.unpack('I', rf.read(4))[0]
read = rf.read(n)
print 'Read:', read
time.sleep(2)
EDIT: tested on Linux Mint 17, Python 3.4 & 2.7
I've solved it with PyWin32(http://sourceforge.net/projects/pywin32/files/) which seems to be the right tool for windows. I would rather use something more cross-plataform oriented but it has solved the problem.

Read continuous data from serial port with pyserial

I have strings being continuously sent from my arduino.
For example, I am sending an integer (0-1023) line by line, so it should be:
"51\r\n233\r\n37\r\n166\r\n"
And infinitely long as it is continuously streaming.
I am currently using pyserial's function readline() to read the data, but constantly see broken/missing bytes. For example, instead of "37\r\n" followed with "11\r\n", it will get "3\r11\r\n" or even "3711\r\n"!
Here's my full Python-end code:
import serial
import time
if __name__ == '__main__':
ser = serial.Serial('COM3', baudrate=1000000)
data = []
time0 = time.time()
while (time.time() - time0 < 5): # Read data for 5 seconds
data.append(ser.readline())
ser.close()
For those interested, the (probably relevant) arduino code is simply:
#define FASTADC 1 // Flag for prescale 16
// Code pasted for modifying ADCSRA
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
void setup() {
Serial.begin(1000000);
#if FASTADC
// set prescale to 16
sbi(ADCSRA,ADPS2) ;
cbi(ADCSRA,ADPS1) ;
cbi(ADCSRA,ADPS0) ;
#endif
}
void loop() {
int val;
val = analogRead(A0);
Serial.println(val);
}
As you can see from the code, the baud rate, parity, stop bit were both set to 1,000,000; None; 1.

Categories

Resources