Setting a 5 digit count using 4x4 matrix keypad & the Arduino Uno

6v6gt:
use unsigned long. Something like (because count is a char array) :

unsigned long total ;

total = (count[ 5 ] - '0')  + (count[ 4 ] - '0') *10 + (count[ 3 ] - '0') *100  . . .  ;

Thanks for suggesting this. But I am confused about how to incorporate it into my code.

Gautam

This is what I have tried:

void loop()
{
  const byte entryMaxSize = 5;
  static char count[entryMaxSize];
  unsigned long total;

  // index
  static byte x = 0;
  char key = keypad.getKey();

  if (key != NO_KEY) // Check for a valid key.
  {
    switch (key)
    {
      case 'A':
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Set Count:");
        // reset the counter
        x = 0;
        a = true;
        break;

      case 'D':
        if (a) {
          if (x == 0)
          {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Invalid Count!!");
            lcd.setCursor(0, 1);
            lcd.print("Press A"); // suggesting the user to enter the count again
            a = false;
          }
          else {
            lcd.clear();
            lcd.print("Count Set:");
            for (byte i = 0; i < x; i++) {
              lcd.print(count[i]);

              a = false;
            }
          }
        }
        break;

      default:
        if (a)
        {
          // if not 5 characters yet
          if (x < entryMaxSize)
          {
            // add key to userinput array and increment counter
            if ( key >= '0' && key <= '9' ) {
              // key is of type char and has a value between 0 and 9 so do something with it.
              count[x++] = key;
              lcd.print( key ) ;  // new print statement <<<<<<<<<<<<<<<<
              total = ((count[ 5 ] - '0')  + (count[ 4 ] - '0') * 10 + (count[ 3 ] - '0') * 100 + (count[4] - '0') * 1000 + (count[5] - '0') * 10000);
            }
          }
          else {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("5 Digits Only!!"); // warning for the user if more than permitted digits are entered
            lcd.setCursor(0, 1);
            lcd.print("Press A"); // suggesting the user to enter the count again
            a = false;
          }
        }
        break;
    }
  }
}

I get the following warning:

Compiling sketch...
"C:\Users\Umesh\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Umesh\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.20\cores\arduino" "-IC:\Users\Umesh\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.20\variants\standard" "-IC:\Users\Umesh\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.20\libraries\Wire\src" "-IC:\Users\Umesh\Documents\Arduino\libraries\hd44780-master" "-IC:\Program Files (x86)\Arduino\libraries\Keypad" "C:\Users\Umesh\AppData\Local\Temp\arduino_build_887319\sketch\sketch_oct06a_experimental.ino.cpp" -o "C:\Users\Umesh\AppData\Local\Temp\arduino_build_887319\sketch\sketch_oct06a_experimental.ino.cpp.o"
C:\Users\Umesh\Documents\Arduino\sketch_oct06a_experimental\sketch_oct06a_experimental.ino: In function 'void loop()':

C:\Users\Umesh\Documents\Arduino\sketch_oct06a_experimental\sketch_oct06a_experimental.ino:51:17: warning: variable 'total' set but not used [-Wunused-but-set-variable]

unsigned long total;

^

  1. The compiler appears to be telling you that you have gone to a lot of effort to set "total" in the loop() but not used it anywhere. Either turn it into a global variable (put the definition outside the loop) or use it say with Serial.println( total ) ;

  2. atoi(), as has been pointed out to you, would be an even better choice. One reason is that it handles the situation better if characters other than 0-9 are present.

  3. Here: (count[5] - '0') * 10000) it would be good to say (count[5] - '0') * 10000UL) instead. The UL ensures that the number is not treated as an int which could be too small for the result.

Thanks for the quick reply.

Corrections:

unsigned long total;
void loop()
{
total = ((count[ 5 ] - '0')  + (count[ 4 ] - '0') * 10 + (count[ 3 ] - '0') * 100 + (count[4] - '0') * 1000 + (count[5] - '0') * 10000UL);

My max count is going to be 99,999. Would using atoi() be feasible?

Gautam

A slight correction from:

total = ((count[ 5 ] - '0')  + (count[ 4 ] - '0') * 10 + (count[ 3 ] - '0') * 100 + (count[4] - '0') * 1000 + (count[5] - '0') * 10000UL);

to:

total = ((count[ 5 ] - '0')  + (count[ 4 ] - '0') * 10 + (count[ 3 ] - '0') * 100 + (count[2] - '0') * 1000 + (count[1] - '0') * 10000UL);

There is no problem with atoi() and numbers which are bigger would fit in an int (max 65,536) if you follow the same structure:

total = . . . + . . . + atoi( count[1] ) * 10000UL);

