Incremental/Decremental switches

Hello all, I've incorporated the following code in my sketch, in order to have two pushbuttons that will go through 5 cases, either up or down. As you can see, the code only includes an incremental switch(also only 3 cases instead of 5), and for some reason I cannot get to add a decremental one.

mode-- works just fine if my initial state is >1, but once it reaches 1 it will not rotate to 5. Any idea?

/*
 Using a single switch to select between 3 modes
*/
// Schematic: http://www.pwillard.com/files/mode4.jpg
//===============================================================
// Global Variables & Constants
//===============================================================

const int ledPinOne = 2; // LED1 ANODE
const int ledPinTwo = 4; // LED2 ANODE
const int ledPinThree = 7; // LED3 ANODE
const int modePin = 13; // Active HIGH, held low by 4.7K

int mode = 0; // Selector State (Initial state = ALL OFF)
int val = 0; // Pin 13 HIGH/LOW Status
int butState = 0; // Last Button State
int modeState = 0; // Last Mode State
boolean debug = 1; // 1 = Print Serial Enabled / 0 = disabled

//===============================================================
// SETUP
//===============================================================
void setup () {
 pinMode(ledPinOne, OUTPUT);
 pinMode(ledPinTwo, OUTPUT);
 pinMode(ledPinThree, OUTPUT);
 pinMode(modePin, INPUT);
 if (debug){
 Serial.begin(9600);
 Serial.print("Initial Mode: ");
 Serial.println(mode);
 Serial.print("Setup Complete\n");
 }
}

//===============================================================
// Main Loop
//===============================================================
void loop() {

 val = digitalRead(modePin);

 // If we see a change in button state, increment mode value
 if (val != butState && val == HIGH){
 mode++;
 }

 butState = val; // Keep track of most recent button state

 // No need to keep setting pins *every* loop
 if (modeState != mode){

 // If no keys have been pressed yet don't execute
 // the switch code below
 // if (mode != 0) {

 switch ( mode ) {
 //case 1 is actually handled below as default

case 2:
 digitalWrite(ledPinOne, LOW);
 digitalWrite(ledPinTwo, HIGH);
 showState();
 break;
 case 3:
 digitalWrite(ledPinTwo, LOW);
 digitalWrite(ledPinThree, HIGH);
 showState();
 break;
 default:
 mode = 1;
 // loop back to 1 by default, seems redundant but
 // it also handles the "mode is > 3" problem
 digitalWrite(ledPinThree, LOW);
 digitalWrite(ledPinOne, HIGH);
 showState();
 break;
 } // end switch
// } // end of "if mode = 0" check
 } // end of ModeState check
 modeState = mode; // Keep track of mode recent mode value
 delay(10); // slow the loop just a bit for debounce
}

//===============================================================
// Subroutine
//===============================================================
void showState() {
 if (debug){
 Serial.print("Mode: ");
 Serial.println(mode);
 }
}

Wow, you fought really hard to stop the IDE from making your code readable, didn’t you? The indentation is almost flat. Press Ctrl+T and see how much clearer that already looks.

And what exactly is the problem to add the decrement? Just duplicate everything of the increment switch.

And couple of free tips:

Computers start counting at 0, it’s easier if you do also :wink: So make that the fist case. Also, why have a default case instead of a case for 0 and 1?

Once you start numbering variables (even if that’s in text), it’s time for arrays :slight_smile: Also for the switches this can save writing code.

I assume you use an external pull down resistor? If you connect the switch between GND and a pin you can enable the internal pull up resistors (pinMode(pin, INPUT_PULLUP)) and save the hassle of adding resistors to every button. Mind a pressed button will now read LOW (but that’s a matter of flipping the logic).

delay(10) is not a very good debounce. Not only is 10ms pretty short in terms for a switch, it’s also pretty long for the Arduino and wasting time doing nothing. A nice, easy and neat solution is to grab a library like Bounce2 to do the debouncing and the state change detection.

And you mix the terms “state” and “mode”. The variable is called mode but the function to print it is called showState()…

You are setting mode to 1 if its not 2 or 3, so it will step from 0 straight to 1 and stay there.

You need to do:

mode = (mode+1) % 5;[tt]
and
[tt]mode = (mode+4) % 5;[tt]

for your mode stepping.  +4 rather than -1 because C's % operator is 'broken' for negative values
and does not compute modulo(), but modulo(abs()).

A simple if will be quicker, because of the "broken modulo" you could just and because it's weird to have mode signed:

//increment
if(mode == MaxMode){
  mode = 0;
}
else{
  mode++;
}

//decrement
if(mode == 0){
  mode = MaxMode;
}
else{
  mode--;
}


PS I don't see that broken behavior in the Arduino IDE. If I compute var = -13 % 5 I get -3.