Very slow serial communication - Raspberry Pi 4> Arduino Mega

My serial communication between my Raspberry Pi 4 4GB RAM and my Arduino Mega 2560 is very slow. When I send a serial.write from my Arduino it takes about 2 seconds to arrive.

I can tell that it takes 2 seconds because before the led is turned on or off they are printed twice on the console, with a 2 second sleep.

Is there a solution to make it faster?

From doc "Serial.readString() reads characters from the serial buffer into a string. The function terminates if it times out (see setTimeout())."

And default timeout is 1 sec. You can decrease a timeout using S****etTimeout().
Or better use readStringUntil, so you know you have a complete string when you get a terminator character (like a newline).

Replace

Command = Serial.readString();

with

Command = Serial.readStringUntil('\n');

And use corresponding delimiter at your RPi code

Have a look at this Simple Python - Arduino demo

...R

To be honest it is not clear to me what the solution is.

My problem is:
I try to send data from my Raspberry pi with

serial.write (b'led-on')

To my Arduino with

digitalWrite (led, HIGH)

when the' led-on' command is sent.

It is very slow. By the way, I am new to Arduino.

raym3d:
To be honest it is not clear to me what the solution is.

Have you tried the programs in my link in Reply #2

Note how the Arduino program is not using Serial.readString()

If you just want to turn an LED on or off why not just send 'B' for on and 'b' for off. Then the Arduino has only a single character to deal with.

...R

I have a simpler example, with a serial monitor.

When I press 1 or 2, the led turns on or off, but it doesn't work immediately, the delay is noticeable.

I notice that I immediately write 1 or write a command in Arduino, the led that comes with the arduino integrated turns on, but the led that I put on pin 12 does not turn on immediately, it has a delay. I want to make it faster.

After the led that arduino brings by default turns on, it takes approximately 1.5 seconds to perform the command indicated by the serial monitor.

Regarding answer 2, I put berial.begin (115200) ;, but it's still just as slow

int led = 12;

void setup() {
  Serial.begin(115200);
  pinMode(led , OUTPUT);
}

void loop() {
  if (Serial.available()) {
    int command = Serial.parseInt();
    if (command == 1) {
      digitalWrite(led, HIGH);
    } 
    else if (command == 2) {
      digitalWrite(led, LOW);
    } 
  }
}

Add

Serial.setTimeout(100);

To setup()

Can you imagine what would happen if a timeout of 0 was set?
Serial.setTimeout(0)

raym3d:
Can you imagine what would happen if a timeout of 0 was set?
Serial.setTimeout(0)

It's not a good idea. Timeout defines how long the readString iswaiting to make sure that the sending of the string is finished and has the complete string.
If you need faster communication use

readStringUntil

as I explained at post #1

Serial communication is slow compared to the speed of an Arduino. If you're sending some data on the wire, the Arduino will see the first byte and will have to wait a long time in its terms until the next one arrives.

Parseint is a way to deal with that. It waits for the timeout period before concluding that the whole thing must have been received by now.

Readstringuntil is an alternative. You can specify a character that comes after the text you're sending and once the receiver sees it there is confirmation that it's done and can move on. No timeout? Less delay.

wildbill:
and will have to wait a long time in its terms until the next one arrives.

The code in the link in Reply #2 does all of that in the background.

...R

I read what you wrote in the posts of answer 2, but honestly it's a bit complicated for my level, I'm learning little by little. There are terms that I do not know.

I have a new question.
Why is it that when I put a While in Python and send the data to the serial, and I don't put a delay of at least 0.9 seconds, the information is not sent?

That is, I send a number to tell Arduino to do something and immediately I send another number. The first action is not fulfilled, only the second.

When I put a While in Python, a heap is sent every second, but none arrives. I realize this is sending because the Arduino's led turns on.

Is there a way for information to get there faster? I use serial.write from python.

What I did before Serial.setTimeout (100);
It helped that when the information reaches the Arduino, it arrives immediately, but, my current problem is that I have to wait 0.9 seconds for it to arrive at the Arduino.

raym3d:
I read what you wrote in the posts of answer 2, but honestly it's a bit complicated for my level, I'm learning little by little. There are terms that I do not know.

