0

I am trying to execute external button interrupt with Arduino and 16*2 alphanumeric LCD. What I am trying to do is when I press the button then the screen should switch between different options. When I pressed the button once the first option is displayed on LCD, but pressing the button second time the screen is still the same. But the code is entering other else if conditions as I checked with Serial output but it switches fast from press 2 - 8 or so in one press and then when I pressed again it switch to 9 and pressing again switch to 10. What might be the issue? The code -

#include <LiquidCrystal.h>

const int rs = 12, en = 13, d4 = 8, d5 = 9, d6 = 10, d7 = 11;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

#define BUTTON              

unsigned long int timer = 0;
uint8_t buttonState = 0;
uint8_t buttonPressNo = 0;  // stores number of times button is pressed
uint8_t enter_flag = 1;

void setup()
{
    Serial.begin(9600);
    pinMode(BUTTON, INPUT);
    attachInterrupt(digitalPinToInterrupt(BUTTON), button, RISING); // use interrupt 1 (pin 3) and run function
                                      // wakeUpNow when pin 3 gets HIGH
    lcd.begin(16, 2);
    Serial.println(F("Setup done"));
}

void loop()
{
    buttonPressNo += buttonState;
    Serial.print(F("buttonState: "));Serial.println(buttonState);
    Serial.print(F("buttonPressNo: "));Serial.println(buttonPressNo);

    if(buttonPressNo == 1)
    {
        Serial.println(F("F1"));
        if(enter_flag == 1)
        {
            lcd.clear();
            lcd.setCursor(3, 0);
            lcd.print("T=");

            lcd.setCursor(3, 1);
            lcd.print("Calib");
            buttonState = 0;
            Serial.println(F("F1"));
            enter_flag = 0;
        }
        
        if(2-1 == 2)
        {
            Serial.println("1");
        }
        else
        {
            Serial.println("0");
        }
        
        if(millis() - timer >= 10000)
        {
            reset();
        }
            
    }
    
    else if(buttonPressNo == 2)
    {
        Serial.println(F("F2"));
        if(enter_flag == 1)
        {
            lcd.clear();
            lcd.setCursor(3, 0);
            lcd.print("T=");

            lcd.setCursor(3, 1);
            lcd.print("scale");
            buttonState = 0;
            Serial.println(F("F2"));
            enter_flag = 0;
        }

        if(2-1 == 2)
        {
            Serial.println("1");
        }
        else
        {
            Serial.println("0");
        }

        if(millis() - timer >= 10000)
        {
            reset();
        }
    }

    else if(buttonPressNo == 3)
    {
        Serial.println(F("F3"));
        if(enter_flag == 1)
        {
            lcd.clear();
            lcd.setCursor(3, 0);
            lcd.print("T=");

            lcd.setCursor(3, 1);
            lcd.print("memory");
            buttonState = 0;
            Serial.println(F("F3"));
            enter_flag = 0;
        }

        if(2-1 == 2)
        {
            Serial.println("1");
        }
        else
        {
            Serial.println("0");
        }

        if(millis() - timer >= 10000)
        {
            reset();
        }
    }

    else if(buttonPressNo == 4)
    {
        Serial.println(F("F4"));
        if(enter_flag == 1)
        {
            lcd.clear();
            lcd.setCursor(3, 0);
            lcd.print("T=");

            lcd.setCursor(3, 1);
            lcd.print("surface");
            buttonState = 0;
            Serial.println(F("F4"));
            enter_flag = 0;
        }

        if(2-1 == 2)
        {
            Serial.println("1");
        }
        else
        {
            Serial.println("0");
        }

        if(millis() - timer >= 10000)
        {
            reset();
        }
    }

    else if(buttonPressNo == 5)
    {
        Serial.println(F("F5"));
        if(enter_flag == 1)
        {
            lcd.clear();
            lcd.setCursor(3, 0);
            lcd.print("T=");

            lcd.setCursor(3, 1);
            lcd.print("buzzer");
            buttonState = 0;
            Serial.println(F("F5"));
            enter_flag = 0;
        }

        if(2-1 == 2)
        {
            Serial.println("1");
        }
        else
        {
            Serial.println("0");
        }

        if(millis() - timer >= 10000)
        {
            reset();
        }
    }

    else
    {
        //delay(1000);
        buttonState = 0;
        Serial.println(F("no function"));
        if(millis() - timer >= 10000)
        {
            reset();
        }
    }
}

