Reputation: 31
I need to use data collected from a sensor connected to an arduino Uno in a Python code. It's a basic question of getting the state of the digitalPin to my Python code. I first wanted to try my hand at just making a communication going both ways, from Python to Arduino, and after from Arduino to Python.
So I tried doing a ping-pong with Python sending a command, and Arduino sending back 0 if it didn't reach or 1 if it worked. The thing is: I can see the command test in Arduino, but the back data is not working.
Here's my Arduino code :
void setup() {
Serial.begin(9600);
delay(1000);
}
void loop() {
if (Serial.available() > 0) { // check if there's data from python
String command = Serial.readStringUntil('\n'); // read python command
Serial.println(command); // show command in Arduino monitor
Serial.write("command\n");
if (command == "test") { // if command is "test"
Serial.write(1);} // Envoie 1 en tant que byte
else {
Serial.write(0);} // Envoie 0 en tant que byte
Serial.flush();
}
}
And here's my Python code:
import serial
import time
capt = serial.Serial('COM5',9600,timeout=5)
def testcomm(test):
out = 0
com = (test + '\n').encode() # Send test command with end ligne indicator \n
print(f"Commande envoyée : {com}")
capt.write(com) # send command to Arduino
time.sleep(4)
# Check if there's data
if capt.in_waiting > 0 :
testout = capt.readline() # read
print(f'testout val (raw): {testout}') # show raw
if testout:
out = testout.strip() # clean answer
print(f'testout val (cleaned): {out}')
else:
print("Doesn't work")
return out
test1 = testcomm('test')
capt.close()
And here's the result in my Python console:
Commande envoyée : b'test\n'
Doesn't work
I checked whether the command line in itself worked inside the Arduino monitor, it does, and it sends back 1, but really, I can't read it in Python.
I also tried read(), readline() and readlines() just in case. I tried a lot of different things, but I didn't keep track, and I was also learning the pyserial library in parallel, so a lot of my tries were just weird. What can I try next?
Upvotes: 2
Views: 57
Reputation: 31
So, after looking a bit more into it, again, I played with time.sleep()
. The problem was that I was sending a command too quickly after I opened the port, so it was unable to catch the command. The solution was to add a time.sleep()
after the port was opened (in my case I put it before the capt.write()
command).
Upvotes: 1
Reputation: 1008
The issue you're encountering is likely due to the way you're handling the serial communication between your Arduino and Python. In your Arduino code, you're using Serial.write(1)
and Serial.write(0)
to send back the response. This sends the values as raw bytes, which might not be what you expect on the Python side. Instead, you should send the response as a string to make it easier to read in Python.
Updated Arduino code:
void setup() {
Serial.begin(9600);
delay(1000);
}
void loop() {
if (Serial.available() > 0) { // check if there's data from python
String command = Serial.readStringUntil('\n'); // read python command
Serial.println(command); // show command in Arduino monitor
if (command == "test") { // if command is "test"
Serial.println(1); // Send 1 as a string
} else {
Serial.println(0); // Send 0 as a string
}
Serial.flush();
}
}
and updated python code:
import serial
import time
capt = serial.Serial('COM5', 9600, timeout=5)
def testcomm(test):
out = 0
com = (test + '\n').encode() # Send test command with end line indicator \n
print(f"Commande envoyée : {com}")
capt.write(com) # send command to Arduino
time.sleep(1) # Give some time for Arduino to process and respond
capt.flushInput() # Clear the input buffer
capt.flushOutput() # Clear the output buffer
time.sleep(1) # Give some time for Arduino to send the response
if capt.in_waiting > 0:
testout = capt.readline().decode().strip() # read and decode the response
print(f'testout val (raw): {testout}') # show raw
if testout:
out = testout # clean answer
print(f'testout val (cleaned): {out}')
else:
print("Doesn't work")
return out
test1 = testcomm('test')
capt.close()
The Arduino code now uses Serial.println()
to send the response back as a string. This ensures that the response is sent with a newline character, which makes it easier to read on the Python side.
The Serial.flush()
is used to ensure that all data is sent out of the serial buffer.
The python code uses capt.flushInput()
and capt.flushOutput()
functions to clear the input and output buffers, ensuring that any residual data is cleared before reading the response.
The capt.readline().decode().strip()
function is used to read the response from the Arduino, decode it from bytes to a string, and strip any leading or trailing whitespace.
Upvotes: 0