Problem with LCD and hardware debounce

Hi everyone. I have Genuino Uno and i’m creating a 4-way mixing valve controller for my house heating system with pellet burner.
Uno is powered via ac-dc 9V, 1A adapter. Breadboard is powered via 5V and GND pin. Lcd is soldered to I2C driver and connected to SDA and SCL pin on Uno and VCC, GND to breadboard. On Breadboard i also have four push buttons(two via resistors on analog input and two with hardware debounce to trigger interrupts), 2x DS18B20, 74HC14, 1x LED.
When i try push buttons with hardware debounce it counts randomly(either pressed or not), but when upload program just to test debounce it works perfect with every push.
Another problem is with lcd. After some time it showing weird characters. After pushed reset button on Uno it shows weird characters immediately. When i upload program only to initialize lcd and print some text in (either loop or setup) it works fine for a long time.

Is it possible there is a lack of current or loose contacts on breadboard?

#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>


#define ONE_WIRE_BUS 5

void page1();
void page2();
int readKeypad();
void mainDisplay();
void menu();
void onOff();

int i = 0; //promenjiva za povratak u mainDisplay i za cekanje podesavanja parametara, while(i)
int m = 0;
int o = 0;
int analogInput = A0;
int keyValue;

float tk = 0;
float tg = 0;
float tz = 20;
float tzNew = tz;
float tu = 28;
float tuNew = tu;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup() {

  pinMode(A0, INPUT_PULLUP);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(7, OUTPUT);
  digitalWrite(7, LOW);
 
  
  attachInterrupt(digitalPinToInterrupt(2), menu, RISING);
  attachInterrupt(digitalPinToInterrupt(3), onOff, RISING);
  sensors.begin();
  sensors.setResolution(10);
  lcd.begin(16,2);

  
  

  lcd.setCursor(2, 0);
    lcd.print("Mixing Valve");
    lcd.setCursor(3, 1);
    lcd.print("Controller");
    delay(2000);
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("Software V-1.0");
    lcd.setCursor(3, 1);
    lcd.print("by Namilax");
    delay(2000);
  mainDisplay();
}

void menu() {
  m++;
}
void onOff() {
  o++;
}

//Podesi Tz
void page1() {
  i = 1;
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("Podesi Tz");

  while (i == 1) {
    lcd.setCursor(6, 1);
    lcd.print(tzNew, 1);
    lcd.noCursor();

    if (m == 2) {
      tz = tzNew;
      page2();
    }
    readKeypad();
    if (keyValue == 1) {
      tzNew--;
      delay(200);
    }
    else if (keyValue == 2) {
      tzNew++;
      delay(200);
    }
  }
}


//podesi Tu
void page2() {
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("Podesi Tu");

  while (i == 1) {
    lcd.setCursor(6, 1);
    lcd.print(tuNew, 1);
    lcd.noCursor();

    if (m >= 3) {
      tu = tuNew;
      i = 0;
      m = 0;
      mainDisplay();
    }
    readKeypad();
    if (keyValue == 1) {
      tuNew--;
      delay(200);
    }
    else if (keyValue == 2) {
      tuNew++;
      delay(200);
    }
    else readKeypad();
  }
}

int readKeypad() {
  int keypadValue;
  keypadValue = analogRead(analogInput);

  if (keypadValue > 400) {
    keyValue = 0;
  }
  else if (keypadValue < 80) {
    keyValue = 1;
  }
  else if (keypadValue < 250 && keypadValue > 210) {
    keyValue = 2;
  }
  return keyValue;
}




void mainDisplay() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Tk=");
  lcd.setCursor(9, 0);
  lcd.print("Tg=");
  lcd.setCursor(0, 1);
  lcd.print("Tu=");
  lcd.setCursor(3, 1);
  lcd.print(tu, 1);
  lcd.setCursor(9, 1);
  lcd.print("Tz=");
  lcd.setCursor(12, 1);
  lcd.print(tz, 1);
}