Suppose I want to enter a count 99,999 then using:

total = ((count[ 5 ] - '0')  + (count[ 4 ] - '0') * 10 + (count[ 3 ] - '0') * 100 + (count[2] - '0') * 1000 + (count[1] - '0') * 10000UL);

It would mean:

count[5] = 9
count[4] = 910
count[3] = 9
100
count[2] = 91000
count[1] = 9
10000UL

I am right?

Gautam

Sort of.

Except that I now see there is an error in that count should go from 0 to 4, not 1 to 5 so you should change the code accordingly.

It is like if you pressed the '9' key 5 times on a pocket calculator.
The first press give the number of 10,000's, the second press gives the number of 1,000's etc. etc.

The complete number, that is, 99,999 is an integer which can be used in the following calculation.

Should be this way? Using this I have an int now? And don't need to use atol()?

 total = ((count[ 0 ] - '0') * 10000UL  + (count[ 1 ] - '0') * 1000 + (count[ 2 ] - '0') * 100 + (count[3] - '0') * 10 + (count[4] - '0'));

What is PaulS trying to say here:

PaulS:
Correct. But, there are assumptions in that code that atol() does not make.

Using atoi() would be even better as I said in post #28 part 2 and presumably for the same reason that Pauls recommended it.

So instead of:

total = ((count[ 0 ] - '0') * 10000UL  + (count[ 1 ] - '0') * 1000 + (count[ 2 ] - '0') * 100 + (count[3] - '0') * 10 + (count[4] - '0'));

you could write:

total = ( atoi(count[0]) * 10000UL  + atoi(count[1]) * 1000 + atoi(count[2])  * 100 + atoi(count[3])  * 10 + atoi(count[4]) );

If the data is clean, both methods will work fine.

what do you mean by " if data is clean?"

both methods?

what do you mean by " if data is clean?"

That the data is a valid decimal digit.

Thanks @AWOL , the data is going to be clean.

So after using the following method, 'total' is an now an unsigned long int and can be saved in the EEPROM?

total = ( atoi(count[0]) * 10000UL  + atoi(count[1]) * 1000 + atoi(count[2])  * 100 + atoi(count[3])  * 10 + atoi(count[4]) );

Assuming count is a two dimensional array of strings containing single digit strings, yes.

Okay. Currently as I enter the digits for the count they are displayed from left to right. How to display them from right to left?

If count is an array of chars, capable of holding 6 elements, and contains values like so:

count[0] = '3';
count[1] = '5';
count[2] = '0';
count[3] = '0';
count[4] = '7';
count[5] = '\0'; // A NULL terminator

then

unsigned long val = atol(count);

would result in val containing 35007.

If count[3] contained a 'E', then val would contain 350.

With the code you have been trying, val would contain some meaningless garbage if any element in the array was not a digit.

PaulS:
If count is an array of chars, capable of holding 6 elements, and contains values like so:

count[0] = '3';

count[1] = '5';
count[2] = '0';
count[3] = '0';
count[4] = '7';
count[5] = '\0'; // A NULL terminator




then



unsigned long val = atol(count);




would result in val containing 35007.

If count[3] contained a 'E', then val would contain 350.

With the code you have been trying, val would contain some meaningless garbage if any element in the array was not a digit.

@PaulS I want to implement it the way you are suggesting. I want to obtain a count which can be any number between 0 to 99,999 and then storing it in the Arduino EEPROM for comparison. What changes I shall make to my current code since you say that my current code is not helping me achieve what I want. Thanks.

Gautam

What changes I shall make to my current code since you say that my current code is not helping me achieve what I want.

You want to get from point A (what the code does now) to point B (the code does what you want it to do). I have no ideal where point A is (you have not said what you current code looks like OR what it actually does) or where point B is (I do not understand what you are trying to actually store in EEPROM).

I can't help you get from point A to point B.