Monthly Archives: March 2015

ESP8266 WS2812B LEDs on a Plate

LEDSWell, now that I’ve cracked using the WS2812B LEDs – I guess I’d better share the results – especially as it was the work of others that started me off on this road!

I went down a LOT of dead routes with this – firstly I was going to have it programmable how many outputs I would dedicate to the WS2812B LEDs – then ultimately I realised, because we’re talking about a memory buffer feeding the LEDS I might as well just do one long run and split it up as I need!! That also got around some timing issues.  If you look at previous items on this- one fellow wrote a driver for the LEDs and it kind of worked – then if you looked at his ISSUES others said it had problems and another guy wrote an improved version and fretted about needing a capacitor on the output to stop one of the LEDs (the first one) flashing. You don’t need any of that – it’s ALL down to timing.

So – why read further than this line – because I’ve had 300 LEDs on a 5m strip working PERFECTLY and the only reason I’ve not tried 600 LEDs is I don’t have a power supply powerful enough to run 600 of the things!!!  And how quick is the update? Well, to turn all from off to on, you can’t SEE the update.

So…. I#m assuming you’re happy programming in C and know a little about the ESP8266. In my case I’m using the Eclipse environment on a Windows 8.1 PC and having a ball (as against my first steps in a Linux virtual environment which was enough to make a grown man eat his own bairns). Follow me and let’s get started.  I’m using GPIO12 on the ESP-12 – I’ve also used GPIO4, GPIO5 and there’s no reason that I can think of why you can’t use GPIO0 on an ESP-01.

To start the ball rolling you need some place to store info – I find structs handy for that so create this.

typedef struct{
    uint8_t reda;
    uint8_t greena;
    uint8_t bluea;

    uint8_t red;
    uint8_t green;
    uint8_t blue;

    uint32_t rainbow;
    uint16_t rgbnum;
    uint16_t rgbdelay;
    uint8_t  buffer[900];
} LEDS;

LEDS rgb;

 

LEDS[6]That 900 byte buffer.. depending on what you’re doing you may not need more than 3 bytes so by all means change it. A single LED uses 3 bytes – for RED, GREEN and BLUE.  If you want all the LEDS the same colour at any time you can just repeat using the same 3 bytes – but if you want them all different colours then you need 3 bytes per LED. Given that if you’re using C as against Lua (I’m only talking C here, I gave up on Lua) then you probably have bags of RAM, this will hardly make a dent (and we put up with Arduinos for years for WHAT reason?).

So, and you might want to do everything differently to me – but this is what I’ve done… I like to FADE LEDs over time as against turning them on and off so I need the ACTUAL colour of the LED against what I WANT it to be – hence REDA and RED in the above struct.

For GPIO12 I defined this lot..

#define LED_GPIO_12 12
#define LED_GPIO_MUX_12 PERIPHS_IO_MUX_MTDI_U
#define LED_GPIO_FUNC_12 FUNC_GPIO12
#define OUT_ON 1
#define OUT_OFF 0

and in my INIT routine I have this..

PIN_FUNC_SELECT(LED_GPIO_MUX_12, LED_GPIO_FUNC_12);

and that’s it basically – if you want to turn the output on:

GPIO_OUTPUT_SET(LED_GPIO_5, OUT_ON);

or off

GPIO_OUTPUT_SET(LED_GPIO_5, OUT_OFF);

or at least historically that’s how I did it – but you’ll need the initialisation anyway.

You need a callback function to do your timing for you – I have one which debounces keys and handles the RGB delays… so in your INIT you need this.

 

os_timer_disarm(&bounce_timer);
os_timer_setfn(&bounce_timer, (os_timer_func_t *) bounce_cb, (void *) 0);
os_timer_arm(&bounce_timer, 50, 1);

 

Well, you don’t have to call it bounce_timer of course.

