Going loopy, looping the loop

As part of a larger project, I’m trying (and failing) to sequentially input three variables via a 12 button keypad.

Each variable is 4 digits long and is displayed on an LCD and then used elsewhere in the program. (Keypad and LCD hardware has been tested and are working fine with ‘Hello world’ examples).

I was heading down this path before getting stuck and doing a search;

// borrowed from various sources


 void loop() {
   // loop for the 3 variable inputs:
   for (int variable = '1'; variable <= '3'; variable++) {
     // loop for the 4 digit elements they contain:
       for (int  = '1'; contentsa <= '4'; contentsa++) {
     char key = keypad.getKey();
     if (key != NO_KEY){

//errrr, then where???...

       }
     }
   }

Looking for snippets, tutorials or examples I could learn from, I searched here for any posts containing;

if (key != NO_KEY)

Most posts seem to relate to entering a password and then comparing that with a previously stored password rather than getting and holding a variable from the keypad…

Widening the search, I have seen suggestions to similar but different questons which suggested:

“case” (that was in answer to a multi menu question)

or

an array … ?

or

“make your variables global (declared outside of “loop”)”
(that was in answer to a question about running one loop behind another… which is what I think I am wanting to do!)

Could someone nudge me in the best direction here, I can see several steps in my initial approach that are over my pay grade! :slight_smile:

I will also add debounce if required and press and hold options at some future point if that makes a difference to the answer(?)

Many thanks

PS
I’m a retired mech eng, never programmed before so a complete noob at all this… (I may be having problems with the software but the project mechanicals are a thing of beauty! :sunglasses: )

 void loop() {
   // loop for the 3 variable inputs:
   for (int variable = 1; variable <= 3; variable++) { // lose the single quotes
     // loop for the 4 digit elements they contain:
       for (int  = 1; contentsa <= 4; contentsa++) { // and here
     char key = keypad.getKey();
     if (key != NO_KEY){

//errrr, then where???...

       }
     }
   }

Single quotes say that the value is an ASCII character, so ‘1’ actually has the decimal value 49.
Can you be a little clearer about what it is you want to do?
Posting snippets of code doesn’t always help, if the goal isn’t clear.

You don’t say what your keypad is, either.

Start simple - try lots of the examples, pick them apart and try to put them back together.

Yes, “arrays” and “case statements” may help, but you need to pick up the basics and have a clear goal.

Hi Groove Nice one! Thanks for that, I wasn't aware of the connection between quotes and ascii! I would probably have spent time figuring that out later. (will never forget it now!)

The keypad is a standard 0-9 # and * buttons, 3 colums, 4 rows... typical of Sparkfun, Ladyada, etc. this one came from Rapid electronics but is the same. (9 connections, two outside connections not used)

The overal goal is to build a semi automatic donkey feeder! (don't laugh, someone has to!) The 3 loops are for feeding 3 donkeys at a time and the 4 elements are the different food stuffs their mix can be made from.

Their mixture varies from day to day and to each donkey, hence the need for 3 x 4 digit variables I mentioned.

3 donkies are fed at the same time, but from different bowls...

Completely agree with you about the start simple approach. I've split the project, and the software into small self contained lumps that I can test and verify independantly of anything else.

All of those are completed except this one. The user IO part. I am hoping to enter at the keypad a sequence like, 0122#0901#1141# then there's three happy donkies! ;D

Do I have a clear goal? Crystal clear! :)

As I mentioend the problem seems to be I can't find any examples of this sort of thing to try! There's plenty of password / servo examples, on here and elsewhere but I dont think that helps.

Your for (int  = 1; contentsa <= 4; contentsa++) { // and here

You also need a variable name, too:

for (int contentsa = 1; contentsa <= 4; contentsa++) { // and here

Forgive my directness, but do you really want to trust a hobby microcontroller to what appears to be a life-support function?

Do you trust your programming skills and the hardware to deliver consistently and reliably in potentially difficult environments?

Groove, no apology necessary. it must be difficult to assist any question on only the barest of incomplete information. Rest assurred "life support" is NOT a function of this project!

As I mentioned I'm retired and this is to assist my bad back, moving scoops of feed from feed bins to the bowls for 7 donks, 3 times a day, 7 days a week, 365 days a year!

As is clear from the user required keypad input, it is not an unattended or automatic system. It's more akin to a coffee making machine than a spoon.

The environment is not IP68! It's a nice warm garage :-)

Do I trust my programming skills, no. ...But I do trust my testing proceedures? Absolutely.

If you can help, that's great... if you are uncomfortable for whatever reason, that's ok too. Thanks for your time and your concern.

:-)

@PaulS

thanks Paul, there's a flicker of enlightenment here, (I think!)

looking at my notes, I'm reading that I need a name, a value, and a type for each variable.

Type = int I guess. Value is coming from the keyboard and Name would be.. .er, a global declaration of something thats relevant to what it is doing?

If that's so, then the only part of the jigsaw I'm missing is the line of code that would put a keypad entry into the variable previously declared?

Half way there? I may know the question! ;D

If your using the Keypad library, the value returned by getKey is a character, and can be stored in a character or a position in a character array. This code constructs a string of 3 groups of 4 characters, separated by #s.

char keyData[16];
int keyNum = 0;

void loop()
{
   char key = keypad.getKey();
   if (key != NO_KEY)
   {
      keyData[keyNum] = key; // Store the key
      keyNum++;                   // Advance to the next position
      keyData[keyNum] = '\0'; // Add a null to the string

      // After every 4th key, add a #
      if(keyNum == 4 || keyNum == 9 || keyNum == 14)
      {
          keyData[keyNum] = '#';
          keyNum++;
          keyData[keyNum] = '\0';
      }
   }

   if(keyNum == 15) // All 3 values have been entered
   {
       // Do something with the string
   }
}

PaulS Thanks you most kindly good sir!

I see what it does and how it does it, Most helpful in understanding the problem as well as solving it! I'll post the completed code here when I've finished the testing should others tread the same path and find this thread...

Purely for the purpose of my curiosity... is ther a way of putting the keypad input istraight into a variable?

char key=keypad.getkey (var_one)

or

char key=keypad.getkey () var_one == keypad.getkey()

??? sort of thing?

Thanks again.

There's a reason to have key as a separate variable. You need to test that a key has been pressed, and store the result only if the result is valid.

Since loop is executed many times a second, you can not assume that getKey will return a good value every time. In fact, most times, it will return NO_KEY.

Purely for the purpose of my curiosity... is ther a way of putting the keypad input istraight into a variable?

As of now, there is no such function available. But I think it is a good idea! A very good idea, actually.

Sorry for hijacking.

Maybe I should add these functions: (or something in the likes of them)

void setMemory(char* str, int size);
void startRemember();
void stopRemember();
char* getMemory();
int numberOfMemories();

Could lead to code like:

char keyData[16];
kpd.setMemory(keyData,16);
kpd.startRemember();
//block processing until the memory contains 15 memories (chars)
while (kpd.numberOfMemories()!=15) {
  kpd.getKey(); //call function so that the keypad library gets updated
}
kpd.stopRemember();

//use keyData here

What do you think?

I like the idea of having the keypad library handle saving the key presses to strings. The issue I see is, as I mentioned, that loop may execute many times between key presses. Some mechanism would need to be defined to say when enough keys had been pressed. Presumably, the caller would be responsible ofr this, but it's something that needs to be considered.

Thanks for all the help here on this, may I impose further upon your hospitality and further my learning for today;

Instead of my previous scenario question, If it was wanted to: enter the first 4 digits as var_one, display var_one via LCD or serial, the next 4 digits as var_2 display var_2 as above the last 4 digits and var_3

how would they do it today without strings??

I'm assuming here that;

a:there must be a way!

b:someone must have done it (although I found no evidence of that)

c: adding "if (key ! = NO_KEY) is not going to solve the problem that PaulS mentions

?

If you enter '1', '7', '8', '3', are you trying to populate an integer variable with the value 1783?

Perhaps it's time to tell us what you want to do with the data entered via the keypad.

I'm assuming here that;

a:there must be a way!

b:someone must have done it (although I found no evidence of that)

c: adding "if (key ! = NO_KEY) is not going to solve the problem that PaulS mentions

a) There is. b) Lots of times. c) It will.

Yes, spot on! In your example, "1783" would be the value I would use elsewhere. Specifically as the number of 'millis ()' I'll use with an actuator.

The actuator code, the interface to the mechanicals and the mechanicals have been completed and tested.

During this testing, - the sketch had "1783" entered manually into the appropriate variable, it was then uploaded to the Arduino and the correct operation verified. Less than ideal for operation but fine for the test phase.

a,b,c noted! :-[

Here's how to save key presses as an integer.

int keyCode = 0;
void loop()
{
   char key = keypad.getKey();
   if(key != NO_KEY)
   {
       keyCode *= 10;
       keyCode += key - '0';
   }
}

Enter '1'. keyCode starts at 0. 10*0 = 0. Add '1' - '0', which is 1. So, keyCode now equals 1.

Enter '7'. 10*1 = 10. Add '7' - '0', which is 7. So, keyCode now equals 17.

Repeat for '8' (keyCode equals 178) and '3' (keyCode new equals 1783).

Use the value in keyCode, and start over.

Or create 3 such variables, and a counter to count the number of keys pressed. Use the appropriate variable to collect the data, based on the total number of keys pressed.

Thats terrific, thanks again for all the help I've received.

Most generous.