Go Down

Topic: 4x3 Keypad from Sparkfun (Read 6490 times) previous topic - next topic

Angelsbane72

I was able to fix these issues.

The first issue I had was that i could not physically locate the A0 pin on my LCD button shield, as I couldn't find a schematic of the pinout.
Trial and error brought me to the conclusion that the LCD shield A0 pin is the first pin in the J2 strip of pins.

My second question was: Did I need to account in my sketch the A0 on LCD to A0 on Arduino connection.
I did, in the form of the analogRead statement.


raschemmel

The shield A0 pin connects to the Arduino A0 through the header pin. The voltage on that pin is different for each button because they are connected at different points of the voltage divider and the code used an array that contains a value that falls in the midrange of the voltage for each button. Look at the LCD SHIELD example sketch.
You wouldn't be asking any of these questions if you had looked at the LinkSprite  LCD SHIELD page
that has the code and schematic.
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

Angelsbane72

I had looked at the linksprite page numerous times.
As I said, the issue wasn;t the theory behind it, it was that I did not know which pin on the LCD button shield was A0.
I determined it was the first pin on the J2 strip through trial and error, that's all.

raschemmel

Did you find the example code & schematic ?
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

Angelsbane72

#19
Mar 15, 2015, 07:44 pm Last Edit: Mar 15, 2015, 09:24 pm by Angelsbane72
I found only the example code, although that only told me to use A0, which I knew already. i hadn;t known where it was physically.

In any case, I am able to get the keys (EDIT: LCD buttons) working with my current code, but am having trouble in creating a submenu system within a current menu system I have:
Code: [Select]

// Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
 
//States for the menu.
int currentMenuItem = 0;
int lastState = 0;
 
void setup() {
   //Set the characters and column numbers.
   lcd.begin(16, 2);
   //Print default title.
   clearPrintTitle();
}
 
void loop() {
  //Call the main menu.
  mainMenu();
}
 
void mainMenu() {
  //State = 0 every loop cycle.
  int state = 0;
  //Refresh the button pressed.
  int x = analogRead (0);
  //Set the Row 0, Col 0 position.
  lcd.setCursor(0,0);
 
  //Check analog values from LCD Keypad Shield
  if (x < 100) {
    //Right
  } else if (x < 200) {
   //Up
    state = 1;
  } else if (x < 400){
   //Down
    state = 2;
  } else if (x < 600){
    //Left
  } else if (x < 800){
    //Select
    state = 3;
  }
 
  //If we are out of bounds on the menu, then reset it.
  if (currentMenuItem < 0 || currentMenuItem > 4) {
   currentMenuItem = 0;
  }
 
   //If we have changed Index, saves re-draws.
   if (state != lastState) {
      if (state == 1) {
         //If Up
          currentMenuItem = currentMenuItem - 1;
          displayMenu(currentMenuItem);
      } else if (state == 2) {
         //If Down
          currentMenuItem = currentMenuItem + 1; 
          displayMenu(currentMenuItem);
      } else if (state == 3) {
         //If Selected
         selectMenu(currentMenuItem);
      }
      //Save the last State to compare.
      lastState = state;
   }
   //Small delay
  delay(5);
}
 
//Display Menu Option based on Index.
void displayMenu(int x) {
     switch (x) {
      case 1:
        clearPrintTitle();
        lcd.print ("-> CFM");
        break;
      case 2:
        clearPrintTitle();
        lcd.print ("-> FAM X");
        break;
       case 3:
        clearPrintTitle();
        lcd.print ("-> FAM Y");
        break;
      case 4:
        clearPrintTitle();
        lcd.print ("-> FAM Z");
        break;
    }
}
 
//Print a basic header on Row 1.
void clearPrintTitle() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Part Family?");
  lcd.setCursor(0,1);
}
 
//Show the selection on Screen.
void selectMenu(int x) {
   switch (x) {
      case 1:
        clearPrintTitle();
        lcd.print ("Selected CFM");
        //Call the function that belongs to Option 1
        break;
      case 2:
        clearPrintTitle();
        lcd.print ("Selected FAM X");
        //Call the function that belongs to Option 2
        break;
       case 3:
        clearPrintTitle();
        lcd.print ("Selected FAM Y");
        //Call the function that belongs to Option 3
        break;
      case 4:
        clearPrintTitle();
        lcd.print ("Selected FAM Z");
        //Call the function that belongs to Option 4
        break;
    }
}


In my code above, upon selecting a part family, it will display the selected family.
But my code implies I can call another function at this time as well.
Can I set a delay between the printing of "Selected _______" and that case creating a submenu for that part family?

