Week 11 - Networking and Communications

This week we have the following tasks to complete:

  • design, build, and connect wired or wireless node(s) with network or bus addresses and local input &/or output device(s)
  • send a message between two projects

Group Assignment

The weekly group assignment can be accessed here. For that Matthias and I used our Xiao ESP32C3 to control the brightness from the Neopixel connected to the other Xiao.

I2C

In Week 10 and Week 11, I already used the I2C protocol to communicate with a BME688 environmental sensor and several OLED displays.

ESP Now

The base idea is to get a XIAO ESP32-C3 as an remote with some rotary encoder as input devices and an indicator led that represent the color of the led strips. The receiver is an esp32-C3 WRoom dev kit 3 which controlled two RGB LED-strips and some LED-spots with some MOSFET's with a MOSFET driver. The PCB from the receiver already exist, this is also why I will use a this specific board and not another one like a XIAO ESP32-C3. I designed the receiver a few months ago before I know about the FabInventory and its handy MOSFET's that can directly controlled with a microcontroller.
To get a better idea how to use ESP now I looked up the documentation from Espressif and also for further information and understanding I looked up at Seedstudio's example and at Randomnerdstutorial.

I followed the instructions to get the MAC Address of both ESP32 boards and used the following code:

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/get-change-esp32-esp8266-mac-address-arduino/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.  
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <WiFi.h>                                           // include wifi library to activate and use wifi from the ESP32-C3 chip
#include <esp_wifi.h>                                       // include esp wifi library to read out the MAC Address from the ESP32-C3 chip

void readMacAddress(){                                      // function to read out the MAC Address
  uint8_t baseMac[6];                                       // initialize a 6 byte array to store the chars from the MAC Address
  esp_err_t ret = esp_wifi_get_mac(WIFI_IF_STA, baseMac);   // read out MAC Address im Station mode
  if (ret == ESP_OK) {                                      // if it was possible to read out a MAC Address it will sent to the serial monitor in a formation like xx:xx:xx:xx:xx:xx, where every x is replaced by a letter or digit
    Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
                  baseMac[0], baseMac[1], baseMac[2],
                  baseMac[3], baseMac[4], baseMac[5]);
  } else {                                                  // if it was not possible to read out a MAC Address it will sent to the serial monitor an error message
    Serial.println("Failed to read MAC address");
  }
}

void setup(){
  Serial.begin(115200);                                     // initialize serial communication with a baudrate of 115200

  WiFi.mode(WIFI_STA);                                      // ESP is set in to station mode and not into access point
  WiFi.STA.begin();                                         // start the Wifi in station mode, probably not need it and optional but I'm not sure
}

void loop(){
  Serial.print("[DEFAULT] ESP32 Board MAC Address: ");      // this lines are original in the void setup function which didn't give me anything out, it just send a message to the serial monitor
  readMacAddress();                                         // this lines are original in the void setup function which didn't give me anything out, call up the readMacAddress function 
}

After flashing the XIAO ESP32-C3 I opened the Serial Monitor in the Arduino IDE and note down the Mac Address. I tried to repeated this for the ESP32-Wrover-E module but for some reasons my PC's could recognized the board, so I designed a small adapter pcb to use a XIAO ESP32-C3 on the footprint of the ESP32-Wrover-E module. I firstly wanted to use the Wroover module because it was already used in the receiver part of the project but after I encounter the connection problem I switched to an XIAO ESP32-C3.

XIAO 1: ec:da:3b:be:74:1c
XIAO 2: ec:da:3b:be:68:10
XIAO 3: 54:32:04:89:8e:00

Before setting up the connection it self I checked the functionality of the remote, for that I use following code:

#include <Adafruit_NeoPixel.h>                                               // library for NeoPixels
#include <Encoder.h>                                                         // library for rotary encoder

