Netherlands
Offline
Tesla Member
Karma: 88
Posts: 9392
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #30 on: December 01, 2010, 01:35:01 pm » |
Well done Carl, your skills are improving, however (there allways is) readkeyboard() reads the keyboard again and by doing so it could read again a value below 25 or so. So instead I propose a function that will interpret the keyboardValue read Note: Code not compiled or tested void loop() { keyboardValue = analogRead(keyboardPin); // read the keyboard value (0 - 1023) while (keyboardValue < 25) { //do nothing until a key is pressed keyboardValue = analogRead(keyboardPin); delay(50); } //end of do nothing till a key is pressed int k = kbValue(keyboardValue); // maps the value of the key being pressed "keypressed" i.e. 0-9 Serial.println(k); // print the value back to the Serial view window on your PC delay(1000); }
// interpret the keyboard routine int kbValue(int kbv) { keypressed = 1; if (keyboardValue >=68) keypressed++; if (keyboardValue >=108) keypressed++; if (keyboardValue >=153) keypressed++; if ((keyboardValue >=186) keypressed++; if ((keyboardValue >=254) keypressed++; if ((keyboardValue >=361) keypressed++; if ((keyboardValue >=457) keypressed++; if ((keyboardValue >=525) keypressed++; if ((keyboardValue >=621) keypressed++; if ((keyboardValue >=738) keypressed++; if ((keyboardValue >=812) keypressed++; if ((keyboardValue >=854) keypressed++; if ((keyboardValue >=898) keypressed++; if ((keyboardValue >=945) keypressed++; if (keyboardValue >=970) keypressed++; do { delay (100); keyboardValue = analogRead(keyboardPin); // read the value (0-1023) } while (keyboardValue > 68); //wait until key no longer being pressed before continuing return keypressed; }
Another point of attention is that in readkeyboard you test keyboard value even if keypressed has gotten a value. Replace all the if's with multiple nested if else .. Here a snippet of code how that could be done. keyboardValue = analogRead(keyboardPin); // read the value (0-1023) if (keyboardValue < 68){keypressed = 1;} else if (keyboardValue < 108)) {keypressed = 2;} else if (keyboardValue < 153)) {keypressed = 3;} else if (keyboardValue < 186)) {keypressed = 4;} else if .... etc
The tests are simpler and the number of tests are less. This is caused by the fact that we use earlier tested information. If a value is not smaller than 68 it must be greater or equal so we do not need to test that.
|
|
|
|
« Last Edit: December 01, 2010, 01:35:56 pm by robtillaart »
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 242
Posts: 16485
Available for Design & Build services
|
 |
« Reply #31 on: December 01, 2010, 02:00:09 pm » |
too bad we can't combine them; 'case xx:' needs to be a discrete value for xx: int value = 0; void setup(){} void loop(){ value = analogRead(keypess); // or whatever the read statement is switch (value) { case (value<25): // do something break;
case (value>25 && value <68): // do something else break; } }
|
|
|
|
|
Logged
|
|
|
|
|
AZ
Offline
Jr. Member
Karma: 0
Posts: 52
Effectiveness is the measure of truth
|
 |
« Reply #32 on: December 01, 2010, 02:51:41 pm » |
Boy, you guys are snappy,
@robtillaart
I see how your code is superior; if i understand it correctly, instead of checking the values for each if statement, it instead reads through all the possible values incrementing the keypressed and once it exceeds the value it doesn't increment any further an stays the value right before the value it no longer exceeds. brilliant
@CrossRoads
you say that Case won't work right? it would be nice if it did. why wouldn't it and what situation would be appropriate for the case function??
I haven't come across that yet.
thanks again,
Carl
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 242
Posts: 16485
Available for Design & Build services
|
 |
« Reply #33 on: December 01, 2010, 03:27:22 pm » |
You will need to define the number using the if statements you have, then you can proceed with this funtionality switch(keypressed) { case 1: // break; case 2: // break; : : case 16: // break; } The compiler won't accept the 'case (value<25): type statement, I tried : 
|
|
|
|
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 88
Posts: 9392
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #34 on: December 01, 2010, 03:31:56 pm » |
you say that Case won't work right? it would be nice if it did. why wouldn't it and what situation would be appropriate for the case function?? "Case" is part of the switch statement and it needs discrete values like int char long or byte. A typical usage of a switch is incomingChar = Serial.read(); switch (incomingChar) { case 'A' : DoTheAcommand(); break; // this jumps out of the switch case 'B' : DoTheBcommand(); break; ... default: DoError("unexpected char"); } In essence a switch statement is a faster and more intuitive way to write many if .. if ... if ... statements or many if .. else if ... statements. See more http://arduino.cc/en/Reference/SwitchCase
|
|
|
|
« Last Edit: December 01, 2010, 03:33:13 pm by robtillaart »
|
Logged
|
|
|
|
|
AZ
Offline
Jr. Member
Karma: 0
Posts: 52
Effectiveness is the measure of truth
|
 |
« Reply #35 on: December 01, 2010, 05:20:14 pm » |
robtillaart said: Another point of attention is that in readkeyboard you test keyboard value even if keypressed has gotten a value. Replace all the if's with multiple nested if else .. Here a snippet of code how that could be done. keyboardValue = analogRead(keyboardPin); // read the value (0-1023) if (keyboardValue < 68){keypressed = 1}; else if (keyboardValue < 108)) {keypressed = 2}; else if (keyboardValue < 153)) {keypressed = 3}; else if (keyboardValue < 186)) {keypressed = 4}; else if .... etc
The tests are simpler and the number of tests are less. This is caused by the fact that we use earlier tested information. If a value is not smaller than 68 it must be greater or equal so we do not need to test that. would that work like that or would I need to start a the high end and work my way down ie keyboardValue = analogRead(keyboardPin); // read the value (0-1023) if (keyboardValue > 970){keypressed = 16;} else if (keyboardValue > 945)) {keypressed = 15;} else if (keyboardValue > 898)) {keypressed = 14;} else if (keyboardValue > 854)) {keypressed = 13;} ... else if (keyboard value > 24) {keypressed = 1;} that way in the case where no key is pressed is represented by nothing happening and it will just loop around and scan the value again and evaluate it against the multiple nested if else statements until it is above 24 another thing that concerns me with the code is Serial.println(k); // print the value back to the Serial view window on your PC delay(1000); the delay seems long. won't it take a second between each keypress? or is that so it doesn't put out multiple digits for the same key press? am I misunderstanding the function of the delay there? one final question, in the code you sent, don't I need to initialize all the new variables you mention int k = 0; int kbvalue = 0; int kbv = 0; Thanks again, Carl
|
|
|
|
« Last Edit: December 02, 2010, 09:41:56 am by Deep_C »
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 242
Posts: 16485
Available for Design & Build services
|
 |
« Reply #36 on: December 01, 2010, 06:36:22 pm » |
The other thing you could is this: (sticking in all your correct names & values, before setup & in setup, etc) void loop(){ value = readAnalog(inputpin);
if (value<=25) { delay (30); // for debounce of next press //do nothing} // and all the else if's are skipped, no key has been pressed else if (value>25 or value <=68) {keypressed = 1;} // or the sequencing up/down in the last exchange else if (value >68 or value <=125) {keypressed = 2;} // ... down to 16th
switch(keypressed){ case 1: // break; case 2: // break; etc down to 16th
}
make sure to set value = 0 if no key is pressed so that the switch:case is not going to try and work on an old value. Or add value=0 prior to each break statement so it gets cleared after good button press.
|
|
|
|
« Last Edit: December 01, 2010, 06:39:28 pm by CrossRoads »
|
Logged
|
|
|
|
|
AZ
Offline
Jr. Member
Karma: 0
Posts: 52
Effectiveness is the measure of truth
|
 |
« Reply #37 on: December 02, 2010, 09:55:58 am » |
That makes sense, if it is less than or equal to 25 it will wait 30mS and reevaluate it again for 25, once it exceeds 25 it will continue with the other else if commands and when it finds which one it satisfies, sets the keypressed value to that number and then it has a discrete value for the switch/case statements which will easily implement the corresponding commands. then it goes back to the beginning. if a key is pressed though and held longer than the 30mS will it then execute the case again? thanks for throwing more ideas at me, I rewrite the code each time and learn a new way of looking at it. a great learning experience.  -carl
|
|
|
|
« Last Edit: December 02, 2010, 10:05:02 am by Deep_C »
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 242
Posts: 16485
Available for Design & Build services
|
 |
« Reply #38 on: December 02, 2010, 10:01:03 am » |
No problem Carl. I started arduino-ing myself in August (after not having done any code writing since the late 80's), am starting to get the hang of it myself again. Robert
|
|
|
|
|
Logged
|
|
|
|
|
AZ
Offline
Jr. Member
Karma: 0
Posts: 52
Effectiveness is the measure of truth
|
 |
« Reply #39 on: December 02, 2010, 11:25:57 am » |
if i understand this right, I could redefine keypressed as char long and then use the actual names for the keys, ie 0 -9 a b c d menu enter, instead of 1-16 then when writing the code for the different cases I don't mix up which key I'm actually pressing Another question can I nest case statements? ie switch(keypressed){ case menu: //display options
switch (keypressed){ case a: //do a break;
case b: //do b break;
case c: //do c break;
case d: //do d break; } break;
case xx: //continue other cases
and then continue primary case commands for other keys thanks again, Carl
|
|
|
|
« Last Edit: December 02, 2010, 11:53:41 am by Deep_C »
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 88
Posts: 9392
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #40 on: December 02, 2010, 12:39:43 pm » |
Yes you can nest switch statements but proper indenting your code will help to keep the overview in the editor. Use tools >> auto format or press CTRL-T
|
|
|
|
« Last Edit: December 02, 2010, 12:40:08 pm by robtillaart »
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 242
Posts: 16485
Available for Design & Build services
|
 |
« Reply #41 on: December 02, 2010, 01:23:01 pm » |
Not sure if you can use just letters like that, or if they need to defined as 'a', 'b', etc. Try it, see which way works. not sure 'char long' is a type - think you only get char, or unsigned char. 1 byte long in either case.
Nested Switch:case works. Need to watch the {} and getting the break; out of the case in all the right places. switch(value) { case 1: switch(value2) { case 'a': // code 'a' break; } break; case 2: // code 2 break; }
|
|
|
|
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 88
Posts: 9392
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #42 on: December 02, 2010, 01:52:15 pm » |
Must be defined as 'a' 'b' as then they are of the type char, just a would be a variable name. The values allowed in a switch statement behind the case include byte, char, int, long and unsigned versions of it. Furthermore the enum type can be used. // sample code to show the usage of enum type enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };
void setup() {
Days thisDay = Sunday; switch ( thisDay ) { case Sunday: break; case Monday: break; case Tuesday: break; } }
void loop() { }
[edit]enums are ideal for state machines[/edit]
|
|
|
|
« Last Edit: December 02, 2010, 02:00:21 pm by robtillaart »
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 242
Posts: 16485
Available for Design & Build services
|
 |
« Reply #43 on: December 02, 2010, 01:57:06 pm » |
enum - that's kinda neat. Could make following code easier.
|
|
|
|
|
Logged
|
|
|
|
|
AZ
Offline
Jr. Member
Karma: 0
Posts: 52
Effectiveness is the measure of truth
|
 |
« Reply #44 on: December 02, 2010, 02:26:46 pm » |
it's not liking my using char's for keypressed values; i'm assuming because it's a case label and needs to be an integer keypad:62: error: case label does not reduce to an integer constant it refers to line 62 which is the line prior to where I declare case "a" line 62 is blank ; there is of course one of these errors for each non numerical keypressed value I declare case "a": // do a break; keypad:35: error: invalid conversion from 'const char*' to char else if ((keyboardValue >108) && (keyboardValue <=153)){keypressed = 3;} else if ((keyboardValue >153) && (keyboardValue <=186)){keypressed = "a";} line 35 is the line where I declare (keypressed = 3;) I guess I could define the cases as numbers and just have a comment for the non numerical keys as to what they represent and change keypressed back to an integer; will try that;
|
|
|
|
|
Logged
|
|
|
|
|
|