ESP8266 and IBM IoT on Bluemix
Hickmat 100000QA3T Comments (2) Visits (11006)
In January I stared picking up tweets commenting about the capabilities of the ESP8266 Wifi-to-Serial module and more importantly that a port of MQTT had been done for it already. So not one to like to miss out on a bit of fun I decided to get myself a couple of this devices and have a play at connecting them to my IBM IoT Service running in Bluemix.
First thing I needed to do was make sure that along with the devices I picked up a FTDI USB to TTL Serial Adapter Module as my reading up on the ESP8266 showed that if I wanted to be able to re flash the ROM I was going to need to connect with it via a serial connection. Once all the hardware arrived I set about building up a development environment on one of my spare Thinkpads (I have a few old ones I keep for random tinkering ). The operating system I had on the Thinkpad was Debian Wheezy and it was a breeze to set up the necessary tool chain by following the instructions in the ESP8266-Wiki which can be found HERE.
With the toolchain in place I did a quick test to make sure I could build and flash the sample "Blinky" code to one of my ESP8266's. This took a bit of fiddling around and reading up on the web as the pin config for the ESP8266 is not necessarily 100% clear when you first look. A good resource to look at for setting things up is this one. In addition to connecting RX and TX, PWR and GRN you need to make sure the CH_PD is held HIGH and GPIO0 is held LOW. In addition I found that I some times and to flick RST LOW in order to reset the device ready for flashing.
As everything was now in place I turned my attention to the task in hand and pulled down esp-mqtt from GitHub. After updating user_config.h (in ./include) to reflect my WiFi and Mosquitto I compiled and flashed the code onto my ESP8266 and then fired up minicom on my Thinkpad so I could monitor the execution of the code. This is where I hit my first problem. I could see the connect to the broker flowing and a connection being set up but I couldn't get any messages to flow. Looking at the output coming from my Mosquitto instance I could see that I was getting issues related to the MQTT protocol version. I started to look at the structure of the MQTT code and then I spotted that a new version of esp-mqtt had been released which addressed this very problem. With the new code pulled down and my user_config.h copied across I re-tired to code and this time it worked like a dream.
So with a working code base I began to look at how to modify it to connect to my IBM IoT service instance running on Bluemix. The majority of this was simply a case of updating the user_config.h to align with the connection requirements of IBM IoT. The result was as follows:
#define CFG_HOLDER 0x00FF55A4 /* Change this value to load default configurations */
#define CFG_LOCATION 0x3C /* Please don't change or if you know what you doing */
#define MQTT_HOST "<or
#define MQTT_PORT 1883
#define MQTT_BUF_SIZE 1024
#define MQTT_KEEPALIVE 120 /*second*/
#define MQTT_CLIENT_ID "DVES_%08X" // This doesn't work for IBM IoT so over ridden in user_main
#define MQTT_USER "use-token-auth" // Set to drive authentication based on Token created during registration
#define MQTT_PASS "<IBM IoT Token from registration process>" // Set to the Token created during client registration
// Set to values for connecting to local WiFi
#define STA_SSID "<Your SSID>"
#define STA_PASS "<Your password>"
#define STA_TYPE AUTH_WPA2_PSK
#define DEFAULT_SECURITY 0
#define QUEUE_BUFFER_SIZE 2048
#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/
//PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with http
As you can see from the comments above I found that I had an issue if I pushed my IBM IoT registered device ID in to the MQTT_CLIENT_ID define. The issue was related to the fact that the code plugs in the chip id into the MQTT_CLIENT_ID slot in the in memory config. To over come this I pushed the passing of the registered device ID into the user_main.c code. Next I set up a couple of #define statements to hold the publish and subscribe topics and updated the base code to pass a valid IBM IoT JSON message payload. This allowed me to test connectivity and showed that I could indeed connect to my Bluemix service.
So with the barebones in place I looked at building a simple demo where I would toggle an LED connected to GPIO2 on my ESP8266 and in addition publish regular messages giving the status of the LED i.e. ON or OFF. Code wise I used the "Blinky" sample code from the ESP toolkit to show how to drive the GPIO which then left me with the challenge of how to regularly push messages from the ESP8266. Reading some of the documentation (which is a little limited just now) for the ESP SDK I could see that the SDK provides an os level timer driven processing loop. To use this a callback function is registered and this is called when the timer fires. The problem I had was that this was already being used to support the MQTT protocol and as far as I could tell only one callback could be registered. Looking at the code in more detail I could see that the code uses a structure called MQTT_Client to hold the callbacks for events like message received etc. The approach I took was to extend this structure to add a general callback which would get called every time the os level timer driven MQTT callback was invoked. As this meant that the additional callback would be called EVERY time the timer fired I had to add some code to the callback function to only publish a message after a number of invocation calls. The os time was set to fire every 1 second so it was a relatively simple task to set up a global counter and use this to manage the time between posts. I then updated the MQTT_OnData registered function to control the state of the LED via GPIO2. That completed the code changes and I flashed the code to my ESP8266 and this is where I hit a number of issues
The first problem was that when I restarted my ESP8266 with GPIO2 connected it just locked up.... Hmmm back to some reading and I found that I needed to delay connecting the LED to GPIO2 until the initial boot sequence was triggered. As I didn't have time to build a circuit to do this I simple relied on plugging the GPIO2 jumper cable into my breadboard at the appropriate time - which worked. This then lead me on to the next problem in that the LED came on but refused to be controlled. I knew the code should work as the "Blinky" example code worked just fine. After digging around a trying a number of configurations I determined that the issue was related to the use of the UART code. As I was only using this code to print out debug statements with the serial connection to my Thinkpad I decided to comment out this from user_main.c. With this commented out the control of the LED worked fine.
The final step was to create a very basic NodeRED flow in my Bluemix account to receive the posts from my ESP8266 and allow a message to be pushed to the ESP8266 to toggle the LED. Using this I checked the flow of messages and the toggling of the LED all of which worked treat.
So I now have a good working base for link an ESP8266 to IBM IoT running on Bluemix, going forward I plan to look at linking one of my ESP8266's with one of the many Arduino Nano's and also have a crack at driving GPIO0 as well as GPIO2 on the ESP8266 (which for some reason is proving to be trickier than I expected).