In other words, once a part family is selected and printed to screen, a time delay occurs, and then the "parts in family" submenu appears.
The time delay I can do, but as for each case moving to it's own 'parts in family' submenu, this is where I am struggling.
I feel as if this can be achieved, but I am not sure how to go about it.

raschemmel

My specialty is H/W not S/W but I'll look at it.
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

Angelsbane72


raschemmel

In Reply#13 you say you are not going to use the keypad but your code in Reply#19. has keypad code not LCD Shield code. What's up with that ?
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

Angelsbane72

If there is, it's not being used. I currently have a LCD button shield connected to my Arduino MEGA and will be using the buttons on it to navigate the menu. I'm no longer using the keypad at this time.

raschemmel

#24
Mar 15, 2015, 09:57 pm Last Edit: Mar 15, 2015, 10:26 pm by raschemmel
Here is one example sketch: Note: The code says it uses the "LiquidCrystal library but it only compiles with the "LiquidCrystal_I2C" Library (see attached zip file)

Code: [Select]
#include <LiquidCrystal.h>
#include <LCDKeypad.h>

#define MINVAL 1
#define MAXVAL 1000

LCDKeypad lcd;

byte c_up[8] = {
  B00100,
  B01110,
  B10101,
  B00100,
  B00100,
  B00100,
  B00100,
  B00100,
};

byte c_down[8] = {
  B00100,
  B00100,
  B00100,
  B00100,
  B00100,
  B10101,
  B01110,
  B00100,
};

byte c_select[8] = {
  B00000,
  B01110,
  B11111,
  B11111,
  B11111,
  B11111,
  B01110,
  B00000,
};

void setup()
{
  int i,k;

  lcd.createChar(1,c_select);
  lcd.createChar(2,c_up);
  lcd.createChar(3,c_down);
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("     Guess");
  lcd.setCursor(0,1);
  lcd.print("   The Number");
  delay(3000);
  for (k=0;k<3;k++)
  {
    lcd.scrollDisplayLeft();
    delay(200);
  }
  for (i=0;i<3;i++)
  {
    for (k=0;k<6;k++)
    {
      lcd.scrollDisplayRight();
      delay(200);
    }
    for (k=0;k<6;k++)
    {
      lcd.scrollDisplayLeft();
      delay(200);
    }
  }
  for (k=0;k<16;k++)
  {
    lcd.scrollDisplayLeft();
    delay(200);
  }
}

void loop()
{
  int bottom=MINVAL, top=MAXVAL;
  int trynumber=0;
  int guess, buttonPressed;

  lcd.clear();
  lcd.print("Make up a number");
  lcd.setCursor(0,1);
  lcd.print("from ");
  lcd.print(MINVAL,DEC);
  lcd.print(" to ");
  lcd.print(MAXVAL,DEC);
  lcd.print(" ");
  waitButton();
  waitReleaseButton();
  do
  {
    lcd.clear();
    guess=bottom+(top-bottom)/2;
    trynumber++;

    lcd.print("Is it ");
    lcd.print(guess,DEC);
    lcd.print("?");
    lcd.setCursor(0,1);
    lcd.write(1);
    lcd.write(' ');
    lcd.write(2);
    lcd.write(' ');
    lcd.write(3);
    lcd.write(' ');
    do
    {
      buttonPressed=waitButton();
    }
    while(!(buttonPressed==KEYPAD_SELECT || buttonPressed==KEYPAD_UP || buttonPressed==KEYPAD_DOWN));
    lcd.setCursor(0,1);
    lcd.write(buttonPressed==KEYPAD_SELECT?1:' ');
    lcd.write(' ');
    lcd.write(buttonPressed==KEYPAD_UP?2:' ');
    lcd.write(' ');
    lcd.write(buttonPressed==KEYPAD_DOWN?3:' ');
    delay(100);
    waitReleaseButton();
    if (buttonPressed==KEYPAD_UP)
    {
      bottom=constrain(guess+1,MINVAL,top);
    }
    else if (buttonPressed==KEYPAD_DOWN)
    {
      top=constrain(guess-1,bottom,MAXVAL);
    }
  }
  while (buttonPressed!=KEYPAD_SELECT && top!=bottom);
  lcd.clear();
  if (top==bottom)
  {
    lcd.print("It must be ");
    guess=top;
  }
  else
  {
    lcd.print("It is ");
  }
  lcd.print(guess,DEC);
  lcd.print("!");
  lcd.setCursor(0,1);
  lcd.print("Tries: ");
  lcd.print(trynumber,DEC);
  lcd.print(" ");
  waitButton();  
  waitReleaseButton();  
}

