Limit multiple limit switch monitoring

I am trying to write a code that will monitor the status of 2 limit switches at the same time, serial printing the status of each one.

Currently it wont print that neither limit is active, nor will it update if both limits are pressed when one is held and the second is activated and de activated.

any help would be great.

code is below:

int Lswitch = 2;
int Rswitch = 4;
int Lflag = 0;
int Rflag = 0;
int Ract = 0;
int Lact = 0;
int Rinact = 0;
int Linact = 0;

void setup()
{
Serial.begin(9600);
pinMode(Lswitch, INPUT);
pinMode(Rswitch, INPUT);
}

void loop()
{
if( ((digitalRead(Lswitch) == LOW) && (Linact == 0)) && ((digitalRead(Rswitch) == LOW) && (Rinact == 0)))
{
Serial.println("no limit active");
Linact = 1;
Rinact = 1;
delay(20);
}

if( ((digitalRead(Lswitch) == HIGH) && (Lact == 1)) && ((digitalRead(Rswitch) == HIGH) && (Ract == 1)))
{
Serial.println("both limits active");
Lact = 0;
Ract = 0;
delay(20);
}

if( (digitalRead(Lswitch) == HIGH) && (Lflag == 1))
{
Serial.println("L switch limit active");
Lflag = 0;
Lact = 1;
delay(20);
}

if( (digitalRead(Lswitch) == LOW) && (Lflag == 0))
{
Serial.println("L switch limit inactive");
Lflag = 1;
Linact = 1;
delay(20);
}

if( (digitalRead(Rswitch) == HIGH) && (Rflag == 1))
{
Serial.println("R switch limit active");
Rflag = 0;
Ract = 1;
delay(20);
}

if( (digitalRead(Rswitch) == LOW) && (Rflag == 0))
{
Serial.println("R switch limit inactive");
Rflag = 1;
Rinact = 1;
delay(20);
}

if( (digitalRead(Lswitch) == LOW) && (Lflag == 0))
{
Lflag = 1;
Linact = 0;
delay(20);
if( (digitalRead(Rswitch) == LOW) && (Rflag == 0))
{
Rflag = Rflag;
Rinact = 0;
}
delay(20);
}

if( (digitalRead(Rswitch) == LOW) && (Rflag == 0))
{
Rflag = 1;
Rinact = 0;
delay(20);
if( (digitalRead(Lswitch) == LOW) && (Lflag == 0))
{
Lflag = Lflag;
Linact = 0;
}
delay(20);
}

digitalWrite(Lswitch, HIGH);
digitalWrite(Rswitch, HIGH);

}

Read the how to use this forum-please read sticky to see how to properly post code. Remove useless white space and format the code with the IDE autoformat tool (crtl-t or Tools, Auto Format) before posting code.

Put some prints between the ifs to monitor the values of the variables.

And how are the switches wired? A schematic drawing done on paper, take a picture, and post it in image tags would be great.

Posting images
How to post an image.
Another page on posting images.

This is NOT the way to deal with this problem.

if( ((digitalRead(Lswitch) == HIGH) && (Lact == 1)) && ((digitalRead(Rswitch) == HIGH) && (Ract == 1)))

You should read all the switches and save their values in variables and then use the saved values in the logic in that iteration of loop()

The way you are doing it each IF statement may be working with different results and you have no means to know what those results are. If you save the values you can print them for debugging purposes. However printing in each iteration of loop() will probably slow the working program.

...R

If you want to read 2 inputs at the exact same time, put them on 2 adjacent pins on the same port, then they can be read in one call to :

inPins = PINx & 0b00000011; // for pins 0 and 1 in PORTx.

But not relevant for switches. :roll_eyes:

Robin2:
This is NOT the way to deal with this problem.

if( ((digitalRead(Lswitch) == HIGH) && (Lact == 1)) && ((digitalRead(Rswitch) == HIGH) && (Ract == 1)))

You should read all the switches and save their values in variables and then use the saved values in the logic in that iteration of loop()

The way you are doing it each IF statement may be working with different results and you have no means to know what those results are. If you save the values you can print them for debugging purposes. However printing in each iteration of loop() will probably slow the working program.

...R

I changed up the code, to read the limits in the begining and assinged them to variables, and i am still at the same situation. when it starts, it says no limit active, L inactive, R inactive, if i press both i get both active, and R active, and L active, but if i leave one limit on, and toggle the other, i do not get a repeating both active.

the grand scheme of the code is to have a moving servo, that will stop when it hits either one of the limits. but i need to monitor if there is a failure and both limits are triggered, and to monitor the lack of either limits if the servo is not moving to indicate and alarm as well.

