ESP8266 and the Dallas DS18B20 and DS18B20P

Please note – this information has now been superseded by the info on the new blog at – please visit the new blog.

Having wasted half the night following up dodgy temperature readings for the DS18B20P only to realise I’d left existing code running for the DHT22 !!!  I managed in the process to reduce the necessary code down to a minimum.

If you look at a previous blog in here I referred to some simplified Arduino code I’d written back in the dark ages and wondering if I could get similar here.  I’m only interested in temperatures to the nearest degree C for thermostatic control and was very concerned about the typical 1 second delay to read these chips.

I reasoned that if you were to read the chip before conversion then start a conversion off, your first reading would be rubbish – but subsequent readings would be fine without the delays associated with the more normal code.

So, here is what I ended up needing for a library – very little as you’ll see… most of it is comments…


* Adaptation of Paul Stoffregen’s One wire library to the ESP8266 and
* Necromant’s Frankenstein firmware by Erland Lewin <>
* Paul’s original library site:
* See also
* Stripped down to bare minimum by Peter Scargill for single DS18B20 or DS18B20P integer read

static int gpioPin;

void ICACHE_FLASH_ATTR ds_init( int gpio )
//set gpio2 as gpio pin
//disable pulldown
//enable pull up R
// Configure the GPIO with internal pull-up
// PIN_PULLUP_EN( gpio );
gpioPin = gpio;

// Perform the onewire reset function.  We will wait up to 250uS for
// the bus to come high, if it doesn’t then it is broken or shorted
// and we return;

void ICACHE_FLASH_ATTR ds_reset(void)
//    IO_REG_TYPE mask = bitmask;
//    volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
uint8_t retries = 125;
// noInterrupts();
// DIRECT_MODE_INPUT(reg, mask);
// interrupts();
// wait until the wire is high… just in case
do {
if (–retries == 0) return;
} while ( !GPIO_INPUT_GET( gpioPin ));
// noInterrupts();
GPIO_OUTPUT_SET( gpioPin, 0 );
// DIRECT_WRITE_LOW(reg, mask);
// DIRECT_MODE_OUTPUT(reg, mask);    // drive output low
// interrupts();
// noInterrupts();
// DIRECT_MODE_INPUT(reg, mask);    // allow it to float
// r = !DIRECT_READ(reg, mask);
//r = !GPIO_INPUT_GET( gpioPin );
// interrupts();