So – I have a callback (ie a function that gets called by the system every 50ms (see last line).

Here’s what it looks like – I’ll give you a filled in one later.

LOCAL void ICACHE_FLASH_ATTR bounce_cb(void *arg) {

}

Hey, make loads of these with different times and names – they’re really useful. All that ICACHE stuff – if you don’t put that in, you’ll start eating into RAM – so just include that in your functions.

Ok, here’s the real version..

LOCAL void ICACHE_FLASH_ATTR bounce_cb(void *arg) {

if ((rgb.red != rgb.reda) || (rgb.green != rgb.greena) || (rgb.blue != rgb.bluea)) {
    if (rgb.reda < rgb.red)
        rgb.reda += ((rgb.red - rgb.reda) / (rgb.rgbdelay * 20)) + 1;
    if (rgb.greena < rgb.green)
        rgb.greena += ((rgb.green - rgb.greena) / (rgb.rgbdelay * 20)) + 1;
    if (rgb.bluea < rgb.blue)
        rgb.bluea += ((rgb.blue - rgb.bluea) / (rgb.rgbdelay * 20)) + 1;
    if (rgb.reda > rgb.red)
        rgb.reda -= ((rgb.reda - rgb.red) / (rgb.rgbdelay * 20)) + 1;
    if (rgb.greena > rgb.green)
        rgb.greena -= ((rgb.greena - rgb.green) / (rgb.rgbdelay * 20)) + 1;
    if (rgb.bluea > rgb.blue)
        rgb.bluea -= ((rgb.bluea - rgb.blue) / (rgb.rgbdelay * 20)) + 1;

    if (rgb.rgbnum == 0) { rgb.rgbnum = 1; rgb.reda=rgb.red; rgb.greena=rgb.green; rgb.bluea=rgb.blue; } // instant
    rgb.buffer[0] = ledTable[rgb.reda];
    rgb.buffer[1] = ledTable[rgb.greena];
    rgb.buffer[2] = ledTable[rgb.bluea];

    WS2812OutBuffer(rgb.buffer, 3, rgb.rgbnum); // 3 leds in array, number of repetitions
  }

}

What on EARTH is all that about – well the first line reads – IF the expected colour is in any way from the ACTUAL colour…. DO this lot.

So there’s a little maths depending on rgb.rgbdelay that sets what you want rgb.red, rgb.green and rgb.blue to be. and when that’s done – you fill in the first 3 bytes of the buffer – not with the actual value of the LED but with that put through a lookup table – why? Because the sensitivity of your eyes is not linear. If you don’t use the lookup table, the fade will appear pretty good up to 20% brilliance then will seem to slow down.

Here’s the table – put it anywhere in the same file.

static const uint8_t ledTable[256] = {
        0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3,
        3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8,
        9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16,
        16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26,
        26, 27, 28, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 39,
        40, 40, 41, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
        56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 72, 73, 75,
        76, 77, 78, 80, 81, 82, 83, 85, 86, 87, 89, 90, 91, 93, 94, 95, 97, 98,
        99, 101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 119,
        121, 122, 124, 125, 127, 129, 130, 132, 134, 135, 137, 139, 141, 142,
        144, 146, 148, 150, 151, 153, 155, 157, 159, 161, 163, 165, 166, 168,
        170, 172, 174, 176, 178, 180, 182, 184, 186, 189, 191, 193, 195, 197,
        199, 201, 204, 206, 208, 210, 212, 215, 217, 219, 221, 224, 226, 228,
        231, 233, 235, 238, 240, 243, 245, 248, 250, 253, 255 };

 

SO – every 50ms, you call a routine pointing to the buffer, 3 bytes (which is how much of the buffer you want to use without starting again and the number of LEDS you want to light up.  So in my case – and you can do things differently once you get this running and do your own thing – I only put the same value (the first 3 locations in the table) into all the LEDS I want to light.   If you use 30 instead of 3 for 10 LEDs, basically whatever you put into those 30 locations (3 per LED) will be what you see. So I’m just repeating the use of the 3 bytes for all the LEDs I’m lighting up – this has been tested from one LED to 300 LEDs.

So all you need now (and this is the one we’ve been waiting for) is the routine to actually drive the LEDs.

I’ll just say that you need some things to be FAST – so don’t say “why did you use that macro to drive the LEDs – another one is more understandable – because then I’d have trouble lighting the LEDs like others.

You need this at the start of your file.. and it MUST be a static.

static uint32_t rainb12;

and in you’re init do this.

rainb12=1<<12;

I know – why do a calculation at compile time – because it makes it easier for you to understand – it’s port 12 !!  Why not a define? Because you might want to use more than one pin! I’m not getting into that one but this is the right starting point. Here’s the routine. Not original – just fixed from the versions that don’t work.

void ICACHE_FLASH_ATTR SEND_WS_12_0() {
    uint8_t time;
    time = 4;
    while (time--)
        WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 4, rainb12);
    time = 9;
    while (time--)
        WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, rainb12);
}

