Right, I have a FSM that is working just fine, now I'd like to add a "configuration" menu to it - inside a single state.
This is my FSM
getState();
switch(mode)
case 1:
....bla bla bla
case 2:
....bla bla bla
case 3:
lcd.display();
lcd.setCursor(0,0);
lcd.print(".oo00( CONFIG )00oo.");
lcd.setCursor(3,2);
lcd.print("PULL TO CONFIG");
if (buttonState == btnPull){
lcd.clear();
while(readArm() != btnPush){
lcd.setCursor(0,0);
lcd.print("CONFIG ");
lcd.print((int)buttonState);
delay(300);
}
}
break;
default:
...and the readArm() routine. reads a value from the ADC to determine what position the switch(arm) has. Uses also serial commands so I can debug on the computer where I do not have the switch.
int readArm(){
int ret = 0,
val = 0,
val2 = 0,
last = 0;
unsigned long currentMillis = millis();
if (currentMillis - prevMillis > btnBlock){
prevMillis = currentMillis;
power_adc_enable();
delay(5);
val = analogRead(BTN1);
delay(2);
val2 = analogRead(BTN2);
power_adc_disable();
if (Serial.available() > 0)
char incomming = Serial.read();
}
if ((val > 660 && val < 681) || incomming == 'd')
ret = (btnDown);
else if ((val > 680 && val < 688) || incomming == 'm')
ret = (btnMode);
else if ((val > 687) || incomming == 'c')
ret = (btnChange);
else if ((val2 > 640 && val2 < 660) || incomming == 'u')
ret = (btnUp);
else if ((val2 > 660 && val2 < 685) || incomming == 't')
ret = (btnPull);
else if ((val2 > 684) || incomming == 's')
ret = (btnPush);
Serial.print("State: ");
Serial.print(ret);
return(ret);
}
The problem is that the buttonState changes just fine when I'm in all states in the FSM, but once I enter the while loop - buttonState "hangs" at 6, where it should read 6 once I pull the switch and the go back to 0 - but it just stays at 6..
I tried altering the while loop to this:
while (1==1){ //to make it run in never ending loop
buttonState = readArm();
lcd.print((int)buttonState);
}
..but that gives me the same error - button state is always 6
I know that readArm() is called since I get my debug info on Serial - but why on earth does buttonState (ret) not change once in the while loop?
Perhaps you need to explain what is supposed to be happening better. Why does the value returned by readArm() depend on the values on two different analog pins AND the time AND serial port data?
Perhaps you need to explain what is supposed to be happening better.
buttonState shuld not "hang" with a value of 6. It should read 6 (for button pull), then go back to 0 - just like when I'm not in a while loop.
But it keeps that value of 6 despite I call the function withn the while statement.
Why does the value returned by readArm() depend on the values on two different analog pins AND the time AND serial port data?
Time to make a rough debounce on the button.
Two Analog values because this is the way the switch is made (it's a radio stalk from a Peugeot 306, it has one feed and two outputs - thus I need two analog pins to get all 6 actions)
Serial - like I wrote to be able to "simulate" the switch when I have the Arduino on the table and not in the car. if you look at it you'll see I OR the buttons and the serial, not AND.
delay(5);
val = analogRead(BTN1);
delay(2);
val2 = analogRead(BTN2);
Serial - like I wrote to be able to "simulate" the switch when I have the Arduino on the table and not in the car. if you look at it you'll see I OR the buttons and the serial, not AND.
Yeah, I saw that right after I posted...
once I enter the while loop - buttonState "hangs" at 6, where it should read 6 once I pull the switch and the go back to 0 - but it just stays at 6..
Those delays are to make sure the ADC settles properly before trying to read data from it. Normally I take x readings and average the vales found, this is just a quick'n'dirty
Where do you assign a new value to buttonState? Shouldn't buttonState get the value returned by readArm()?
I don't. problem is that I in readArm() send the ret value to the seriel, it is that value that "hangs" at 6. under normal operation I'd assign the return value from readArm to buttonState - but it is the ret (and the return value) from readArm that gets stuck at 6 somehow.
Those delays are to make sure the ADC settles properly before trying to read data from it.
Yes that is what you might hope they are doing but they are doing nothing. If the A/D has to change channel then all that settling time has gone to the channel that you are not going to read. If you want to allow time you have to :-
Read the channel
Delay
Read same channel again
That way the delay does allow the voltage to settle before the reading. This is a technique you can use if you have high impedance sources on the analogue inputs.
Well, 6 seems to be some magic number that only you know about. Without knowing which variable (btnDown, btnMode, btnChange, btnUp, btnPull, btnPush) contains that value, it's hard to know which if test has issues.
buttonState shuld not "hang" with a value of 6. It should read 6 (for button pull), then go back to 0 - just like when I'm not in a while loop.
But it keeps that value of 6 despite I call the function withn the while statement.
You are never assigning a new value to buttonState, so it should NOT read 6 then go back to 0.
Well, 6 seems to be some magic number that only you know about. Without knowing which variable (btnDown, btnMode, btnChange, btnUp, btnPull, btnPush) contains that value, it's hard to know which if test has issues.
You are never assigning a new value to buttonState, so it should NOT read 6 then go back to 0.
Read my last post, the ret value in readArm() never changes despite it is being called properly. It just returns 6 - no matter what.
THAT is the issue.
There are still some unknowns. We can't tell how long btnBlock makes the function skip reading the button/switch/knob/whatever state or serial input.
I still can't see why you have this block in here at all. If it is necessary to wait, and I can't see that it is, don't return until the time has elapsed.
Why don't you post ALL of your code? It is quite possible that something is stepping on btnBlock, giving it a value that is unlike what you expect it to contain, causing the d0-nothing-until block to be skipped for much longer than you expect.