#define PIN_NEO_PIXEL D0                                                     // Xiao pin that connects to NeoPixel
#define NUM_PIXELS 4                                                         // number of LEDs
#define dt1 D5                                                               // Xiao pin that connects to the first rotary encoder dt
#define clk1 D6                                                              // Xiao pin that connects to the first rotary encoder clk
#define sw1 D2                                                               // Xiao pin that connects to the first rotary encoder sw
#define dt2 D3                                                               // Xiao pin that connects to the second rotary encoder dt
#define clk2 D4                                                              // Xiao pin that connects to the second rotary encoder clk
#define dt3 D8                                                               // Xiao pin that connects to the third rotary encoder dt
#define clk3 D7                                                              // Xiao pin that connects to the third rotary encoder clk
#define dt4 D10                                                              // Xiao pin that connects to the fourth rotary encoder dt
#define clk4 D9                                                              // Xiao pin that connects to the fourth rotary encoder clk

Adafruit_NeoPixel NeoPixel(NUM_PIXELS, PIN_NEO_PIXEL, NEO_GRB + NEO_KHZ800); // set the NeoPixel initialization
Encoder encoder_red(dt1,clk1);                                               // initiate object rotary encoder with the name encoder_red
Encoder encoder_green(dt2,clk2);                                             // initiate object rotary encoder with the name encoder_green
Encoder encoder_blue(dt3,clk3);                                              // initiate object rotary encoder with the name encoder_blue
Encoder encoder_brightness(dt4,clk4);                                        // initiate object rotary encoder with the name encoder_brightness

int red = 0;                                                                 // red value for the NeoPixel
int green = 0;                                                               // green value for the NeoPixel
int blue = 0;                                                                // blue value for the NeoPixel
int encoder_value = 0;                                                       // value of rotary encoder
int brightness_value = 255;                                                  // brightness value for the NeoPixel
int brightness_value_old = 0;                                                // previous brightness value for the NeoPixel
bool sw_control = false;                                                     // switch control variable to check if the switch is reactivated

void setup() {                                           
  NeoPixel.begin();                                                          // initialize the NeoPixel strip object
  pinMode(sw1, INPUT);                                                       // set pin for rotary encoder button as an input
}

void IRAM_ATTR fallout() {                                                   // fallout function
  if (sw_control == false){                                                  // if the button is not pressed
    brightness_value = brightness_value_old;                                 // overwrite the momentary brightness value with the old one
    sw_control = true;                                                       // set the control value to true
  }
  else if (sw_control == true){                                              // if the button is pressed
    brightness_value_old = brightness_value;                                 // overwrite the old brightness value with the momentary one
    brightness_value = 0;                                                    // set the momentary brightness value to 0
    sw_control = false;                                                      // set the control value to false
  }
}

void loop() {
  if (encoder_value != encoder_brightness.read()){                           // if the stored encoder value for the brightness is different then the momentary encoder value
      encoder_value = encoder_brightness.read();                             // overwrite the encoder value
      brightness_value = encoder_value;                                      // overwrite the brightness value with the encoder value
  }

  red = encoder_red.read();                                                  // read out the encoder value for red
  green = encoder_green.read();                                              // read out the encoder value for green
  blue = encoder_blue.read();                                                // read out the encoder value for blue

  for (int i = 0; i <= 3; i++){                                              // cycle through the 4 NeoPixels
    NeoPixel.setPixelColor(i, red, green, blue);                             // set color
    NeoPixel.setBrightness(brightness_value);                                // set brightness
    NeoPixel.show();                                                         // output the color and brightness
  }

  attachInterrupt(sw1, fallout, RISING);                                     // open the interrupt function fallout, if the switch have a raising slope
}

With this information I can setup the ESP-Now connection. For that I followed further the instruction from Random Nerds Tutorials to setup the ESP-now. Beginning with the transmitter with the following code:

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <esp_now.h>                                                                      // include ESP-NOW library to use ESP-Now
#include <WiFi.h>                                                                         // include wifi library to activate and use wifi from the ESP32-C3 chip

uint8_t broadcastAddress[] = {0x54, 0x32, 0x04, 0x89, 0x8E, 0x00};                        // replaced with the receiver XIAO's MAC Address that I read out earlier it set up the broadcast MAC Address

typedef struct struct_message {                                                           // Structure example to send data that must match the receiver structure
  char a[32];
  int b;
  float c;
  bool d;
} struct_message;

