XIAO ESP32C6 6-Channel Relay with supporting code

Blynkers.
My target ESP32 platforms of choice are Adafruit’s ESP32V2, with its high quality and Neopixel LED on the board, and Seeed Studio’s XIAO ESP32C6: tiny footprint, great with batteries.

This is not an advertisement, not a promotion, but an opportunity for me to return value to the Blynk community with an extremely useful product and my supporting code.

Seeed Studio’s XIAO 6-Channel Wi-Fi 5V DC Relay combines the XIAO ESP32C6 with 6 relays, indicator lights, and easy Blynk programmability in a surprisingly affordable package. I’ve built one project already with this product.

The six relays are heavy-duty, all completely isolated from each other and from the ESP32. The relays work with AC and DC and are rated to 15A at 120VAC. I am replacing a bunch of Shelly 1 switches with this, and may replace some Sonoffs, too. All in a nice compact package.

Here’s my almost-bare-bones Blynk code to demonstrate this device. Compiling to ESP32C6 and using default partitions, this sketch needs only your Blynk and WiFi credentials (in the two #include files) to demo this device.

There’s a screenshot at the end of my simple demo Blynk app. It’s just a demo.

I hope this is useful to someone in the Community.
Code: sketch with two #include files – one for WiFi credentials, the other for Blynk credentials. I have posted this on Github, will post more robust code soon.

All thoughts welcome.
Main sketch. (#include files to follow.)

// XIAO 6-Channel Relay Demo Sketch
// Seeed Studio https://www.seeedstudio.com/6-Channel-Wi-Fi-5V-DC-Relay-p-6373.html
// Seeed Studio https://www.seeedstudio.com/Seeed-Studio-XIAO-ESP32C6-p-5884.html

// Board: XIAO_ESP32C6
// PARTITION SCHEME: DEFAULT 4MB with spiffs


#define SERIAL_SPEED 230400   // My usual speed for Serial/development work
//#define SERIAL_SPEED 115200


#define BLYNK_FIRMWARE_VERSION "1.0.1"  // 
#define PROGRAM_NAME_VERSION   "1-0-1"  // Dashes, not Dots


#define SKETCH_NAME "XIAO_Relay_v" PROGRAM_NAME_VERSION  // used in WiFi setup, Blynk and OTA 
#define DEVICE_NAME "XIAO-Relay-v" PROGRAM_NAME_VERSION  // used in WiFi setup, Blynk and OTA 



// ****************** XIAO 6-Channel Relay ***************** 
#include "MY_BLYNK_CREDENTIALS_DEMO.h"
#define BLYNK_TEMPLATE_ID          MY_XIAO_RELAY_TEMPLATE_ID        // FROM MY_BLYNK_CREDENTIALS.h
#define BLYNK_TEMPLATE_NAME        MY_XIAO_RELAY_TEMPLATE_NAME      // FROM MY_BLYNK_CREDENTIALS.h
#define MY_BLYNK_AUTHCODE          MY_XIAO_RELAY_DEVICE_AUTHCODE    // FROM MY_BLYNK_CREDENTIALS.h
// Added April 2026



#include "MY_WIFI_CREDENTIALS_DEMO.h"   // #defines MY_WIFI_SSID AND MY_WIFI_PASSWORD
#include "MY_BLYNK_COLORS.h"



// WiFi Stuff
#include "WiFi.h"                              // Now included from Espressif ESP32 3.0.0 Board package
#include <WiFiMulti.h>
WiFiMulti wifiMulti;                           // set up the WiFi object
const uint32_t connectTimeoutMs = 5000;        // timing for WiFiMulti testing connection



// Blynk Stuff
#include <BlynkSimpleEsp32.h> 





////////////////////////////////////////////////////////////////////////////////////////////////////////
// Blynk Timers
// This sketch uses timers to kick off key processes
// See Pete Knight's doc at https://community.blynk.cc/t/using-blynktimer-or-simpletimer/53326

// Set up my standard timer here, before we bring in the Heartbeat
BlynkTimer myTimer; 

/*  1 - Heartbeat (heartbeatBlink) - Interval Timer - simple pulse to show we're alive. May be switched off.
 *      Timer call turns heartbeat ON and prints diagnostics. 
 *      It uses a second Duration timer to turn the heartbeat back OFF
 *  2 - Do something with the Switches every three seconds
 */

// ** timers get randomized in the code **

// Timer 1: Heartbeat LED and optional Blynk LED on and off 
#define HEARTBEAT_INTERVAL 4250    // interval between heartbeats for Blynk Virtual LED in millisec 
int heartbeatTimerID;              // HEARTBEAT_INTERVAL WILL BE RANDOMIZED +-500 ms (once at startup)

#define HEARTBEAT_DURATION 1250    // duration of each blink in millisec 
int heartbeatDurationTimerID;      // (set as an interval timer once heartbeat is ON ... to turn it back OFF)



// Timer 2: Do something with the Switches every three seconds
#define TOGGLE_GPIO_INTERVAL 3 * 1000 // Do something every 3 seconds
int toggleGPIOtimerID; 

// ***************************************************************************************************
////////////////////////////////////////////////////////////////////////////////////////////////////////
// End of Timers                                                                                      //
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////







////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
//
// Key Program Global Variables
//
////////////////////////////////////////////////////////////////////////////////////////////////

// Sets up HEARTBEAT widget, heartbeatBlink
#define HEARTBEAT_VPIN                      V0            // My standasrd Heartbeat VPIN
#define HEARTBEAT_LABEL                     "Working" 
#define HEARTBEAT_COLOR                     BLYNK_LT_BLUE


bool heartbeatLEDon = false;    // this lets me use the same routine for the turn-on timer and the turn-off interval



// Sets up the 6 Switch Widgets
#define SWITCH_WIDGET_COLOR         BLYNK_BLACK
#define SWITCH_WIDGET_ON_COLOR      BLYNK_GREEN
#define SWITCH_WIDGET_OFF_COLOR     BLYNK_GREY

//// XIAO 6-CHannel Relay
// https://wiki.seeedstudio.com/6_channel_wifi_relay/
// https://www.seeedstudio.com/6-Channel-Wi-Fi-5V-DC-Relay-p-6373.html?srsltid=AfmBOoqth5qb8CrGU001aOXWS33ozvj0V8Ax3FVixJnjHNz0Us07LpExMR0

//  ||  Switch 1   GPIO2     GPIO18  Switch 6   /\
//  ||  Switch 2   GPIO21    GPIO19  Switch 5   ||
//  \/  Switch 3   GPIO1     GPIO00  Switch 4   ||

const int switchGPIO[6]    = { 02, 21, 01, 00, 19, 18 }; // GPIOs on the ESP32C6
const int switchVPIN[6]    = { 31, 32, 33, 34, 35, 36 }; // Blynk VPINs for the 6 Switch ON/OFF Widgets
bool currentSwitchState[6] = { false };                  // All OFF initially












//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SETUP WIFI, BLYNK, HEARTBEAT, AND 6 SWITCHES
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{ 
  // Turn ON all Switches
  initializeAllSwitchGPIOs();         // Initialize to OFF
  allSwitchesONorOFF ( HIGH );  // Turn all 6 ON (before we try to connect to Serial)


  // Use a timer here for any OTA device, particularly the XIAO ESP32
  // CONTAINS DELAYS !!
  #define SERIAL_PRINT_DELAY 2500         // I use this delay for all ESP32s
  time_t serialWaitStartTime = millis();  // Protect against ESP32 hangup of no Serial Monitor available
  time_t serialWaitTime = 0; 

  Serial.begin ( SERIAL_SPEED );

  while ( ( ! Serial ) && ( serialWaitTime < SERIAL_PRINT_DELAY ) )
  { /* wait for serial port to connect. Needed for native USB */ 
    serialWaitTime = millis() - serialWaitStartTime; 
  } 
  delay ( SERIAL_PRINT_DELAY - serialWaitTime );


  // Turn OFF all Switches
  allSwitchesONorOFF ( LOW );  



  Serial.println ( "\n\n**********************************************" );
  Serial.println ( "Firing up " + String ( SKETCH_NAME ) );
  Serial.println();



  // Connect to WiFi and Blynk
  connectToWiFiAndBlynk();  // Connect to WiFi, then to Blynk server
  // calls initialzeBlynkWidgets from BLYNK_CONNECTED



  // Set Blynk Virtual Heartbeat LED OFF
  heartbeatLEDon = false;
  heartbeatBlink();            // start first heartbeat 

  Blynk.virtualWrite ( HEARTBEAT_VPIN, 000 );  


  // Blynk timers control heartbeat, status checking for ON/OFF vs schedule, etc. 
  setupBlynkTimers();  // Establish Blynk timers after Blynk is connected


  Serial.println ( "\n**********************" ); 
  Serial.println (   "... Setup complete ..." );   
  Serial.println (   "**********************\n" ); 

} // end setup





void loop()   // Standard void loop (no OTA for simplicity)
{
  Blynk.run();
  myTimer.run();  

} // end loop





// SET UP BLYNK TIMERS FOR EVERYTHING
void setupBlynkTimers()
{
  Serial.println ( "\nSetting up Blynk timers" );  


  // Introduce a little randomness to all times so they don't all sync up
  long randomizedInterval;


  // Timer 1: Heartbeat LED and optional Blynk LED on and off
  randomizedInterval = HEARTBEAT_INTERVAL + random ( -500, +500 );  // plus of minus half a second
  Serial.print ( "... heartbeat interval = " ); Serial.println ( randomizedInterval );
  heartbeatTimerID = myTimer.setInterval ( randomizedInterval, heartbeatBlink );  



  // Timer 2: Do something with the Switches every three seconds
  Serial.print ( "... toggleGPIOtimerID = " ); Serial.println ( TOGGLE_GPIO_INTERVAL );  
  toggleGPIOtimerID = myTimer.setInterval ( TOGGLE_GPIO_INTERVAL, randomlyChangeSwitchStates ); 


  Serial.println ( "... Blynk timers all set up.\n" );  
  
} // end setupBlynkTimers





// BLYNK_CONNECTED GETS CALLED WHEN CONNECTING TO BLYNK SERVERS
// GETS CALLED IMMEDIATELY ON FIRST CONNECT TO BLYNK SERVER, TOO
BLYNK_CONNECTED()
{
  Serial.println ();  
  Serial.println ( "*************************************************" ); 
  Serial.println ( "BLYNK_CONNECTED..." );  
  Serial.println ( "*************************************************\n" ); 


  // Set up the Blynk App with all the static info (colors and labels)
  // Set up all the Blynk widgets
  initializeBlynkWidgets(); 

} // end BLYNK_CONNECTED





// Set up all Blynk widgets in the app includinng Heartbeat and Reboot
void initializeBlynkWidgets()
{
  Serial.println ( "Initializing all Blynk widgets" );


  // Set up heartbeat label and color
  Blynk.setProperty ( HEARTBEAT_VPIN, "label", HEARTBEAT_LABEL );  
  Blynk.setProperty ( HEARTBEAT_VPIN, "color", HEARTBEAT_COLOR ); 



  // Set up the 6 Channel Switch Widgets
/*
const int switchGPIO[6]    = { 02, 21, 01, 00, 19, 18 }; // GPIOs on the ESP32C6
const int switchVPIN[6]    = { 31, 32, 33, 34, 35, 36 }; // Blynk VPINs
bool currentSwitchState[6] = { false };                  // All OFF initially

#define SWITCH_WIDGET_COLOR         BLYNK_BLACK
#define SWITCH_WIDGET_ON_COLOR      BLYNK_GREEN
#define SWITCH_WIDGET_OFF_COLOR     BLYNK_GREY
*/
  for ( int switchIndex = 0; switchIndex < 6; switchIndex++ ) // Switches numbered 1-6; Index goes from 0-5
  {
    Blynk.setProperty ( switchVPIN[switchIndex], "label",       "Switch " + String ( switchIndex + 1 ) );  
    Blynk.setProperty ( switchVPIN[switchIndex], "color",       SWITCH_WIDGET_COLOR ); 
    Blynk.setProperty ( switchVPIN[switchIndex], "offColor",    SWITCH_WIDGET_OFF_COLOR ); 
    Blynk.setProperty ( switchVPIN[switchIndex], "onColor",     SWITCH_WIDGET_ON_COLOR ); 
  }

  allSwitchesONorOFF ( LOW );  

} // end initializeBlynkWidgets





void initializeAllSwitchGPIOs() // Initialize all 6 GPIO relay controls to OUTPUT and turn OFF
{
  Serial.println( "Initializing All GPIOs to OFF" ); 

  for ( int switchIndex = 0; switchIndex < 6; switchIndex++ )
  {
    pinMode ( switchGPIO[switchIndex], OUTPUT ); 

    setSwitchState ( switchIndex, LOW ); 

    Serial.println ( "Initialized Switch " + String ( switchIndex + 1 ) + " at GPIO " + String ( switchGPIO[switchIndex]) + " and VPIN " + String ( switchVPIN[switchIndex] ) ); 
  }

  Serial.println(); 

} // end initializeAllSwitchGPIOs





void allSwitchesONorOFF ( bool newState )  // Turn all 6 switches ON or OFF
{

/*
const int switchGPIO[6]    = { 02, 21, 01, 00, 19, 18 }; // GPIOs on the ESP32C6
const int switchVPIN[6]    = { 31, 32, 33, 34, 35, 36 }; // Blynk VPINs
bool currentSwitchState[6] = { false };                  // All OFF initially
*/

  for ( int switchIndex = 0; switchIndex < 6; switchIndex++ )
  {
    setSwitchState ( switchIndex, newState ); 

    Serial.println ( "Changed Switch " + String ( switchIndex + 1 ) + " at GPIO " + String ( switchGPIO[switchIndex]) + " and VPIN " + String ( switchVPIN[switchIndex] ) + " to " + String ( newState)  ); 
  }

  Serial.println(); 

} // end allSwitchesONorOFF





BLYNK_WRITE_DEFAULT() // Using BLYNK_WRITE_DEFAULT to more easily handle 6 different switch inputs with same code
                      // Also allows keeping the VPINs in an array
{
  // THE VIRTUAL PIN THAT SENT THE MESSAGE TO BLYNK
  int writeVpin = request.pin; 

  String message = "BLYNK_WRITE_DEFAULT called from VPin " + String ( writeVpin ); 

  Serial.println ( "\n\n" + message ); 


/*
const int switchGPIO[6]    = { 02, 21, 01, 00, 19, 18 }; // GPIOs on the ESP32C6
const int switchVPIN[6]    = { 31, 32, 33, 34, 35, 36 }; // Blynk VPINs
bool currentSwitchState[6] = { false };                  // All OFF initially
*/

  // See which switch - if any - just got changed
  for ( int switchIndex = 0; switchIndex < 6; switchIndex++ )
  {
    if ( writeVpin == switchVPIN[switchIndex] ) // Check which widget got hit
    {
      bool newSwitchState = param[0].asInt(); 

      Serial.println ( "User Hit Switch " + String ( switchIndex + 1 ) + ": " + String ( newSwitchState ) ); 

      if ( newSwitchState != currentSwitchState[switchIndex] )  // Change Switch State only if needed
      {
        setSwitchState ( switchIndex, newSwitchState ); 
      }

      else
      {
        // Do nothing
      }
      return; 
    }
  }

} // end BLYNK_WRITE_DEFAULT





void randomlyChangeSwitchStates() // Randomly change switch states
{
  Serial.println ( "\nRandomly changing two Switches" ); 


  int randomSwitch = random ( 0, 6 ); 
  setSwitchState ( randomSwitch, LOW ); 



  randomSwitch = random ( 0, 6 ); 
  setSwitchState ( randomSwitch, HIGH ); 


  reportSwitchStates(); 

} // end randomlyChangeSwitchStates





void reportSwitchStates() // Read the 6 Switches and print out their GPIO states
{
  Serial.println(); 

  for ( int switchIndex = 0; switchIndex < 6; switchIndex++ )
  {
    int switchState = digitalRead ( switchGPIO[switchIndex] );

    Serial.println ( "Reading Switch " + String ( switchIndex + 1 ) + ": " + String ( switchState ) ); 

  }

} // end reportSwitchStates





void setSwitchState ( int switchIndex, bool newSwitchState )  // Set a Switch to a value
{
  digitalWrite ( switchGPIO[switchIndex], newSwitchState ); 
      
  Blynk.virtualWrite ( switchVPIN[switchIndex], newSwitchState ); 

  currentSwitchState[switchIndex] = newSwitchState; 

} // end setSwitchState





// OPTIONAL Cutting down on the brightness of the Blynk LED Widget
#define BLYNK_LED_WIDGET_MAX_BRIGHTNESS 150         // Led Widget is [0-255]  150 = not very bright (from 255)

void heartbeatBlink()                               // Standard code (I usually put in an #include'd file)
{
  if ( heartbeatLEDon )                                             // LED is ON. Turn it OFF
  {
    Blynk.virtualWrite ( HEARTBEAT_VPIN, 000 );                     // Blynk LED off


    Serial.println ( " ..." ); 
  }

  else                                                              // LED is OFF. Turn it ON
  {
    // Turn LED_BUILTIN ON (via PWM) and Turn Blynk LED Widget ON
    Blynk.virtualWrite ( HEARTBEAT_VPIN, BLYNK_LED_WIDGET_MAX_BRIGHTNESS );       // BLynk LED on


    Serial.print ( "\n... heartbeat <" + String ( SKETCH_NAME ) + ">" ); 

    int wifiStatus = WiFi.status(); 
    if ( wifiStatus == WL_CONNECTED )
    {

      Serial.print ( " connected as " ); Serial.print ( WiFi.localIP() ); 
      Serial.print ( " to " + String ( WiFi.SSID() ) + 
                  " at " + String ( WiFi.RSSI() ) + "dBm" ); 
    }

    else // not connected to WiFi
    {
      Serial.print ( " WiFi.status()=" ); 

      if ( wifiStatus <= 7 && wifiStatus >= 0 ) { Serial.print ( myWiFiStatus[wifiStatus] ); }
      else { Serial.print ( wifiStatus ); };  
    }



    // Set a timer to turn off the heartbeat LEDs in a bit  
    heartbeatDurationTimerID = myTimer.setTimeout ( HEARTBEAT_DURATION, heartbeatBlink ); 
    
  }

  heartbeatLEDon = ! heartbeatLEDon; // flip heartberat ON/OFF status

} // end heartbeatBlink





void connectToWiFiAndBlynk()  // My standard (simplified) WiFi connection code - usually in an #include file
{
  Serial.println(); 
  Serial.println ( "connectToWiFiAndBlynk called ..." ); 

  // Try to connect to WiFi, REBOOTS UNTIL IT WORKS.  
  connectToWiFi();  
  // Sets wifiOnline = true... or it reboots after 5-10 minutes



  Serial.println ( "Next, connect to Blynk. \n" );  
  Blynk.config ( MY_BLYNK_AUTHCODE );
  Blynk.connect() ; 
  


  // If Blynk is not connected, start the Blynk connect cycle
  if ( ! Blynk.connected() )
  {
    // Blynk is NOT online
    Serial.println();  
    Serial.println ( "connectToWiFiAndBlynk INITIALLY CANNOT connect to Blynk" );  
    Serial.println(); 

    ESP.restart(); 
  
  } // Blynk is offline


  else
  {
    Serial.println ( "... Blynk connected up nicely\n" ); 
  }

} // end connectToWiFiAndBlynk





// Global variable indicating WiFi Online
#define WIFI_INITIAL_CONNECT_DURATION 1500          // Wait 1.5 seconds between WiFi.begin and first test for connectivity
#define WIFI_RETRY_CONNECT_INTERVAL   10L * 1000L   // 10 seconds between WiFi connect retries
#define WIFI_RETRIES_BEFORE_REBOOTING 5

void connectToWiFi()    // Connect to WiFi. Reboot on repeated failure
{
  WiFi.persistent ( false ); // Don't save anything in EEPROM or LittleFS 
  WiFi.mode ( WIFI_STA );    // Station mode


  // Count the number of WiFi connection retries
  int WiFiTries = 0; 


///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////

  Serial.println ( "******************* connectToWifi using Static SSID/Pswd *****************" ); 
  Serial.println ( "******************* connectToWifi using Static SSID/Pswd *****************" ); 


  // Register THREE multi WiFi networks
  wifiMulti.addAP ( MY_WIFI_SSID,  MY_WIFI_PASSWORD  );
  wifiMulti.addAP ( MY_WIFI_SSID2, MY_WIFI_PASSWORD2 );
  if ( MY_WIFI_SSID3 != "" ) wifiMulti.addAP ( MY_WIFI_SSID3, MY_WIFI_PASSWORD3 );


  // Test for WiFi connectivity. Reboot after 5 tries. 
  while ( wifiMulti.run ( connectTimeoutMs ) != WL_CONNECTED ) 
  {
    WiFiTries++; 

    Serial.print ( "WiFi not connected... #" ); Serial.println ( WiFiTries ); 

    if ( WiFiTries >= WIFI_RETRIES_BEFORE_REBOOTING  )
    {
      Serial.println ( "RESTARTING!  Cannot connect to WiFi\n\n" );  
      
      delay ( 5000 ); 
      ESP.restart(); 
    }

    delay ( WIFI_RETRY_CONNECT_INTERVAL ); // This delay is ok for OTA and Blynk prior to WiFi connection
  }

  // Tell the world we are connected to WiFi
  Serial.print ( "WiFi connected on attempt #" + String ( WiFiTries + 1 ) + " just fine to ");
  Serial.print ( WiFi.SSID() ); Serial.print ( " at " ); Serial.println ( WiFi.localIP() ); Serial.println();  
  Serial.println();  

} // end connectToWiFi

End of Code.

Now, the #include files

I use #include files to keep my Blynk and WiFi credentials out of my code. Here are two examples for the XIAO code, above:

#include "MY_WIFI_CREDENTIALS_DEMO.h" // #defines MY_WIFI_SSID AND MY_WIFI_PASSWORD

// #include "MY_WIFI_CREDENTIALS.h"   // #defines MY_WIFI_SSID AND MY_WIFI_PASSWORD



#define MY_WIFI_SSID      "myPrimarySSID"                // network SSID (name)
#define MY_WIFI_PASSWORD  "myPassword"                   // network password

// Use as a backup SSID if #1 fails so I can use my phone to reconnect, reprogram when needed
#define MY_WIFI_SSID2     "myNextSSID"                   // network SSID (name)
#define MY_WIFI_PASSWORD2 "AnotherPSWD"                  // network password

//  Can add a 3rd SSID and password here... (but must have 3 in total)
#define MY_WIFI_SSID3      ""                            // network SSID (name)
#define MY_WIFI_PASSWORD3  "passowordo"                  // network password


// for diagnostic and heartbeat use
// WiFi.status ( return codes )  
const char *myWiFiStatus[8] = { "0-WL_IDLE_STATUS", "1-WL_NO_SSID_AVAIL",  "2-UNKNOWN", 
  /* for use in heartbeat*/     "3-WL_CONNECTED",   "4-WL_CONNECT_FAILED", "5-UNKNOWN",
                                "6-WL_CONNECT_WRONG_PASSWORD", 
                                "7-WL_DISCONNECTED" };
/*
0 : WL_IDLE_STATUS when Wi-Fi is in process of changing between statuses
1 : WL_NO_SSID_AVAILin case configured SSID cannot be reached
3 : WL_CONNECTED after successful connection is established
4 : WL_CONNECT_FAILED if connection failed
6 : WL_CONNECT_WRONG_PASSWORD if password is incorrect
7 : WL_DISCONNECTED if module is not configured in station mode 

Useful commands
WiFi.printdiag ( Serial ); lots of stuff, (not RSSI)
*/

#include "MY_BLYNK_CREDENTIALS_DEMO.h"

//#include "MY_BLYNK_CREDENTIALS.h"  // #defines MY_BLYNK_SERVER and MY_xxx_AUTHCODE

#define MY_BLYNK_SERVER                            "blynk.cloud"                  // Common to all New Blynk sketches

#ifndef BLYNK_FIRMWARE_VERSION
  #define BLYNK_FIRMWARE_VERSION                     "1.2.3"
#endif

//#define BLYNK_USE_128_VPINS true // Gives codes for VPINS up to V127


//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
  // These are dummy Template IDs and Device Authcode for the XIAO demonstration
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////



// ****************** XIAO 6-Channel Relay ***************** 
// 6 //
#define MY_XIAO_RELAY_TEMPLATE_ID                   "TMPL2aaaaaaaa" // Use YOUR credentials
#define MY_XIAO_RELAY_TEMPLATE_NAME                 "XIAO Relay Template"
#define MY_XIAO_RELAY_DEVICE_AUTHCODE               "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" 
// ADDED June 2026



// ************** DUMMY TEMPLATE ************** 
// 99 //
// THESE ARE DUMMY SETTINGS FOR MY STARTUP TEMPLATE IN EXAMPLES
#define MY_STARTUP_TEMPLATE_ID                      "XXXXXXXXXXXX"                // My Blynk Startup Template in Examples
#define MY_STARTUP_TEMPLATE_NAME                    "Startup Template"
#define MY_STARTUP_DEVICE_AUTHCODE                  "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"

Screenshot of a very simple Blynk app

Again, I hope this is useful.