LCD keypad shields

I'm not sure if this is the right place to post this question but please give me some grace! I am still relatively new to Arduino so this may be a newbie error.. I have been creating a series of projects using my Arduino UNO R3 board with a basic 16x2 SainSmart lcd shield with a keypad.

In most all of my projects, I have a menu setup on the lcd with a toggle method (right/left) to view live streaming data from a series of individual sensors. While my toggling works, sometimes I have to press a button on the shield multiple times before I will get a response. I have found that sometimes I get the best response time when I hold down a button for about 3 seconds, and when I let go, the programmed reaction plays out. I thought it could just be that my UNO R3 board's processor was too slow to handle running all my sensors and the lcd so I tried my same setup on a MEGA 2560 board with the same result. :0

My question is simple: Is my problem with button response time an issue with programming, or the buttons on my particular shield? I have seen other shields have lightning fast button response while running far more complex programming than mine. I need a pro to point me in the right direction. What kind of lcd shield have you found works the most consistently and fastest?

Any tips or examples greatly appreciated! :smiley:

I would say that this is a perfect example of what is wrong with the Arduino/Wiring programming paradigm and the challenges that it gives. Any "larger" embedded system will contain several tasks/threads; in your case at least 1) monitor the keypad, 2) sample the sensors, 3) do some logging and/or calculations, 4) handle the display, and 5) service communication with host/network.

Doing this as a pure sequential program is difficult and it is easy to miss external events, mix-up states, etc. This can occur when sampling the sensors, etc. Or even when updating the LCD. Remember that clearing a 1602 LCD takes over 2 ms.

Now this is not helping you :wink: or even giving any advice.

What could you do? Here I have to do some guessing as you have not provided any code.

The first advice I would give you is sample the keypad with a periodic event (timer). You could also use a pin change interrupt handler but the keypad is actually implemented with a resistor net and sampled with an analog pin which makes this "difficult".

BW: Sampling the analog pin takes over 100 us. So it all adds up.

Cheers!

PS: You could look at this and dig into Cosa for some inspiration. Cosa is a totally different programming paradigm. Cosa/LCD Menu System - Displays - Arduino Forum

Thanks for the tip! :slight_smile: I have actually ran multiple system checks on my setup. The reason why I did not provide code, is because it is very inconsistent with any codes I uses. This is the part that makes me unsure of the problem: Some programs I use with my shield have instant response time on the buttons, and then over time as the program is running, it quickly slows down to a seemingly non responsive state. I’m not looking for unrealistic lightning fast responses, just a relatively quick or consistent response after a single button press.

I believe it is simply related to the button quality on my shield, but I could be missing something… I am inexperienced with multiple kinds of lcd shields and I just want to see if anyone else has had a similar problem and/or if they fixed it.

Though I have the same problem with all my codes… here is one of the very basic programs I am playing with and the problem is obvious.

//Arduino Greenhouse project. Coded by Aaron Maybury A.K.A GlassCurtain
//Used sample code for the DHT11 By Ladyada

#include <LiquidCrystal.h>
#include <DFR_Key.h>
#include "DHT.h"

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

DFR_Key keypad;

// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11 
#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

int sensePin = 11; //Arduino Pin number the sensor plugged into. The schematics that come with the LCD shield are incorrect.
//Pin 2 on the arduino is actually pin 5 on the LCD shield. The headers that plug into the arduino's Digital pins 0 - 7, on the LCD Shield the exact middle pin is pin 2 on the arduino.
//Use your multimeter to test continuity to find the pin you want.
int currentButton = 0; //Current button pressed
int displayTemp = 1; //Keeps track of what screen is currently being displayed. If displatTemp is 1 temp is showing. If 0 Humidity is showing.
int displayHumid = 0;
int setTemp = 75; //Default to set the desired temp
int setHumid = 50; //Defualt to set the desired humidity
int outputPin = 3; //Output pin to the relay to trip the fans

DHT dht(sensePin, DHTTYPE);

void setup() 
{ 
  pinMode(outputPin, OUTPUT);
  
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  
  Serial.begin(9600); 
  
  dht.begin();
}

