#include <Adafruit_NeoPixel.h>
#define NUM_PIXELS 5
#define PIXEL_PIN 8
#define POT1_PIN 0
#define POT2_PIN 1
#define POT3_PIN 2
#define POT4_PIN 3
#define RELAY1_PIN 4
#define RELAY2_PIN 5
#define RELAY3_PIN 6
#define RELAY4_PIN 7
#define BUTTON_PIN 9
#define TOLERANCE 2 // Acceptable range around target (±2)
Adafruit_NeoPixel pixels(NUM_PIXELS, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
// Current and target pot values
int val1, val2, val3, val4;
const int target1 = 25;
const int target2 = 50;
const int target3 = 75;
const int target4 = 100;
// State flags
bool triggered1 = false, triggered2 = false, triggered3 = false, triggered4 = false;
// Blinking logic for status pixel
unsigned long lastBlink = 0;
bool blinkState = false;
void setup() {
Serial.begin(115200);
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);
pinMode(RELAY4_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
digitalWrite(RELAY1_PIN, LOW);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);
digitalWrite(RELAY4_PIN, LOW);
pixels.begin();
pixels.clear();
pixels.show();
}
void loop() {
// Read analog and map to 0–100
int newVal1 = map(analogRead(POT1_PIN), 0, 4095, 0, 100);
int newVal2 = map(analogRead(POT2_PIN), 0, 4095, 0, 100);
int newVal3 = map(analogRead(POT3_PIN), 0, 4095, 0, 100);
int newVal4 = map(analogRead(POT4_PIN), 0, 4095, 0, 100);
// Only update if anything changed
if (newVal1 != val1 || newVal2 != val2 || newVal3 != val3 || newVal4 != val4) {
val1 = newVal1; val2 = newVal2;
val3 = newVal3; val4 = newVal4;
Serial.printf("Pot1: %d | Pot2: %d | Pot3: %d | Pot4: %d\n", val1, val2, val3, val4);
updatePixelProximity(val1, target1, 0);
updatePixelProximity(val2, target2, 1);
updatePixelProximity(val3, target3, 2);
updatePixelProximity(val4, target4, 3);
}
// Check each pot against its target with tolerance
if (!triggered1 && withinTolerance(val1, target1)) triggerRelay(RELAY1_PIN, 0, triggered1);
if (!triggered2 && withinTolerance(val2, target2)) triggerRelay(RELAY2_PIN, 1, triggered2);
if (!triggered3 && withinTolerance(val3, target3)) triggerRelay(RELAY3_PIN, 2, triggered3);
if (!triggered4 && withinTolerance(val4, target4)) triggerRelay(RELAY4_PIN, 3, triggered4);
// Blink blue pixel 4 until all relays triggered
if (!(triggered1 && triggered2 && triggered3 && triggered4)) {
if (millis() - lastBlink > 500) {
blinkState = !blinkState;
pixels.setPixelColor(4, blinkState ? pixels.Color(0, 0, 100) : 0);
pixels.show();
lastBlink = millis();
}
} else {
pixels.setPixelColor(4, pixels.Color(0, 150, 255)); // Locked: full blue
pixels.show();
}
// Button resets everything
static bool lastBtn = HIGH;
bool btn = digitalRead(BUTTON_PIN);
if (lastBtn == HIGH && btn == LOW) {
Serial.println("🔄 Reset triggered");
triggered1 = triggered2 = triggered3 = triggered4 = false;
digitalWrite(RELAY1_PIN, LOW);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);
digitalWrite(RELAY4_PIN, LOW);
pixels.clear();
pixels.show();
}
lastBtn = btn;
}
void updatePixelProximity(int val, int target, int pixelIndex) {
int diff = abs(val - target);
int green = map(constrain(100 - diff, 0, 100), 0, 100, 0, 255);
pixels.setPixelColor(pixelIndex, pixels.Color(0, green, 0));
pixels.show();
}
bool withinTolerance(int val, int target) {
return (val >= target - TOLERANCE && val <= target + TOLERANCE);
}
void triggerRelay(int pin, int pixel, bool &triggeredFlag) {
digitalWrite(pin, HIGH);
pixels.setPixelColor(pixel, pixels.Color(0, 255, 0)); // Full green
pixels.show();
triggeredFlag = true;
Serial.printf("✅ Relay %d triggered!\n", pixel + 1);
}
Loading
xiao-esp32-c3
xiao-esp32-c3