Paul__B:
But not relevant for switches. :roll_eyes:

If they are debounced in hardware?

mikeyfl:
I changed up the code, to read the limits in the begining and assinged them to variables,

Please post the latest version of your program in your next Reply so we can see exactly what you have done.

...R

GoForSmoke:
If they are debounced in hardware?

Well that is indeed an interesting point!

I pointed out that it is essentially meaningless to be concerned about microseconds between reading switches, so reading them in the same operation is entirely unnecessary and a couple of microseconds to deal with how digitalRead and allocation of a variable is managed in the IDE is not worth worrying about.

When you take contact bounce into account, it really is a "different ball game" again - you are now talking about errors of several milliseconds and you should be de-bouncing in software as it is more accurate as well as much simpler. :astonished:

I wondered why you made that statement.

Debounce in hardware changes the pin state and keeps it there.

Debounce in software watches the pin state change wildly and waits for the state to settle an arbitrary time before the switch is considered debounced.

Hardware debounce uses a 1 uF cap across the button terminals and the state change is caught on contact.
Software debounce requires code to catch the state change milliseconds after the fact.

You seem to have different ideas about what simpler means and what accurate means as well.


When you read multiple switches on a port it saves CPU cycles over reading one at a time. Is that a problem?

Direct port manipulation is also 5x as fast to read 1 pin as using digitalRead(), which has make-safe code, once.
To read 2 switches on 1 port vs read 2 switches with digitalRead() saves about 90% of the cycles the latter requires.

mikeyfl:
the grand scheme of the code is to have a moving servo, that will stop when it hits either one of the limits. but i need to monitor if there is a failure and both limits are triggered, and to monitor the lack of either limits if the servo is not moving to indicate and alarm as well.

If you detect when the servo is close to a limit and slow it down just before it hits, would that be any better?

Arduino can sense and respond in a fraction of a millisecond with code that lets it run unimpeded.

Have you connected just one switch and see if it is detected by the Uno with a simplified sketch of read the pin and show the pin state in serial monitor, and that schematic how you doing with posting one? Detecting a simple switch open close with a Uno is quite simple and somehow this whole thing do is complex. Time to pare it down to the simple component and see if that works. Just one switch, print open or close. Can you do that?

Yeah, it could be very instructive.

untested,

const byte  switchPin = 2;
byte            prevRead;

unsigned long startTime, interval;


void setup()
{
  Serial.begin( 115200 );  // be sure to set Serial Monitor speed to match
  Serial.println( F( "\n\nwatch the button pin!\n\n" ));  //  \n is newline character

  pinMode( switchPin, INPUT_PULLUP );

  prevRead = digitalRead( switchPin );
}

void loop()
{

  if ( digitalRead( switchPin ) != prevRead )  // inside of this the pin state just changed
  {
    startTime = millis();
    interval = 50;

    if ( prevRead == 1 )
    {
      Serial.println( "0" )); 
    }
    else
    {
      Serial.println( "1" )); 
    }

    prevRead = !prevRead;  // toggles it match the digital read
  }

  if ( interval > 0 )
  {
    if ( millis() - startTime >= interval )
    {
      interval = 0;
      Serial.println();
    }
  }

}

When you press the button you should see many changes for 1 press or release.
It should print a blank line between if nothing changes for 50ms.

Idahowalker:
Have you connected just one switch and see if it is detected by the Uno with a simplified sketch of read the pin and show the pin state in serial monitor, and that schematic how you doing with posting one? Detecting a simple switch open close with a Uno is quite simple and somehow this whole thing do is complex. Time to pare it down to the simple component and see if that works. Just one switch, print open or close. Can you do that?

Yes, one switch at a time is simple. i do see the simple on off state of the one. the complications come in with the second, and the array of possibilities that the two can have together.

Two switches and time as well. It takes time (mucho millis) to go from one limit to the other.

the problem im having, is the serial printing. having to code something that will only serial print one time, and not repeatedly. using the "flags" and changing the values after each trigger or un trigger. if i only watch the two independently and not together or seperate, i see them printing properly.

mikeyfl:
the problem im having,

Take a moment to think about our problem ...

You have not posted the latest version of your program so we can't see what exactly you have done. Please include it in your next Reply

...R

mikeyfl:
the problem im having, is the serial printing. having to code something that will only serial print one time, and not repeatedly. using the "flags" and changing the values after each trigger or un trigger. if i only watch the two independently and not together or seperate, i see them printing properly.

Did you try the 1 button sketch I posted? It should show contact bounce making a print for each bounce detected. Press or release and > 1 print since > 1 event is detected.

Does your code have delays to stop that?