pythonarduinopyserial

Python code not sending data to Arudino if there is an interval using Serial connection


I have been trying to send data to my Arduino Nano via a serial connection. The data is sent properly once I start sending data immediately after initialising. However, if there is a pause in sending data, it stops sending properly.

This is my Python code. I created it for debugging:

import serial
import time
port = 'COM6' 
baudrate = 9600

# Open the serial connection
ser = serial.Serial(port, baudrate)
time.sleep(3)
data_to_send = "hello, world~"

# Encode data as bytes (optional for some data types)
data_bytes = data_to_send.encode('utf-8')  # Encodes string to bytes
while True:
    # Send data to Arduino
    ser.write(data_bytes)
    data = ser.readline()
    print("data", data)

    print(f"Data sent: {data_to_send}")

This is the Arduino code:

#include <Servo.h>


bool newData = false;
char receivedChars[64];
void setup() {
  // Motor control pins as outputs

  Serial.begin(9600);
  delay(1000);  // Give the serial connection time to initialize
  Serial.println("READY");
}

void loop() {
  static byte ndx = 0;
  char endMarker = '~';
  char rc;

  while (Serial.available() && newData == false) {
    rc = Serial.read();
    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
    } else {
      // receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }
  }
  Serial.println(receivedChars);
    

Now if I remove time.sleep(3) from the Python code, it keeps sending data immediately after the port has been initialised. The output looks something like this:

Data sent: hello, world~
data b'hello, world\r\n'
Data sent: hello, world~
data b'hello, world\r\n'
Data sent: hello, world~
data b'hello, world\r\n'
Data sent: hello, world~
data b'hello, world\r\n'
Data sent: hello, world~
data b'hello, world\r\n'

However, when time.sleep(3) is present in the code, this is the output:

Data sent: hello, world~
data b'\r\n'
Data sent: hello, world~
data b'\r\n'
Data sent: hello, world~
data b'\r\n'
Data sent: hello, world~
data b'\r\n'

I have tried setting the timeout parameter to a large value or to None but that doesn't help either.


Solution

  • From what it looks like, the while loop (that starts with while (Serial.available() > 0…) is exiting early while the python sending program is sleeping, as @timroberts pointed out.

    But since you’ve put the serial print call after the while loop, the loop ends and the Arduino ends up spamming the computer’s serial receive buffer with \r\n over and over until it’s full.

    So I can see two solutions:

    1. Correct the Arduino code so that it doesn’t call Serial.println if ndx is zero.
    2. In Python, Add a ser.reset_input_buffer() immediately before the while loop to wipe the buffer and get fresh data when the loop starts.