void ICACHE_FLASH_ATTR SEND_WS_12_1() {
    uint8_t time;
    time = 8;
    while (time--)
        WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 4, rainb12);
    time = 6;
    while (time--)
        WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, rainb12);
}

void ICACHE_FLASH_ATTR WS2812OutBuffer(uint8_t * buffer, uint16_t length, uint16_t repetition) {
    uint16_t i;
    os_intr_lock();

        WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, rainb12);
        WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, rainb12);
        WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, rainb12);
        while (repetition--) {
            for (i = 0; i < length; i++) {
                uint8_t mask = 0x80;
                uint8_t byte = buffer[i];
                while (mask) {
                    (byte & mask) ? SEND_WS_12_1() : SEND_WS_12_0();
                    mask >>= 1;
                }
            }
        }

    os_intr_unlock();
}

Ok, so 2 routines for setting the output – the first one turns the output OFF then on (more off than on) – the second one does the same – but more on than off… and it is that kind of timing that, fired into the WS2812B that makes them work.

The third routine sends a reset pulse to the chips then loops through – if you study the loop you’ll see what I meant about repeating the same buffer section over and over again if you don’t actually want separate colours per LED.

Now to make sense of this – you need to know how these chips work. So let’s say you have a strip of 10 of them. You have on the input power, signal in and ground. You CAN run these on 3v3 – but good luck getting a high power 3v3 supply and they are brighter on 5v anyway. If you buy the LEDs and make your own strip – be REALLY careful as they die even looking at a large soldering iron. Each LED has an input and an output and you string them together in series.

As you can imagine – flashing them when you have to send a signal from one to the next takes time – that’s why they are FAST and why the code is critical.

So basically a wide pulse resets ALL the LEDs so they are listening for info. You send an RGB value to the first input – it sucks it in and lights itself up – from that point on it merely buffers and passes on the message – so when you fire the next 3 bytes worth – the SECOND LED lights up and from there on passes everything on – rather than replicate the wheel…

