Run Serial.read() in the background?

Hey! I am a little new to Arduino and don't have extensive knowledge about C but I am sure this is possible. The idea of the project is an automatic door closer that responds to commands from the serial monitor. I want there to be multiple modes that the Arduino enters to then respond differently based on what mode it's on. What I want is for the code to be running and also checking if a command has been entered and hence switching modes. This is my code so far and I only have one mode done.

#include <Servo.h>

Servo mainServ;
int trigPin = 7;
int echoPin = 6;
long duration; //time between wave from trig to echo pin
int distance;
int timer = 0;
bool status = false; //saves state of door true = open, false = closed


void setup()
{
  //set input output
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  
  mainServ.attach(8, 600, 2300);
  Serial.begin(9600);
}

//sense distance to door, print distance and time open to serial
void sense(){
  mainServ.write(0);
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration * 0.034 /2;
  Serial.print("Distance: ");
  Serial.println(distance);
  Serial.print("   Timer: ");
  Serial.println(timer);
}

//open trap door to weight to close door
void close(){
  mainServ.write(90);
  delay(1000);
  mainServ.write(0);
}

void modeOne(){
  sense(); //check door distance
  
  //if open and hasnt already been open (timer being 0) then set status
  if(distance >= 100 && timer == 0){
    status = true;
  }
  //if door is closed when it was previously open, reset timer and set status
  else if(distance < 100 && status){
    timer = 0;
    status = false;
    return;
  } //if door is closed then restart
  else if (status == false){
    return;
  }
  timer++; //begin timer
  delay(1000);
  
  //if door has been open for 10 seconds, close it
  if(timer > 10){
    close();
    timer = 0;
    status = false;
  }
}

void loop(){
  while(Serial.available()){
  	delay(3);
    char comm = Serial.read();
    
    while (comm == 'A'){
      modeOne();
    }
  }
}

If there is another way to do this or any other suggestions, all comments will be much appreciated, thanks!

void loop(){
  static char comm=0;
  if(Serial.available()>0) {
   comm = Serial.read();
   while(Serial.available()>0)Serial.read();
  }
  if(comm == 'A') modeOne();
}
1 Like

You'll have to rewrite the code to avoid the use of delay. When you call this line the code is stuck at that line for a whole second.

See the "Blink Without Delay" example and any of the thousands of tutorials and write-ups on how to write non-blocking code. There's no reason for any of this to have to block serial reception.

2 Likes

Thanks so much! This worked perfectly.