struct_message myData;                                                                    // Create a struct_message called myData

esp_now_peer_info_t peerInfo;

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {                  // callback function which tracks if data is sent
  Serial.print("\r\nLast Packet Send Status:\t");                                         // send a message to a serial monitor
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");  // send a message to a serial monitor if the delivery of the data was a success or if it fails
}

void setup() {
  Serial.begin(115200);                                                                   // initialize serial communication with a baudrate of 115200
  WiFi.mode(WIFI_STA);                                                                    // ESP is set in to station mode and not into access point

  if (esp_now_init() != ESP_OK) {                                                         // initialize ESP-NOW
    Serial.println("Error initializing ESP-NOW");                                         // if the ESP encounter any setup errors it will send a error message to a serial monitor
    return;                                                                               // exit function
  }

  esp_now_register_send_cb(OnDataSent);                                                     // after a successful initialization of ESP-NOW it will call up the OnDataSent function from earlier

  memcpy(peerInfo.peer_addr, broadcastAddress, 6);                                        // Register another XIAO to peer with
  peerInfo.channel = 0;                                                                   // set peer chanel to 0, multiple channels are possible to make sure that they are no interference
  peerInfo.encrypt = false;                                                               // don't encrypt the transmit messages

  if (esp_now_add_peer(&peerInfo) != ESP_OK){                                             // function to send a MAC Address to the receiver to add a peer 
    Serial.println("Failed to add peer");                                                 // send an error message to the serial monitor if the connection setup failed
    return;                                                                               // exit function
  }
}

void loop() {
  strcpy(myData.a, "THIS IS A CHAR");                                                     // set values to send
  myData.b = random(1,20);
  myData.c = 1.2;
  myData.d = false;

  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); // send message via ESP-NOW

  if (result == ESP_OK) {                                                                 // send positive message to a serial monitor if the transmit was successful
    Serial.println("Sent with success");
  }
  else {                                                                                  // send error message to a serial monitor if the transmit was not successful
    Serial.println("Error sending the data");
  }
  delay(2000);                                                                            // set a delay between sending messages
}

After this I setup the receiver XIAO with the following code:

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/  
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/

#include <esp_now.h>                                                          // include ESP-NOW library to use ESP-Now
#include <WiFi.h>                                                             // include wifi library to activate and use wifi from the ESP32-C3 chip

typedef struct struct_message {                                               // Structure example to send data that must match the transmitter structure
    char a[32];
    int b;
    float c;
    bool d;
} struct_message;

struct_message myData;                                                        // Create a struct_message called myData

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {  // callback function that will be executed when data is received
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("Char: ");
  Serial.println(myData.a);
  Serial.print("Int: ");
  Serial.println(myData.b);
  Serial.print("Float: ");
  Serial.println(myData.c);
  Serial.print("Bool: ");
  Serial.println(myData.d);
  Serial.println();
}

void setup() {
  Serial.begin(115200);                                                       // initialize serial communication with a baudrate of 115200
  WiFi.mode(WIFI_STA);                                                        // ESP is set in to station mode and not into access point

  if (esp_now_init() != ESP_OK) {                                             // initialize ESP-NOW
    Serial.println("Error initializing ESP-NOW");                             // if the ESP encounter any setup errors it will send a error message to a serial monitor
    return;                                                                   // exit function
  }                 

  esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));                    // after a successful initialization of ESP-NOW it will call up the OnDataRecv function from earlier to get a package information about the received data
}

void loop() {
  Serial.println(myData.a);
  Serial.println(myData.b);
  Serial.println(myData.c);
  Serial.println(myData.d);
}

The next step is to test if the setup works, which I did with two ArduinoIDE serial monitors in different windows with different com ports.

esp now test 01

The result looks like that:

esp now test 02

Light Controller

The next step would be to combine the example code for the transmitter with the test code from the remote and the receiver code with the light controller code from week 09.
I designed a small pcb for a the remote, which consist out of a XIAO ESP32-C3, four Rotary Encoder and four Neopixels as an indicator.

remote 01

The code for the remote looks like that:

