MediaPipe Face Landmarker → XIAO ESP32S3 over Web Serial
—// XIAO ESP32S3 — RGB rainbow on D7/D8/D9 driven by serial commands
// Wiring: common-cathode RGB LED with current-limiting resistors on each leg.
// For common-anode, set COMMON_ANODE to true.
#define COMMON_ANODE false
const int PIN_R = D7;
const int PIN_G = D8;
const int PIN_B = D9;
bool rainbow = false;
float hue = 0.0f;
void writeRGB(uint8_t r, uint8_t g, uint8_t b) {
if (COMMON_ANODE) { r = 255 - r; g = 255 - g; b = 255 - b; }
analogWrite(PIN_R, r);
analogWrite(PIN_G, g);
analogWrite(PIN_B, b);
}
void hsvToRgb(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) {
float c = v * s;
float x = c * (1 - fabsf(fmodf(h / 60.0f, 2) - 1));
float m = v - c;
float rf, gf, bf;
if (h < 60) { rf = c; gf = x; bf = 0; }
else if (h < 120) { rf = x; gf = c; bf = 0; }
else if (h < 180) { rf = 0; gf = c; bf = x; }
else if (h < 240) { rf = 0; gf = x; bf = c; }
else if (h < 300) { rf = x; gf = 0; bf = c; }
else { rf = c; gf = 0; bf = x; }
r = (uint8_t)((rf + m) * 255);
g = (uint8_t)((gf + m) * 255);
b = (uint8_t)((bf + m) * 255);
}
void setup() {
Serial.begin(115200);
pinMode(PIN_R, OUTPUT);
pinMode(PIN_G, OUTPUT);
pinMode(PIN_B, OUTPUT);
writeRGB(0, 0, 0);
}
void loop() {
if (Serial.available()) {
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd == "RAINBOW") rainbow = true;
else if (cmd == "OFF") { rainbow = false; writeRGB(0, 0, 0); }
}
if (rainbow) {
uint8_t r, g, b;
hsvToRgb(hue, 1.0f, 1.0f, r, g, b);
writeRGB(r, g, b);
hue += 0.6f;
if (hue >= 360.0f) hue -= 360.0f;
delay(15);
}
}