Notice I’ve written that reset pulse 3 times – in the original code, there was a flickering I could not explain on the first LED (I’m running ground and signal into one end of the LED strip, +5v and ground into the other end. I extended that reset pulse a little and completely eliminated the issue.

 

timing

So as you can see – the timings are simple but critical – 0, 1 and reset… then send out bunches of 3 bytes per LED. That’s it.

In my code I might send an instruction like – I want purple full brilliance, repeated across 10 LEDs – and take 10 seconds to do it…

rgb.red=255;

rgb.green=0;

rgb.blue=255;

rgbnum=10;

rgbdelay=10;

That’s it – it happens in the background;

Enjoy and if this works for you – be sure to let others know the link!

Around the corner – code that does this, responds to both serial and MQTT commands and allows extending the controls to external Arduinos, handles both types of temperature sensor, a debounced input used to count electricity meter pulses OR to manually over-ride an output, central heating control and much more – all working and all at the same time…. more on this later. We’re even getting a board made that handles the lot and includes a mains power supply.

Facebooktwittergoogle_pluspinterestlinkedin

WS2812b Success on the ESP-12

This one has been long in the making.  I’ve had a fair bit of success with the little ESP-12 and it is now my favourite despite the 2mm centres.

WS2812BWhy, because it HAS everything – lots of port bits, A/D convertor etc. why on EARTH we all went off and used the little ESP-01 I can no longer understand especially as the ESP-12 is the same price!

Ok, so getting ports on and off was no big deal and even reading them was simple – but getting the timings right for the WE2812b LEDs has been a pain.

I eventually found a blog (all of this is referred to in the comments section of a blog a couple of days ago in here) which detailed how to use the WS2812b. Then I found a guy saying it was no good – and offering his slight modification – and I tested it and.. lo and behold – on GPIO0 it works.           

But could I HELL get it to work on other ports – as I was stumbling around in the dark as to how to use the PORTS – the problem is timings – the WS2812b need VERY short pulses and they are not very forgiving if you don’t get the timings right. There are LOADS of ways to turn ports on and off on the ESP8266 but they all take differing times and if the port operation is part of your (very tight) timing – then any change will stop this from working.

Here is the original code that worked – on GPIO2 -  this is just the bit for individual pulses and is commented out

//void ICACHE_FLASH_ATTR SEND_WS_0()
//{
//    uint8_t time;
//    time = 4; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
//    time = 9; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0 );
//}

//void ICACHE_FLASH_ATTR SEND_WS_1()
//{
//    uint8_t time;
//    time = 8; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
//    time = 6; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0 );
//}

So you see, that statement WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 ); is an integral part of the loop timing. Can’t go messing with it… but here’s the thing – this UTTERLY MEANINGLESS gook is actually incredibly simple…

Taking the first one it is this..

(*((volatile uint32_t *)(0x60000300 + (0+(0))))) = (uint32_t)(1)

and narrowing that down it is simply..

*(0x60000300)=1

Ok, so this made NO sense to me AT ALL…. until I hit THIS link thanks to one of you kind people.

https://github.com/esp8266/esp8266-wiki/wiki/gpio-registers

STUDY THIS… IT WILL REMOVE ALL HEADACHES.

It turns out that there are two magical locations on the chip – which I’m now using to turn things on and off. They are 0x6000304 to turn things on and 0x6000308 to turn things off – go ahead and define pretty names for them. This is weird. If you fire a 32 bit number at these locations – the first one will turn on any port who’ bit is HIGH while ignoring the rest. The second address does the same to turn them back off.

So if you consider binary 1 to be GPIO0, 2 to be GPIO1 etc etc this makes sense.

These two lines will turn the port 12 (GPIO12) on then off VERY, VERY quickly.

WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + 4, 0x1000 );
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + 8, 0x1000 );

EH? 0x1000 in binary is 1000000000000

Port 0 would be 000000000001 or just 0.

Weird, yes, FAST, certainly. Now you might say well that’s all good for one port but what happens if I want to use another port – well as long as you don’t want to handle them at the same time, it turns out you can use a STATIC variable and it appears to work just as well!!!

So – enough bull – here’s some code. I do not claim ownership – little bits are mine, little bits are from other people etc… well done to all I would say.

 

Somewhere up at the top – some global vars

uint16_t reda;
uint16_t greena;
uint16_t bluea;

uint16_t red;
uint16_t green;
uint16_t blue;

uint16_t rgbnum;
uint16_t rgbdelay;

 

static uint32_t theport;

Now the bits that do the work…

void ICACHE_FLASH_ATTR SEND_WS_0()
{
    uint8_t time;
    time = 4; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + 4, theport );
    time = 9; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + 8, theport );
}

void ICACHE_FLASH_ATTR SEND_WS_1()
{
    uint8_t time;
    time = 8; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + 4, theport );
    time = 6; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + 8, theport );
}

void ICACHE_FLASH_ATTR WS2812OutBuffer( uint8_t * buffer, uint16_t length, uint16_t repetition )
{
    uint16_t i;
    os_intr_lock();
    //GPIO_OUTPUT_SET(GPIO_ID_PIN(WSGPIO), 0);
    WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + 8, theport );