#include <Adafruit_NeoPixel.h>                                               // library for NeoPixels
#include <Encoder.h>                                                         // library for rotary encoder

#define PIN_NEO_PIXEL D0                                                     // Xiao pin that connects to NeoPixel
#define NUM_PIXELS 4                                                         // number of LEDs
#define dt1 D5                                                               // Xiao pin that connects to rotary encoder dt
#define clk1 D6                                                              // Xiao pin that connects to rotary encoder clk
#define sw1 D2                                                               // Xiao pin that connects to rotary encoder sw
#define dt2 D3                                                               // Xiao pin that connects to rotary encoder dt
#define clk2 D4                                                              // Xiao pin that connects to rotary encoder clk
#define dt3 D8                                                               // Xiao pin that connects to rotary encoder dt
#define clk3 D7                                                              // Xiao pin that connects to rotary encoder clk
#define dt4 D10                                                              // Xiao pin that connects to rotary encoder dt
#define clk4 D9                                                              // Xiao pin that connects to rotary encoder clk

Adafruit_NeoPixel NeoPixel(NUM_PIXELS, PIN_NEO_PIXEL, NEO_GRB + NEO_KHZ800); // set the NeoPixel initialization
Encoder encoder_red(dt1,clk1);                                               // initiate object rotary encoder with the name encoder_red
Encoder encoder_green(dt2,clk2);                                             // initiate object rotary encoder with the name encoder_green
Encoder encoder_blue(dt3,clk3);                                              // initiate object rotary encoder with the name encoder_blue
Encoder encoder_brightness(dt4,clk4);                                        // initiate object rotary encoder with the name encoder_brightness

int red1 = 0;                                                                // red value for the first LED strip
int green1 = 0;                                                              // green value for the first LED strip
int blue1 = 0;                                                               // blue value for the first LED strip
int red2 = 0;                                                                // red value for the second LED strip
int green2 = 0;                                                              // green value for the second LED strip
int blue2 = 0;                                                               // blue value for the second LED strip
int brightness_led1 = 0;                                                     // brightness value for the first LED strip
int brightness_led2 = 0;                                                     // brightness value for the second LED strip
int brightness_spot1 = 0;                                                    // brightness value for the first LED spot
int brightness_spot2 = 0;                                                    // brightness value for the second LED spot

bool sw_control = false;                                                     // control variable for the button
int sw_counter = 1;                                                          // count button presses

void setup() {
  Serial.begin(115200);            // initial serial communication with a baud rate of 115200
  NeoPixel.begin();                // initialize the NeoPixel strip object
  pinMode(sw1, INPUT);             // set pin for rotary encoder button as an input
}

void IRAM_ATTR mode_switch() {
  if (sw_counter <= 4){
    sw_counter ++;
  } if else (sw_counter > 4){
    sw_counter = 1;
  }
}

void loop() { 
  switch (sw_counter){
    case 1:
      red1 = encoder_red.read();
      green1 = encoder_green.read();
      blue1 = encoder_blue.read();
      brightness_led1 = encoder_brightness.read();
    break;
    case 2:
      red2 = encoder_red.read();
      green2 = encoder_green.read();
      blue2 = encoder_blue.read();
      brightness_led2 = encoder_brightness.read();
    break;
    case 3:
      brightness_spot1 = encoder_brightness.read();
    break;
    case 4:
      brightness_spot2 = encoder_brightness.read();
    break;
  }

  NeoPixel.setPixelColor(0, red1, green1, blue1);                // indicate the color from the first LED strip
  NeoPixel.setBrightness(brightness_led1);                       // indicate the brightness from the first LED strip
  NeoPixel.setPixelColor(1, red2, green2, blue2);                // indicate the color from the first LED strip
  NeoPixel.setBrightness(brightness_led2);                       // indicate the brightness from the first LED strip
  NeoPixel.setPixelColor(2, 255, 255, 255);                      // define led indicator for the first LED spot
  NeoPixel.setBrightness(brightness_spot1);                      // indicate the brightness from the first LED spot
  NeoPixel.setPixelColor(3, 255, 255, 255);                      // define led indicator for the second LED spot
  NeoPixel.setBrightness(brightness_spot2);                      // indicate the brightness from the second LED spot
  NeoPixel.show();                                               // output on the NeoPixel

  attachInterrupt(sw1, mode_switch, RISING);
}

