ESP8266 Timers

Work today but I got up early and decided to take a break from solving the WS2812b issue – I’m getting a wide pulse at the beginning of every package caused by compiler optimisation and I cannot at this point figure a way around it (apart from using an Arduino to handle the serial LEDs which is cheating a bit). I figured I’d take a look at more leisurely timing.

Here’s an example use of a timer.

So you want to send a signal to the ESP8266 and you want to read the temperature.  Two things here.. the temperature reading is not instant – so every time you want a reading you have to call the temperature sensing routine.. wait for it – and then return the result. That is time wasted. How often does temperature change? Well, seriously I cannot imagine one wanting in a typical domestic or external environment,  to take readings more than, say every minute.. or even 5 minutes but here we are polling away and wasting time.

A better way then is to check the temperature every now and then – store the result.. and your polling operation merely reads the values.

But how do you set timers going in ESP8266.  I’m not going to pretend to be an expert – I simply took code from another example and put it into my project – and it works.

So – reading the temperature every 30 seconds

You’ll need temperature sensing software.

Up at the top of your program where your init stuff is..

#define LED_GPIO 2
#define LED_GPIO_MUX PERIPHS_IO_MUX_GPIO2_U
#define LED_GPIO_FUNC FUNC_GPIO2

float temperature,humidity;

#define DELAY 30000 /* milliseconds for temperature */

in the init() routine set up GPIO2

PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO2_U);

#define LED_GPIO 2
#define LED_GPIO_MUX PERIPHS_IO_MUX_GPIO2_U
#define LED_GPIO_FUNC FUNC_GPIO2

float temperature,humidity;

#define DELAY 30000 /* milliseconds for temperature */

in the init() routine set up GPIO2

PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO2_U);

and here’s a routine to read temperature and humidity and store them in variables of that name. I didn’t write this..

#define MAXTIMINGS 10000
#define BREAKTIME 20
static void ICACHE_FLASH_ATTR readDHT()
{
    int counter = 0;
    int laststate = 1;
    int i = 0;
    int j = 0;
    int checksum = 0;
    //int bitidx = 0;
    //int bits[250];

    int data[100];

    data[0] = data[1] = data[2] = data[3] = data[4] = 0;

    GPIO_OUTPUT_SET(2, 1);
    os_delay_us(250000);
    GPIO_OUTPUT_SET(2, 0);
    os_delay_us(20000);
    GPIO_OUTPUT_SET(2, 1);
    os_delay_us(40);
    GPIO_DIS_OUTPUT(2);
    PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO2_U);

    // wait for pin to drop?
    while (GPIO_INPUT_GET(2) == 1 && i<100000) {
          os_delay_us(1);
          i++;
    }

        if(i==100000)
          return;

    // read data!

    for (i = 0; i < MAXTIMINGS; i++) {
        counter = 0;
        while ( GPIO_INPUT_GET(2) == laststate) {
            counter++;
                        os_delay_us(1);
            if (counter == 1000)
                break;
        }
        laststate = GPIO_INPUT_GET(2);
        if (counter == 1000) break;

        //bits[bitidx++] = counter;

        if ((i>3) && (i%2 == 0)) {
            // shove each bit into the storage bytes
            data[j/8] <<= 1;
            if (counter > BREAKTIME)
                data[j/8] |= 1;
            j++;
        }
    }

/*
    for (i=3; i<bitidx; i+=2) {
        os_printf("bit %d: %d\n", i-3, bits[i]);
        os_printf("bit %d: %d (%d)\n", i-2, bits[i+1], bits[i+1] > BREAKTIME);
    }
    os_printf("Data (%d): 0x%x 0x%x 0x%x 0x%x 0x%x\n", j, data[0], data[1], data[2], data[3], data[4]);
*/
    float temp_p, hum_p;
    if (j >= 39) {
        checksum = (data[0] + data[1] + data[2] + data[3]) & 0xFF;
        if (data[4] == checksum) {
            /* yay! checksum is valid */

            hum_p = data[0] * 256 + data[1];
            hum_p /= 10;

            temp_p = (data[2] & 0x7F)* 256 + data[3];
            temp_p /= 10.0;
            if (data[2] & 0x80)
                temp_p *= -1;
            temperature=temp_p; humidity=hum_p;
        }
    }
}

So now you have a routine you can call and it will return the temperature – oh- you’ll need a DHT22 (NOT the DHT11) attached to ground, GPIO2 and 3v3. And put a capacitor, maybe 10uf across the power right next to the DHT-22. Occasionally especially with longer leads or poor power regulation I find they simply won’t respond without this.

How to get that routine ( readDHT() ) to call every 30 seconds – so that you can simply read the 2 variables temperature and humidity – at your own leisure…

Doddle.

Put this at the top of your program

LOCAL os_timer_t temperature_timer;

Put this in your init…

os_timer_disarm(&temperature_timer);
os_timer_setfn(&temperature_timer, (os_timer_func_t *)temperature_cb, (void *)0);
os_timer_arm(&temperature_timer, DELAY, 1);

and put your temperature reading in this routine..

LOCAL void ICACHE_FLASH_ATTR temperature_cb(void *arg)
{
    readDHT();
}

and that… is that – every 30 seconds it will go take a temperature reading. If you need the temperature straight after power up you might want to do a one-off call to readDHT() in the init() routine  as it’s not going to get a value for 30 seconds. And where did all of that come from? Merely by studying the BLINKY example in the Eclipse environment for Windows.

So now I have a little ESP01 which can respond to MQTT, which can turn a light or solid state relay on and off, which can read the temperature and which can ALMOST set up a line of WS2812B chips – – I just need someone further down the learning curve than I to help me solve the compiler optimisation issues with WS2812B writing.

You can see where this is going can’t you.. yup – next stop – real time clock timer -  a 1 second RTC which could be updated by an MQTT message.

Now there IS an RTC inside the ESP8266 chips – and one of the boards supports it – the new white ESP8266 board has a clock crystal – however as that needs ESPRESSIF to tell us how it works and as that ALSO needs pins which we don’t have on some of the boards including the popular ESP-01 – we’ll ignore that for now and do our own thing.

The question is – how accurate would such a real time clock be – it’s going to get updated by messages every now and then but still it would be good if it could last a couple of days or so without being updated.

Here we go…

More setup

LOCAL os_timer_t rtc_timer;
unsigned long myrtc=0;

More init

os_timer_disarm(&rtc_timer);
os_timer_setfn(&rtc_timer, (os_timer_func_t *)rtc_cb, (void *)0);
os_timer_arm(&rtc_timer, 1000, 1);

more function…

LOCAL void ICACHE_FLASH_ATTR rtc_cb(void *arg)
{
    ++myrtc;
}
Advertisements

3 thoughts on “ESP8266 Timers

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s