How to stop a sketche running in a loop via an IRRemote ?

Hello, It's my first post on this forum and i have bought a Mega 2560 one month ago. I just finished a Robot Car with the Uno and all is ok. I have put 2 sketches in one and can choose one of them with the IRRemote via a switchCase statement BUT : I can't stop the sketche that is running in a loop via my IRRemote ? I'm thinking to use interrupts but don't know how ? Thanks in advance for your help and excuse my poor engkish i'm from Belgium. Alain

AlainP:
I can’t stop the sketche that is running in a loop via my IRRemote ?

Post your complete sketch (and use the code tags, use the </> button) and someone might have a look at it.

Yours,
TonyWilk

AlainP: I can't stop the sketche that is running in a loop via my IRRemote ?

As @TonyWilk has said, post your program.

I wonder if the problem is the way the loops are written - perhaps they are not checking the input from the IRRemote often enough. Have a look at Planning and Implementing a Program. Note how each function runs very briefly and returns to loop() so the next one can be called.

...R

Define "stop the sketch"! Do you want to put the sketch in an endless loop so it looks like "stopped"? You have to reset the board to get it running again.

AlainP: Hello, It's my first post on this forum and i have bought a Mega 2560 one month ago. I just finished a Robot Car with the Uno and all is ok. I have put 2 sketches in one and can choose one of them with the IRRemote via a switchCase statement BUT : I can't stop the sketche that is running in a loop via my IRRemote ? I'm thinking to use interrupts but don't know how ? Thanks in advance for your help and excuse my poor engkish i'm from Belgium. Alain

The sketches must be made to share, for now one is blocking the other from running.

Everything with a delay has to change, but I have a cut-and-dry method for that regardless of the code the delays are in.

When Arduino loop() finishes running, it runs again. What you put inside of loop() runs again and again.

How's that?

Thanks all for your contribution, it help me to try new solution, but i’m always sticked.
So i put code here. Big part is from the Elegoo Robot Car v2.
I’d like to be able to run the function ObstacleAvoidance when i press the button “9” on my IRRemote (actualy it is ok) but, after running this function, i’d like to stop my car and have the possibiliy to run other fonctions with the IRRemote.

#include <IRremote.h>
#include <Servo.h> //servo library


#define F 16736925
#define B 16754775
#define L 16720605
#define R 16761405
#define S 16712445
#define UNKNOWN_F 5316027
#define UNKNOWN_B 2747854299
#define UNKNOWN_L 1386468383
#define UNKNOWN_R 553536955
#define UNKNOWN_S 3622325019

#define UNKNOWN_9 71952287
#define Button9 16734885
/*
  IR Receiver Button Code - IR Remote Elegoo Smart Robot Car v2
  16736925 - FF629D - Up
  16720605 - FF22DD - <
  16712445 - FF02FD - OK
  16761405 - FFC23D - >
  16754775 - FFA857 - Down
  16738455 - FF6897 - 1
  16750695 - FF9867 - 2
  16756815 - FFB04F - 3
  16724175 - FF30CF - 4
  16718055 - FF18E7 - 5
  16743045 - FF7A85 - 6
  16716015 - FF10EF - 7
  16726215 - FF38C7 - 8
  16734885 - FF5AA5 - 9
  16728765 - FF42BD - *
  16730805 - FF4AB5 - 0
  16732845 - FF52AD - #
  4294967295 - - REPEAT
*/

const byte ENA = 5;
const byte in1 = 6;
const byte in2 = 7;
const byte in3 = 8;
const byte in4 = 9;
const byte ENB = 11;
const byte RECV_PIN = 12;

byte ABS = 255;

Servo myservo; // create servo object to control servo
int Echo = A4;
int Trig = A5;
int rightDistance = 0, leftDistance = 0, middleDistance = 0 ;

IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long val;

