The Arduino library you must use with the AirLift is a variant of the Arduino WiFiNINA library because the official WiFi101 library doesn't support the ability to change the pins. However, this library will not recover a temporarily lost WiFi connection. The return value from WiFi.begin() returns WL_CONNECTED when successfully connected, and when NOT connected to the WiFi. The client.connected() method always reports a value of 0, when the WiFi is and is not connected. The only reliable method of determining a connection is when you actually connect to a server with client.connect(SERVER,PORT).
The SOLUTION is to connect a GPIO pin to the AirLift / ESP32 module ESPRST pin and pull it LOW to reset the ESP32 module. Don't pull it low through a resistor, wire it directly (a 10 k resistor didn't work). In setup(), set the GPIO pin as output and pull it HIGH. Then in your code when you detect a client.connect() has faile, pull it low briefly with the GPIO pin, then pull HIGH and wait 10 seconds for the ESP32 to restart. The exact timing was not optimized, but it works. With the AirLift FeatherWing connected to the M4 Express SAMD51 Feather, I used pin #16/A2 (Arduino reference).
This FeatherWing adds WiFi in the form of an ESP32 chip. The ESP32 WiFi co-processor handles the tough work of connecting to a WiFi network and transferring data, including using the latest TLS/SSL encryption (root certificates pre-burned in). Send basic socket-based comments over SPI from a M0 or M4 Feather (Feather M4 or nRF52840 for CircuitPython). As of June 2022, connection to Enterprise WiFi is not supported. BLE (Bluetooth Low Energy) is also supported, but not simultaneously with WiFi.
Using the AirLift with the Feather M4 Express SAMD51 I was able to HTTPS GET/POST and only use 7% of the available memory on the MCU. Using the AirLift ESP32 co-processor frees up the MCU to focus on sensor data collection and processing.
RGB LED connected to pin #26 (red), #25 (green), and #27 (blue). The I2C pins I2C SCL (22) & SDA (21) are not used and are available for I2C or GPIO. Free pins are 14/A0, 15/A1, 16/A2, 17/A3. (all Arduino pin references, not CircuitPython).
Only about 250 mA available on 3V pin from the 3.3V regulator (250 mA used by ESP32).
The pinout diagram below is organized to lay over the physical footprint of the devices when they are oriented with the USB connector at the top, and looking from the top of the devices (header pins pointing downward).
AirLift FeatherWing |
Feather M0 Basic |
Feather M4 Express |
| | AirLift FeatherWing |
Feather M0 Basic |
Feather M4 Express |
---|---|---|---|---|---|---|
RST | RST | RST | | | --- | --- | --- |
3V3 | 3V3 | 3V3 | | | --- | --- | --- |
NC | ARf | ARf | | | --- | --- | --- |
GND | GND | GND | | | --- | --- | --- |
A0 14 | A0 14 | A0 14 | | | Li+ | Vbat | Vbat |
A1 15 | A1 15 | A1 15 | | | EN | EN | EN |
A2 16 | A2 16 | A2 16 | | | Vusb | Vbus | Vbus |
A3 17 | A3 17 | A3 17 | | | ESPCS D13 LED |
D13 LED |
D13 LED |
NC | A4 18 | A4 18 | | | ESPRST | 12 | 12 |
NC | A5 19 | A5 19 | | | ESPBUSY | 11 | 11 |
24 SCK |
24 SCK |
25 SCK |
| | ESPGPIO0 | 10 | 10 |
23 MOSI |
23 MOSI |
24 MOSI |
| | NC | A7 9 | 9 |
22 MISO |
22 MISO |
23 MISO |
| | NC | 6 | 6 |
ESPRX | 0 | 0 | | | NC | 5 | 5 |
ESPTX | 1 | 1 | | | 21 SCL |
21 SCL |
21 SCL |
NC | GND | 4 | | | 20 SDA |
20 SDA |
22 SDA |
Color Key: SPI I2C GPIO free
The Arduino library you must use with the AirLift is a variant of the Arduino WiFiNINA library because the official WiFi101 library doesn't support the ability to change the pins.
Data transfer is over SPI, not UART Serial. You simply make the normal WiFi calls, and the library handles all of the communication details for you. The SPI bus may be shared with other FeatherWings.
/*
AF_Feather_M4_Express_SAMD51_AirLift.ino
Adafruit Feather M4 Express SAMD51 + AirLift FeatherWing ESP32 WiFi
In Arduino IDE, set board to 'Adafruit Feather M4 Express (SAMD51)'
If bootloading frozen, click RST button twice quickly.
The red LED will pulse and the RGB LED will be green when you are
in bootloader mode.
NeoPixel = green if OK, RED on USB failure.
The yellow “charging” LED flickers constantly whenever the Feather is powered by USB
Arduino C++ code or CircuitPython
WARNING: The Arduino IDE serial monitor causes setup() to wait until
the serial monitor IDE is run.
The script:
NeoPixel Red If WiFi is not connected, or server connection failure.
White Reset AirLift/ESP32
Cyan Connecting to server (HTTPS GET/POST)
Rainbow When loop() runs
AirLink FeatherWing RGB cyan when connecting to server
yellow if the server response != 200
PROBLEM:
If WiFi connection lost, cannot get device to recover connection.
Possible solution is to pull pin ESPRST to LOW to cause reset.
*/
// Turn on/off output to Arduino IDE serial monitor
#define DEBUG false
/////////////////////////////////////////////////////////////////////////
// Built in LED(s)
// WARNING: AirLift uses pin #13 for chip select!
//const uint8_t pinBuiltInLED = 13;
/////////////////////////////////////////////////////////////////////////
// Built-in NeoPixel (RGB LED)
//
// set it up as a single-LED strand on pin 8
const uint8_t pinBuiltInNeoPixel = 8;
#include <Adafruit_NeoPixel.h>
#define NUMPIXELS 1
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, pinBuiltInNeoPixel, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
const unsigned long neoPixelTimerInterval = 500;
unsigned long neoPixelTimerLap = millis(); // timer
void neoPixelRainbow() {
uint16_t i, j;
uint8_t maxBright = 4;
for(j=0; j<256; j++) {
for(i=0; i<pixels.numPixels(); i++) {
pixels.setPixelColor(i, WheelDim((i+j) & 255, maxBright));
}
if (neoPixelTimerLap > millis()) neoPixelTimerLap = millis();
if (millis() - neoPixelTimerLap > neoPixelTimerInterval) {
neoPixelTimerLap = millis(); // reset the timer
pixels.show();
}
}
} // neoPixelRainbow()
// A version of Wheel that dims pixels down for photos/video
// maxBright is from 0 to 255; low numbers are dimmer.
// NeoPixel brightness is nonlinear, so play with the maxBright number. I used 4 for recent video.
uint32_t WheelDim(byte WheelPos, uint8_t maxBright){
WheelPos = 255 - WheelPos;
uint16_t r = 0, g = 0, b = 0;
if(WheelPos < 85) {
r = 255 - WheelPos * 3;
b = WheelPos * 3;
} else if(WheelPos < 170) {
WheelPos -= 85;
g = WheelPos * 3;
b = 255 - WheelPos * 3;
} else {
WheelPos -= 170;
r = WheelPos * 3;
g = 255 - WheelPos * 3;
}
r = r * maxBright / 255;
g = g * maxBright / 255;
b = b * maxBright / 255;
return pixels.Color(r, g, b);
}
/////////////////////////////////////////////////////////////////////////
// Built-in 2 MB QSPI (Quad SPI) Flash chip
// (acts as storage that you can read/write files to)
// Connected to 6 pins not brought out to GPIO pads
// QSPI allows 4 data in/out lines.
// Arduino library: https://github.com/adafruit/Adafruit_SPIFlash
// See examples 'Adafruit SPIFlash'
// Full QSPI/SPI support with SdFat as the FAT filesystem manager
//
// Write speed : 546.99 KB/s.
// Read speed : 5698.78 KB/s.
#include "SdFat.h"
#include "Adafruit_SPIFlash.h"
// Uncomment to run example with custom SPI and SS e.g with FRAM breakout
// #define CUSTOM_CS A5
// #define CUSTOM_SPI SPI
#if defined(CUSTOM_CS) && defined(CUSTOM_SPI)
Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI);
#elif defined(ARDUINO_ARCH_ESP32)
// ESP32 use same flash device that store code.
// Therefore there is no need to specify the SPI and SS
Adafruit_FlashTransport_ESP32 flashTransport;
#else
// On-board external flash (QSPI or SPI) macros should already
// defined in your board variant if supported
// - EXTERNAL_FLASH_USE_QSPI
// - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI
#if defined(EXTERNAL_FLASH_USE_QSPI)
Adafruit_FlashTransport_QSPI flashTransport;
#elif defined(EXTERNAL_FLASH_USE_SPI)
Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, EXTERNAL_FLASH_USE_SPI);
#else
#error No QSPI/SPI flash are defined on your board variant.h !
#endif
#endif
Adafruit_SPIFlash flash(&flashTransport);
/////////////////////////////////////////////////////////////////////////
// AirLift FeatherWing ESP32 WiFi
// Small RGB LED to left of ESP32 on AirLift
// See: setLEDs()
// Note: Cannot use pinMode(), etc.
// WiFi library is variant of the Arduino WiFiNINA library
// (The official WiFi101 library won't work because it doesn't support the ability to change the pins)
// https://github.com/adafruit/WiFiNINA/archive/master.zip
// See Arduino IDE Examples under 'WiFiNINA'.
#include <SPI.h>
#include <WiFiNINA.h>
// Configure the pins used for the ESP32 connection
#if defined(ADAFRUIT_FEATHER_M4_EXPRESS) || \
defined(ADAFRUIT_FEATHER_M0) || \
defined(ADAFRUIT_FEATHER_M0_EXPRESS) || \
defined(ARDUINO_AVR_FEATHER32U4) || \
defined(ARDUINO_NRF52840_FEATHER) || \
defined(ADAFRUIT_ITSYBITSY_M0) || \
defined(ADAFRUIT_ITSYBITSY_M4_EXPRESS) || \
defined(ARDUINO_AVR_ITSYBITSY32U4_3V) || \
defined(ARDUINO_NRF52_ITSYBITSY)
// Configure the pins used for the ESP32 connection
// Feather M0, M4, 32u4, or NRF52840 (this Feather)
#define SPIWIFI SPI // The SPI port
#define SPIWIFI_SS 13 // Chip select pin
#define ESP32_RESETN 12 // Reset pin
#define SPIWIFI_ACK 11 // a.k.a BUSY or READY pin
#define ESP32_GPIO0 -1
#elif defined(ARDUINO_AVR_FEATHER328P)
#define SPIWIFI SPI // The SPI port
#define SPIWIFI_SS 4 // Chip select pin
#define ESP32_RESETN 3 // Reset pin
#define SPIWIFI_ACK 2 // a.k.a BUSY or READY pin
#define ESP32_GPIO0 -1
#elif defined(TEENSYDUINO)
#define SPIWIFI SPI // The SPI port
#define SPIWIFI_SS 5 // Chip select pin
#define ESP32_RESETN 6 // Reset pin
#define SPIWIFI_ACK 9 // a.k.a BUSY or READY pin
#define ESP32_GPIO0 -1
#elif defined(ARDUINO_NRF52832_FEATHER )
#define SPIWIFI SPI // The SPI port
#define SPIWIFI_SS 16 // Chip select pin
#define ESP32_RESETN 15 // Reset pin
#define SPIWIFI_ACK 7 // a.k.a BUSY or READY pin
#define ESP32_GPIO0 -1
#elif !defined(SPIWIFI_SS) // if the wifi definition isnt in the board variant
// Don't change the names of these #define's! they match the variant ones
#define SPIWIFI SPI
#define SPIWIFI_SS 10 // Chip select pin
#define SPIWIFI_ACK 7 // a.k.a BUSY or READY pin
#define ESP32_RESETN 5 // Reset pin
#define ESP32_GPIO0 -1 // Not connected
#endif
// Feather M0, M4, 32u4, or NRF52840
//#define SPIWIFI SPI // The SPI port
//#define SPIWIFI_SS 13 // Chip select pin
//#define ESP32_RESETN 12 // Reset pin
//#define SPIWIFI_ACK 11 // a.k.a BUSY or READY pin
//#define ESP32_GPIO0 -1
char ssid[] = "YourWiFiSSID"; // your network SSID (name)
char pass[] = "YourWiFiPassword"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS)
#define SERVER "postman-echo.com"
#define PATH "/basic-auth"
// Initialize the SSL client library
WiFiSSLClient client;
// Time in micros() of the last successful WiFi connection to the server.
unsigned long lastWiFiTxSuccess = millis();
// A JsonDocument is *not* a permanent storage; it's only a temporary storage
// used during the serialization phase. See:
// https://arduinojson.org/v6/faq/why-must-i-create-a-separate-config-object/
// https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
//#include <ArduinoJson.h>
//static char msg[500];
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
/////////////////////////////////////////////////////////////////////////
void blinkERR(){
// S-O-S on built-in NeoPixel on Feather M4 Expres
// AND built-in RGB on AirLift FeatherWing
const int S = 600, O = 2000;
for(uint8_t i = 3; i>0; i--){
pixels.setPixelColor(0, 255, 0, 0, 4); // red
pixels.show();
WiFi.setLEDs(255, 0, 0); // red
delay(S);
pixels.setPixelColor(0, 0, 0, 0, 4); // black
pixels.show();
WiFi.setLEDs(0, 0, 0); // black
delay(S);
}
delay(1000);
for(uint8_t i = 3; i>0; i--){
pixels.setPixelColor(0, 255, 0, 0, 4); // red
pixels.show();
WiFi.setLEDs(255, 0, 0); // red
delay(O);
pixels.setPixelColor(0, 0, 0, 0, 4); // black
pixels.show();
WiFi.setLEDs(0, 0, 0); // black
delay(O);
}
delay(1000);
for(uint8_t i = 3; i>0; i--){
pixels.setPixelColor(0, 255, 0, 0, 4); // red
pixels.show();
WiFi.setLEDs(255, 0, 0); // red
delay(S);
pixels.setPixelColor(0, 0, 0, 0, 4); // black
pixels.show();
WiFi.setLEDs(0, 0, 0); // black
delay(S);
}
delay(1000);
} // blinkERR()
// timer_https_post
// 86400000 ms = 86400 sec = 24 hr
// 3600000 ms = 3600 sec = 1 hr
// 1000000 us = 1000 ms = 1 sec = 1 Hz
// 1000 us = 1 ms = 0.001 sec = 1 kHz
// 100 us = 0.1 ms = 0.0001 sec = 10 kHz
// 1 us = 0.001 ms = 0.000001 sec = 1000 kHz
const unsigned long timer_https_post = 30000;
unsigned long timer_https_post_lap = millis();
/////////////////////////////////////////////////////////////////////////
void setup() {
// For ATSAMD21 and ATSAMD51:
// ARef pin, use analogReference(AR_EXTERNAL)
// Pin with pullup:
// Use: pinMode(pin, INPUT_PULLUP)
// NOT: pinMode(pin, INPUT)
// digitalWrite(pin, HIGH)
#if DEBUG
Serial.begin(115200);
while (!Serial) {
delay(1);
}
Serial.println("\nSerial ready");
#endif
// 16/A2 is connected to ESPRST pin directly (no resistor).
// Pull LOW briefly to reset ESP32 / AirLift.
pinMode(16, OUTPUT);
digitalWrite(16, HIGH);
// Initialize the built-in NeoPixel (initially set to green)
pixels.begin();
pixels.show();
// NeoPixel color test
// .setPixelColor(n, red, green, blue, white);
//pixels.setPixelColor(0, 255, 0, 0, 4); // red
//pixels.show();
//
//pixels.setPixelColor(0, 0, 255, 0, 4); // green
//pixels.setPixelColor(0, 0, 0, 255, 4); // blue
//pixels.setPixelColor(0, 255, 255, 255, 4); // white
//pixels.setPixelColor(0, 0, 128, 255, 4); // cyan
//pixels.setPixelColor(0, 0, 0, 0, 4); // black
// 2 MB QSPI (Quad SPI) Flash chip
#if DEBUG
Serial.println("\n2 MB QSPI (Quad SPI) Flash chip");
#endif
flash.begin();
#if DEBUG
Serial.print("JEDEC ID: 0x"); Serial.println(flash.getJEDECID(), HEX);
Serial.print("Flash size: "); Serial.print(flash.size() / 1024); Serial.println(" KB\n");
#endif
// WARNING: Must format to use as SD drive (see examples Adafruit SPIFlash -> SdFat_format)
// Formatting will erase CircuitPython!
// AirLift FeatherWing ESP32 WiFi
WiFi.setPins(SPIWIFI_SS, SPIWIFI_ACK, ESP32_RESETN, ESP32_GPIO0, &SPIWIFI);
// check for the WiFi module:
while (WiFi.status() == WL_NO_MODULE) {
#if DEBUG
Serial.println("Communication with WiFi module failed!");
#endif
blinkERR();
delay(100);
}
// RGB mounted on AirLink
// (warning, reset of AirLink will turn off RGB)
// .setLEDs(red, green, blue);
//WiFi.setLEDs(255, 0, 0); // red
//delay(3000);
//WiFi.setLEDs(0, 255, 0); // green
//delay(3000);
//WiFi.setLEDs(0, 0, 255); // blue
//delay(3000);
//WiFi.setLEDs(128, 128, 0); // yellow
//delay(3000);
//WiFi.setLEDs(255, 0, 255); // purple
//delay(3000);
//WiFi.setLEDs(0, 128, 255); // cyan
//delay(3000);
//WiFi.setLEDs(0, 0, 0); // black
// Check the AirLift FeatherWing ESP32 WiFi firmware version...
String fv = WiFi.firmwareVersion();
// AirLift FeatherWing ESP32 WiFi firmware 1.2.2
if (fv < "1.0.0") {
#if DEBUG
Serial.println("Upgrade the AirLift FeatherWing ESP32 WiFi firmware");
#endif
while (1) blinkERR();;
}
#if DEBUG
Serial.print("AirLift FeatherWing ESP32 WiFi firmware ");
Serial.print(fv);
Serial.println(" ");
#endif
// print your WiFi MAC address:
byte mac[6];
WiFi.macAddress(mac);
// WiFi MAC: 58:BF:25:E7:2B:FC
#if DEBUG
Serial.print("WiFi MAC: ");
for (int i = 5; i >= 0; i--) {
if (mac[i] < 16) {
Serial.print("0");
}
Serial.print(mac[i], HEX);
if (i > 0) {
Serial.print(":");
}
}
Serial.println("\n");
#endif
// attempt to connect to WiFi network
pixels.setPixelColor(0, 255, 0, 0, 4); // red
pixels.show();
do {
client.stop();
#if DEBUG
Serial.print("setup() attempting to connect to SSID: ");
Serial.println(ssid);
#endif
status = WiFi.begin(ssid, pass);
if (status == WL_CONNECT_FAILED) {
#if DEBUG
Serial.println("WiFi connection failed");
#endif
}
// Note: status = 3 = WL_CONNECTED when NOT connected!!!
delay(5000); // wait until connected
} while (status != WL_CONNECTED);
pixels.setPixelColor(0, 0, 0, 0, 4); // black
pixels.show();
// client.connected() when NOT connected & when connected. Useless!
// Possibly connnected to WiFi. Print out the connection details:
#if DEBUG
printWifiStatus();
#endif
// virtual void setCertificate(const char *client_ca);
// virtual void setPrivateKey (const char *private_key);
#if DEBUG
Serial.println("\nSetup complete\n");
#endif
} // setup()
void loop() {
neoPixelRainbow();
if (timer_https_post_lap > millis()) timer_https_post_lap = millis();
if (millis() - timer_https_post_lap > timer_https_post) {
httpRequest();
timer_https_post_lap = millis(); // reset the timer
} // timer_https_post_lap
} // loop()
void httpRequest() {
// Make a HTTP connection to the server.
// Determine if last successful WiFi communication was
// past the normal httpRequest() interval...
if (millis() - lastWiFiTxSuccess > timer_https_post+5000) {
#if DEBUG
Serial.print("Last successful WiFi Tx was ");
Serial.print((millis() - lastWiFiTxSuccess)/1000);
Serial.println(" sec ago!");
#endif
} else {
#if DEBUG
Serial.print("Last successful WiFi Tx was only ");
Serial.print((millis() - lastWiFiTxSuccess)/1000);
Serial.println(" sec ago");
#endif
}
// close any connection before send a new request.
// This will free the socket on the Nina module
client.stop();
pixels.setPixelColor(0, 0, 128, 255, 4); // cyan
pixels.show();
WiFi.setLEDs(0, 128, 255); // cyan
// Try to connect to SERVER
// port 443 is default for HTTPS
if (client.connect(SERVER, 443)) {
#if DEBUG
Serial.print("Connecting to ");
Serial.print(SERVER);
Serial.print(PATH);
Serial.println(" ...");
#endif
// send the HTTPS request:
client.println("GET " PATH " HTTP/1.1");
client.println("Host: " SERVER);
client.println("User-Agent: AirLiftWiFi/1.1");
// Configure the basic authentication Username and Password.
//Base64 encoding of "username:password" follows ": Basic" below..
//Get the value from: https://base64tools.com/enc/wifi/
// "postman:password" = "cG9zdG1hbjpwYXNzd29yZA=="
client.println("Authorization: " "Basic cG9zdG1hbjpwYXNzd29yZA==");
//client.println("Connection: keep-alive");
client.println("Connection: close");
client.println(); // This line is VERY IMPORTANT !!!
// Check HTTP status
char status[32] = {0};
client.readBytesUntil('\r', status, sizeof(status));
if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
#if DEBUG
Serial.print(F("Unexpected response: "));
Serial.println(status);
#endif
WiFi.setLEDs(128, 128, 0); // yellow
} else {
// HTTP successful. WiFi working and server connection successful.
lastWiFiTxSuccess = millis();
WiFi.setLEDs(0, 0, 0); // black
#if DEBUG
Serial.println("HTTPS GET successful");
Serial.println(status);
// Print out the WiFi connection details...
printWifiStatus();
#endif
}
#if DEBUG
Serial.println();
#endif
} else {
// Connection to the server failed
pixels.setPixelColor(0, 255, 0, 0, 4); // red
pixels.show();
#if DEBUG
Serial.print("Connection to ");
Serial.print(SERVER);
Serial.println(" failed");
Serial.println("Check WiFi connection and server\n");
#endif
// attempt to connect to WiFi network:
do {
client.stop();
pixels.setPixelColor(0, 255, 255, 255, 4); // white
pixels.show();
#if DEBUG
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
#endif
status = WiFi.begin(ssid, pass);
if (status == WL_CONNECT_FAILED) {
client.stop();
WiFi.disconnect();
#if DEBUG
Serial.println("WiFi connection failed");
Serial.println("RESET ESP32...\n");
#endif
// 16/A2 is connected to ESPRST pin directly (no resistor).
// Pull LOW briefly to reset ESP32 / AirLift.
digitalWrite(16, LOW); // Reset ESP32
delay(1000);
pixels.setPixelColor(0, 255, 0, 0, 4); // red
pixels.show();
digitalWrite(16, HIGH); // Keep HIGH normally
// Give the ESP32 module 10 sec to restart
delay(5000);
}
delay(5000); // wait until connected
} while (status != WL_CONNECTED);
} // client.connect()
} //httpRequest()
Do you need help developing or customizing a IoT product for your needs? Send me an email requesting a free one hour phone / web share consultation.
The information presented on this website is for the author's use only. Use of this information by anyone other than the author is offered as guidelines and non-professional advice only. No liability is assumed by the author or this web site.