Arduino CLI not sending serial data to board right away

I'm working on embedding the arduino-cli as part of an electron application I'm developing, and I'm running into some trouble getting serial communication to work between the arduino-cli and an attached Arduino Uno (my application is talking to the arduino-cli over gRPC).

I'm sending serial data to the Uno board with the following gRPC command. What I'm finding is that is seems the arduino-cli is buffering the data, and it gets sent to the board some unpredictable amount of time in the future (30 seconds later, 1 minute later, etc.)

Interestingly, data received from the Arduino Uno is immediately transmitted to my application from the arduino-cli.

I'm wondering if this is expected, and if there's a way to force / flush serial data, or could this be a bug?

async sendMessageToSerial(message) {
        if (!this.serialConnection) {
            return Status.NOT_CONNECTED;
        }
        const req = new StreamingOpenRequest();
        req.setData(new TextEncoder().encode(message));
        return new Promise((resolve) => {
            if (this.serialConnection) {
                this.serialConnection.duplex.write(req, () => {
                    resolve(Status.OK);
                });
                return;
            }
            this.disconnect().then(() => resolve(Status.NOT_CONNECTED));
        });
    }

Thank you for any and all help!

Austin

What "arduino-cli" are we talking about? How to you terminate the line you are sending so the Arduino knows to send it from its internal buffer? Are you running interrupts? are you using delay()? More information will help.

This one:
https://arduino.github.io/arduino-cli/latest/

Here is the documentation for the gRPC interface:

Thanks for the replies!

Thanks for adding the references to the cli.

I'm running a very simple Sketch on the Arduino to repeat back the serial data. If I run this in the Arduino IDE 2.0, I get the string back on my computer right away. In my application, the time the string comes back is unpredictable. So I don't think the issue is with the Arduino Uno, rather it's probably with how I'm using the gRPC interface.

As for line endings, I've tried with all of the following combinations ('', '\n', '\n\r') all with the same result.

void setup() {
  Serial.begin(9600);
}

int i = 0;
void loop() {
  if (Serial.available() > 0) {
    String incomingString = Serial.readString();
    Serial.print("I received: ");
    Serial.println(incomingString);
  }
}

As an interesting aside, I added a hack after calling sendMessageToSerial (the code in my first post above), where I initiate a BoardSearchRequest. This causes the buffered data to be sent to the Arduino immediately.

Just for the sake of eliminating any unnecessary complexity, I would recommend not using Serial.readString() for now. The reason is that it is line ending dependent. If there is no line ending, it has to time out:

However, the default timeout is only 1000 ms, so that still shouldn't cause the sort of delays you are observing.

This is a very minimal echo sketch:

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    Serial.write(Serial.read());
  }
}

I have found this nice tool to be very useful for quick experiments with gRPC:

You might like to do quick experiments with it to check whether unexpected results are specific to your Electron application code.

Something to note about the Uno is that it will automatically reset when the serial port is opened, after which there is a short delay for the bootloader to time out before the sketch code starts running. I didn't actually figure out how to navigate that with grpcui, but I just tried it with my Leonardo (which does not have the auto reset behavior like the Uno) and I was able to send and receive serial data via grpcui without any unusual delay.

I suggest you start the daemon process with the --debug flag, it should show more information, you should see something like this:

$ arduino-cli daemon --debug
Daemon is now listening on 127.0.0.1:50051
CALLED: /cc.arduino.cli.commands.v1.ArduinoCoreService/Create
|  REQ:  {}
|  RESP: {
|    "instance": {
|      "id": 1
|    }
|  }

This can be helpful to know if the CLI is actually receiving the message or not.

Also don't use grpcui for bidirectional stream APIs, you can't interact with them. I suggest grpcurl for those.

This is an example call to Create:

$ grpcurl -plaintext \
-proto cc/arduino/cli/commands/v1/board.proto \
-proto cc/arduino/cli/commands/v1/commands.proto \
-proto cc/arduino/cli/commands/v1/common.proto \
-proto cc/arduino/cli/commands/v1/compile.proto \
-proto cc/arduino/cli/commands/v1/core.proto \
-proto cc/arduino/cli/commands/v1/lib.proto \
-proto cc/arduino/cli/commands/v1/upload.proto \
-proto cc/arduino/cli/debug/v1/debug.proto \
-proto cc/arduino/cli/monitor/v1/monitor.proto \
127.0.0.1:50051 cc.arduino.cli.commands.v1.ArduinoCoreService.Create

You must be in the rpc folder of the arduino-cli project to call it though.

Hope this helps. :slight_smile:

2 Likes

Silvano and in0, thank you for the replies!

Enabling the --debug was very helpful. I was able to confirm that the gRPC messages were not reaching the server.

After a much deeper investigation I found the problem, which is that I was running my gRPC client code inside the Electron renderer process. After moving my client code to the main process, everything works perfectly!

I found some Github issues reporting similar problems:

While this may be obvious to others to avoid running gRPC in a renderer/UI process, I hope this can help someone else if they encounter the same issue.

Best,

Austin

1 Like