-1

I am trying to send float values from Python on Windows to an Arduino. The first problem I encounter is that I cannot view the serial monitor when I think I am sending data from my Python script. I have read online that this is becuase only one application can manage the port at once: https://forum.arduino.cc/t/serial-communication-only-working-when-serial-monitor-is-opened/601107/12

However I have seen examples where the user is viewing the serial monitor to see data coming in over serial from Python and serial.print outs from the Arduino. So I am unsure what is the case... not being able to view the serial monitor sure does make debugging this senario hard.

My Python code:

import struct
import serial
import time
print('test123')
x=0.8
y=0.2

ser = serial.Serial('COM5', 9600, timeout=1)

#print(ser)
time.sleep(3)

def sendmess():
    bin = struct.pack('ff',x,y) #Pack float value into 4 bytes
    data = ser.write(bin)

    #print(bin)
    #print(len(bin))
    #print([ "0x%02x" % b for b in bin])

    
    #ser.close()

while True:
    sendmess()
   

My Arduino Code:

int d = 250;
float incomingByte = 1;
void setup() {
  // initialize the serial communication:
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  
}

void loop() {
  digitalWrite(2, HIGH);
  delay(d);
  digitalWrite(2, LOW);
  delay(d);
 // reply only when you receive data:
  if (Serial.available() > 0) {
    // read the incoming byte:
    d = 1000;
    float incomingByte = Serial.read();

    // say what you got:
    Serial.println(incomingByte);
    
  }
  else{
Serial.println(incomingByte);    
d = 20;
  }
}

I see the LED flash every second so I know the serial buffer is >0, but I cannot get any data out :(.

Thanks in advance!

Mark

I have tried examples online, but I never get any data to display in the serial monitor. Nor can I say have a pin turn HIGH when I think I am getting the data I think I have sent. But without the Serial Monitor how can I debug this?

1
  • Serial.read(); return a byte, not a float (which is 4-byte long), to get a floating point number, use float myFloat = Serial.parseFloat(SKIP_ALL, '\n');, Read the doc. Commented Nov 8, 2022 at 0:57

1 Answer 1

0

Unfortunately, you aren't able to connect more than two devices to the serial connection. However, using Python you should be able to read a response from your arduino and then print that to the python Terminal (or a file) and take a look at that.

The easiest way to do that would be to use pySerial and either ser.read(4) to read back 4 bytes of your float or ser.readline() which will look for either a '\n' which you can add to your arduino code, or a timeout. Then just print it to the python terminal with print().

As for actually reading the float, Serial.read() will only read in the next byte in the buffer. Since a float is 4 bytes long, you need to either read the 4 bytes into an array or use Serial.parseFloat()

Python Code

import struct
import serial
import time
x=0.8
y=0.2

ser = serial.Serial('COM5', 9600, timeout=1)

#print(ser)
time.sleep(3)

def sendmess():
    bin = str(x) + str(y) #Pack float value into 4 bytes
    data = ser.write(bin.encode())
    echo = ser.readline()
    print("Echo: " + echo)
    #ser.close()

while True:
    sendmess()

Arduino Code:

int d = 250;
float X;
float Y;
char buffer[40];
void setup() {
  // initialize the serial communication:
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  
}

void loop() {
  digitalWrite(2, HIGH);
  delay(d);
  digitalWrite(2, LOW);
  delay(d);
 // reply only when you receive data:
  if (Serial.available() > 0) {
    // read the incoming byte:
    d = 1000;
    X = Serial.parseFloat();
    Y = Serial.parseFloat();

    // say what you got:
    sprintf(buffer, "X: %f Y: %f", X, Y);
    Serial.println(buffer);
    
  }
  else{
   Serial.println(buffer);  
d = 20;
  }
}
Sign up to request clarification or add additional context in comments.

7 Comments

echo doesn't give you the floating point that you think to be, you need to struct.unpack('f', data) to get a floating point back and you might lost the precision.
@hcheung I believe the println() function from the arduino library returns a human readable version of the float and not the raw data of the float itself. I updated the code to ensure it reads the entire line but the code you provided above will not find a float. You'd need to parse the incoming ascii characters with float(echo). For debugging purposes, it shouldn't really matter.
Thanks for the repsonse, I can now see what python is sending. However it looks like it is just sending 0.00 infrequntly not 0.8 & 0.2. Echo: 0.00 Echo: Echo: Echo: Echo: Echo: 0.00 Echo: Echo: Echo: Echo: 0.00 Echo: Echo: Echo: Echo: 0.00 Echo: Echo: Echo: Echo: Echo: 0.00 Echo: Echo: Echo: Echo: 0.00 Echo: Echo:
Thanks, I can now view what Python is sending. But it looks like it is just sending 0.00 intermittanly? and not the 0.8 and 0.2 vaules I have? Echo: 0.00 Echo: Echo: Echo: Echo: 0.00 Echo: Echo: Echo: Echo: Echo: Echo: Echo: Echo: Echo: 0.00 Echo: Echo: Echo: Echo: 0.00
@masmith8 I modified the code above by removing the data packing in python. The Serial.parsefloat() function expects a string and not raw bytes. I ran it through an arduino emulator, wokwi, and it works as expected now. I also cleaned up the print statements in the arduino code so that it will respond with both X and Y in a single string.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.