void setup()
{
  myservo.attach(3);// attach servo on pin 3 to servo object
  pinMode(Echo, INPUT);
  pinMode(Trig, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  _mStop();
  irrecv.enableIRIn();
  Serial.begin(9600);
}

void loop() {
  if (irrecv.decode(&results)) {
    val = results.value;
    Serial.println(val);
    irrecv.resume();
    switch (val) {
      case Button9:
      case UNKNOWN_9:
        do
        {
//          ABS = 150 ;
          ObstacleAvoidance() ;
//          if (irrecv.decode(&results))
//          {
//            irrecv.resume();
//            break ;
//          }
        }
        while (true) ;
        break ;
      case F:
      case UNKNOWN_F: _mForward(); break;
      case B:
      case UNKNOWN_B: _mBack(); break;
      case L:
      case UNKNOWN_L: _mleft(); break;
      case R:
      case UNKNOWN_R: _mright(); break;
      case S:
      case UNKNOWN_S: _mStop(); break;
      default: break;
    }
  }
}

void ObstacleAvoidance()
{
  myservo.write(90);//setservo position according to scaled value
  delay(500);
  middleDistance = Distance_test();
#ifdef send
  Serial.print("middleDistance=");
  Serial.println(middleDistance);
#endif

  if (middleDistance <= 40)
  {
    _mStop();
    delay(500);
    myservo.write(10);//10°-180°
    delay(1000);
    rightDistance = Distance_test();

#ifdef send
    Serial.print("rightDistance=");
    Serial.println(rightDistance);
#endif

    delay(500);
    myservo.write(90);
    delay(1000);
    myservo.write(180);
    delay(1000);
    leftDistance = Distance_test();

#ifdef send
    Serial.print("leftDistance=");
    Serial.println(leftDistance);
#endif

    delay(500);
    myservo.write(90);
    delay(1000);
    if (rightDistance > leftDistance)
    {
      _mright();
      delay(360);
    }
    else if (rightDistance < leftDistance)
    {
      _mleft();
      delay(360);
    }
    else if ((rightDistance <= 20) || (leftDistance <= 20))
    {
      _mBack();
      delay(180);
    }
    else
    {
      _mForward();
    }
  }
  else
    _mForward();
}

/*Ultrasonic distance measurement Sub function*/
int Distance_test()
{
  digitalWrite(Trig, LOW);
  delayMicroseconds(2);
  digitalWrite(Trig, HIGH);
  delayMicroseconds(20);
  digitalWrite(Trig, LOW);
  float Fdistance = pulseIn(Echo, HIGH);
  Fdistance = Fdistance / 58;
  return (int)Fdistance;
}

void _mForward()
{
  analogWrite(ENA, ABS);
  analogWrite(ENB, ABS);
  digitalWrite(in1, HIGH); //digital output
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  Serial.println("go forward!");
}

void _mBack()
{
  analogWrite(ENA, ABS);
  analogWrite(ENB, ABS);
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  Serial.println("go back!");
}

void _mleft()
{
  analogWrite(ENA, ABS);
  analogWrite(ENB, ABS);
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  Serial.println("go left!");
}

void _mright()
{
  analogWrite(ENA, ABS);
  analogWrite(ENB, ABS);
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  Serial.println("go right!");
}
void _mStop()
{
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
  Serial.println("Stop!");
}

AlainP:
I’d like to be able to run the function ObstacleAvoidance when i press the button “9” on my IRRemote (actualy it is ok) but, after running this function, i’d like to stop my car and have the possibiliy to run other fonctions with the IRRemote.

Is this what you want?

   case UNKNOWN_9:
       ObstacleAvoidance();
       _mStop(); 
       break;

Yours,
TonyWilk

Yes and Thanks Tony, but i want _mStop() when i press "OK button (S or UNKNOWN_S in code)" from my IRRemote.

AlainP: Yes and Thanks Tony, but i want _mStop() when i press "OK button (S or UNKNOWN_S in code)" from my IRRemote.

Well, move it then.

Yours, TonyWilk

The function _mStop() is already in place in the code. It's also reachable from my irRemote as long as i press "9" and enter in the ObstacleAvoidance loop, then i can't stop via my irRemote.

Hello AlainP, I see the code and there are two places I can change to stop obstacle detection from blocking the IR code from running as often as it should.

One is this, I take out the commented lines... I see the trying to add the IR in there, a good try.

      case UNKNOWN_9:
        do
        {
          ObstacleAvoidance() ;
        }
        while (true) ;

That loop will never exit even if ObstacleAvoidance does change the state variable 'val' since the code can't get back to the switch-case start.

The other place I spotted is the ObstacleAvoidance function that I will get back and fix but for now I have to go out, RL is at the door.

AlainP: The function _mStop() is already in place in the code. It's also reachable from my irRemote as long as i press "9" and enter in the ObstacleAvoidance loop, then i can't stop via my irRemote.

Ah... are you wanting to STOP while it is doing the Obstacle Avoidance routine ?

To do that you will have to rewrite ObstacleAvoidance() because it seems to have a lot of fixed delays in there at the moment and your code will not look at the irRemote again until it has finished.

Yours, TonyWilk

I have a cut&dry method for un-delaying code and gave the ObstacleAvoidance function a full treatment.
Check it out, help find errors!

However my Arduino IDE is running on XP and I get here with a Linux boot flash it’s a pain to get files while using the IDE. I wasn’t able to compile what I did but Autoformat worked, the braces might be balanced and right.

It doesn’t look bad but I’d be very surprised if there are no errors. Here it is anyway:

#include <IRremote.h>
#include <Servo.h> //servo library

byte xpa, xpb;
int xpx, xpy, xpz;

#define F 16736925
#define B 16754775
#define L 16720605
#define R 16761405
#define S 16712445
#define UNKNOWN_F 5316027
#define UNKNOWN_B 2747854299
#define UNKNOWN_L 1386468383
#define UNKNOWN_R 553536955
#define UNKNOWN_S 3622325019

#define UNKNOWN_9 71952287
#define Button9 16734885

/*
  IR Receiver Button Code - IR Remote Elegoo Smart Robot Car v2
  16736925 - FF629D - Up
  16720605 - FF22DD - <
  16712445 - FF02FD - OK
  16761405 - FFC23D - >
  16754775 - FFA857 - Down
  16738455 - FF6897 - 1
  16750695 - FF9867 - 2
  16756815 - FFB04F - 3
  16724175 - FF30CF - 4
  16718055 - FF18E7 - 5
  16743045 - FF7A85 - 6
  16716015 - FF10EF - 7
  16726215 - FF38C7 - 8
  16734885 - FF5AA5 - 9
  16728765 - FF42BD - *
  16730805 - FF4AB5 - 0
  16732845 - FF52AD - #
  4294967295 - - REPEAT
*/

const byte ENA = 5;
const byte in1 = 6;
const byte in2 = 7;
const byte in3 = 8;
const byte in4 = 9;
const byte ENB = 11;
const byte RECV_PIN = 12;

byte ABS = 255;

Servo myservo; // create servo object to control servo
int Echo = A4;
int Trig = A5;
int rightDistance = 0, leftDistance = 0, middleDistance = 0 ;

IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long val;

void setup()
{
  myservo.attach(3);// attach servo on pin 3 to servo object
  pinMode(Echo, INPUT);
  pinMode(Trig, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  _mStop();
  irrecv.enableIRIn();
  Serial.begin(9600);
}

void loop() {
  if (irrecv.decode(&results)) {
    val = results.value;
    Serial.println(val);
    irrecv.resume();
    switch (val) {
      case Button9:
      case UNKNOWN_9:

        ObstacleAvoidance() ;
        break ;

      case F:
      case UNKNOWN_F: _mForward(); break;
      case B:
      case UNKNOWN_B: _mBack(); break;
      case L:
      case UNKNOWN_L: _mleft(); break;
      case R:
      case UNKNOWN_R: _mright(); break;
      case S:
      case UNKNOWN_S: _mStop(); break;
      default: break;
    }
  }
}

void ObstacleAvoidance()
{
  static byte oState = 0;   // first time value is 0
  static unsigned long oStart = 0, oWait = 0;

  if ( oWait > 0 )  // the timer only runs when it's supposed to and turns itself off when finished, a 1=shot delay
  {
    if ( millis() - oStart >= oWait )
    {
      oWait = 0; // timer is finished, shut it off
    }
    else
    {
      return;  // timer is not finished, come back later
    }
  }

  switch ( oState )  // every time this function runs it only does the STEP it is supposed to.
  {

    case 0 :
      myservo.write(90);//setservo position according to scaled value

      oStart = millis();    // set the timer start
      oWait = 500;         // set the timer wait
      oState = 1;            // set state to the next to run

      break;

    case 1 :
      middleDistance = Distance_test();
#ifdef send
      Serial.print("middleDistance=");
      Serial.println(middleDistance);
#endif

      if (middleDistance <= 40)
      {
        _mStop();
        oState = 2;
      }
      else
      {
        _mForward();
        oState = 0;
      }
      break;

    case 2 :
      oStart = millis();    // set the timer start
      oWait = 500;         // set the timer wait
      oState = 3;          // set state to the next to run
      break;

    case 3 :
      myservo.write(10);//10°-180°

      oStart = millis();    // set the timer start
      oWait = 1000;         // set the timer wait
      oState = 4;          // set state to the next to run
      break;

    case 4 :
      rightDistance = Distance_test();
#ifdef send
      Serial.print("rightDistance=");
      Serial.println(rightDistance);
#endif

      oStart = millis();    // set the timer start
      oWait = 500;         // set the timer wait
      oState = 5;          // set state to the next to run
      break;

    case 5 :
      myservo.write(90);

      oStart = millis();    // set the timer start
      oWait = 1000;         // set the timer wait
      oState = 6;          // set state to the next to run
      break;

    case 6 :
      myservo.write(180);

      oStart = millis();    // set the timer start
      oWait = 1000;         // set the timer wait
      oState = 7;          // set state to the next to run
      break;

    case 7 :
      leftDistance = Distance_test();

#ifdef send
      Serial.print("leftDistance=");
      Serial.println(leftDistance);
#endif

      oStart = millis();    // set the timer start
      oWait = 500;         // set the timer wait
      oState = 8;          // set state to the next to run
      break;

    case 8 :
      myservo.write(90);

      oStart = millis();    // set the timer start
      oWait = 1000;         // set the timer wait
      oState = 9;          // set state to the next to run
      break;

    case 9 :
      oState = 0;  // all results go back to start next time 
      if (rightDistance > leftDistance)
      {
        _mright();

        oStart = millis();    // set the timer start
        oWait = 360;         // set the timer wait
      }
      else if (rightDistance < leftDistance)
      {
        _mleft();

        oStart = millis();    // set the timer start
        oWait = 360;         // set the timer wait
      }
      else if ((rightDistance <= 20) || (leftDistance <= 20))
      {
        _mBack();

        oStart = millis();    // set the timer start
        oWait = 180;         // set the timer wait
      }
      else
      {
        _mForward();
        oState = 0;
      }
      break;
  }
}

/*Ultrasonic distance measurement Sub function*/
int Distance_test()
{
  digitalWrite(Trig, LOW);
  delayMicroseconds(2);
  digitalWrite(Trig, HIGH);
  delayMicroseconds(20);
  digitalWrite(Trig, LOW);
  float Fdistance = pulseIn(Echo, HIGH);
  Fdistance = Fdistance / 58;
  return (int)Fdistance;
}

void _mForward()
{
  analogWrite(ENA, ABS);
  analogWrite(ENB, ABS);
  digitalWrite(in1, HIGH); //digital output
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  Serial.println("go forward!");
}

void _mBack()
{
  analogWrite(ENA, ABS);
  analogWrite(ENB, ABS);
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  Serial.println("go back!");
}

void _mleft()
{
  analogWrite(ENA, ABS);
  analogWrite(ENB, ABS);
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  Serial.println("go left!");
}

void _mright()
{
  analogWrite(ENA, ABS);
  analogWrite(ENB, ABS);
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  Serial.println("go right!");
}

void _mStop()
{
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
  Serial.println("Stop!");
}

I would want the sensor running all the time even as the car moves. My goal would be no automatic stops and only slow down on need, just drive around obstacles. However that would add a layer or two of complexity.

The oStates could use an enumerator or 10 #defines for clarity.

Many many thanks for your code and patience GoForSmoke. I compile your code with no error and upload it but it doesn't move my car. A good things for me. I had to learn in depth the new (for me) ideas behind your code and found that it was in the loop() i had to change code. I mainly add an else statement in loop() so the code "loop" in the obstacleAvoidance() function when the "9Key" is pressed.

void loop()
{
  static int oldKeyCommand = 0 ;
  if (irrecv.decode(&results))
  {
    val = results.value;
    Serial.println(val);
    irrecv.resume();
    switch (val)
    {
      case Button9:
      case UNKNOWN_9:
        oldKeyCommand = val ;
        ObstacleAvoidance() ;
        break ;
      case F:
      case UNKNOWN_F: _mForward(); oldKeyCommand = val ; break;
      case B:
      case UNKNOWN_B: _mBack(); oldKeyCommand = val ; break;
      case L:
      case UNKNOWN_L: _mleft(); oldKeyCommand = val ; break;
      case R:
      case UNKNOWN_R: _mright(); oldKeyCommand = val ; break;
      case S:
      case UNKNOWN_S: _mStop(); oldKeyCommand = val ; break;
      default: break;
    }
  }
  else
  {
    switch (oldKeyCommand)
    {
      case Button9:
      case UNKNOWN_9:
        ObstacleAvoidance() ;
        break ;
      default: break;
    }
  }
}

Thanks again Alain

GoForSmoke: I have a cut&dry method for un-delaying code

Nice use of the state machine there.

Yours, TonyWilk

TonyWilk:
Nice use of the state machine there.

Yours,
TonyWilk

I came up with this while fixing a greenhouse system that was loaded with delays.
At first I was putting timers in the states then realized that one would do for all.

It’s cut and dry. When I fixed the greenhouse code I didn’t know what the code actually did and did not want to. Those parts functioned, they just didn’t share. I just changed the shape while keeping the flow and it worked.

The sketch could use more work but since last night I’ve got flu symptoms and now 102F fever. I might be away for a while.

Hi AlainP,

How do you find the "UNKNOW_" values ? I don't see these values when I sniff the IR signal ?

AlainP: ```

define UNKNOWN_9 71952287