int waitButton()
{
  int buttonPressed;
  waitReleaseButton;
  lcd.blink();
  while((buttonPressed=lcd.button())==KEYPAD_NONE)
  {
  }
  delay(50);  
  lcd.noBlink();
  return buttonPressed;
}

void waitReleaseButton()
{
  delay(50);
  while(lcd.button()!=KEYPAD_NONE)
  {
  }
  delay(50);
}

 



Why aren't you using the LCDKeypad Library ?
Everything you need is on this page.

Also how can you initialize a library that is not included in your code ?
Code: [Select]
// Initialize the library with the numbers of the interface pins

Look at the code you posted in Reply#19. Do you see a "#include <LiquidCrystal.h> "  ?

Look at your code. You have not defined variables for the buttons. That is poor programming practice. ALL I/O should be defined with variables that describe the I/O. If you took the time to look at the LinkSprite code you would see they have defined the buttons with the proper names "LEFT ,RIGHT, UP , DOWN, and SELECT. 

To do this:
Code: [Select]
if (x < 100) {

instead of this:
Code: [Select]
  case BUTTON_UP:

is poor practice and makes it harder to debug the code. You have not defined any I/O , like , for example, this:
Code: [Select]
#define RIGHT_10BIT_ADC           0  // right
#define UP_10BIT_ADC            145  // up
#define DOWN_10BIT_ADC          329  // down
#define LEFT_10BIT_ADC          505  // left
#define SELECT_10BIT_ADC        741  // right



and this:

Code: [Select]
#define BUTTON_NONE               0  //
#define BUTTON_RIGHT              1  //
#define BUTTON_UP                 2  //
#define BUTTON_DOWN               3  //
#define BUTTON_LEFT               4  //
#define BUTTON_SELECT             5  // 
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

Angelsbane72

It was in my code, but must not have copied it into the reply.
The codes from those sites allow me to determine what buton was pressed, which is nice, but I've already done those tutorials and know how they work.

My goal now is to be able to press a concave push button and activate a servo once a part number has been selected through the menu system.
Here is my current code:
Code: [Select]

#include <LiquidCrystal.h>
#include <Servo.h>
// Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
 
//States for the menu.
int currentMenuItem = 0;
int lastState = 0;
//Button and Servo Setup
const int buttonPin = 22; //button pin
const int servoPin = 32; //servo pin
int buttonState = 0; //var for button status
int directionState = 0; //var for direction of servo
Servo demoservo; //create servo control object
int pos = 0; //var for servo position storage

void setup() {
   //Set the characters and column numbers.
   lcd.begin(16, 2);
   //Print default title.
   clearPrintTitle();
   pinMode(buttonPin, INPUT); //button initialized as input
   demoservo.attach(32); //servo connected to pin 32
}
 
void loop() {
  //Call the main menu.
  mainMenu();
}
 
void mainMenu() {
  //State = 0 every loop cycle.
  int state = 0;
  //Refresh the button pressed.
  int x = analogRead (0);
  //Set the Row 0, Col 0 position.
  lcd.setCursor(0,0);
 
  //Check analog values from LCD Keypad Shield A0 pin
  //This verifies the correct analog response of the buttons
  if (x < 100) {
    //Right
  } else if (x < 200) {
   //Up
    state = 1;
  } else if (x < 400){
   //Down
    state = 2;
  } else if (x < 600){
    //Left
  } else if (x < 800){
    //Select
    state = 3;
  }
 
  //If we are out of bounds on the menu, then reset it to home position.
  if (currentMenuItem < 0 || currentMenuItem > 4) {
   currentMenuItem = 0;
  }
 
   //Index Changing
   if (state != lastState) {
      if (state == 1) {
         //If Up is pressed, move one item down
          currentMenuItem = currentMenuItem - 1;
          displayMenu(currentMenuItem);
      } else if (state == 2) {
         //If Down is pressed, move one item down
          currentMenuItem = currentMenuItem + 1; 
          displayMenu(currentMenuItem);
      } else if (state == 3) {
         //If Select is Pressed
         selectMenu(currentMenuItem);
      }
      //Save the last State to compare.
      lastState = state;
   }
   //Small delay
  delay(5);
}
 
//Display Menu Option based on Index.
void displayMenu(int x) {
     switch (x) {
      case 1:
        clearPrintTitle();
        lcd.print ("-> CFM");
        break;
      case 2:
        clearPrintTitle();
        lcd.print ("-> FAM X");
        break;
       case 3:
        clearPrintTitle();
        lcd.print ("-> FAM Y");
        break;
      case 4:
        clearPrintTitle();
        lcd.print ("-> FAM Z");
        break;
    }
}
 
//Print a basic header on Row 1.
void clearPrintTitle() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Part Family?");
  lcd.setCursor(0,1);
}
 
