Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python to arduino serial read & write

Tags:

I'm trying to "ping pong" info back and forth between some python code and arduino code. I want to send two setpoints to the arduino code periodically (for instance on the minute), read them on arduino & update variables then send status info from arduino back to python periodically (such as on the :30 second). Eventually python will be sending and pulling info from a mySQL db (later dev).

Right now I can't get the info to bounce back and forth reliably. I haven't found anything close to this in the searches and everything I've tried to modify isn't working. Closest I have is this (and it doesn't actually switch back and forth between send and receive):

Python

#!/usr/bin/python import serial import syslog import time  #The following line is for serial over GPIO port = '/dev/ttyS0'   ard = serial.Serial(port,9600,timeout=5)  i = 0  while (i < 4):     # Serial write section      setTempCar1 = 63     setTempCar2 = 37     ard.flush()     setTemp1 = str(setTempCar1)     setTemp2 = str(setTempCar2)     print ("Python value sent: ")     print (setTemp1)     ard.write(setTemp1)     time.sleep(4)      # Serial read section     msg = ard.readline()     print ("Message from arduino: ")     print (msg)     i = i + 1 else:     print "Exiting" exit() 

Arduino:

// Serial test script  int setPoint = 55; String readString;  void setup() {    Serial.begin(9600);  // initialize serial communications at 9600 bps  }  void loop() {   while(!Serial.available()) {}   // serial read section   while (Serial.available())   {     if (Serial.available() >0)     {       char c = Serial.read();  //gets one byte from serial buffer       readString += c; //makes the string readString     }   }    if (readString.length() >0)   {     Serial.print("Arduino received: ");       Serial.println(readString); //see what was received   }    delay(500);    // serial write section    char ard_sends = '1';   Serial.print("Arduino sends: ");   Serial.println(ard_sends);   Serial.print("\n");   Serial.flush(); } 

All I end up getting is the same values repeated (not what was actually sent, not sure if its a string or byte issue) and nothing back to the python script. Any help or ideas are greatly appreciated. Thanks.

EDIT: Modified code to what I'm currently running as suggested below. Arduino is receiving fine and serial communication verified by minicom. But python script still prints a blank line after "Message from arduino: ".

like image 829
Boombrewer Avatar asked Jun 06 '14 05:06

Boombrewer


People also ask

Can Arduino read Python?

The Arduino IDE does not yet support Python. Instead, we can use OpenMV, a platform that supports programming Arduino boards with MicroPython. Through the OpenMV editor, we can install MicroPython, and upload scripts directly to the board. There's also a number of examples available directly in the editor.


1 Answers

You shouldn't be closing the serial port in Python between writing and reading. There is a chance that the port is still closed when the Arduino responds, in which case the data will be lost.

while running:       # Serial write section     setTempCar1 = 63     setTempCar2 = 37     setTemp1 = str(setTempCar1)     setTemp2 = str(setTempCar2)     print ("Python value sent: ")     print (setTemp1)     ard.write(setTemp1)     time.sleep(6) # with the port open, the response will be buffered                    # so wait a bit longer for response here      # Serial read section     msg = ard.read(ard.inWaiting()) # read everything in the input buffer     print ("Message from arduino: ")     print (msg) 

The Python Serial.read function only returns a single byte by default, so you need to either call it in a loop or wait for the data to be transmitted and then read the whole buffer.

On the Arduino side, you should consider what happens in your loop function when no data is available.

void loop() {   // serial read section   while (Serial.available()) // this will be skipped if no data present, leading to                              // the code sitting in the delay function below   {     delay(30);  //delay to allow buffer to fill      if (Serial.available() >0)     {       char c = Serial.read();  //gets one byte from serial buffer       readString += c; //makes the string readString     }   } 

Instead, wait at the start of the loop function until data arrives:

void loop() {   while (!Serial.available()) {} // wait for data to arrive   // serial read section   while (Serial.available())   {     // continue as before 

EDIT 2

Here's what I get when interfacing with your Arduino app from Python:

>>> import serial >>> s = serial.Serial('/dev/tty.usbmodem1411', 9600, timeout=5) >>> s.write('2') 1 >>> s.readline() 'Arduino received: 2\r\n' 

So that seems to be working fine.

In testing your Python script, it seems the problem is that the Arduino resets when you open the serial port (at least my Uno does), so you need to wait a few seconds for it to start up. You are also only reading a single line for the response, so I've fixed that in the code below also:

#!/usr/bin/python import serial import syslog import time  #The following line is for serial over GPIO port = '/dev/tty.usbmodem1411' # note I'm using Mac OS-X   ard = serial.Serial(port,9600,timeout=5) time.sleep(2) # wait for Arduino  i = 0  while (i < 4):     # Serial write section      setTempCar1 = 63     setTempCar2 = 37     ard.flush()     setTemp1 = str(setTempCar1)     setTemp2 = str(setTempCar2)     print ("Python value sent: ")     print (setTemp1)     ard.write(setTemp1)     time.sleep(1) # I shortened this to match the new value in your Arduino code      # Serial read section     msg = ard.read(ard.inWaiting()) # read all characters in buffer     print ("Message from arduino: ")     print (msg)     i = i + 1 else:     print "Exiting" exit() 

Here's the output of the above now:

$ python ardser.py Python value sent: 63 Message from arduino: Arduino received: 63 Arduino sends: 1   Python value sent: 63 Message from arduino: Arduino received: 63 Arduino sends: 1   Python value sent: 63 Message from arduino: Arduino received: 63 Arduino sends: 1   Python value sent: 63 Message from arduino: Arduino received: 63 Arduino sends: 1   Exiting 
like image 84
Peter Gibson Avatar answered Sep 21 '22 17:09

Peter Gibson