Switch statement not working..?

Hello,
First time on this forum (other then leeching from existing posts) :sweat_smile:

I have been working on a Arduino pro micro project for a while now, i added a display, joystick and 2 buttons and currently working on movement through the menu. however im running into a problem.

The problem i am encountering is that for some reason the switch statement is not working out the way its supposed to. it will only go into the case when action == 1 but when action >= 2 it skips the switch statement all together.

The piece of code giving me headaches:

  if (controller.obtainActions()) { // returns true or false depending on captured input

    byte tmpSelector;
    byte tmpState = 0;
    
    byte action = controller.returnAction(); //return a byte 0-6
    byte actionStrength = controller.returnStrength(); //return a byte 0-6
    if (debugJoystick) { Serial.println("Loop action  "+String(action)+" and strength is "+String(actionStrength)+" "); }


    if(inMenu()) { // bool inMenu() { bool val = false; if (loopState == 1) { val = true; } return val; }
      tmpSelector = menu.getMenuSelector(); // byte 0-6
      if (debugMenu) { Serial.println("Is inMenu()"); }
      if (debugMenu) { Serial.println("Has Action "+String(action)); }
      if (debugMenu) { Serial.println("Has Selector "+String(tmpSelector)); }

      switch(action) {
        case 1: // left
          if (debugMenu) { Serial.println("Case 1"); }
        break;
        case 2: // right
          if (debugMenu) { Serial.println("Case 2"); }
          if (debugMenu) { Serial.println("open submenu "); }
          //setState(tmpState); // sets isSubmenu() to true and isMenu() to false
        break;
        case 3: // up
          if (debugMenu) { Serial.println("Case 3"); }
          if (debugMenu) { Serial.println(F("menu up")); }
          menu.setMenuSelector(tmpSelector-1);
        break;
        case 4: // down
          if (debugMenu) { Serial.println("Case 4"); }
          if (debugMenu) { Serial.println(F("menu down")); }
          menu.setMenuSelector(tmpSelector+1);
        break;
        case 5: // left click
          if (debugMenu) { Serial.println("Case 5"); }
        break;
        case 6: // right click
          if (debugMenu) { Serial.println("Case 6"); }
        break;
        default:
          if (debugMenu) { Serial.println("Case Default"); }
        break;
      } // end switch action
    }

When i run the code and press left (action 1) on the joystick it outputs the following text:

Loop action 1 and strength is 1
Is inMenu()
Has Action 1
Has Selector 1
Case 1

When action is above 1 (tested 2-6) it prints

Loop action 2 and strength is 1
Is inMenu()
Has Action 2
Has Selector 1

Is there anyone that may be able to sniff out the issue?
Greetings, Sneekyheart

In this case a code snippet won't do.

When you add in a Seril.println( action); right after the above line what numbers do you get?

When trying to add

Serial.println(action);

above the line

byte action = controller.returnAction();

it has a compile error because action dous not exist.

ino:626:20: error: 'action' was not declared in this scope
Compilation error: exit status 1

controller.returnAction() will return a value between 0 and 6 after they are obtained by controller.obtainActions().

the action is printed by the following line and already incuded in the origional post:

if (debugJoystick) { Serial.println("Loop action "+String(action)+" and strength is "+String(actionStrength)+" "); }

Edit:
Just in case it peeks your interest, here is the class i wrote:

class SnController {
  public:
  SnController(byte pinX, byte pinY, byte pinL, byte pinR, bool debugging=false) { //initiate the object with correct pins.
    this->pinX = pinX;
    this->pinY = pinY;
    this->pinL = pinL;
    this->pinR = pinR;
    this->debugging = debugging;
    //possibly treshold ?
    //possibly debounce delay ?
  }
  byte init() { //initialize the joystick by setting the correct pins
    pinMode(pinX, INPUT);
    pinMode(pinY, INPUT);
    pinMode(pinL, INPUT);
    pinMode(pinR, INPUT);
    //no checks for pinMode(pin, INPUT); so just say success lol
    return true; // just for fun
  }
  bool obtainActions() { //returns true or false; obtain input and calculate if action is required
    float tmpStr = 1; // float because its range is 0-1024 and we want to round up with decimals //starting state as 1 because we unset strength if no input is given. this also allowes to capture movement when the remainder is too small for ceil (e.g. ceil(605) <= 0.002 == 0
    byte tmpAction = 0;

    //unset the return variables pre-hand to avoid issues (tbh its not needed, just a precaution)
      action = 0;
      actionStr = 0;

    // OBTAIN VOLTAGES OF INPUT HARDWARE and push it to State variables
    obtainVoltages();

    // INPUT DEBOUNCE TIMER SO WE DONT SPAM BUTTONS
    if (millis() - DebounceTime >= DebounceDelay) {

      // LEFT AND RIGHT ACTION
      if (stateX > XYinnerTreshold[1]) { // left
        tmpStr += ceil((stateX-XYinnerTreshold[1])/stepUp);
        tmpAction = 1; // left
      } else if (stateX < XYinnerTreshold[0]) { // right
        tmpStr += ceil((XYinnerTreshold[0]-stateX)/stepDown);
        tmpAction = 2; // right

      // UP AND DOWN ACTION
      } else if (stateY > XYinnerTreshold[1]) { // up
        tmpStr += ceil((stateY-XYinnerTreshold[1])/stepUp);
        tmpAction = 3; // up
      } else if (stateY < XYinnerTreshold[0]) { // down
        tmpStr += ceil((XYinnerTreshold[0]-stateY)/stepDown);
        tmpAction = 4; // down

      // LEFT AND RIGHT BUTTON
      } else if (stateL > ButtonTreshold ) {
        tmpAction = 5; // left button
        tmpStr = 1;
      } else if (stateR > ButtonTreshold ) {
        tmpAction = 6; // left button
        tmpStr = 1;
      }
      
      // PUSH ANY CAPTURED ACTION AND STRENGTH TO STORAGE
      if (tmpAction >= 1) {
        // DISPLAY INFORMATION WHEN DEBUGGING IS TRUE
        if (debugging){
          Serial.println("Controller trigger obtained at "+String(millis())+" ms. ("+String(millis()-DebounceTime)+"ms since last input.");
          Serial.println("Action "+String(tmpAction)+" with "+tmpStr+" strength.");
        }
        // RESET THE DEBOUNCE TIMER
        DebounceTime = millis();

        // PASS GENERATED DATA TO STORAGE
        action = tmpAction;
        actionStr = byte(tmpStr); // dont forget the convert the float to byte just in case..
        
        // RETURN TRUE IF A NEW ACTION IS OBTAINED
        return true;
      } else { // UNSET ACTION AND STR IF NOTHING COULD BE OBTAINED.
        return false;
      }
    } else {
        return false;
    }
  }
  // PUBLIC RETURN FUNCTIONS
  byte returnAction()   { return action; }
  byte returnStrength() { return actionStr; }
  bool isLeft()       { if (action == 1) { return true; } else { return false; } }
  bool isRight()      { if (action == 2) { return true; } else { return false; } }
  bool isUp()         { if (action == 3) { return true; } else { return false; } }
  bool isDown()       { if (action == 4) { return true; } else { return false; } }
  bool isLeftClick()  { if (action == 5) { return true; } else { return false; } }
  bool isRightClick() { if (action == 6) { return true; } else { return false; } }

  void tmpReturnState() {
    obtainVoltages();
    Serial.println("Controller state X: "+String(stateX)+"  state Y: "+String(stateY)+"    state L: "+String(stateL)+"    state R: "+String(stateR)); 
  }
  
  private:
  // USER DEFINED OPTIONS
  bool debugging; // FOR PRINTLN DEBUGGING INFORMATION
  int XYinnerTreshold[2] = {350,600}; 
  int XYouterTreshold[2] = {0,1024};
  int ButtonTreshold = 950;
  long DebounceDelay = 300; // XX ms before registering a new trigger

  // VARIABLES FOR ARDUINO PINS
  byte pinX; // left right
  byte pinY; // up down
  byte pinL; // left btn
  byte pinR; // right btn

  // STORAGE TO SAVE THE LAST RECORDED VOLTAGE
  int stateX;
  int stateY;
  int stateL;
  int stateR;

  // STORAGE OF ACTION GENERATED BY LOOKING AT THE RAW VOLTAGE
  byte action; // where action == 1 = left, 2= right, 3 = up, 4 = down // used to store the action if any input is registered
  byte actionStr; // contains the strength used to trigger the joystick

  // STRENGTH STEPPER FOR INPUT
  int steps = 5; // amount of steps in movement strength (MAX 64)
  int stepDown = ceil(XYinnerTreshold[0]/steps);
  int stepUp = ceil((XYouterTreshold[1]-XYinnerTreshold[1])/steps);
  // sidequestion: dous this calculate every time the int is called or once at setup?
  
  // INPUT DEBOUNCE TIMER (ANTI BUTTON SPAM)
  long DebounceTime; // last registered time of trigger
  
  void obtainVoltages() { //obtain current voltage and push it to state storage
    int newReading[4];
    newReading[0] = analogRead(pinX);
    newReading[1] = analogRead(pinY);
    newReading[2] = analogRead(pinL);
    newReading[3] = analogRead(pinR);
    stateX = newReading[0];
    stateY = newReading[1];
    stateL = newReading[2];
    stateR = newReading[3];
  }

}; // end of SnController

P.S. the class is a rudementry start; still have to clean things up and optimize things..

sorry for the double post; I have found the solution..

byte action = controller.returnAction();

shouldve been

byte action;
action = controller.returnAction();

Thanks @Idahowalker for pointing me in the right direction (if that was the point you were trying to make)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.