//Show the selection on Screen.
void selectMenu(int x) {
   switch (x) {
      case 1:
        clearPrintTitle();
        lcd.print ("Selected CFM");
        delay(1500);
        lcd.clear();
        lcd.print("Part Number?");
        lcd.setCursor(0,1);//Sets cursor at first spot, bottom row
        lcd.print("->CFM 1");
        buttonState = digitalRead(buttonPin);
        if (directionState == 0){
          if (buttonState == HIGH){ //button is pushed
            directionState = 1;
            for(pos = 0; pos < 180; pos = pos+1){
              demoservo.write(pos);
              delay(15);
            }
          }
       
        else if (directionState == 1){
          if (buttonState == HIGH){
            directionState = 0;
            for(pos = 180; pos>=1; pos= pos-1){
              demoservo.write(pos);
              delay(15);
            }
          }
        }
        }
        //Call the function that belongs to Option 1
        break;
      case 2:
        clearPrintTitle();
        lcd.print ("Selected FAM X");
        delay(1500);
        lcd.clear();
        lcd.print("Part Number?");
        lcd.setCursor(0,1);//Sets cursor at first spot, bottom row
        lcd.print("->PART X 1");
        //Call the function that belongs to Option 2
        break;
       case 3:
        clearPrintTitle();
        lcd.print ("Selected FAM Y");
        delay(1500);
        lcd.clear();
        lcd.print("Part Number?");
        lcd.setCursor(0,1);//Sets cursor at first spot, bottom row
        lcd.print("->PART Y 1");
        //Call the function that belongs to Option 3
        break;
      case 4:
        clearPrintTitle();
        lcd.print ("Selected FAM Z");
        delay(1500);
        lcd.clear();
        lcd.print("Part Number?");
        lcd.setCursor(0,1);//Sets cursor at first spot, bottom row
        lcd.print("->PART Z 1");
        //Call the function that belongs to Option 4
        break;
    }
}


CASE 1 is the current case where I'd like to get the pushbutton and servo working. SO far, my code gets me to the LCD saying "Part Number? -> CFM 1", but once here the pushbutton does nothing to the servo and I dont know why.

raschemmel

#26
Mar 15, 2015, 10:39 pm Last Edit: Mar 15, 2015, 11:05 pm by raschemmel
Quote
Also, the red wires are touching the metal pin holes in the keypad, so there is a connection there without solder
This is nonsense. You post on the forum for help and then when we tell you exactly what the problem is you tell us it's not a problem (in your mind) because (in your mind), metal touching metal is good enough.
What is your problem ? If you don't know how to solder or you don't have a soldering iron, then say so, but
don't tell US what is or isn't a problem if you are posting here for help. We have a reason for telling you it needs to be soldered. If you are going to work with electronics, "When in Rome, do as the Romans do...".

(Yes I know you are not using the keypad anyway but it doesn't change my comment)


Quote
CASE 1 is the current case where I'd like to get the pushbutton and servo working. SO far, my code gets me to the LCD saying "Part Number? -> CFM 1", but once here the pushbutton does nothing to the servo and I dont know why.
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

raschemmel

Where is your complete schematic with the servo connections ?
Draw one by hand and post a photo of it.
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

Angelsbane72

I know how to solder, believe it or not, I modify nerf guns in my spare time. I can't solder this stuff because it isn't mine, so I can't make it permanent now.

Once my codes are correct, then I can solder it all together.

Anyway, the servo has 3 leads, ground, 5V, and signal.
I currently have my servo wired correctly and moving now, it was just its placement in teh code that was the issue.

My current predicament is that I'd like my servo to move to a position (doesn't matter what degrees, 90, 180, whatever) and stop. No sweeping or anything, just move to and hold a set position.

raschemmel

#29
Mar 15, 2015, 11:04 pm Last Edit: Mar 15, 2015, 11:19 pm by raschemmel
Quote
My current predicament is that I'd like my servo to move to a position (doesn't matter what degrees, 90, 180, whatever) and stop. No sweeping or anything, just move to and hold a set position.
Maybe you should change this code:

Code: [Select]
if (directionState == 0){
          if (buttonState == HIGH){ //button is pushed
            directionState = 1;
            for(pos = 0; pos < 180; pos = pos+1){
              demoservo.write(pos);
              delay(15);
            }
          }
        
        else if (directionState == 1){
          if (buttonState == HIGH){
            directionState = 0;
            for(pos = 180; pos>=1; pos= pos-1){
              demoservo.write(pos);
              delay(15);
            }  



The servo works fine on my system.

FYI, you're not going to get anywhere here until you post the menu tree and the servo action desired
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,<br />DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

Go Up