Raspberry Pi WiFi With The ESP8266
Written by Harry Fairhead   
Monday, 12 September 2016
Article Index
Raspberry Pi WiFi With The ESP8266
AT Commands
Some Utility Functions
Getting A Web Page
A Web Server
Listing

Some Utility Functions

Before we get into the details of connecting to a network and transferring data it is worth constructing some useful utility functions.

Assuming that you have managed to make the AT command work it is time to move on to other AT commands. The first useful command is to find the Version number of the firmware. This is more or less the same as the AT function, but the command is AT+GMR and we get back more data - hence the longer wait time:

int getVersionWiFi() {
 dprintf(sfd, "AT+GMR\r\n");
 return getBlock();
}

The device in use returned:

AT+GMR
AT version:0.60.0.0(Jan 29 2016 15:10:17)
SDK version:1.5.2(7eee54f4)
Ai-Thinker Technology Co. Ltd.
May  5 2016 17:30:30
OK

The manual says that it should return AT, SDK and the time it was compiled - so we get a little extra with this third party device.

Another useful function is Reset. The device often gets stuck and then a reset is all that you can try. This is a software reset; another option is to use a GPIO line to connect to reset pin 6. By controlling this line you can force the device to hard reset. 

The soft reset command is AT+RST and all you get back in theory is "OK", but in practice the device sends a few hundred bytes of configuration data:

int resetWiFi() {
 dprintf(sfd, "AT+RST\r\n");
 return getBlock();
}

The final utility function is to set the serial connection parameters to 115200, 8 bits, 1 stop bit, no parity, no flow control:

int setUARTWiFi() {
 dprintf(sfd, "AT+UART_CUR=115200,8,1,0,0\r\n");
 return getBlock();
}

If you change the baud rate to something other than what is in use you will, of course, lose communication with the device until you reconfigure the serial connection. 

Configuring WiFi

The first thing we need to configure is the operating mode. The ESP8622 can operate as an access point, i.e. it can allow other devices to connect to it. However, in most cases you will want it to work in client mode, i.e. connecting to your existing WiFi. 

Mode

A function to set its operating mode is:

int modeWiFi(int mode) {
 dprintf(sfd, "AT+CWMODE_CUR=%d\r\n", mode);
 return getBlock();
}

In this case the command is: 

AT+CWMODE_CUR=n

where n is 1 for client, 2 for access point and 3 for both.  If you want to make the change permanent then change CUR to DEF and the setting is stored in Flash. 

Older devices do not support CWMODE_CUR. Simply change it to CWMODE, which is deprecated.

To set client you would call:

modeWiFi(1);

and see OK sent back.

Scan

The scan function is one that everyone wants to try out, but in practice it isn't very useful. Why would you want a list of WiFi networks? There are some applications for this function, but not as many as you might think. In most cases you simply want to connect to a known WiFi network - which is what we do in the next section.

The scan command is easy - just send AT+CWLAP and the device sends you a complete list of WiFi networks.

The problem is that scanning takes a long time and often hangs for a few seconds - clearly we can't simply read a single block of data. We need a more powerful reading function that retrieves multiple blocks with an overall timeout. While it is doing this it might as well also scan the incoming data for a target like "OK" to use as a signal that it can stop reading blocks;

int getBlocks(int num, char target[]) {
 int i;
 struct timespec pause;
 pause.tv_sec = 1;
 pause.tv_nsec = 0;
 for (i = 0; i < num; i++) {
  nanosleep(&pause, NULL);
  getBlock();
  if (strstr(buf, target))return i;
 }
 return -1;
}

Notice that we try to retrieve a maximum of num blocks and wait 1 second between trying each. If a block contains the target string then we return with the number of blocks read. The getBlock function is used to get each block and it displays what it has retrieved if DEBUG is set to 1. In a more sophisticated application you would probably want to concatenate the received blocks into a single larger buffer for further processing. 

Now we can retrieve multiple blocks we can implement the scan function:

int scanWiFi() {
 dprintf(sfd, "AT+CWLAP\r\n");
 return getBlocks(20, "OK");
}

In this case the function is set to retrieve a maximum of 20 blocks, which could mean waiting as long as 20 seconds for the function to exit. However, in most cases it exits after only a small number of blocks because it detects an "OK".

The getBlocks function is so useful that you might as well go back and change the call to getBlock to getBlocks(20, "OK") which will improve the reliability of the program. 

Connecting to WiFi

Our final and most useful functions connect the device to a known WiFi network. All you have to do is supply the SSID and password. There are other versions of the command that allow you to specify the connection more precisely, but this general form is the most useful. 

Connection to a network takes a while and there is quite a lot of data sent back, so we need to use a long timeout in the getBlocks function introduced in the scan function:

int connectWiFi(char ssid[], char pass[]) {
 dprintf(sfd, "AT+CWJAP_CUR=\"%s\",\"%s\"\r\n",
                                   ssid, pass);
 return getBlocks(20, "OK");
}

Notice the way the dprintf command is used to insert the ssid an password into the command. 

If you have an older device you might need to change CWJAP_CUR to the deprecated CWJAP command. There is also a CWJAP_DEF command that will save the connection in the Flash memory. 

When the connection is made:

connectWiFi("myWiFi","myPassword");

after a few seconds you should see:

AT+CWJAP_CUR="myWiFi","myPassword"
WIFI DISCONNECT
WIFI CONNECTED
WIFI GOT IP
OK

Once you are connected and the "WIFI GOT IP" message has been received you can ask what the IP address is:

int getIPWiFi() {
 dprintf(sfd, "AT+CIFSR\r\n");
 return getBlocks(10, "OK");
}

Of course, if you really need to know the IP address within a program you need to extract it from the string. The device replies with:

IP address:
AT+CIFSR
+CIFSR:STAIP,"192.168.253.4"
+CIFSR:STAMAC,"5c:cf:7f:16:97:ab"
OK

This makes it very easy to get the IP address even without the help of a regular expression. 

 



Last Updated ( Monday, 12 September 2016 )