To read the state of two break beam sensors for robot arm

I'm been trying to find a simple example of using setjmp and longjmp. I'm posting a code for a robot arm to pick up and object and set it down somewhere else. Using two break beam sensors the robot arm will not work if the sensor where it's set down is made or LOW. That's what I want because it's blocked or there's an object is already there. The code works using a "goto" function. This is just a short code to make an example. I've read that it`s advised to use setjmp and longjmp. I would like somebody to change the code using setjmp and longjmp so myself and the rest of the world might have simple a example of using those functions.

#include <VarSpeedServo.h>

#define SENSORPIN1 2
#define SENSORPIN2 1

VarSpeedServo servo1;
VarSpeedServo servo2;
VarSpeedServo servo3;
VarSpeedServo servo4;
VarSpeedServo servo5;

int sensorState1 = 0, lastState1 = 0;
int sensorState2 = 0, lastState2 = 0;


void setup() {
  servo1.attach(4);
  servo2.attach(5);
  servo3.attach(6);
  servo4.attach(7);
  servo5.attach(8);
  servo1.write(85);
  servo2.write(90);
  servo3.write(90);
  servo4.write(100);
  servo5.write(90);
  pinMode(SENSORPIN1, INPUT_PULLUP);
  pinMode(SENSORPIN2, INPUT_PULLUP);
}

void loop() {
  sensorState1 = digitalRead(SENSORPIN1);
  sensorState2 = digitalRead(SENSORPIN2);
  if (sensorState2 == LOW) {
    goto homePosistion;
  }
  if (sensorState1 == LOW) {
    servo1.write(48, 50, true);
    servo3.write(110, 40);
    servo2.write(43, 60, true);
    servo4.write(90, 70);
    delay(500);
    servo5.write(150, 70, true);
    delay(500);
    servo2.write(130, 60, true);
    servo4.write(130, 70);
    servo1.write(170, 40, true);
    servo4.write(50, 70, true);
    servo4.write(90, 70);
    servo3.write(145, 40);
    servo2.write(60, 60, true);
    delay(500);
    servo5.write(90, 70, true);
    delay(250);
    servo3.write(80, 40);
    servo2.write(100, 60, true);
    delay(500);
  } else (digitalRead(SENSORPIN1) == HIGH);
  (digitalRead(SENSORPIN2) == HIGH);
homePosistion:
  {
    servo1.write(85, 40);
    servo2.write(90, 60);
    servo3.write(90, 40);
    servo4.write(100, 40);
    servo5.write(90, 70);
  }
}

Check whether the setjmp() and longjmp() functions are even implemented on whichever Arduino you are using. If they are, the documentation and examples would be worth a look.

1 Like

Please show the link to this advice. setjmp and longjmp are low level function, to use that you must know much about controller internal. I can't imagine a beginner would need it.
I don't see any reason to use setjmp and longjmp in you code, or like a goto.

I think, any C/C++ program can be written without using a goto.

1 Like

I'm wanting the robot arm to not pick up an object if the destination is already blocked . Using the goto function is the only way i could make it work. I'm sure there's a better way.

Why not place the code located by the homePosistion label - right in the condition where you place the goto:

void loop() {
  sensorState1 = digitalRead(SENSORPIN1);
  sensorState2 = digitalRead(SENSORPIN2);
  if (sensorState2 == LOW) {
   // goto homePosistion;  instead of goto - place the code here:
    servo1.write(85, 40);
    servo2.write(90, 60);
    servo3.write(90, 40);
    servo4.write(100, 40);
    servo5.write(90, 70);
  }
  else {
   if (sensorState1 == LOW) {
     servo1.write(48, 50, true);
     servo3.write(110, 40);
     servo2.write(43, 60, true);
     servo4.write(90, 70);
     delay(500);
     servo5.write(150, 70, true);
     delay(500);
     servo2.write(130, 60, true);
     servo4.write(130, 70);
     servo1.write(170, 40, true);
     servo4.write(50, 70, true);
     servo4.write(90, 70);
     servo3.write(145, 40);
     servo2.write(60, 60, true);
     delay(500);
     servo5.write(90, 70, true);
     delay(250);
     servo3.write(80, 40);
     servo2.write(100, 60, true);
     delay(500);
     } 
  //  else (digitalRead(SENSORPIN1) == HIGH);
    //        (digitalRead(SENSORPIN2) == HIGH);
 }
}

What do you try to achieve with this two lines:

    else (digitalRead(SENSORPIN1) == HIGH);
           (digitalRead(SENSORPIN2) == HIGH);

It looks really nonsense for me

Thank You! For your help. I should always post the whole code. Your changes would work if that was the only operation the robot is doing. I shortened the code to just one operation to post it, that's why there are two sensorpins under else.

This is independent of the number of operations. The theory states that code containing goto can always be rewritten without this operator.

You need to use a different approach to programming your robot. Look at what finite state machines are.

You didn't answer what these lines do.

Wow! Are setjmp() and longjmp() still a thing? They were deprecated 20 years ago when I still did serious programming. They were replaced with exceptions in C++. If your processor doesn't support exceptions (most small micros don't), then it also probably doesn't support the environment to handle setjmp() and longjmp().