If you tell me what you don't understand I will try to help.

The programs are probably as simple as you can make them and have a robust working system that responds quickly - almost instantly.

Have you tried my programs just as they are?. If you are using Windows you will need to edit the Python code to use the Windows serial port style COMx

...R

Thank you very much for your help, Robin2, and others.

I refer to this article: Serial Input Basics - updated - Introductory Tutorials - Arduino Forum
Question 1:
Example two, I don't know what the recvWithEndMarker function is used for. That is, what is char endMarker = '\ n'; for?

Question 2:
I use raspberry pi 4. I send numbers with serial.write in Python and receive it in the Arduino. If the command == to the number I sent, then I run digitalWrite on Arduino.

Regarding the last thing I said, the number immediately arrives at the arduino, the digitalWrite is executed, so I set it from

Serial.begin (115200);
Serial.setTimeout (100);

My problem is that to send the number I must wait at least 0.9 seconds, that is, I can't send consecutive numbers via Raspberry Pi in Python, to the Arduino. Any solution?

Q1 ...

The function recvWithEndMarker() is used when you want to receive text that is followed by a character that marks the end of the message. In the example the endMarker is the linefeed character which is '\n' If your text is terminated with a different character you can change endMarker

Q2 ...

I don't think your question is about my Python program. And if you use the programs from my Python tutorial there should be no waiting for nearly a second.

...R

@raym3d, we seem to be going round in circles and gettiing nowhere.

I still do not know whether you tried the example code in my Tutorial or what happened when you tried it.

Of course I won't be in the least upset if you prefer not to use my advice. All I can say in my defence is that my code works.

...R

I tried your code, but I still have no solution to my problem, because your codes do not do exactly what I am looking for.

I have a Python While that sends data to turn on (b'1') and turn off (b'2') every millisecond. Unless I put a time.sleep(1), the action is not executed (turn on a led).

raym3d:
I tried your code, but I still have no solution to my problem, because your codes do not do exactly what I am looking for.

I am not at surprised that my code does not do exactly what you want. But you have given me no information about what you want it to do that is different and without knowing that I can't help you.

...R

I have this code on Arduino.

int led = 12;

void setup() {
  Serial.begin(115200);
  pinMode(led , OUTPUT);
  Serial.setTimeout(100);
}

void loop() {
  if (Serial.available() > 0) {
    int command = Serial.read();;
    if (command == '1') {
      digitalWrite(led, HIGH);
    }
    else if (command == '2') {
      digitalWrite(led, LOW);
    }
  }
}

Raspberry Pi:

import serial
import time

while True:
    ser = serial.Serial("/dev/ttyUSB0", 115200)
    ABC = 1

    if ABC > 0:
        print("Sent")
        ser.write(b'1')
        
    else:
        print("Waiting")
        ser.write(b'2')

In Raspberry a bunch of "Sent" is printed and sent (b'1') to Arduino every microsecond. The problem is that it never turns on unless I put a delay in python time.sleep(1)
It's just sample code, because I actually have a sensor that sends ABC data every microsecond.

But... If I put this it works with the time.sleep(0.1), but, if I remove the first time.sleep(1) it stops working:

import serial
import time

while True:
    ser = serial.Serial("/dev/ttyUSB0", 115200)
    ABC = 1
    time.sleep(1)
    if ABC > 0:
        print("Sent")
        ser.write(b'1')
        time.sleep(0.1)
        ser.write(b'2')
        time.sleep(0.1)
        ser.write(b'1')
        ser.write(b'1')
        time.sleep(0.1)
        ser.write(b'2')

    else:
        print("Waiting")
        ser.write(b'2')

If I remove the first time.sleep(1) or put a number less than 1 it stops working.

raym3d:
In Raspberry a bunch of "Sent" is printed and sent (b'1') to Arduino every microsecond.

I presume that is a mistake.

At 115200 baud it takes over 80 microsecs to send a single byte

You should not have

ser = serial.Serial("/dev/ttyUSB0", 115200)

inside your WHILE loop. You should just open the Serial port once and keep it open until the PC is finished with the Arduino. When the PC opens the serial port it makes the Arduino reset and that is what is taking the time.

That's why I wanted you to study how it is done in the code my Tutorial.

...R