0

I have a question regarding serial buffer readout.

At program start, I send a serial command to a sensor that 1. activates him and 2. let him send data - that works. When I unplug the sensor, the serial buffer remains empty and the program goes into the else condition of void loop. But if I connect the sensor again, the serial buffer should be filled again and the program should jump into the if condition of the void loop. But it does not.

I added the variable i because the serial buffer becomes empty too quickly and the program then sends the start command of the else condition again, even though the sensor is connected and still works. Then the readout gets mixed up...that works too.

Why doesn't the program jumps back in the if condition of void loop when the sensor gets connected again after it was disconnected some time? Then serial.available() should be bigger 0 and it should readout data?

#include <SoftwareSerial.h>
int i = 0; 

void setup()  {
    Serial.begin(9600);
    Serial1.begin(9600);
    Serial1.write(Send Start Sequence);
    Serial1.write(Start continuously read out sensor data);
}

void loop() {
  if (Serial1.available() > 0) {
    char incomingByte = Serial1.read();
    Serial.write(incomingByte);
  i = 0; 
  }
  else {
    i++; 
    if (i > 5) {
      Serial1.write(Send Start Sequence);
      Serial1.write(Start continuously read out sensor data);
    }
  }
}

2 Answers 2

1

I second Nick Gammon in recommending a time-based condition, rather than counting the loop iterations. You can do it in a non-blocking fashion though:

  • keep track of when was the last time you communicated with the sensor
  • if this was too long ago, resend the “start sequence” command

Note that sending the command counts as a communication event, which rearms the timer. Otherwise you would be repeatedly sending the command too fast.

// After this delay, assume we lost the sensor.
const unsigned long timeout = 200;

// Last time we communicated with the sensor.
unsigned long last_comm_time;

void loop() {
    // Check the clock.
    unsigned long now = millis();

    // Process incoming data.
    if (Serial1.available() > 0) {
        last_comm_time = now;
        char incomingByte = Serial1.read();
        Serial.write(incomingByte);
    }

    // Try to wake up the sensor if we lost it.
    if (now - last_comm_time >= timeout) {
        last_comm_time = now;  // count this as a communication event
        Serial1.write(start_sequence);
        Serial1.write(continuously_read_out_sensor_data);
    }
}

You could potentially have separate timeouts for “the sensor just stopped sending data” and “the sensor should be processing the start command we just sent”. This would be a bit more complex though, requiring some sort of state machine. If you can use a single timeout value, things are simpler.

1
  • Ach, Edgar! You beat me to it by a few seconds! Anyway, you are right. :)
    – Nick Gammon
    Commented Sep 29, 2023 at 7:30
0

Your loop going to 5 is going to happen extremely quickly. Instead I would do a delay, say of one second (1000 ms), maybe less. Constantly sending the start sequence my be misinterpreted if the sensor comes online in the middle of the sequence. Plus your (counting) delay would only happen once. Putting a delay in the loop would make it happen every time.


I suggest a different way of recovering from an unplugged sensor:

#include <SoftwareSerial.h>

void setup()  {
    Serial.begin(9600);
    Serial1.begin(9600);
    Serial1.write("Send Start Sequence");
    Serial1.write("Start continuously read out sensor data");
}

unsigned long lastDataReceived;

void loop() {
  if (Serial1.available() > 0) {
    char incomingByte = Serial1.read();
    Serial.write(incomingByte);
    lastDataReceived = millis ();
  }
  else {
    if ((millis() - lastDataReceived) > 5000) {
      Serial1.write("Send Start Sequence");
      Serial1.write("Start continuously read out sensor data");
      lastDataReceived = millis ();
    }
  }
}

What this will do is wait 5 seconds before sending out the new start sequence. At 9600 baud your loop will be a lot faster than incoming bytes. This will be more reliable.

2
  • Thanks for your comment. But I think thats a problem, because the start sequence also gets me an answer from the sensor. Then I get every second loop a wrong output, not the value from the sensor but the answer of the start sequence. ATM I get the following: Sensordata, 1, 2, Sensordata, 1, 2, Sensordata, and so on. So I > 2 would be enough, but to be sure..
    – Gymknopf
    Commented Sep 29, 2023 at 6:23
  • See my edited answer (it wasn't a comment).
    – Nick Gammon
    Commented Sep 29, 2023 at 7:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.