Hello,
First time on this forum (other then leeching from existing posts)
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
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..