Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending serial communication (using Python on Ubuntu) to Arduino

This is the strangest thing I have seen in quite a while.

I have very basic Python code to send commands to a Arduino Uno R3 using Python running on Ubuntu.

import serial
import time

ser = serial.Serial('/dev/ttyACM0', 115200)
time.sleep(2)
if ser.isOpen():
    print "Port Open"
print ser.write("START\n")
ser.close()

The above code works accordingly and it prints:

Port Open
6

And I have an Arduino running which receives this command and toggles an LED. It is that simple.

The strange thing is that if I remove the line time.sleep(2), the Arduino stops toggling the LED. Python still prints that the port is open and it has successfully transmitted 6B.

Why is that delay needed?

I have seen it nowhere else? I have also tested the program from a PC running Windows with the same result.

I have tested with different baud rates. It does not matter and the behavior is the same.

The following is the Arduino code, but I don't think it is relevant.

#define LED_PIN  2
#define FAKE_DELAY 2*1000

String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  Serial.begin(115200);
  inputString.reserve(50);
}


void loop() {
  // print the string when a newline arrives:
  if (stringComplete) {

    digitalWrite(LED_PIN, HIGH); // turn the LED on (HIGH is the voltage level)

    Serial.print("Processing incoming command: ");
    Serial.println(inputString);

    if (inputString.startsWith("START")) {
      Serial.print("processing START...");
      delay(FAKE_DELAY);
    }

    // clear the string:
    inputString = "";
    stringComplete = false;

    digitalWrite(LED_PIN, LOW); // turn the LED off
  }
}


/*
  SerialEvent occurs whenever a new data comes in the
  hardware serial RX.  This routine is run between each
  time loop() runs, so using delay inside loop can delay
  response.  Multiple bytes of data may be available.
 */
void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    inputString += inChar;

    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inputString.endsWith("\n")) {
      stringComplete = true;
    }
  }
}
like image 816
theAlse Avatar asked Nov 26 '25 05:11

theAlse


1 Answers

Arduino Uno resets automatically when opening or closing the serial port through USB. So you have to give enough time to Arduino to complete the reset. I normally use a ready check (print (Arduino) - read (Python)) to avoid the delay in Python:

Arduino:

void setup ()
{
    // ..... //
    Serial.begin (115200);
    Serial.print ("Ready...\n");
}

Python:

import serial

ser = serial.Serial('/dev/ttyACM0', 115200)
print (ser.readline())

In this way, Python waits until the ready message is read, giving time to complete the reset.

You have to wait too for Arduino to finish its tasks before closing the serial port.

If auto-reset is a problem for your project, you can try to disable it Disabling Arduino auto reset

like image 156
credondo Avatar answered Nov 28 '25 20:11

credondo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!