while (repetition--)
    {
    for( i = 0; i < length; i++ )
    {
        uint8_t mask = 0x80;
        uint8_t byte = buffer[i];
        while (mask)
        {
            ( byte & mask ) ? SEND_WS_1() : SEND_WS_0();
            mask >>= 1;
            }
    }
    }
    os_intr_unlock();
}

Now why do I have REDA and RED -  well I don’t want these lights instantly changing colour – that’s boring – I want it to happen in the background – so – make yourself a 50ms timer callback and dump this inside.

/// rgb to fade from any colour to any other colour for any number of LEDS for any given period (rgbdelay)

if ((red!=reda)||(green!=greena)||(blue!=bluea))
    {
    uint8_t myBuffer[3];
    if (reda<red) reda+=((red-reda)/(rgbdelay*20))+1;
    if (greena<green)  greena+=((green-greena)/(rgbdelay*20))+1;
    if (bluea<blue)  bluea+=((blue-bluea)/(rgbdelay*20))+1;
    if (reda>red) reda-=((reda-red)/(rgbdelay*20))+1;
    if (greena>green)  greena-=((greena-green)/(rgbdelay*20))+1;
    if (bluea>blue)  bluea-=((bluea-blue)/(rgbdelay*20))+1;

    myBuffer[0]=ledTable[reda];
    myBuffer[1]=ledTable[greena];
    myBuffer[2]=ledTable[bluea];
    if (rgbnum==0) rgbnum=1;
    WS2812OutBuffer(myBuffer,3,rgbnum);
    }

I’ve only allocated 3 bytes for the RDB buffer as I’m not interested in individual colours – just changing them at once – and I repeat the whole thing by rgbnum – the number of LEDS and rgbdelay the time you want this to take to change from one colour to the next. It will do a nice job and smoothly without any horror colour changes – basically for each colour if the desired colour does not match the actual colour, adjust it by 10%.

oh and you’ll need this table… I found that on the web too. It’s simple enough – note that increasing values have little effect at first, getting more and more relevant as you get higher up. That’s because the difference in brilliance between 10 and 20 is large, the difference between 240 and 250 is almost zilch – to our eyes anyway.

So this is non-lossy –as the colours fade down, colour accuracy goes down but as you fade them back up it returns.

uint8_t ledTable[256] = {
  0,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
  1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
  1,   2,   2,   2,   2,   2,   2,   2,   2,   3,   3,   3,   3,   3,   4,   4,
  4,   4,   4,   5,   5,   5,   5,   6,   6,   6,   6,   7,   7,   7,   7,   8,
  8,   8,   9,   9,   9,  10,  10,  10,  11,  11,  12,  12,  12,  13,  13,  14,
14,  15,  15,  15,  16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  22,
22,  23,  23,  24,  25,  25,  26,  26,  27,  28,  28,  29,  30,  30,  31,  32,
33,  33,  34,  35,  36,  36,  37,  38,  39,  40,  40,  41,  42,  43,  44,  45,
46,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,
61,  62,  63,  64,  65,  67,  68,  69,  70,  71,  72,  73,  75,  76,  77,  78,
80,  81,  82,  83,  85,  86,  87,  89,  90,  91,  93,  94,  95,  97,  98,  99,
101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 119, 121, 122, 124,
125, 127, 129, 130, 132, 134, 135, 137, 139, 141, 142, 144, 146, 148, 150, 151,
153, 155, 157, 159, 161, 163, 165, 166, 168, 170, 172, 174, 176, 178, 180, 182,
184, 186, 189, 191, 193, 195, 197, 199, 201, 204, 206, 208, 210, 212, 215, 217,
219, 221, 224, 226, 228, 231, 233, 235, 238, 240, 243, 245, 248, 250, 253, 255 };

Oh, you also need to ensure that the output you use is actually an output!!!! So why are you waiting – moodlighting – SAD LIGHTS ---  I’ve not tested more than 30 LEDS so do some tests before going wild.

Another thing to note – avoid the callback fading starting while the WIFI is setting up… I found using this immediately at startup caused issues – once you have connections it’s fine.

Facebooktwittergoogle_pluspinterestlinkedin