// Write a bit. Port and bit is used to cut lookup time and provide
// more certain timing.
static inline void write_bit( int v )
// IO_REG_TYPE mask=bitmask;
//    volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
GPIO_OUTPUT_SET( gpioPin, 0 );
if( v ) {
// noInterrupts();
//    DIRECT_WRITE_LOW(reg, mask);
//    DIRECT_MODE_OUTPUT(reg, mask);    // drive output low
GPIO_OUTPUT_SET( gpioPin, 1 );
// DIRECT_WRITE_HIGH(reg, mask);    // drive output high
// interrupts();
} else {
// noInterrupts();
//    DIRECT_WRITE_LOW(reg, mask);
//    DIRECT_MODE_OUTPUT(reg, mask);    // drive output low
GPIO_OUTPUT_SET( gpioPin, 1 );
//    DIRECT_WRITE_HIGH(reg, mask);    // drive output high
//        interrupts();

// Read a bit. Port and bit is used to cut lookup time and provide
// more certain timing.
static inline int read_bit(void)
//IO_REG_TYPE mask=bitmask;
//volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
int r;
// noInterrupts();
GPIO_OUTPUT_SET( gpioPin, 0 );
// DIRECT_MODE_OUTPUT(reg, mask);
// DIRECT_WRITE_LOW(reg, mask);
// DIRECT_MODE_INPUT(reg, mask);    // let pin float, pull up will raise
// r = DIRECT_READ(reg, mask);
r = GPIO_INPUT_GET( gpioPin );
// interrupts();
return r;
// Write a byte. The writing code uses the active drivers to raise the
// pin high, if you need power after the write (e.g. DS18S20 in
// parasite power mode) then set ‘power’ to 1, otherwise the pin will
// go tri-state at the end of the write to avoid heating in a short or
// other mishap.
void ICACHE_FLASH_ATTR  ds_write( uint8_t v, int power ) {
uint8_t bitMask;
for (bitMask = 0x01; bitMask; bitMask <<= 1) {
write_bit( (bitMask & v)?1:0);
if ( !power) {
// noInterrupts();
GPIO_OUTPUT_SET( gpioPin, 0 );
// DIRECT_MODE_INPUT(baseReg, bitmask);
// DIRECT_WRITE_LOW(baseReg, bitmask);
// interrupts();
// Read a byte
uint8_t ICACHE_FLASH_ATTR ds_read() {
uint8_t bitMask;
uint8_t r = 0;
for (bitMask = 0x01; bitMask; bitMask <<= 1) {
if ( read_bit()) r |= bitMask;
return r;

and here is the code that ended up in my timer callback routine, sending off an MQTT message for the temperature every 5 seconds – this works with both chips and works reliably.

    ds_init(2); // one off for the DS18B20

The above goes in my INIT routine – note that I’ve referred to GPIO2  – this will not work for other port bits as the Port initialisations seems to be partly hard coded – if anyone cares to re-write that so that anyone can easily access any of the usable pins.. would be nice..

I’ve also renamed the  routines, adding ds_ at the start to avoid confusion with other routines.

And now  for the actual code.. I call this every 5 seconds for testing and as you’ll see there’s a little extra code to send this out via MQTT. The extra code is in bold. “Temperature” is an integer defined elsewhere.  As you can see, no search, no checksum, no delay for processing – this works with both the DS18B20 and the DS18B20P chips.

char *tBuf = (char*)os_zalloc(6);

if (temperature>100) temperature-=4096;
os_sprintf(tBuf, “%d”, temperature);
MQTT_Publish(&mqttClient, “temperature”,tBuf,strlen(tBuf), 0, 0);

And so how to test all of this. For the life of me I can’t find a simple, no-nonsense program to read MQTT and graph it – you would think there would be loads around – I have asked the writer of MQTT-SPY if he’d like to add something into the program – for what’s out there – you seem to have to sign up and go through a whole learning curve – a little excessive for what I wanted (i.e. MQTT in – graph out), so I hooked up Node-RED to simply store the incoming data in a file.

And now having that information in a simple text file, it was easy to graph in EXCEL but again a whole FAFF to simply update dynamically until I discovered Live-Graph – not the prettiest but set to read the file every 5 seconds and update the graph –  I have to say it works a treat.

Here is my little sensor, as it happens the P variety I was originally having problems with, happily monitoring the ambient air temperature with a little excitement added on two occasions from my Dust-off air blower which is able to freeze the life out of the sensor on demand!


As you can see, the code is working well – doesn’t even need averaging.

Lua and the DS18B20/DS18B20P temperature sensor

DS18B20 or DS18B20PA long time ago, back in the dark ages when all we had were Arduinos (seems such a long time ago) I spent a bit of time playing with the Dallas DS18B20 chips.

There are a number of ways to read these and so I’ll explain my logic as I go along. Not everyone will agree with my conclusions and that’s fine. Works for me as they say.

The example that comes with the Lua interpreter caters for almost everyone by making the software check for missing chips, multiple chips and offering a range of output options including degrees C and F.  As the language subset does not include floats, it simulates that with two catenated numbers.

In order to avoid issues with delays stopping communications ( and I can confirm that delays WILL stop for example incoming MQTT messages), it also does away with the typical setup delay.

So –  a number of issues with this.  Firstly, for me, if I am reading temperature and maybe controlling something, I cannot for the life of me see the need for sub-degree precision. Accuracy yes but precision? Really, you’re going to keep the house at exactly 22.15c?   Probably not. I control 2 properties and this code will likely control the third – 24-7, 365 days as year if it works as reliably as the Arduino version.

Secondly, when I received my Dallas chips I got a mixed bunch on special offer and ended up with some with a P suffix. I quickly discovered that the delay is needed for these chips and today when using the example software with Lua I was set back temporarily before remembering this fact. The P suffix chips simply would not work AT ALL and constantly returned 85c. That delay is needed one way or another.

Because it has been removed, the first reading you take with the code will be incorrect.. and that’s not really a problem – you could take that during setup. There are ways around this but it’s not worth the bother when it’s so easy to circumvent.

Now personally I don’t see me using more than one chip per board and if I did I could always use another pin – so that whole search scenario is a waste of time, resources and RAM for me.

So given these criteria I have a MUCH simpler version of the driver for you – and one which will work without alteration with both chips. It’s also fast.

Instead of seeking the address of the chip, then starting the conversion, then reading the chip…  I assume one chip, simply read the value then start the conversion.

This seems utterly wrong but then remember your first reading is naff anyway. Assuming you don’t try to read the unit more than, say, once a second, the time in between reads will be more an enough to do the conversion for BOTH types of chip. I plan to stick this on a timer, say, every 10 seconds, dumping the value into a global variable so it’s “just there”.

Also as I’m just reading an integer, about the only check I have to do is for overflow so as to perhaps create a negative number (for freezing conditions) and finally all that CRC stuff and the buffer needed to store the data – why bother, with only one chip it’s not going to go wrong unless you have a long lead between the board and the chip. You only need to read 2 bytes!! Speed, storage…

So here’s the EASY version.

I have to say, I simply do not understand the registration system for LUA modules yet (wasn’t there last time I looked in) so those first few lines at the start I’ve copied verbatim.

Can you make it even simpler and also explain this stuff at the very first few lines to do with modname? Oh, I’m using all 3 leads (GND, D and VDD) of the Dallas chip and a 4k7 pull-up from D to VDD. I found the pull-up un-necessary on short leads but let’s not test fate?

Please note – this information has now been superseded by the info on the new blog at – please visit the new blog where you can search many hundreds of IOT-related entries.

— DS18B20 one wire module for NODEMCU
— Vowstar <>
— Dramatic simplification: Peter Scargill

— Set module name as parameter of require
local modname = …
local M = {}
_G[modname] = M
— Local used modules
— Table module
local table = table
— String module
local string = string
— One wire module
local ow = ow
— Timer module
local tmr = tmr
— Limited to local environment
— Implementation – you don’t get any shorter than this

function readNumber(pin)
ow.write(pin, 0xCC, 1)
ow.write(pin, 0xBE, 1)
data = nil
data = “”
for i = 1, 2 do
data = data .. string.char(
t = (data:byte(1) + data:byte(2) * 256) / 16
if (t>100) then
ow.write(pin, 0x44,1)
return t

— Return module table
return M

That’s it!!! So there’s the library done… now here’s the test code…

t = nil
ds18b20 = nil

Notice that this, too is simplified. “4” refers to GPIO2 in the Lua tables. I’m using an ESP-01 and I use GPIO0 to control a relay.

and here are the results showing a swing across through zero thanks to my handy liquid air spray. I do wish I could figure out how to turn the UART off except when I’m firing prints out – anyone know how to do this? Results buried in that mess are –2, 0, 1 and are degrees C (you could easily mod the code to F).  Suggest not trying to measure over 84C.

> t=require(“ds18b20”)
> t.setup(4)
> print(t.readNumber())
> t = nil
> ds18b20 = nil
> package.loaded[“ds18b20”]=nil
> t=require(“ds18b20”)
> t.setup(4)
> print(t.readNumber())
0t = nil
> ds18b20 = nil
> package.loaded[“ds18b20”]=nil
> t=require(“ds18b20”)
> t.setup(4)
> print(t.readNumber())
1t = nil
> ds18b20 = nil
> package.loaded[“ds18b20”]=nil

If you’re on Facebook why not LIKE here.

ESP8266 LUA and MQTT

After a few days break wherein work got in the way of interests (not a good thing) I got up early this morning, determined to do some work on my ESP-01 boards while I have a clear weekend ahead of me. I checked for updates for MQTT and there are none – which is fine – that indicates that nothing has gone wrong this week.

On a whim I decided to go check the LUA site. I already new that the latest MQTT had been imported from conversations with Minh  who’s been doing the MQTT work but I was delighted to see signs that also some more work had been done on integration with Eclipse.

Every single time I’ve tried to install the nodemcu LUA code into Eclipse there has been a problem – something not found, some path missing, some issue taking hours to resolve.

Yet this morning I downloaded the latest ZIP file (updated yesterday) and imported it into Eclipse. CLEAN – COMPILE – FLASH…  not a hiccup – it worked perfectly. Not only that but when I tried powering Lua up – it came up straight away without any hint of an issue. This is new for me as I’ve always had some trouble or other. Magic.

Though it is possible to debug Lua code using the simple terminal you can install into the Eclipse environment, I did develop my own serial terminal  and then subsequently discovered ESPLorer.

I powered up ESPlorer and checked the available RAM on my newly installed Lua installation on an ESP-01 (I’m still waiting for my new white board to turn up from China with all the pins available – meanwhile I have ESP-01, ESP-03 and ESP-12 boards to play with).

A quick node.heap() call showed that we’re starting off with 22,144 bytes of working RAM which is a good improvement on the earlier versions especially as MQTT is now incorporated.

First things first, I told the unit about my router and then my MQTT broker which regular readers will know is sitting on a Synology DiskStation and has been sitting there working flawlessly for weeks now despite my attempts to bombard it to death with messages.

I noted when using wifi.sta.getip() that the unit remembered my router from previous experiments (I wish someone would produce a nice graphical memory map to show where these various elements are stored and how to tinker with them). So that was easy.

I followed this example – obviously filling in the bits that apply to my installation..

— init mqtt client with keepalive timer 120sec
m = mqtt.Client("clientid", 120, "user", "password")

— setup Last Will and Testament (optional)
— Broker will publish a message with qos = 0, retain = 0, data = "offline"
— to topic "/lwt" if client don’t send keepalive packet
m:lwt("/lwt", "offline", 0, 0)

m:on("connect", function(con) print ("connected") end)
m:on("offline", function(con) print ("offline") end)

— on publish message receive event
m:on("message", function(conn, topic, data)
  print(topic .. ":" )
  if data ~= nil then

— for secure: m:connect("", 1880, 1)
m:connect("", 1880, 0, function(conn) print("connected") end)

— subscribe topic with qos = 0
m:subscribe("/topic",0, function(conn) print("subscribe success") end)

— publish a message with data = hello, QoS = 0, retain = 0
m:publish("/topic","hello",0,0, function(conn) print("sent") end)

— you can call m:connect again

(again ignore the IP address and port – I filled in my own) – I ran this and… connected no problem. All seemed well.   I had subscribed to “test” rather than “/topic” and had commented out the publish for now.

I tried publishing “test” to see what would happen – nothing. But then I guessed as the last line was “m:close()” I figured it reasonable that the ESP-01 would not be listening and so called the connect line again – after all – there is a comment in there “you can call m:connect again”.

The result (passwords have been changed to protect the innocent):

> m = mqtt.Client("peteluatestid", 120, "xxxxxx", "yyyyyyy")

NodeMCU 0.9.5 build 20150123  powered by Lua 5.1.4
lua: cannot open init.lua

Yes that’s a crash. Oh dear, this is not the first time I’ve seen Lua just die. I can handle error messages but this tendency to just simply reboot…

Meanwhile, my experiments with programming in C, using MQTT directly have, thanks to Minh Tuan’s constant vigilance in fixing things, produced rock-solid results. Indeed I’ve been away since last weekend and I turned off a perfectly working MQTT temperature sensor in order to give Lua another go. I thought the one-wire library in Lua might make the transition to a Dallas DS18B20 a little easier but I’m not going to start another round of failed experiments while Lua so easily crashes.

Incidentally, I had several attempts with this Lua installation – rebooting several times along the way. When I finally managed to get the whole thing to work and in commenting out the CLOSE – as you need the connection open to receive anything, I noted my wonderful 22k of RAM had dropped down to 17.2K.  I really do wish they’d put a little more RAM on that chip.

Having checked that the compilation had included all the modules (app/include/user_config.h) which as far as I can tell the default combination SHOULD do… I thought I’d try the DS18B20 module – the idea being to send an MQTT request – and get an MQTT message back with the temperature in it.

I thought I would avoid experiment and merely check the temperature first.  I duly attached a working SD18B20 unit and pull up resistor to GPIO2 (that’s input 4 according to the table).

The code looked simple enough..

t = nil
ds18b20 = nil

But no..

> t=require("ds18b20")
stdin:1: module ‘ds18b20’ not found:
    no field package.preload[‘ds18b20’]
    no file ‘ds18b20.lua’
    no file ‘’

Oh dear….

Thoughts? Am I missing the point here?

The Battle of the ESP-201 Giants

ESP-201This is a relatively new one – the ESP-201 – larger than other game-changing miniature WIFI boards (or miniature powerful programmable devices with WIFI as you prefer)  but with one big advantage – unless I’m mistaken this new WIFI board (which will be functionally identical to others as it has the same parts) appears to have 0.1” spacing which means for the first time other than the pin-challenged ESP-01 we’ll be able to experiment with this board on normal breadboard or with normal prototyping wire – and that has to be a good thing.

The only question is – do you want to pay £3.29 or £2.58 (that’s Pounds Sterling as I am UK based)

Here they are – if anyone has any CHEAPER links do let me know…

These boards like the others run on 3v3 and like some of the others have an on-board antenna – but there is also an option for an external antenna (I’ve not found the need for one myself).

The point is – unless SIZE is a big issue, these almost compete on cost-price alone with the ESP-01 but without the pin restrictions – let’s see what we get – and if anyone has done some work with one of these could they please let us know how these pin-mappings compare to somewhat more conventional pin names for these devices.  I expect I’ll have mine soon and am looking forward to taking the opportunity, perhaps even at the weekend, to mess with second UART debugging, I2C and a host of other features denied to ESP-01 users (except those with obscenely accurate soldering skills and very fine wire). Mind you, a planned BURNS night on Saturday might slow progress a little.

ESP8266 I2c

There seems to be chatter going around about how the ESP8266 does not have I2c.  So much so that there are implementations of bit-banged I2c out there..  here for example and this one is good for those with ESP-01 boards which only have 2 pins available – but beware that GPIO-0 is also used in hold-low mode on powerup for flashing the chips – and also the developer of this driver states that works needs to be done. I noted that it is NOT done under interrupts.

If you want to see the official line on i2c it is that it IS supported – here it is in the SDK documentation.  – available in both WORD and PDF versions…  granted this is early documentation 0.9.1– there is later (around December 0.9.4) but as far as I am AWARE you have to sign an NDA to get the newer information – I may be wrong.. you could check with Espressif themselves.

According to the documentation you have full I2c master control (it would have been nice had it specified which pins to use!)

It would be nice if someone would submit a really trivial I2c example using the above, stating which pins needs to do what.

What I don’t understand is – when ESPRESSIF distribute the various SDKs there’s a directory in there called document that is always empty – you would think they’d take the opportunity to include the documents in there!!

Of interest if you have the pins available there is also a dual UART (ie 2 lots of serial lines) and PWM control of some of the pins.

MQTT for ESP8266 not QUITE but nearly

Minh Tuan is doing an excellent job with MQTT – he has it working stand alone – and in the LUA code (not yet brought into the main code)… but..

Before you go off getting annoyed if things don’t go quite to plan, there still seems to be a tiny but important bug  -I’ve reported it today and Minh will look at it tomorrow. I’m working on code from just an hour ago here (late after noon UK)

I set up a demo, subscribing to 7 short topics. With the exception of the first, all the topic names are short… and all responses are short…. I’ve changed the broker name below to protect the innocent (that would be me).

MQTT: subscribe, topic"home/openHAB/out/Light_FF_Bath_Ceiling/command" at broker xxx.yyy.zzz:1884
MQTT: subscribe, topic"myleds" at broker  xxx.yyy.zzz:1884
MQTT: subscribe, topic"mytime" at broker
MQTT: subscribe, topic"time" at broker xxx.yyy.zzz:1884
MQTT: subscribe, topic"dusk" at broker xxx.yyy.zzz:1884
MQTT: subscribe, topic"dawn" at broker hoxxx.yyy.zzz:1884
MQTT: subscribe, topic"timestring" at broker xxx.yyy.zzz:1884

As you can see all of them subscribed successfully or so it would seem.

Ah, but…

4 of them are broadcast every minute from a page I demonstrated in a previous blog or it’s notes and over on another computer I have MQTT spy watching… time, dawn, dusk and timestring are send out by the same page once per minute.

But what is being seen by the little ESP8266 program is….

TCP: data received
MQTT topic: time, data: {1484956800}
TCP: data received
MQTT topic: timestring, data: {15:15 Saturday 17-01-15}
TCP: data received
MQTT topic: time, data: {1484956800}
TCP: data received
MQTT topic: timestring, data: {15:16 Saturday 17-01-15}

As you can see, dawn and dusk have “disappeared into the dusk”.

Similar happens with the Lua/MQTT code – I thought at first that might be due to the callback not being done before being called again but seeing this I’m thinking… no.

As soon as this one is resolved I’ll report back. It is important that the system can handle several simultaneous incoming messages and that it it reaches it’s limit, something obvious tells us that.   The info above is the minimum I would be sending to any module –ok of course I could merge them into one – but that’s not the point – I could not do that if they were coming from different sources.

Suggest looking in again tomorrow for any fixes…

If I go quiet, I’m off to Brussels for a couple of days for some EU business.

And there’s more… I reduced the number of subscriptions to 3..

MQTT: subscribe, topic"dusk" at broker xxx.yyy.zzz:1884
MQTT: subscribe, topic"dawn" at broker xxx.yyy.zzz:1884
MQTT: subscribe, topic"timestring" at broker
MQTT: Sending..type: 8,qos: 4
TCP: Sent
TCP: data received
MQTT: Sending..type: 8,qos: 4
TCP: Sent
TCP: data received
MQTT: Sending..type: 8,qos: 4
TCP: Sent
TCP: data received
TCP: data received
MQTT topic: timestring, data: {16:43 Saturday 17-01-15}
TCP: data received
MQTT topic: dawn, data: {27208}
TCP: data received
MQTT topic: timestring, data: {16:44 Saturday 17-01-15}
TCP: data received


Couple of things of concern – firstly again it’s SAYING it has subscribed to 3 but it only taking two of them – the last 2 (that’s not a clue, wasn’t last 2 last time) but the messages are also a concern… “Sending..type:8 qos:4”   there ISN’T a qos 4 !!! Don’t know what that is about…

ESP8266 the unstoppable March of Progress

esp01I’ve been following the progress of this little chipset as you know since day one – having spend a year more developing skills at using horrible little NRF24L01 radios with as much indoor range as my legs – and Arduino Ethernet cards (which to be fair are WONDERFUL other than their need for a marriage-endangering WIRE), out of the blue came a little Chinese board with the potential to change everything. The ESP-01 showed much promise but very little reality at first. The instructions were in Chinese, the documentation was in Chinese or missing, people told me “there are these other boards for only a tenner that do so much more”.

And yet here we are today with much of that about to change. The new so called white ESP8266 board with it’s development “kit” for less than a tenner is winging it’s way to me now – and the ESP-12 boards are neat and even have approval stickers to keep people happy not to mention a health range of I/O.

There are now a range of boards, all cheap  (there is a question mark over the ESP-07 – not for the first time I’ve heard there are 2 versions one of which is “suspect”) – and the ESP-01 remaining, I think true to my original statement – the title of one of my blogs “the cheapest computer in the world”. At under £2 tell me I’m wrong. 1 plug in the wall power supply , one ESP-01, one cheap solid state relay and you have a functioning WIFI-controlled device – with the right software that is.

But like all such devices, software makes or breaks this dream and in recent weeks we’ve seen the emergence of the ECLIPSE environment for Windows – I’m sure there are many such environments for Linux – and others will blog about them – I’m not interested in the command line and haven’t been for a long time. Eclipse and the tremendous work by the fellow who set this all up for us – means everyone from expert to complete beginner can “have a go”.

This week however is a bit special – we have in one corner TUAN and his MQTT code – on the other corner we have ZERODAY and his LUA interpreter – ( I really should find out everyone’s proper names) and this weekend – they look like merging.  I’m hoping that the MQTT code will continue to be developed independently of LUA as I think there are uses for both. I DO have code that WORKS – it’s not just a promise. We have some great tools such as Esplorer for testing Lua and the AT command set.

I can’t tell you what is possible with the software and hardware out there – all I can tell you is what I’m doing and why – I hope my blogs up to date have given you all the links you need. For days now I’ve been testing the MQTT software – and as far as I can tell there is only one “bug” left of note and it’s not even a bug – it’s an inconvenience – something to “wrapped up” – essentially the code works – but it’ not too happy about empty messages. I expect right now that is being fixed and I am so grateful to so many authors who have communicated, helped, changed things – in the main for no commercial gain – because they love it.. it’s almost like the days of the first 8-bit micros – the rush of learning.  Meanwhile I got an email this morning to say that MQTT and LUA were merging and a test set of .BIN files was available.

So, despite a head that is spinning like a TOP due to flu, this afternoon I set up a test rig…  let me take you through that quickly… erm… it works but read on as you need the bits that come before it.

The plot so far:

In order to use MQTT as the base of your control system (in my humble version of this vastly diverse Internet of Things) you need an “MQTT broker” running somewhere and it needs to be reliable – ROCK SOLID. In my case I have a Synology Diskstation (the link is an example – mine is not white) and with a little help I got the free MOSQUITTO running on it – you could put this on an old PC, a Linux box – just about anything with a brain – but it needs to be reliable. There are services out there – the free ones they generally warn you not to rely on them – so I’m not going to – I’ll have my own thanks – I’ve talked about several variations elsewhere – at the end of it I went with Mosquitto.  My disk backup DISKSTATION is on 24-7 so it seemed the ideal place for this. As for testing Mosquitto on a PC – you are not going to beat the EXCELLENT MQTT-SPY.

So now a place to fire messages to – and a place to receive them from… and the software tools for ESP8266 to send and receive those messages – the sky is the limit. But what about issues people have had – swapping modes – you might need the time from a time server for your little board or some other info. Well, I found a way around that.   MOSQUITTO is on all the time – what is needed is for it to make available info to the little boards, be it time, lighting up time, perhaps other information.  I found a PHP library – the nice kind – the type you don’t actually have to understand to use.  Some time ago I documented a web page I was using to fire back time and other information – I used it as I found NTP time servers to be slow at times.  I have cheap web space with a provider much as many of you will – with CPANEL – which means I get all the benefits of using a reliable Linux based web service while staying within my pretty coloured boxes visual interface comfort zone (I’m sure there’s an abbreviation for that).

With such a setup you can write PHP pages like one that will send time messages for example and with the ability to run those pages on demand using CRON (doddle) you can make the time and over information available to your toys.

Here’s the deal.


$mqtt = new phpMQTT("", 1884, "somenamePub");
if ($mqtt->connect(TRUE,NULL,"mymqttuser","mymqttpass")) {
            if ($_GET[‘loc’]!="") $locn= $_GET[‘loc’];
            if ($_GET[‘lat’]!="") $lat= $_GET[‘lat’];
            if ($_GET[‘lon’]!="") $lon= $_GET[‘lon’];
            $dateTimeZoneLocal = new DateTimeZone($locn);
            $dateTimeLocal = new DateTime("now", $dateTimeZoneLocal);
            $localDateTime = date("H:i l d-m-y", time());
            $sun_info = date_sun_info($localTime, $lon, $lat);
            foreach ($sun_info as $key => $val) {
                if ($key==’civil_twilight_end’) $mqtt->publish("dusk",$val %86400),0);
                if ($key==’civil_twilight_begin’) $mqtt->publish("dawn",$val %86400,0);

No knocking my coding please – I do not profess to be a PHP expert – indeed – can you think of decent extra publications this page could produce for the little gadgets? If so lets have those ideas! 

This web page connects to your MOSQUITTO or other MQTT broker and every minute (every week if you want – my choice of every minute – gadget turns on – worse case it waits a minute to know the time) I am here publishing 4 items – the TIME in standard seconds-since-1970 format, British lighting up time (DUSK) in seconds since midnight, DAWN in seconds since midnight and TIMESTRING for those with no space in their project to format the time. ANY of my gadgets can choose to subscribe to these  publications – or not. And as you can imagine I’m planning more publications – timed an otherwise. The server load of the above is irrelevant – I don’t see anyone’s provider griping about this.

So – the people I’ve been with keep my web pages up and running 24-7 and and have done for as long as I can remember – why would I not trust this info.

And all of this brings us around to LUA+MQTT – possible only since this morning!!!

Check this out. Sorry it’s not formatted.

mqtt = net.createConnection(net.TCP, 0)
— init mqtt client with keepalive timer 30sec
mqtt:mqtt("myid", 30, "mymqttuser", "Tmqttpassmakeitagoodone")

— on publish message receive event
mqtt:on("receive", function(conn, topic, data) print(topic .. ":" .. data) end)
— on connection event (all event inherit from net module)
mqtt:on("connection", function(con) print("connected") end)
— subscribe topic with qos = 0
mqtt:subscribe("time",0, function(conn) print("subscribe success") end)
— publish a message
— mqtt:send("/topic","hello",0,0, function(conn) print("sent") end)

print (node.heap())

mqtt:subscribe("temperature",0, function(conn) print("subscribe success") end)

mqtt:send("dusk","hmm",0,0, function(conn) print("sent") end)

THAT which you see above and the code to log into your access point (which, once entered should stay there) is it – that code is all I had to put in – to have the little board be subscribing to time, dusk, dawn and temperature from another device (oh – a pair of minuses means comment – you need to see how to publish).

The REST is what you do with such info – Lua has timers (to keep that time going if you lose the internet connection) and GPIO control – to do things – already discussed previously – I’ve had a solid state relay running directly off the board and powering a mains lamp.

And that is it for now – the information isn’t here – it’s out there – check out the links here and in my previous blogs and bear in mind that before Christmas I knew NOTHING about compiling this stuff and I was determined determined not to get into Linux (and still successfully avoiding it)  – I’m now just about ready to openhabproperly embark on some real projects with real control in the comfort of my pretty-coloured Windows environment…  I hope that by putting all of this in one place gives you a head start.

For my next challenge – OpenHab but I think I’ll wait until the flu has gone – this one’s not going to be easy.

ESP8266 MQTT Publications

The PlanIn my last blog I referred to publishing temperature etc and there is one issue with the existing MQTT library that makes that an issue: The MQTT publications are not queued.

For the benefit of anyone still not into the MQTT thing – by publications I mean “sending a message” comprising a topic and a message. The topic might be “BathroomTemperatureReading” and the message might be “20.6”.

What happens right now – and Tuan has said he’ll fix this… if you send 2 messages out in a row IMMEDIATELY after each other – only the last one will go. Well, that’s fine unless you have to send one message off to a thermometer display and another message off to a humidity display.

So… this evening I wrote a queue. This is possible because of a “callback routine”. When you fire a message off it is handled in the background and when it’s done it calls an empty routine. I’ve trapped that.. the basic idea is this.  

Clear a “done” flag at the start and from there on..

If the done flag is clear, set it and send out a publication. If it is NOT clear, put the message in a queue.

In the callback routine, clear the flag – check a queue, if there is anything to go – send out the publication.

Simple really.

So here’s the code I’ve added to the start of the MQTT package..

#define QUEMAX 10  // 10 messages -  need more? – increase
#define QUESIZE 50 // my topics and messages are never more than 50 chars
struct Queues{
    MQTT_Client* cli;
    char top[QUESIZE];
    char mes[QUESIZE];

struct Queues myQueue[QUEMAX];

int queuein=0;
int queueout=0;
int isPublished=0; // my flag to see if I can publish or need to put in a queue

All simple enough – the queue can be maximum 10 deep (it’s rotary – when I get to the end I roll around to the start). I save the client pointer, the topic text and the message text in an array of simple structs.

At the beginning both the in pointer and out pointers for the queue are cleared and isPublished is clear.

Instead of the main publish routine – I have my own – which checks the flag before sending off a message.

void petesPub(MQTT_Client* cli, char *top, char *mes)
if (isPublished==0)    { isPublished=1; MQTT_Publish(cli, top,mes,strlen(mes), 0, 0); }
    if (++queuein>=QUEMAX) queuein=0;

You can see the message going in the queue unless the flag is clear… and in the callback routine, called when a message has gone…

void mqttPublishedCb(uint32_t *args)
    MQTT_Client* client = (MQTT_Client*)args;
    INFO("MQTT: Published\r\n");
    if (queuein!=queueout)
        if (++queueout>=QUEMAX) queueout=0;

The first two lines were there already – I don’t think I actually need to store the client info – I think it gets passed – however – what I have works for now.

So you can see I clear the published flag, look to see if there is anything in the queue and if there is – publish it. I’m sure there’s a bit of recursion going on there – but it all works.

And that’s me done for the day. Meetings again this week so I’ll not get much more done now until the weekend but DHT22, RTC and message queue – not a bad start for the week.

I’m still begging anyone with assembly skills to look at the WS2812B code to see if they can make an accurate job of it Smile

ESP8266 Memory Usage

debugGlen Cook has just made a neat little utility for checking the amount of RAM in Eclipse projects…  here’s the output – and there’s a link below – contact Glen, not me for more info.

Part of the problem of working with new processors – is understanding what is being used and where.  I look forward to seeing a visual version of this with used RAM, FLASH etc. and showing what’s used and what’s left. It would not be the first time I’ve run out of RAM.

Also linked to on my ESP8266 Facebook page.

Does anyone know the significance of the IRAM (initialised RAM) as in one project I’m down to 800 bytes – while having 38K of general RAM left.

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

float temperature,humidity;

#define DELAY 30000 /* milliseconds for temperature */

in the init() routine set up GPIO2


#define LED_GPIO 2

float temperature,humidity;

#define DELAY 30000 /* milliseconds for temperature */

in the init() routine set up GPIO2


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);
    GPIO_OUTPUT_SET(2, 0);
    GPIO_OUTPUT_SET(2, 1);

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


    // read data!

    for (i = 0; i < MAXTIMINGS; i++) {
        counter = 0;
        while ( GPIO_INPUT_GET(2) == laststate) {
            if (counter == 1000)
        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;

    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…


Put this at the top of your program

LOCAL os_timer_t temperature_timer;

Put this in your init…

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)

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_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)