Serial.readStringUntil not working consistently

I'm developing a simple program using the Adafruit RP2040 Feather, Raspbery Pi 4b and a rotary encoder, and for some reason I can't get the Serial.readStringUntil command to work consistently.

It will be hooked up to a RPi 4b via the USB serial port, but right now is running off of a Windows 10 box using Arduino IDE 2.3.3.

The idea is that a "0" will be sent to the Feather via serial and the feather returns "Yes" so that the Pi knows that it's ready and running.

The Pi will then send a count value, say "10" to the Feather, which reads it and figures out the counts from the encoder, and either sends back a "Done" or "Timeout" response so that the Pi can continue it's work.

When it works, here's how it should respond. Please note that I have put some additional Serial.println's for debugging purposes in the code, and all tests are done using the Arduino IDE Serial Monitor.

Sending a message of "0" returns:

0
Yes

Exactly as expected. I can do this many times in a row without it failing.

Sending a message of "10" returns:

10
10
Reading
Timeout

Again, exactly as expected.

Now regardless of what value I send next, "0" or some other number, it will hang and not respond. I think it's something in my code, but I just can't figure out what I'm missing.

Any ideas?

Thanks,

GWFAMI

#include <Arduino.h>
#include <RotaryEncoder.h>
#include <time.h>
#include <sys/time.h>

//Serial pins on feather
#define PIN_IN1 2
#define PIN_IN2 3

time_t start, end;
String inString = "";
String temp = "";

// Setup a RotaryEncoder with 4 steps per latch for the 2 signal input pins:
// RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::FOUR3);

// Setup a RotaryEncoder with 2 steps per latch for the 2 signal input pins:
RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03);

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


void loop() {
  inString = "";
  while (Serial.available() > 0) {
    inString = Serial.readStringUntil('\n');
    Serial.println(inString);
    if (inString.toInt() == 0) {
      Serial.println("Yes");
      inString = "";
    }
    if (inString.toInt() > 0) {
      Serial.println(inString);
      read();
      inString = "";
    }
  }
}

// Read the current position of the encoder and print out when changed.
void read() {
  static int pos = 0;
  int newPos = 0;
  int countTo = inString.toInt();
  bool exit = false;

  Serial.println("Reading");
  time(&start);

  while (!exit) {
    time(&end);
    encoder.tick();
    newPos = encoder.getPosition();
    if (pos != newPos) {
      Serial.println("newPos:");
      Serial.println(newPos);
      Serial.println(" direction:");
      Serial.println((int)(encoder.getDirection()));
      pos = newPos;
      time(&start);
      Serial.println(char(difftime(end, start)));
    }
    if (difftime(end, start) > 5) {
      exit = true;
      Serial.println("Timeout");
    }
    if (pos >= countTo) {
      exit = true;
      Serial.println("Done");
    }
  }
  inString = "";
}

Here are two really good links that should help you

try

#include <Arduino.h>
#include <RotaryEncoder.h>
#include <time.h>
#include <sys/time.h>

//Serial pins on feather
#define PIN_IN1 2
#define PIN_IN2 3
int countTo;
time_t start, end;

// Setup a RotaryEncoder with 4 steps per latch for the 2 signal input pins:
// RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::FOUR3);

// Setup a RotaryEncoder with 2 steps per latch for the 2 signal input pins:
RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03);

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

void loop() {
  if (Serial.available() > 0) {
    countTo = Serial.parseInt();
    while (Serial.available() > 0) Serial.read();
    Serial.println(countTo);
    if (countTo == 0)Serial.println("Yes");
    else read();
  }
}

// Read the current position of the encoder and print out when changed.
void read() {
  static int pos = 0;
  int newPos = 0;
 
  Serial.println("Reading");
  time(&start);

  while (true) {
    time(&end);
    encoder.tick();
    newPos = encoder.getPosition();
    if (pos != newPos) {
      pos = newPos;
      Serial.println("newPos:");
      Serial.println(newPos);
      Serial.println(" direction:");
      Serial.println(int(encoder.getDirection()));
      time(&start);
      Serial.println(char(difftime(end, start)));
    }
    if (difftime(end, start) > 5) {
      Serial.println("Timeout");
      return;
    }
    if (pos >= countTo) {
      Serial.println("Done");
      return;
    }
  }
}

Thanks kolaha, that works. I'll look at the code differences and try figure out why your changes worked.

GWFAMI

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.