The Problem with Ports ESP8266

 

I was about to write about my stunning success with the ESP8266 and WS2812b chips when I’ve hit a snag.

I have a working example of high speed port bashing to control the serial LEDS on GPIO-0.. but I want to use GPIO12. Assuming all of the ports are setup properly..

WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(0), 1 );

WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(0), 0 );

The above toggles GPIO-0 up and down at high speed.

WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(12), 1 );

WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(12), 0 );

The above does not work on GPIO-12

WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(12), 0x1000 );

WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(12), 0 );

The above does not work on GPIO-12 either

WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR,0x1000 );

WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR,0 );

The above works a TREAT on GPIO-12 – but sadly it also messes up the OTHER port bits!!!!

What is the correct code for GPIO-12 ???

Facebooktwittergoogle_pluspinterestlinkedin

C ? Construct

For the LIFE of me I do not know why this statement is failing.  There are two versions of settings for port outputs here – the one in red and the one in blue. If I choose the blue version it will only work in one direction, not the other.

If I choose the version in red – it works full stop.

The same ? construct is used in sending messages out and that works perfectly. This is C programming in Eclipse for the ESP8266 chips… “intvalue” is just the number 0 or 1

 

else if (strcmp(token,"out2")==0)
        {
            if (sysCfg.out_4_status!=intvalue) { sysCfg.out_4_status=intvalue; do_update=1; } // only update if actual change

            if (sysCfg.out_4_status==1) GPIO_OUTPUT_SET(LED_GPIO_4, OUT_ON); // on or off by default
            else GPIO_OUTPUT_SET(LED_GPIO_4, OUT_OFF);

            //GPIO_OUTPUT_SET(LED_GPIO_4, (sysCfg.out_4_status==1) ? OUT_ON : OUT_OFF); // doesnt work - don't know why
            strcpy(token,tBuf); strcat(token,"/out2"); MQTT_Publish(client, token,(sysCfg.out_4_status==0) ? "OFF" : "ON" ,(sysCfg.out_4_status==0) ? 3 : 2, 0, 0);
        }

Thoughts anyone? I must’ve been starting at this for too long.

Facebooktwittergoogle_pluspinterestlinkedin

MongoDB on the Pi

MongoDBI’m busy compiling MongoDB for the Pi and it’s going to take hours apparently – so I figured I’d give you some updates while I’m waiting.

I’ve made some progress with my little ESP8266 board (ESP-12) in terms of deciding how to handle MQTT.  Initially I had a bunch of subscribes to various topics and at some point it hit me.. really, you only need 2… one with your ID (whatever you choose to use) for messages coming in specifically to that one board – and another which does not have an ID attached – i.e. a sort of global incoming message.  The actual message content than then therefore decide what actually happens.  In my case I might want to get the temperature, or turn an output on – or even pass on a message to an Arduino via the serial port.  I’ve done this by coming up with a simple message format not a million miles away from JSON (don’t any purists start on me).  By taking in the message then looping through – I can do several things at once.

So for example lets say this particular ESP8266 unit is ID 999.  I send a message from say the PI to 999/to_esp and the content might be {out1:1;temperature:;ext:”rgb:red=255,green=5,blue=50”}

Let’s break that down… so the first instruction is out1:1; which turns output 1 (GPIO0 on). As it happens I also have it send a message back to confirm that status. The next thing is temperature:; You’ll notice there is no argument there – and that is a request to return the temperature in an MQTT message – which it does. The third item is this.. ext:”rgb:red=255,green=5,blue=50” which does not need a semicolon as it’s the last item in the list… what that says is – here’s an external command to pass to the serial port so that, say an Arduino can handle it.

So what goes out of the serial port after a little dressing is… {rgb:red=255,green=5,blue=50} and I’ve already written the Arduino code to watch for a package coming in the serial line and acting accordingly; In this case it will start a series of high speed pulses out to a port bit to control a 5v serial LED strip WS2812b ….it can do a nice soft fade as it is not taking up any of the ESP8266’s time.

