Capture realtime user inputs

Hello All,
I have written program which takes user input for turning on/off water pump.
Here is program,

int localPumpSwitchValue = 0;

void setup()
{
  Serial.begin(115200);

  delay(1000);

  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
}

void loop()
{ 
  ReconnectWiFiRefreshFirebaseToken();

  ReadLocalSwitchValueAndSaveToFirebase();

  LoadFirebaseToLocalSwitchValue();
  
  SendCommandsToNodes();

  if ( (millis() - fireBaseObj.m_sendDataPrevMillis) > userSettings.m_intervalToUploadSensorDataToFirebase || fireBaseObj.m_sendDataPrevMillis == 0))
  {
    fireBaseObj.m_sendDataPrevMillis = millis();
    fireBaseObj.SaveSensorDataToFireBase(sensorData);
  }
}

void ReadLocalSwitchValueAndSaveToFirebase()
{
  if (digitalRead(4) == LOW)
  {
    localPumpSwitchValue = 1;
  }

  if (digitalRead(5) == LOW)
  {
    localPumpSwitchValue = 0;
  } 
}

My problem is when user press button to turn on/of pump, then at that time code is executing some other functions like saving datat to firebase or receiving data from LoRa, so user input get lost, work around i use is, i keep button pressed until input is read by programm.
So how to make user input real time?

Your picture shows an ESP8266. Is that what you have?
If so, use a RTOS task to sample the pins at 30 millisecond intervals and feed the resulting data into a debounce algorithm.

If you are using a non-RTOS system then use a timer interrupt to do the same thing.

Alternatively use an external SR flip flop chip to latch the button states.

Many thanks.
I am new to these concepts, could you please explain more with sample code.
Or just share material link to study it.

attach an interrupt to your button inputs so when a button is pressed an interrupt routine is called and takes appropriate action, e.g. handling-esp8266-gpio-interrupts-tutorial

1 Like
  • your code is not complete
  • what type of switch do you have ? is it bouncing ?
  • the code you show does not do anything with localPumpSwitchValue

side note:

you use 4 and 5 for the pins

and you are connected to D1 and D2

image

On a typical ESP8266 that would be OK


but it's usually better to use D1 and D2 in the pin related functions to ensure you don't have a mismatch there

1 Like

SendCommandsToNodes();method use localPumpSwitchValue variable to send its value to lora node.
Yes switches are bouncing

@horace Thanks, any limit to declare interrupt, or we can declare more than 1 interupts

you can have more than one GPIO interrupt enabled
the ESP8266 Pinout Reference: Which GPIO pins should you use? states
The ESP8266 supports interrupts in any GPIO, except GPIO16.

e.g.

volatile int isr5Change=-1;
void IRAM_ATTR isr5() {
  isr5Change=digitalRead(5);
}
volatile int isr4Change=-1;
void IRAM_ATTR isr4() {
  isr4Change=digitalRead(4);
}
volatile int isr14Change=-1;
void IRAM_ATTR isr14() {
  isr14Change=digitalRead(14);
}

void setup() {
  Serial.begin(115200);
  delay(3000);
  Serial.printf("\n\nESP8266 GPIO interrupt test");
  pinMode(5, INPUT_PULLUP);
  attachInterrupt(5, isr5, CHANGE);  
  pinMode(4, INPUT_PULLUP);
  attachInterrupt(4, isr4, CHANGE);
 pinMode(14, INPUT_PULLUP);
  attachInterrupt(14, isr14, CHANGE);

}

void loop() {
  if(isr5Change>=0) {
    Serial.printf("GPIO5 change %d\n", isr5Change);
    isr5Change=-1;
  }
  if(isr4Change>=0) {
    Serial.printf("GPIO4 change %d\n", isr4Change);
    isr4Change=-1;
  }
  if(isr14Change>=0) {
    Serial.printf("GPIO14 change %d\n", isr14Change);
    isr14Change=-1;
  }

}

serial monitor displays

ESP8266 GPIO interrupt testGPIO5 change 0
GPIO5 change 1
GPIO5 change 1
GPIO5 change 0
GPIO5 change 0
GPIO5 change 1
GPIO4 change 0
GPIO4 change 1
GPIO4 change 0
GPIO4 change 1
GPIO4 change 0
GPIO4 change 0
GPIO4 change 1
GPIO14 change 0
GPIO14 change 1
GPIO14 change 0
GPIO14 change 0
GPIO14 change 0
GPIO14 change 1

I was plugging/unpluging a jumper wire between the GPIO pins and GND
clearly getting the effect of switch bounce

1 Like

Thanks, so this is enough and no need to go for free RTOS right? or free RTOS worth studying and implementing?

don't think you require aan RTOS for such a simple control system

updated GPIO interrupt test removing switch bounce

// ESP8266 GPIO interrupts - switch bounce removed

// GPIO is pulled up
//  - on grounding pin 0 is displayed on pin high 1 is displayed

// on GPIO interrupt setup timer to remove switch bounce
volatile unsigned long isr5Change = 0;
void IRAM_ATTR isr5() {
  static unsigned long timer=0;
  if(millis()-timer<10) return;  // ingore interrupts for a time
  isr5Change= timer = millis();   // note interrupt time
}

// on GPIO interrupt setup timer to remove switch bounce
volatile unsigned long isr4Change = 0;
void IRAM_ATTR isr4() {
  static unsigned long timer=0;
  if(millis()-timer<10) return;  // ingore interrupts for a time
  isr4Change= timer = millis();   // note interrupt time
}


void setup() {
  Serial.begin(115200);
  delay(3000);
  Serial.printf("\n\nESP8266 GPIO interrupt test\n");
  // set GPIO pullup and enable interrupts
  pinMode(5, INPUT_PULLUP);
  attachInterrupt(5, isr5, CHANGE);
  pinMode(4, INPUT_PULLUP);
  attachInterrupt(4, isr4, CHANGE);
}

void loop() {
  // on interrupt wait a few mSec for level to stablise then display level
  if(isr5Change && millis()-isr5Change > 2) {
    Serial.printf("GPIO5 change %d\n", digitalRead(5));
    isr5Change = 0; // clear the timer
  }
   // on interrupt wait a few mSec for level to stablise
  if(isr4Change && millis()-isr4Change > 2) {
    Serial.printf("GPIO4 change %d\n", digitalRead(4));
    isr4Change = 0; // clear the timer
  }
}

as I press a switch to ground the GPIO and then release it the serial monitor displays

ESP8266 GPIO interrupt test
GPIO5 change 0
GPIO5 change 1
GPIO5 change 0
GPIO5 change 1
GPIO5 change 0
GPIO5 change 1
GPIO5 change 0
GPIO5 change 1
GPIO4 change 0
GPIO4 change 1
GPIO4 change 0
GPIO4 change 1
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.