Adding WiFi To The Pico 2
Written by Harry Fairhead   
Monday, 19 August 2024
Article Index
Adding WiFi To The Pico 2
Connecting the ESP8266 ESP-01
Attention!
Some Utility Functions
Connecting to WiFi
Sending Data
A Web Server
Complete Listing Of Web Server

Some 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:

int getVersionWiFi(uint8_t buf[], int len)
{
uint8_t SendData[] = "AT+GMR\r\n";
uart_write_blocking(uart1, SendData, 8);
return getBlock(buf, len);
}

The device in use returned:

AT+GMR 
AT version:1.3.0.0(Jul 14 2016 18:54:01) SDK version:2.0.0(5a875ba) v1.0.0.3 Mar 13 2018 09:35:47 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.

Reset is another useful function. 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 what the device sends varies:

int resetWiFi(uint8_t buf[], int len)
{
uint8_t SendData[] = "AT+RST\r\n";
uart_write_blocking(uart1, SendData, 8);
return getBlock(buf, len);
}

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(uint8_t buf[], int len)
{
uint8_t SendData[] = "AT+UART_CUR=115200,8,1,0,0\r\n";
uart_write_blocking(uart1, SendData, 28);
return getBlock(buf, len);
}

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 ESP8266 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(uint8_t buf[], int len, int mode)
{
uint8_t command[32];
int count = snprintf(command, 32,
"AT+CWMODE_CUR=%d\r\n", mode);
uart_write_blocking(uart1, command, count);
return getBlock(buf, len);
}

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 memory. Older devices do not support CWMODE_CUR. Simply change it to CWMODE, which is deprecated.

To set client you would call:

modeWiFi(buf, 512, 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 using the getBlock function as it will time out due to the long pauses. 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(uint8_t buf[], int len, int num, 
char target[])
{
for (int i = 0; i < num; i++)
{ if (uart_is_readable_within_us(uart1, 1000 * 1000))
{
getBlock(buf, len);
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 – as written it simply throws this data away.

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

int scanWiFi(uint8_t buf[], int len)
{
uint8_t SendData[] = "AT+CWLAP\r\n";
uart_write_blocking(uart1, SendData, 18);
return getBlocks(buf, len, 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(buf,len,20,"OK"), which will improve the reliability of the program. 



Last Updated ( Saturday, 24 August 2024 )