Had I sent the version of the command to the board with no ID, the result would be the same but no return messages would be sent – so that means you can with one command turn everything on or off no matter how many little ESP8266s you have.

NoSQLSo that’s nice but what does it have to do with MongoDB? Well (still compiling and will be for hours – if you want to have a go try this link but don’t blame me if it does not work as I’ve not tested it yet) – I watched a Node-Red demonstration and the guy was using MongoDB which is a “NoSQL” database which basically works on keys – and one of the more notable aspects was that you don’t have to go defining tables etc., you just give it a name for the data you want to store – and store it  - that seemed eminently civilised and so I figured I’d install it on the Pi (a Pi-specific version in the link) – and so with warnings that it will take several hours – that’s what I’m doing. 

I’m constantly amazed at how these very long and involved loading and compilations actually work – I’m always waiting for something to go wrong..

Still standing by my original comments re: ESP boards.. score ESP-12 10, ESP201 0.

More later when the Pi actually does something other than sitting looking busy.

Update: An hour later, accidentally pulled the plug on the Pi – had to start again…… 2 hours later – after many, many warnings but no errors, lots of “deprecated” messages but the install looks to be done.. just some housekeeping to do… late evening:  It works – considering the number of warnings I had my doubts but the mongo connectors in Node Red are working.

Facebooktwittergoogle_pluspinterestlinkedin

ESP201

Many thanks to readers in here for the comments – I can’t believe how keen people are to help. Ok, so you may recall that some time ago I bought an ESP-201 board and the baseboard to with it – the whole lot was about a tenner on Ebay, a marvellous opportunity to play with the ESP8266 while accessing all the pins AND on a 0.1” pin centre basis – easy for prototyping.

ESP201Well, it didn’t work out that way, the whole package came with zero documentation and frankly the sensitivity of the aerial was ATTROCIOUS or so it seemed. I’ve had feedback from a couple of you and so this morning I decided to go take a look with my new microscope (another Ebay special).

So what did I find? Well, sure enough – look at the board on the right – the centre part is the little ESP201 board itself. See the aerial – see the little link on the right? See the or SMT resistor to the left of it? Does that look like there’s a track going from the chip to the aerial?

No, you’re right – it DOESN’T – the damned thing is connected to the external aerial!!!

ESP-201Just to exaggerate the point here’s another photo in which (click to zoom the image) you can clearly see that the 0r resistor is designed to offer a choice, horizontally it connects to the internal aerial, vertically (default) it connects to the external aerial – why on EARTH would anyone do that?

I’d given up on this board on the basis (again in the absence of any documentation) that it was just a really bad design. Wouldn’t a link have worked??

I don’t know how many of you have tackled surface mount but let me tell you – if your hands shake – forget it.  If they don’t, you need a nice set of tweezers with a 45 degree end on them. If you apply the iron to one side, the chances are both sides of the 0r resistor soldering will melt and you can lift the part off cleanly, Ensure your iron is hot – and as clean as possible.

ESP-201[6]Anyway, thanks to a nice set of snips and a fine soldering iron… a few moments later… I FREELY admit, moving that resistor was neither the finest hour for me or my cheap Chinese tweezers and as I didn’t have any isopropyl handy it’s a little messy – but ultimately it’s a 2 minute job to change the link over. Actually a blob of solder would have done because a 0r resistor is pretty much just a wire.

Did it make any difference? No – not at all – the unit after blowing the chip powered up and would not connect to the router. With some repositioning, it would – which clearly indicates a sensitivity issue.

