Working away with the hardware and software for the modified AI-Thinker T5 board, I decided that it was time to shoehorn the thing into a project case and throw it outside, to measure our night-time lows. Following this line of thought along, I decided I’d have a go at implementing OTA (Over-The-Air) updates, as it would start to get difficult to do updates if I had to climb a ladder with a screwdriver in one hand and the laptop in the other (following the thought even further along, I realised that it was going to be pretty tough to do an OTA update on a device that sits in deep-sleep mode for 99% of the time …but we’ll cross that particular bridge if we ever get to it). Now anyone who’s worked with any of the ESP8266 toolchains over the past year or so can probably guess what I’m going to say next. When you change anything with the ESP, you always run into, not just another problem, but a whole extended family (including in-laws) of problems. I haven’t found any exceptions to this rule to date and I didn’t this time, either.
I was already using v1.6.6 of the Arduino-IDE, but the ArduinoOTA program for the ESP requires v1.6.7 so, not without a little trepidation, I dutifully upgraded. There were no massive problems. The IDE fired up again straight away and recompiled my existing application code with n’er a murmur. I started to get suspicious. Where were the big red flashing warnings? Why hadn’t my cat spontaneously combusted? It’s too quiet!
Moving cautiously on with the plan, I opened the demo application, BasicOTA.ino, in the IDE, compiled it (successfully, again) and then, still using the USB serial adapter, squirted it to the ESP8266 on the T5. A few seconds afterwards I saw the “Ready” message and an IP address for the board appear in the IDE serial console window. At this point I had to heave a fairly major sigh of relief …I’d finally hit a problem …all was as it should be in the ESP world. It was a very, very minor problem, though. The newly minted IP address for the ESP should have shown up in the Arduino-IDE “Tools” menu as an available programmer, but it didn’t. However, the OTA documentation warns that this might happen and suggests simply restarting the IDE, which works just fine. After the restart, I was able to load the original DHT_Test.ino firmware to the ESP8266, hands free. No holding down the program switch while restarting; just choose the newly available network device as the “programmer”, hit the button and away it goes. It’s fast, too! The OTA update only took roughly half the time of the USB method (and I’m not even counting “fiddling with switches” time).
Okay, next step. We need (according to the documentation) to put the code for the OTA functionality into the target application itself, because the OTA code doesn’t sit in some separate, compartmentalized box somewhere in the ESP memory space, it just gets mixed right in there with everything else (so when I programmed my original DHT_Test code in that previous step as a test of the OTA functionality, it overwrote the OTA which was in memory and I lost the ability to do OTA updates again. Duh!).
The documentation suggests that we should take the BasicOTA.ino code and just pop it into the target application, giving a fairly easy-to-follow layout, too. So, we need to add a couple of extra includes. Nothing too exciting there. And then we need to add the OTA callbacks into the
setup() section of the code. This looks a bit weird to me. I’m worried that the code in the example may have been corrupted by the markdown editor, because there are far too many square-brackets and parentheses in there. However, the code looks the same as the BasicOTA.ino code and I know that worked, so I just quickly check with Oogleg and, having found the identical code in another tutorial, do a quick cut-and-paste. Having dropped it into what looks approximately like the right-ish area, I save the file and, out of habit, run indent on it. Oops! very bad move. Indent says, “There’s far too many square-brackets and parentheses in there. It’s given me a right headache and I’m going to puke all over your shoes.”, which it promptly did (figuratively, anyway). After cleaning up the mess (not that difficult when you have
a dog an automatic back-up file), I went back in and inserted those magic, indent incantations,
/* *INDENT-OFF* */ and
/* *INDENT-ON* */ above and below the weird OTA code and ran indent again, without a problem this time.
Now then, I need to put an
ArduinoOTA-handle() call into the
loop() section of the code. Oh dear! The only thing in my loop is a needlessly sarcastic comment and a call to
ESP.restart(), just in case the program ever somehow, mistakenly drops through into it. Bugrit! Never mind, I’ll just try a quick compile to see whether what I already have blows anything up. Tra-la-la, IDE, reload, compile, BLAM! Futtocks! Now what? Maybe indent was right after all!
I’m staring at a simple error message which tells me that I have an error in my lambda function (Wow! Kinky! I don’t think I’ve ever knowingly used a lambda before) and that OTA_RECEIVE isn’t defined in this scope. Eh? I check that I have
ArduinoOTA.h included. I quickly check the include file itself and note that there’s an error enum define which looks okay to me. I check the order of the includes and lose some more time re-compiling with different combinations of includes, all to no avail. I’m just about to do what I should have done in the first place (copy the whole BasicOTA.ino file into my code and use the sections verbatim) when I got the urge to fire up “screen” and use the side-by-side mode (CTL-a followed by the pipe “|” character, if yuz didn’t already knaa) to check those small sections of code directly. Whaddyaknow! My cut-and-paste code, “RECEIVE”. BasicOTA.ino, “RECIEVE”. Bugrit! I go back and take a closer look at the include file. Same spelling error. Rats! I fire up GitHub, go to the ESP8266/Arduino/libraries/ArduinoOTA …and find that Stavros Korokithakis has already fixed it a couple of months back (thanks for that, Stavros. The tiny ESP8266 breakout board looks great, by the way).
Onwards and upwards! So, I fire up the library manager in my squeaky new 1.6.7 Arduino-IDE and have it update da-woyks! I restart the IDE, fire up another compile and find that the OTA_RECEIVE error is magically gone …to be replaced by the much more verbose:-
/tmp/build319.tmp/libraries/esp-mqtt/mqtt/mqtt.c.o:(.bss.default_private_key_len+0x0): multiple definition of `default_private_key_len'
/tmp/build319.tmp/libraries/ESP8266WiFi/WiFiClientSecure.cpp.o:(.bss.default_private_key_len+0x0): first defined here
/tmp/build319.tmp/libraries/esp-mqtt/mqtt/mqtt.c.o:(.bss.default_certificate_len+0x0): multiple definition of `default_certificate_len'
/tmp/build319.tmp/libraries/ESP8266WiFi/WiFiClientSecure.cpp.o:(.bss.default_certificate_len+0x0): first defined here
collect2: error: ld returned 1 exit status
Hmmm! I suppose that the OTA_RECEIVE was just a second cousin (think extended families). This one is definitely a wicked uncle-Ernie, fiddling about (insert air guitar here …only old codgers need apply).
I don’t have much of a clue on where to start with this one, other than the obvious MQTT library. Unfortunately, that particular library hasn’t been updated for a few months and definitely wasn’t changed by my library update. I’m starting to run out of patience with the extended family though, so after some more “fiddling about” of my own, I take the path of least resistance and comment out the defines in
mqtt.c. Why that file and not the ESP8266WiFi stuff? Well, ESP8266WiFi is core and if the lengths are defined there, they’ll get carried through to any other lib in a project which depends upon them (that might not be true in Arduino land, where you need a separate bit of hardware for networking, but I’m fairly sure I’ll be using wireless in everything I do with the ESP …and definitely if I’m using MQTT).
And finally, a clean compile.
It still doesn’t work, of course (no call to the
ArduinoOTA-handle() routine), but I’ve had enough for one day and decide to end the evening on a relatively high point.