Micro:bit - Getting On WiFi |
Written by Harry Fairhead | ||||||||
Monday, 11 July 2022 | ||||||||
Page 2 of 7
AT CommandsThe key idea in using the ESP8266 is that the micro:bit has to send an AT command, literally the characters AT, followed by other command strings. The command has to end with \r\n for the ESP8266 to take notice of it. You can find a full list of commands at the Espressif website, but the most important are: AT Attention AT+RST Reset the board AT+GMR Firmware version This is just a very general overview and omits the commands that allow the device to work as an access point. It is assumed that client mode is the more common application, but it isn't difficult to extend this example to access point operation. SetupWe need a function to set up the hardware ready to communicate with the device: V1 void initWiFi() { uBit.serial.redirect(Tx, Rx); uBit.serial.baud(115200); uBit.serial.setRxBufferSize((uint8_t)+500); } V2 void initWiFi() { uBit.serial.redirect(uBit.io.P1 , uBit.io.P2); uBit.serial.setBaudrate(115200); uBit.serial.setRxBufferSize((uint8_t)+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: V1 #define Tx MICROBIT_PIN_P0 #define Rx MICROBIT_PIN_P1 V2 #define Tx uBit.io.P0 #define Rx uBit.io.P1 The model of ESP8266 used works at 115200 baud by default. Newer models and up-dated firmware are 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". 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. 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 for a human. 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); } For V2 you also need: #define USBTX uBit.io.usbTx #define USBRX uBit.io.usbRx 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 10ms and 9600 baud takes just more than 100ms, 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 150ms 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 |
||||||||
Last Updated ( Tuesday, 12 July 2022 ) |