Go Down

Topic: Setting a 5 digit count using 4x4 matrix keypad & the Arduino Uno (Read 2342 times) previous topic - next topic

GautamD

That looks OK for the second part on quick inspection.

OK? So is there a way to make it better?

You may also have to set "a" back to false.

For the first part (zero characters entered), the code should be in case 'D'
I'll set "a" to false and also try the first part and post the code.

GautamD

I have implemented the first part where invalid count is displayed if user pressed the enter w/o entering the count.

Code: [Select]

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;




It works well !

GautamD

Moving on. I am facing a slight problem while entering the count. Characters on the keypad such as A,B,C,D,# are used for performing certain functions like setting count, enter key, setting time, setting a particular mode of operation. The '*' is going to be used as a decimal point. But while entering the 5 digit count not only numbers from 0 to 9 are taken as input but above characters as well. What shall I do prevent them from being taken as input?
 
GautamD

6v6gt

You should post your latest code since you have made so many changes since first posting it.

In principle, if you want to accept only digits you can do something like this:


Code: [Select]

if ( key >= '0' && key <= '9' ) {

    // key is of type char and has a value between 0 and 9 so do something with it.

}

GautamD

After all the corrections/modifications and additions since original post until post 18, following is the code.

Code: [Select]

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 12, 11}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
bool a = true;

void setup()
{
  lcd.begin(LCD_COLS, LCD_ROWS);
  lcd.setCursor(3, 0);
  lcd.print("  PRIYA");
  lcd.setCursor(3, 1);
  lcd.print("ELECTRONICS");
  delay(100);
  for (int positionCounter = 0; positionCounter < 40; positionCounter++)
  {
    lcd.scrollDisplayLeft();
    delay(150);
  }
  delay(800);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Set Count:");
}


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

  // 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 <<<<<<<<<<<<<<<<
            }
          }
          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;
    }
  }
}


Thanks for all the help @6v6gt :-)

GautamD

hi, using the method I used for setting the 5 digit count can I set float values as well? Or is there a different  method to go about it?

Thanks

GautamD

6v6gt

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

Code: [Select]

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

GautamD

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

Code: [Select]

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

This you are suggesting for the 5 digit count I have been working on right? But when it comes to entering float values through keypad it''ll be different altogether?!

GautamD

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

Code: [Select]

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

if I use this I don't need to use the atol() function?

PaulS

if I use this I don't need to use the atol() function?
Correct. But, there are assumptions in that code that atol() does not make.
The art of getting good answers lies in asking good questions.

GautamD

Correct. But, there are assumptions in that code that atol() does not make.
Are those assumptions good or bad? What kind of assumptions, would you please elaborate?

Thanks

Gautam

GautamD

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

Code: [Select]

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

GautamD

This is what I have tried:

Code: [Select]

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;

                 ^

6v6gt

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.

GautamD

Thanks for the quick reply.

Corrections:

Code: [Select]

unsigned long total;
void loop()
{


Code: [Select]

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

Go Up