WIP

#include <Adafruit_NeoPixel.h>                                                            // library for NeoPixels
#include <Encoder.h>                                                                      // library for rotary encoder
#include <esp_now.h>                                                                      // include ESP-NOW library to use ESP-Now
#include <WiFi.h>                                                                         // include wifi library to activate and use wifi from the ESP32-C3 chip

#define PIN_NEO_PIXEL D0                                                                  // Xiao pin that connects to NeoPixel
#define NUM_PIXELS 4                                                                      // number of NeoPixels
#define dt1 D5                                                                            // Xiao pin that connects to rotary encoder dt
#define clk1 D6                                                                           // Xiao pin that connects to rotary encoder clk
#define sw1 D2                                                                            // Xiao pin that connects to rotary encoder sw
#define dt2 D3                                                                            // Xiao pin that connects to rotary encoder dt
#define clk2 D4                                                                           // Xiao pin that connects to rotary encoder clk
#define dt3 D8                                                                            // Xiao pin that connects to rotary encoder dt
#define clk3 D7                                                                           // Xiao pin that connects to rotary encoder clk
#define dt4 D10                                                                           // Xiao pin that connects to rotary encoder dt
#define clk4 D9                                                                           // Xiao pin that connects to rotary encoder clk

uint8_t broadcastAddress[] = {0x54, 0x32, 0x04, 0x89, 0x8E, 0x00};                        // replaced with the receiver XIAO's MAC Address that I read out earlier it set up the broadcast MAC Address

Adafruit_NeoPixel NeoPixel(NUM_PIXELS, PIN_NEO_PIXEL, NEO_GRB + NEO_KHZ800);              // set the NeoPixel initialization
Encoder encoder_red(dt1,clk1);                                                            // initiate object rotary encoder with the name encoder_red
Encoder encoder_green(dt2,clk2);                                                          // initiate object rotary encoder with the name encoder_green
Encoder encoder_blue(dt3,clk3);                                                           // initiate object rotary encoder with the name encoder_blue
Encoder encoder_brightness(dt4,clk4);                                                     // initiate object rotary encoder with the name encoder_brightness

typedef struct struct_message {                                                           // Structure example to send data that must match the receiver structure
  int red1 = 0;                                                                           // red value for the first LED strip
  int green1 = 0;                                                                         // green value for the first LED strip
  int blue1 = 0;                                                                          // blue value for the first LED strip
  int red2 = 0;                                                                           // red value for the second LED strip
  int green2 = 0;                                                                         // green value for the second LED strip
  int blue2 = 0;                                                                          // blue value for the second LED strip
  int brightness_led1 = 0;                                                                // brightness value for the first LED strip
  int brightness_led2 = 0;                                                                // brightness value for the second LED strip
  int brightness_spot1 = 0;                                                               // brightness value for the first LED spot
  int brightness_spot2 = 0;                                                               // brightness value for the second LED spot
} struct_message;

struct_message myData;                                                                    // Create a struct_message called myData

esp_now_peer_info_t peerInfo;

bool sw_control = false;                                                                  // control variable for the button
int sw_counter = 1;                                                                       // count button presses

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {                  // callback function which tracks if data is sent
  Serial.print("\r\nLast Packet Send Status:\t");                                         // send a message to a serial monitor
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");  // send a message to a serial monitor if the delivery of the data was a success or if it fails
}