ESP-12Frustrated with that I took my sparkly new ESP-7-8-12 baseboard (which has 2 resistors and nothing else, soldered on an ESP-12, wired it (0.1” centres) to my ESP-01 adaptor (the board shown on the left already has a pull-up for CH_PD and a pull-down for GPIO15), blew the chip, turned it on – no problem at all.

I’m beginning to think that life is too short to spend much more time on those EP201 board especially considering the cost of the ESP12s, the fact that they are shielded and that adaptors are so cheap… Next stop – making sense of the A/D so I can use it as a battery voltage indicator.

Facebooktwittergoogle_pluspinterestlinkedin

Webmin for Pi

A friend of mine put me onto this link tonight – a nice web admin panel for the Raspberry Pi… and no I didn’t get around to soldering the ESP-12 module – that’s a writeup for the weekend – and yes, my ESP201 module definitely does NOT have the internal aerial hooked up by default – what WERE they thinking about.

Anyway – check out this link!  It even updates itself once installed!!!

http://c-mobberley.com/wordpress/2014/09/26/webmin-setup-on-raspberry-pi/

While you are on – Nathan Chantrell is using ESP-01 and MQTT in a setup not a million miles away from where I’m heading… see what you think of this – he has code available.. http://nathan.chantrell.net/20141230/wifi-mqtt-display-with-the-esp8266/#comment-334251

Facebooktwittergoogle_pluspinterestlinkedin

Monday Morning at the Lab

Just in case anyone in the UK or EU is even remotely interested, I just put up my little pocket scope on Ebay. http://www.ebay.co.uk/itm/231492939705

Meanwhile talking of Ebay, the Raspberry Pi is currently working a treat on THIS little number…. a cheap WIFI dongle.  http://www.ebay.co.uk/itm/331400872324 -  it’s been running overnight and logging temperatures without a hitch. For under £4 that can’t be bad.  I’m thinking, once I get the Pi and the ESP8266 boards properly communicating over MQTT of putting a display on the Pi and making that the wall unit rather than hiding it away. Well, clearly, I’d rather NOT have to have a network cable going up the wall so the WIFI dongle solves a problem.

my ESP-12 units turned up – still waiting for some little adaptor boards to come that give you 0.1” pitch from the ESP-12s for experimenting.  It seems that it is necessary to ground GPIO-12 as well as taking the PD line high permanently – and I had confirmation yesterday that using GPIO-0 with a ground-based setup (for example an NPN transistor and resistor arrangement is NOT a good idea – personally I’ve been using then to power solid state relays taking the other side of the relay to positive hence ensuring a small amount of positive voltage at power up – and I’ve had no problems.  I plan also to tie GPIO16 to the external reset so I can experiment with the low power sleep mode. All of that late this week when my adaptors arrive.

Oh, I knew there was something else. Has anyone doing C coding with ESP8266s used this yet? Seems like a fine way to mess with ESP8266 GPIOs – giving you a consistent interface to handle GPIO 0,2, 4,5, 12,13 and 14. The author says he HAS used this with SDK 0.9.5 so it is pretty much up to date. As soon as I get my adaptors for the ESP-12s I’ll give it a good thrashing.  https://github.com/eadf/esp8266_easygpio

Facebooktwittergoogle_pluspinterestlinkedin

Raspberry Pi WIFI

Today is going well up to now – I purchased a WIFI dongle for around £4 from EBAY, supposedly specifically for Pi (yeah right) market simply “802.11n”.  Plugged it in, rebooted the Pi 2, nothing.  I scoured the web and discovered you can look to see what’s happening with:

dmesg | more

which shows installed items one page at a time (Spacebar) and sure enough in there was the 802.11 device with a driver missing – looked like a Realtek driver. I went off looking for the name and one of the very first Google responses (sorry I didn’t keep the link) showed a rather long SUDO WGET command to go get the very driver (rtl8188eufw.bin)  - did that, reboot – one working WIFI.

So now my little Pi2 has only ONE wire going to it – the power lead from the little solar/usb charger I’m using for battery backup.

I make no suggestion this will help but if you find yourself missing this driver this is what I did in the Pi2 terminal window (then rebooted) – no breaks…

sudo wget https://github.com/lwfinger/rtl8188eu/raw/c83976d1dfb4793893158461430261562b3a5bf0/rtl8188eufw.bin -O /lib/firmware/rtlwifi/rtl8188eufw.bin

 

I then went off and tied the IP address and MAC together in my router and that’s me one wire down.

Facebooktwittergoogle_pluspinterestlinkedin