Pages: 1 2 [3] 4   Go Down
Author Topic: Matrix Keypad - Optimisation  (Read 6657 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
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.

Code:
 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

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 538
Posts: 27115
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

too bad we can't combine them; 'case xx:' needs to be a discrete value for xx:

Code:
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

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

AZ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
Effectiveness is the measure of truth
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Brattain Member
*****
Karma: 538
Posts: 27115
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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  :smiley
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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

Code:
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

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

AZ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
Effectiveness is the measure of truth
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

robtillaart said:

Quote
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.

Code:
 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

Code:
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

Code:
 
  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

Code:
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 Offline
Brattain Member
*****
Karma: 538
Posts: 27115
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The other thing you could is this:
(sticking in all  your correct names & values,  before setup & in setup, etc)

Code:
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

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

AZ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
Effectiveness is the measure of truth
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.  smiley-wink

-carl
« Last Edit: December 02, 2010, 10:05:02 am by Deep_C » Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 538
Posts: 27115
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

AZ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
Effectiveness is the measure of truth
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Code:

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

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 538
Posts: 27115
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Code:
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

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 538
Posts: 27115
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

enum - that's kinda neat. Could make following code easier.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

AZ
Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
Effectiveness is the measure of truth
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
case "a":
// do a
break;
 

keypad:35: error: invalid conversion from 'const char*' to char

Code:
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

Pages: 1 2 [3] 4   Go Up
Jump to: