Micro:bit IoT In C - Getting On WiFi
Written by Harry Fairhead   
Saturday, 16 July 2016
Article Index
Micro:bit IoT In C - Getting On WiFi
Setup
Utility Functions
Getting A Web Page
A Web Server
Listing

Setup

We need a function to set up the hardware ready to communicate with the device:

void initWiFi() {
 uBit.serial.redirect(Tx, Rx);
 uBit.serial.baud(115200);  uBit.serial.setRxBufferSize(500);
}

The pins that we are using are P0 and P1, but to allow for other choices Tx and Rx are defined as constants at the start of the program:

#define Tx MICROBIT_PIN_P0
#define Rx MICROBIT_PIN_P1

The model of ESP8266 used worked at 115200 baud by default. Newer models and up-dated firmware is reported to work at 9600 baud. If this is the case you need to modify the data rate and/or change the ESP8266's baud rate. 

Attention!

To start with the easiest, but possibly least useful, command let's implement some functions that test that we have a connection to the device - always a good thing to start with. 

In this section we develop the first of a number of functions that send a command to the device and get back a response. To do this we need a few other functions to help and these are reused in other AT functions. Once you have one AT function the rest are very similar so it is worth spending some time following how this most simple AT function works.

If you send the string AT\r\n then the ESP8266 replies with a single "OK". Not much but it proves that the serial interface is working and there isn't much point in moving on until you have tested that AT works.

The AT function is simply:

int ATWiFi() {
 uBit.serial.send("AT\r\n", SYNC_SPINWAIT);
 return 1;
}

You have to use SPINWAIT because things go wrong when you let the fiber continue to process while the data is being transmitted. 

This is the most basic form of function that will do the job but it isn't really practical. We need to check that it works and we need to get some feedback. 

To get feedback we could read what is sent back and then display it on the LED display. This would work, but reading the LED display is very slow. A better idea is to send the data to the USB serial console when in a "debug" mode. The problem with this is that every time you switch pins the serial device generates spurious characters. If we switch after receiving the entire message rather than on each character we can minimize the spurious characters - which the ESP8266 seems to ignore. 

A function to swap to and from the USB pins and send the data is easy:

void debug(ManagedString s) {
 uBit.serial.redirect(USBTX, USBRX);
 uBit.serial.send(s, SYNC_SPINWAIT);
 uBit.serial.redirect(Tx, Rx);
}

Now all we need to do is read the data sent back from the device. The simplest way of doing this is to wait for a period of time that means that the device has to have sent the data or there is something wrong. As 115200 baud allows for more than 100 characters in 10 milliseconds and 9600 baud takes just more than 100 milliseconds you can estimate the time you need to wait for any packet of text to be delivered.

As the response to the AT request only sends a few characters waiting 150 milliseconds is more than enough at any baud rate. We can then read the entire buffer:

uBit.sleep(150);
ManagedString s = uBit.serial.read(500, ASYNC);

Reading in ASYNC mode means that the function will return as many characters are in the buffer as a managed string.

If the AT command has been successful it returns a string containing "OK". One of the problems of working with AT commands is that they don't have an exact syntax and there is no formal "end of message" signal. By observation, any successful command does end with "OK" and if you can't find "OK" in the response then you either haven't read it all or there has been an error. 

Clearly we need a way to test if a string contains "OK";

int find(ManagedString c, ManagedString s) {
 int i; for (i = 0; i < (s.length() - c.length()); i++){
  if (c == s.substring(i, c.length())) break;
 }
 if (i == (s.length() - c.length())) return 0;
 return 1;
}

This is the simplest string scanning function that will do the job. It only checks that the string c is in s once and it will find c if it is embedded in another word. So it will find "OK" in "NotOK" for example.  

With all of this we can now finish the ATWiFi function:

int ATWiFi() {
 uBit.serial.send("AT\r\n", SYNC_SPINWAIT);
 uBit.sleep(150);
 ManagedString s = uBit.serial.read(500, ASYNC);
 if (DEBUG)debug("\n\rAT \n\r" + s + "\n\r");
 return find("OK", s);
}

If the constant DEBUG is a 1 then the string is printed to the USB port and you can examine it. 

#define DEBUG 1

Put all this together with a main program:

#include "MicroBit.h"
MicroBit uBit;
void initWiFi();
int ATWiFi();
int find(ManagedString c, ManagedString s);
void debug(ManagedString s);

#define Tx MICROBIT_PIN_P0
#define Rx MICROBIT_PIN_P1
#define DEBUG 1

int main() {
 initWiFi();
 ATWiFi();
 while (1)uBit.sleep(1000);
 release_fiber();
}

void initWiFi() {
 uBit.serial.redirect(Tx, Rx);
 uBit.serial.baud(115200);
 uBit.serial.setRxBufferSize(500);
}

int ATWiFi() {
 uBit.serial.send("AT\r\n", SYNC_SPINWAIT);
 uBit.sleep(150);
 ManagedString s = uBit.serial.read(500, ASYNC);
 if (DEBUG)debug("\n\rAT \n\r" + s + "\n\r");
 return find("OK", s);
}

void debug(ManagedString s) {
 uBit.serial.redirect(USBTX, USBRX);
 uBit.serial.send(s, SYNC_SPINWAIT);
 uBit.serial.redirect(Tx, Rx);
}

int find(ManagedString c, ManagedString s) {
 int i;
 for (i = 0; i < (s.length() - c.length());i++) {
  if (c == s.substring(i, c.length())) break;
 }
 if (i == (s.length() - c.length())) return 0;
 return 1;
}

When you run this program then you should see: 

AT

OK

Printed on the serial console. If you don't there are five possible reasons:

  1. You have connected the wrong pins - check
  2. The power supply you are using is inadequate - check/replace
  3. The serial console isn't working - check you can see any message sent to it.
  4. The baud rate is wrong - try 9600
  5. The ESP8266 is broken - try another


Last Updated ( Friday, 26 August 2016 )