void loop() {
  
  currentButton = keypad.getKey(); //Read button press
  
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature();

float temp = (t * 1.8) + 32; //Convert *C to *F.

if (displayTemp == 1) //Shows temp screen upon first boot
{
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TEMP       ");
    lcd.print(temp);
    lcd.print("  ");
    lcd.print((char)223); // degree symbol
    lcd.print("F");
    lcd.setCursor(0,1);
    lcd.print("SET TEMP   ");
    lcd.print(setTemp);
    lcd.print(" ");
    lcd.print((char)223);
    lcd.print("F");
    displayHumid = 0;
    
}
else{
  lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("HUMIDITY    ");
    lcd.print(int(h));
    lcd.print(" %");
    lcd.setCursor(0,1);
    lcd.print("SET HUMID   ");
    lcd.print(setHumid);
    lcd.print(" %");
    displayHumid = 1;
}

// Reads which buttons are pressed. 
// No button = 0
// Select button = 1
// Left button = 2
// Up Button = 3
// Down Button = 4
// Right Button = 5

if (currentButton == 5 && displayTemp == 1)
{
   displayTemp = 0; //Turns display temp off so it will show humidity after pressing right button
}

// The following code toggles the screen when the corresponding button is pressed.
// Also sets the screens to wrap around the display. 
// So if you hit right button once it will show humidity and if you hit right button again it will show temp.

if (currentButton == 5 && displayHumid == 1)
{  
  displayTemp = 1;
}

if (currentButton == 2 && displayTemp == 1)
{
   displayTemp = 0;
}

if (currentButton == 2 && displayHumid == 1)
{
  
  displayTemp = 1;
}

if (currentButton == 3 && displayTemp == 1) //When up button is pressed and the temp screen is showing, increment the set temp
{
   ++setTemp;
}

if (currentButton == 4 && displayTemp == 1) //When down button is pressed with the temp screen showing, decrement set temp
{
   --setTemp;
}

if (currentButton == 3 && displayTemp == 0) //When up button is pressed and the humidity screen is showing, inc the set humidity
{
  ++setHumid;
}

if (currentButton == 4 && displayTemp == 0) //When down button is pressed and humidity screen is showing, dec the set humidity
{
  --setHumid;
}

if(temp >= setTemp) //Trip relay if temp is exceeded
{
  Serial.print(temp);
  digitalWrite(outputPin, HIGH); 
}
else
   {
    digitalWrite(outputPin, LOW);
   }



if (h >= setHumid && digitalRead(outputPin) == LOW) //If humidity is exceeded and fan is not on due to temp exceeded, turn fan on.
{
  digitalWrite(outputPin, HIGH);
}


}

@Gustermaximus

Thanks for providing the code. Much easier and you don't have to read my "hand waving". Your program is "small" and the libraries do help with some of the complexity.

First thing to check is the DHT library and that the delay is not active there. There is a version that does a delay of up to 2 seconds between samples.

Second thing to do is write a small test sketch that only uses the keypad and serial output and verify that it isn't a hardware problem.

I'll took a second look at the keypad library code and, hum, you might want to twiddle with the DFR_Key DEFAULT_THRESHOLD (static int DEFAULT_THRESHOLD = 5) it might be a little low. I don't like the logic in the get_key() function. It is possible to have a key reading that is not read.

Cheers!

No problem. :slight_smile: I tried to keep it as simple as possible in order to make it easier to find the problem.

I have had no issues with the DHT sensor so far, or any other sensors I've been using with this setup... but I have no experience in how to "check the library" for a delay. So I'm kinda lost there. :~ but I will definitely do some more checking on the keypad itself with different programs, but I'm pretty sure it's hardware related.

Sorry, I'm ignorant of how the libraries are made and edited. How could I change "DFR_Key DEFAULT_THRESHOLD (static int DEFAULT_THRESHOLD = 5)" to a higher number? This sounds like it could very easily be my problem if it is in fact software related!

Update to previous reply: I set the DFR_Key DEFAULT_THRESHOLD (static int DEFAULT_THRESHOLD = 5) from 5 to 10. It seems to have not made any difference in the performance, but maybe I need to set the number even higher? Any other suggestions to speed up response time?

After further examination.. I found that changing the int of ( _refreshRate = 10; ) in the DFR_Key.cpp file to 100, and then 1000 greatly increased response time of my shield's buttons! They still need a firm press each time, but they are consistently quick! Thanks for pushing me in the right direction.

Can you share Wiring Diagram above Seeting