void setup() {
  Serial.begin(115200);                                                                   // initial serial communication with a baud rate of 115200
  NeoPixel.begin();                                                                       // initialize the NeoPixel strip object
  pinMode(sw1, INPUT);                                                                    // set pin for rotary encoder button as an input
  WiFi.mode(WIFI_STA);                                                                    // ESP is set in to station mode and not into access point

  if (esp_now_init() != ESP_OK) {                                                         // initialize ESP-NOW
    Serial.println("Error initializing ESP-NOW");                                         // if the ESP encounter any setup errors it will send a error message to a serial monitor
    return;                                                                               // exit function
  }

  esp_now_register_send_cb(OnDataSent);                                                     // after a successful initialization of ESP-NOW it will call up the OnDataSent function from earlier

  memcpy(peerInfo.peer_addr, broadcastAddress, 6);                                        // Register another XIAO to peer with
  peerInfo.channel = 0;                                                                   // set peer chanel to 0, multiple channels are possible to make sure that they are no interference
  peerInfo.encrypt = false;                                                               // don't encrypt the transmit messages

  if (esp_now_add_peer(&peerInfo) != ESP_OK){                                             // function to send a MAC Address to the receiver to add a peer 
    Serial.println("Failed to add peer");                                                 // send an error message to the serial monitor if the connection setup failed
    return;                                                                               // exit function
  }
}

void IRAM_ATTR mode_switch() {                                                            // interrupt function triggered by pressing the button from the first rotary encoder
  if (sw_counter <= 4){                                                                   // let the switch counter count between 1 and 4
    sw_counter ++;                                                                        // by each activation increase the switch counter
  } if else (sw_counter > 4){                                                             // if the counter reaches 5
    sw_counter = 1;                                                                       // reset the counter to 1
  }
}

void loop() {
  switch (sw_counter){                                                                    // switch case to control the different light settings related to the selection
    case 1:                                                                               // in case 1 set parameter for the first LED strip
      myData.red1 = encoder_red.read();
      myData.green1 = encoder_green.read();
      myData.blue1 = encoder_blue.read();
      myData.brightness_led1 = encoder_brightness.read();
    break;
    case 2:                                                                                // in case 2 set parameter for the second LED strip
      myData.red2 = encoder_red.read();
      myData.green2 = encoder_green.read();
      myData.blue2 = encoder_blue.read();
      myData.brightness_led2 = encoder_brightness.read();
    break;
    case 3:                                                                                // in case 3 set brightness for the first raw of LED spot
      myData.brightness_spot1 = encoder_brightness.read();
    break;
    case 4:                                                                                // in case 4 set brightness for the second raw of LED spot
      myData.brightness_spot2 = encoder_brightness.read();
    break;
  }

  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));  // send message via ESP-NOW

  if (result == ESP_OK) {                                                                  // send positive message to a serial monitor if the transmit was successful
    Serial.println("Sent with success");
  } else {                                                                                 // send error message to a serial monitor if the transmit was not successful
    Serial.println("Error sending the data");
  }

  NeoPixel.setPixelColor(0, red1, green1, blue1);                                          // indicate the color from the first LED strip
  NeoPixel.setBrightness(brightness_led1);                                                 // indicate the brightness from the first LED strip
  NeoPixel.setPixelColor(1, red2, green2, blue2);                                          // indicate the color from the first LED strip
  NeoPixel.setBrightness(brightness_led2);                                                 // indicate the brightness from the first LED strip
  NeoPixel.setPixelColor(2, 255, 255, 255);                                                // define led indicator for the first LED spot
  NeoPixel.setBrightness(brightness_spot1);                                                // indicate the brightness from the first LED spot
  NeoPixel.setPixelColor(3, 255, 255, 255);                                                // define led indicator for the second LED spot
  NeoPixel.setBrightness(brightness_spot2);                                                // indicate the brightness from the second LED spot
  NeoPixel.show();                                                                         // output on the NeoPixel

  attachInterrupt(sw1, mode_switch, RISING);                                               // enter interrupt function to switch the mode on a rising slope
}

The code for the light controller looks like that:

What I Learned This Week?

  • SoftwareSerial Library is to big for the Attiny412
  • The XIAO ESP32-C3 is most of the time enough for everything you need and allows to easily communicate wirelessly with other XIAO ESP32-C3.
  • Esp Now is a great and fast way to communicate wirelessly between ESP32 modules.

What I want to improve next week

Design Files

light controller project
remote schematic
remote traces
remote holes outline


To create this page, I used ChatGPT to check my syntax and grammar.

Copyright 2025 < Benedikt Feit > - Creative Commons Attribution Non Commercial

Source code hosted at gitlab.fabcloud.org