void loop() {
  if (m == 1) {
    page1();
  }
  else if (tk >= tu && o == 1)
    digitalWrite(7, HIGH);
  else if (o >= 2) {
    o = 0;
    digitalWrite(7, LOW);
  }

  sensors.requestTemperatures();
  tg = sensors.getTempCByIndex(0);
  tk = sensors.getTempCByIndex(1);
  lcd.setCursor(3, 0);
  lcd.print(tk, 1);
  lcd.setCursor(12, 0);
  lcd.print(tg, 1);





}

Hi,

If you are absolutely sure that the hardware debouncing is working well, try to declare the global, variables used inside the ISRs (m and o) as volatile, to prevent compiler optimizations.

I had never tried to use an LCD with I2C, but I notice that the display present garbage text when the LCD Vdd voltage is to low...

I had read about declaring variables that used in ISR as volatile but i forgot that when writing code. I'll try that as soon as possible and write here the result.
Update:
I tried but same thing happened.

Does sound like a coding problem with your switch inputs and ISR code.

Couple of other things, your 9v power adapter, have you checked its voltage output ?
I used a 9v one the other day, and with the low power of the Uno it was showing 13v which means the Unos regulator gets a bit overworked in continuous use.

Not sure why you would want to use a hardware debounce on a micro, all you need is just a 10k pull up with the switch to ground with a 100nf in parallel with the switch.

Breadboards, very handy things but yes, they can be a real source of weird happenings if the connections are dirty or the wires too thin to make good contact; also avoid using long jumper wires as they can only contribute to picking up interference.

Also used a i2C lcd without problems, have you added extra pull up resistors, not normally needed as the converter typically has them on board.
Again sounds like you code is jumping to the wrong places.

Have not used C++ interrupts, but if I was doing that code I would remove the interrupt references and just Read those switches from the main loop and see if things work normally.

Just checked power adapter and it’s 9.45V, on 5V pin it’s 5.00V and overall current consumption is 26mA on 5V pin.
I used this solution for debounce

I used interrupts because sometimes it misses push button when reading sensors.

Project is powered up and running for 7 hours. Lcd is working fine but interrupts isn’t working. First about 20 times works nice but after that it gone crazy and increment variables randomly without button being pushed. After reset on Uno it increments immediately both variables. I start serial monitor to watch those variables.
First variable is “m” and second is “o”.

Screenshot 1 is when it works fine.
Screenshot 2 is when it goes crazy.
Screenshot 3 is immediately after reset.

I removed all jumper wires from Uno and still increment variables after reset. Also uploaded program just to try debounce and same thing. Maybe my Uno board is not working properly. Here is code.

volatile int m;
volatile int o;
void menu();
void onOff();
void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);

attachInterrupt(digitalPinToInterrupt(2), menu, FALLING);
  attachInterrupt(digitalPinToInterrupt(3), onOff, FALLING);
}
  void menu(){
    m++;
  }
  void onOff(){
    o++;
  }
void loop() {
  // put your main code here, to run repeatedly:
Serial.println(m);
Serial.println("------------");
Serial.println(o);
Serial.println("------------");
delay(500);
}

Interrupt problem makes schmitt trigger IC 74HC14. Interrupt push buttons was relatively close to schmitt and when i put my finger near to schmitt it goes crazy. Moved buttons to one side of breadboard and schmitt to another and works fine.
Stupid question but “how to discharge my self”?

When I was a kid (a thousands years ago) people used to say that before touching any electronic device we should discharge our self by touching any iron piece that allows current to flow to the ground...

Anyway, I don't think that a solution that demands users to discharge themselves before using it is a good solution... Are you sure that you need the schmitt trigger as part of the hardware debouncing? I'm a software man, but even so, I would invest on a software, non blocking debouncing.

Long wires, breadboards and input switches, as you can see they act like an input amplifier.

You do not give any values in your diagram for R1 R2 or C but if R1 is about 5 to 20k and R2 is under 1k and C is 10 to 100nf, then remove the inverter chip and connect them directly to the Unos sockets, using the shortest leads possible, even better if you can solder the switch and components together and plug in as close as possible to the Uno.