void reset()
{
    buttonState = 0;
    buttonPressNo = 0;
    enter_flag = 1;
    Serial.println(F("reset done"));
    Serial.flush();
}

// debouncing
void button()
{
    buttonState = 0;
    timer = 0;

    while(1)
    {
        timer++;
        if(timer > 100)
        {
            buttonState++;
            timer = millis();
            break;
        }
    }
}

  • do you have a pull-down resistor on the button? what is timer? count or milliis()? – Juraj Jul 7 at 12:26
  • An ISR should never have a blocking while loop in it. An interrupt isn’t really appropriate for something as slow as a button press. You’d do much better to simply read the button in loop and keep the loop code non-blocking. – Delta_G Jul 7 at 12:51
  • You do know that millis doesn’t count during the ISR right? When your code enters the interrupt it turns all other interrupts off. So lots of things stop working in there. That’s why interrupts aren’t a good band aid for blocking code. – Delta_G Jul 7 at 12:52
  • timer is count only. and I have a pull down resistor connected to button. Like I said the interrupt is working for first time and then not working, That my hunch is that the while loop in all if cases might be causing some malfunction – Robot Jul 7 at 15:16
  • So instead of interrupt I should use nested if loop? – Robot Jul 7 at 15:32
1

You defined the button pin as

#define BUTTON

Something is missing.




Just a note about writing code.

Always pay attention to what the code is doing and try not to repeat the same code over and over.

These two code snippets do the same thing.

if(buttonPressNo == 1) {
    if(enter_flag == 1) {
        Serial.println(F("F1"));
        enter_flag = 0;
    }
}

else if(buttonPressNo == 2) {
    if(enter_flag == 1) {
        Serial.println(F("F2"));
        enter_flag = 0;
    }
}

else if(buttonPressNo == 3) {
    if(enter_flag == 1) {
        Serial.println(F("F3"));
        enter_flag = 0;
    }
}

...

if(enter_flag == 1) {          //  this repeated in all of the "if" blocks

    if(buttonPressNo == 1) {
        Serial.println(F("F1"));
    }
    
    else if(buttonPressNo == 2) {
        Serial.println(F("F2"));
    }
   
    else if(buttonPressNo == 3) {
        Serial.println(F("F3"));
    }

    enter_flag = 0;            // this repeated in all of the "if" blocks
}
| improve this answer | |
  • I'm actually surprised that this compiles then. Because with half of the define missing the pinMode call becomes pinMode( ,INPUT) and that should throw a compile error. – Delta_G Jul 8 at 3:07
0

This is not an answer, but it makes your program much smaller/maintenance friendly.

  1. First remove 2-1 == 2 if statements, which are always false (probably this was for testing).
  2. Move all duplicated content within a separate function (using parameters for variable items).
  3. Use a switch statement instead of if/else.
  4. Use consequent names for variables (changed enter_flag to enterFlag);

Code:

void loop()
{
    buttonPressNo += buttonState;
    Serial.print(F("buttonState: "));Serial.println(buttonState);
    Serial.print(F("buttonPressNo: "));Serial.println(buttonPressNo);

    switch (buttonPressNo)
    {
    case 1:
        processMenu(F("F1"), F("Calib"));
        break;

    case 2:
        processMenu(F("F2", F("Scale"));
        break;

    case 3:
        processMenu(F("F3", F("Memory"));
        break;

    case 4:
        processMenu(F("F4"), F("Surface"));
        break;

    case 5:
        processMenu(F("F5"), F("Buzzer"));
        break;
   
    default:
    {
        //delay(1000);
        buttonState = 0;
        Serial.println(F("no function"));
        if(millis() - timer >= 10000)  // 2 mins timeout
        {
            reset();
        }
    }
 }


 void processMenu(char* button, char* title)
 {
    Serial.println(button);
    if(enterFlag == 1)
    {
        lcd.clear();
        lcd.setCursor(3, 0);
        lcd.print("T=");

        lcd.setCursor(3, 1);
        lcd.print(title);
        buttonState = 0;
        Serial.println(button);
        enterFlag = 0;
    }

    if(millis() - timer >= 10000)  // 2 mins timeout
    {
        reset();
    }
 }
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.