Here

find the results of some research I did, a complete it works setjmp/longjmp mechanism for switching between multiple loop functions.

There's a wokwi demo. It was written for the UNO, but I believe the functions are generally availble.

I think the entire thread is the place where some pesky problems were worked out. I'll look when I'm not moving and see if it was another thread where various hacks were discussed.

HTH

Oh, here

// also see post 30, and the thread that this came from

a7

Goto/setjmp/longjmp are the wrong tool for the job. The correct solution is to use non-blocking waits (search for e.g. blink without delay), so you can then use ordinary control flow constructs.

As a side note, longjmp is almost impossible to use correctly in C++: std::longjmp - cppreference.com

If replacing std::longjmp with throw and setjmp with catch would invoke a non-trivial destructor for any automatic object, the behavior of such std::longjmp is undefined.

I made changes to my code achieving my goal without using goto or setjmp longjmp. Remember this is only one operation I'm gonna be adding more movements. I also added some shorthand. FSM may be better but I may need another week (or two) to learn that I've been doing this less then two weeks.

#include <VarSpeedServo.h>

#define SENSORPIN1 2
#define SENSORPIN2 1

VarSpeedServo servo1;
VarSpeedServo servo2;
VarSpeedServo servo3;
VarSpeedServo servo4;
VarSpeedServo servo5;

int sensorState1 = 0, lastState1 = 0;
int sensorState2 = 0, lastState2 = 0;
int a = HIGH;

void setup() {
  servo1.attach(4);
  servo2.attach(5);
  servo3.attach(6);
  servo4.attach(7);
  servo5.attach(8);
  servo1.write(85);
  servo2.write(90);
  servo3.write(90);
  servo4.write(100);
  servo5.write(90);
  pinMode(SENSORPIN1, INPUT_PULLUP);
  pinMode(SENSORPIN2, INPUT_PULLUP);
}

void loop() {
  sensorState1 = digitalRead(SENSORPIN1);
  sensorState2 = digitalRead(SENSORPIN2);

  if (sensorState1 == !a && sensorState2 == a) 
  {
    servo1.write(48, 50, true);
    servo3.write(110, 40);
    servo2.write(43, 60, true);
    servo4.write(90, 70);
    delay(500);
    servo5.write(150, 70, true);
    delay(500);
    servo2.write(130, 60, true);
    servo4.write(130, 70);
    servo1.write(170, 40, true);
    servo4.write(50, 70, true);
    servo4.write(90, 70);
    servo3.write(145, 40);
    servo2.write(60, 60, true);
    delay(500);
    servo5.write(90, 70, true);
    delay(250);
    servo3.write(80, 40);
    servo2.write(100, 60, true);
    delay(500);
  } 
  else 
    (digitalRead(SENSORPIN1) == a);
    (digitalRead(SENSORPIN2) == a);
  {
    servo1.write(85, 40);
    servo2.write(90, 60);
    servo3.write(90, 40);
    servo4.write(100, 40);
    servo5.write(90, 70);
  }
}

I did it without using goto. I used &&.

Again, what do you try to achieve with this lines:

Explain what you think this line does?

  (digitalRead(SENSORPIN1) == a);

Here is a small introduction to the topic: Yet another Finite State Machine introduction

I removed those lines, still works great. It doesn't need to know if the sensors are not made or HIGH to return to home position.

with those lines the code was interpreted like this

if (sensorState1 == !a && sensorState2 == a)  {
  •••
} else (digitalRead(SENSORPIN1) == a); // <== only this was in the else clause (which was doing nothing)

// THEN THIS IS ALWAYS EXECUTED
(digitalRead(SENSORPIN2) == a);  // doing nothing useful 
servo1.write(85, 40);
servo2.write(90, 60);
servo3.write(90, 40);
servo4.write(100, 40);
servo5.write(90, 70);

without those two lines the code is very different

if (sensorState1 == !a && sensorState2 == a)  {
  •••
} else { // <=== THE writes are only executed in the else case
  servo1.write(85, 40);
  servo2.write(90, 60); 
  servo3.write(90, 40);
  servo4.write(100, 40);
  servo5.write(90, 70);
}

These lines didn't help you to know the state of the sensors.
I asked you twice what these lines do - and you didn’t answer me. I asked you for a reason, but because these lines are absolutely incorrect from the point of view of syntax, they contain at least three errors. You can't write like that

I can only give you an honest answer, I didn't know. After you mentioned FSM programming, I read about that and studied shorthand the rest of the day, I didn't get back to my code till this morning. Thank You for your patience and persistence, it is much appreciated.

is this should be else with condition?

else if ((digitalRead(SENSORPIN1) == a) &&  (digitalRead(SENSORPIN2) == a))
  {

If so, your original lines contains a three errors:

  • if you need an "else with condition", you must use else if rather than else
  • you can't terminate condition with semicolon
  • multiple conditions must be combined with logical operators like "AND" , "OR", "NOT"

Thank You I read that carefully, the else does what i was hoping to achieve by itself.
One piece at a time and patience.