Generally for simple testing your software can get away without any debouncing, though, as said, in a completed project its wise to do so.

( think someone or something has convinced you hardware debouncing is necessary, it is if you are inputting to other logic chips, but not normal for modern digital micros. )

Hi,
Welcome to the forum.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Can you please post a picture of your project?

What part number is the inverter IC you used to debounce?

Thanks.. Tom.. :slight_smile:

Hi,
When you used the code in post 5, did you connect your interrupt digital inputs to gnd/
You cannot leave a used digital input open circuit.

Tom... :slight_smile:

My project isn’t done yet. I still have to implement PID control for controlling actuator which opening and closing mixing valve. Because of that i want to free mcu as much as possible and decided to go with hardware debounce and interrupts rather then reading push buttons.
Inverter is SN74HC14N.
I removed inverter but some times misses push button because it bounce.
I attached image of circuit.

Have never tried ISR on the Ardunio so just been trying out your code snippet and get the same results, random number of read when a switch is pushed.

A bit of research and have to say you are right about the Inverter / hardware debouncer is needed , but only for the External Interrupt function, not a normal switch input to a standard digital pin.

What I have read is that the input to the Schmitt Trigger should be just 10k pull up and a 10uf to 0v.

Do not know what your original R1, R2 a C values were ? but you could just try R1 and C 10k and 10uf and see if that works.

Will have to search around for a Schmitt before I can test it out myself.

Found one and it works fine as the pic shows.

Edit - continued to test out the circuit and while basically much better than your original problem, it still seems to give extra interrupts, sometimes incrementing M twice and even O when its button was not pushed.

Tried increasing the value of C, , putting a large cap across the +5v rail to the inverter chip, adding a millis software debounce of 250 , but none really improved things much.

Reading this post by more experienced folk shows that this External ISR circuit is problematic and if you read through it offers some more ideas on how to overcome it.

Also seems this is the way to address just the Uno Ext Int … Int0 and int1 … correct ??

//attachInterrupt(digitalPinToInterrupt(2), menu, RISING );
// attachInterrupt(digitalPinToInterrupt(3), onOff, RISING);
attachInterrupt(0, menu, RISING);
attachInterrupt(1, onOff, RISING);

r1=10k, r2=1k, c1=100nF
On arduino.cc recommended is "attachInterrupt(digitalPinToInterrupt(2), menu, RISING )" but i tried also
attachInterrupt(0, menu, RISING) and works the same.
Thanks for testing. Now i know what to do next.

You have not said what the purpose of those switches are ? - to invoke a menu system /invoke a change of values for your actuator ?

First is for starting MENU where i can set desired temp for starting PID (Tu) and desired temp going to house after mixing valve (Tg) which will be adjusted with actuator via PID control.
Second is just to simulate relay from wireless room thermostat while testing.
edit: Tried polling and it miss button push very often. So interrupt is best solution. For second button polling can be used because room therm. when ON, relay on receiver is closed all the time. When OFF relay is opened.

Well have done several projects where the menu is activated by reading the key from within the main loop.

There might be a slight delay, up to 1 second before it responds, but thats negligible in my book.

Seems Arduino / C++ ISR are not as easy as the Pic micros I also use

Think as you can see from that link I posted there are ways to control the ISR, though it might take some devious coding, like disabling the interrupts once the first is sensed and not turning them back on until the switch has been turned back for a set time... etc.

I was playing with PIC about two years ago. Setup is more complexed than Arduino but it works as intended.

Hi,

Seems that simple inverter does not do the job required, so was thinking that a flip flop might be better but that requires a dp switch.

This circuit is a simple monostable fired from a typical 10k pullup sp switch, and it can use your existing inverter chip.

Have tested it ok on a breadboard using actual switches with your basic test code and it works fine, so should be rock solid when soldered up on short tracks.

With the components shown it gives a calculated pulse of 80ms . T = 0.8 R C ( ohms , farads )

000124.jpg