AirLift - ESP32 WiFi Co-Processor

 

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).

 

Overview

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.  

AF Product ID 4264

AF Tutorial

Pinout diagram

 

Hardware

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).  

Pinout Diagram

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).  

Pinout Reference
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  

 

Firmware

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

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.  

 

AirLift + Adafruit Feather M4 Express SAMD51

HTTPS GET


/*
  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()

 

HTTPS POST

 

 


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.