IoT impulse counter on ESP8266

As I wrote before in my post about the change counter, I own an electricity meter which is sending 800 impulses per kWh of the power usage. I used to connect it to the Arduino board, when this got broken, I used Onion Omega2+ to handle it. Unfortunately, this Omega board was not working reliably. I noticed crashes, freezes of my simple script so I decided to switch to the well-known ESP8266 board.

For those of you who don’t know ESP8266 yet – it used to be used as an Android extension to get access to the WiFi network. And this is what it is designed for – to provide WiFi connectivity for various electronic devices. But in fact, ESP8266 itself has a really powerful processor onboard and a lot of spare memory, so why not to use it as a standalone solution?

Nowadays ESP8266 is sold soler on the convenient boards such as NodeMCU – this makes my life even simpler – there is no programming hardware required, the board comes with the USB based power connector, handy 3.3V converter, set of gold pins to put it into the breadboard, GPIO, PWM, I2C, 1-Wire and ADC in one board. You can even program it using Lua scripts, but I prefer to use old good Arduino IDE.

Checking changes on the GPIO port

On this board reacting to the GPIO changes is very easy. There are interrupts in place – you can ask your board to execute the particular function once the state of the GPIO pin changes. There are various interrupts: on Change, Rising, Falling signal. As you may expect, on change is fired whenever GPIO state changes from low to high or from high to low. Rising is called when state changes from low to high, falling to the contrary – when the state is changing from high to low.

The piece of script which is taking care of interrupt looks like this:

[...]
const byte interruptPin = 5; // Pin to set interrupt to
int interruptCounter = 0; // counter of interrupt executions
[...]
void setup() {
[...]
// set interrupt handler
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
[...]
}
[...]
// this one is handling GPIO interrupts
void handleInterrupt() {
interruptCounter++;
}
[...]

As you can see, pin mode is set to input with the pull-up (the state is pulled up if no signal is given) because my meter sends low state on each impulse. The interrupt handler is minimalistic and increments the interrupt counter variable.

Interrupt debounce

I noticed that the signal sent by my meter is not clean enough. On each impulse, my interrupt handler was called twice, three times, sometimes even four times. This is because the shape of the signal sent from my meter is not ideal. Once it crosses the border between the low and the high state and vice versa, the GPIO pin is unstable and sends multiple interrupts. To get rid of these, I had to debounce this signal. I added “last interrupt time” variable, and if the last interrupt was called in less than 100 milliseconds, I skip the counter incrementation. It is not likely to get more than 10 impulses from my meter per second so this value seemed to be good (and the experience shows that it is good). My adjusted interrupt handler looks like this:

[...]
// this one is handling GPIO interrupts
void handleInterrupt() {
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();

// If interrupts come faster than 100ms, assume it's a bounce and ignore
if (interrupt_time - last_interrupt_time > 100)
{
interruptCounter++;
}
last_interrupt_time = interrupt_time;
}
[...]

Now our impulses are counted properly and we can take care of storing them on the remote server for further use. In order to do this, we will need to connect to the WiFi network and send the HTML request to the server.

The whole script in one piece and the connection and communication details are outlined in the client-server communication post