Friday, September 4, 2020

Arduino and ESP8266 interrupts

For an index to all my stories click this text

Using interrupts can be very handy when designing a project and yet up until now I have almost never used them in Arduino language. My vibration alarm used an interrupt to send an alarm message. That program was written in ESP-Basic, and not in Arduino C++ code.

As I am moving more and more towards to the Arduino IDE (to keep my programs compatible with the ESP32) I wanted to use the interrupts in my new programs. However that turned out to be a bit more complicated as I thought.

Interrupt

An interrupt on the ESP8266, ESP32 or Arduino (any version) is about the same as an interrupt in real life. You put the ketlle on, start reading a book and then the kettle whistles. That is an interrupt. Getting the kettle from the stove is called an interrupt service routine (ISR).

The complication emerges when you are busy getting the kettle from the stove when the cat starts to meow telling she wants to go out. Now what to do. Opening the door leaves the kettle whistling which is annoying. Ignoring the cat is an option. It depends on where you put your priorities.

The solution is to keep the interrupt service routine as short as possible so you will not get into problems when a second interrupt occurs. Meaning you'll take the ketle from the stove as quick as possible.

Or.... You could also ignore the cat till your done with the kettle. That is exactly what I am going to do in my programs.

Test setup



As a demo setup I'll use the Wemos D1 mini with a simple push button attachted to GPIO pin 4 (D2). Do not forget the pull-up resistor to make sure D3 is always HIGH until you push the button.

The test program



int Button = 4; // D2
int intproc = 0;

void setup() 
{
  Serial.begin(9600);
  delay(50);
  Serial.println("started");
  pinMode(Button, INPUT);
  attachInterrupt(digitalPinToInterrupt(Button), ButtonPressed, FALLING);
}
void loop() 
{
  if (intproc == 1)
  {
    Serial.println("The button is Pressed");
    delay (5000);
    intproc = 0;
    attachInterrupt(digitalPinToInterrupt(Button), ButtonPressed, FALLING);
  }
}

void ButtonPressed() 
{
  detachInterrupt(Button);
  intproc = 1;
}


Let us see how this works.

The program starts with attaching the button to IO port 4 which is D2 on the Wemos D1 Mini board. Then a variable intproc is declared and set at value 0.

In the setup first the Serial port is initialised and the word "started" is print on the Serial Monitor. The pin where the button is attached to is declared as an input which is obvious. And then the interrupt is started.

attachInterrupt(digitalPinToInterrupt(Button), ButtonPressed, FALLING);

This line attaches the interrupt to the Button pin. When an interrupt is detected the program jumps to the routine ButtonPressed. And lastly the interrupt is only activated when the pin goes from VCC to GND which is called FALLING.

So what happens when the button is pressed.
The program jumps to the ButtonPressde routine.

detachInterrupt(Button);

This command makes sure that the interrupt is disconnected from the Button IO pin. So when another interrupt occurs nothing will happen, as the interrupt is disabled. The variable intproc is set to 1.

The program now continues with the loop as if nothing has happened. In the loop intproc is tested. If the value is 1 that means that an interrupt has occured. The Serial Monitor notifies us by printing: The button is pressed. Then there is a delay of 5 seconds an after that intproc is set to 0 again and the interrupt is reactivated.

If an interrupt is detected then that interrupt is immediately disabled. So if another interrupt occurs (AKA you press the button again) nothing happens. The program does what it needs to do (wait 5 seconds) and then re-activates the interrupt.
If you press the button and keep it pressed the interrupt will be fired only once as it is only activated on a FALLING signal (from VCC to GND). If you press the button too soon after eachother, being within the 5 seconds delay, nothing will happen either.

There must be a delay for debouncing the button press. However 5 seconds is far too much. One second would be enough for normal purposes. After the delay let your program do whatever it needs to do and when finished you can attach the interrupt again.

I hope this makes things clear. At least it did for me.

Now let's use this in some neat projects.
That is for another story so........

Till next time
have fun

Luc Volders