1 changed files with 146 additions and 0 deletions
@ -0,0 +1,146 @@ |
|||
/*
|
|||
* LED + Button Controller with Serial Commands and Smooth Pulsing |
|||
* ================================================================ |
|||
* |
|||
* HARDWARE WIRING NOTES: |
|||
* ---------------------- |
|||
* The switch (TRU Components LAS1-AGQ-11E/R/G) has an integrated LED rated |
|||
* for +12V with a built-in resistor. Since the Arduino cannot: |
|||
* a) Supply 12V (it outputs 5V max) |
|||
* b) Drive enough current for the LED directly |
|||
* c) Do PWM dimming at 12V |
|||
* |
|||
* ...you MUST use an NPN Darlington transistor (TIP122) as a low-side switch. |
|||
* |
|||
* WIRING: |
|||
* +12V PSU (+) --> LED+ on switch |
|||
* LED- on switch --> COLLECTOR (TIP122 middle pin) |
|||
* Arduino Pin 10 --> 1k Ohm resistor --> BASE (TIP122 left pin) |
|||
* EMITTER (TIP122 right pin) --> GND |
|||
* Arduino GND + 12V PSU GND --> tied together (common ground) |
|||
* |
|||
* SWITCH (button) WIRING: |
|||
* COM --> Arduino Pin 9 |
|||
* NO --> GND |
|||
* NC --> leave unconnected |
|||
* |
|||
* Pin 10 must be PWM-capable (Uno/Nano/Mega all support this). |
|||
* |
|||
* SERIAL COMMANDS: |
|||
* LED_ON -> Turn LED fully on (100%, stops pulsing) |
|||
* LED_OFF -> Turn LED fully off (stops pulsing) |
|||
* LED_DIM:xx -> Turn LED on at xx percent (0-100), e.g. LED_DIM:50 |
|||
* LED_PULSE_ON -> Start smooth breathing/pulse animation |
|||
* LED_PULSE_OFF -> Stop pulsing (LED goes off) |
|||
* CLEAR -> Turn LED off (legacy command) |
|||
* |
|||
* BUTTON OUTPUT: |
|||
* "B/true" when pressed (LOW with pull-up) |
|||
* "B/false" when released (HIGH) |
|||
*/ |
|||
|
|||
// Constants for pin assignments
|
|||
const int ledPin = 10; // Must be PWM-capable!
|
|||
const int buttonPin = 9; |
|||
|
|||
// Button state variables
|
|||
int buttonState = 1; |
|||
int lastButtonState = 1; |
|||
|
|||
// Debounce timing
|
|||
unsigned long lastDebounceTime = 0; |
|||
unsigned long debounceDelay = 50; |
|||
|
|||
// LED state machine
|
|||
enum LedMode { |
|||
LED_MODE_OFF, |
|||
LED_MODE_ON, |
|||
LED_MODE_DIM, |
|||
LED_MODE_PULSE |
|||
}; |
|||
|
|||
LedMode ledMode = LED_MODE_OFF; |
|||
|
|||
// Pulse animation variables
|
|||
unsigned long pulseStartTime = 0; |
|||
const unsigned long pulseCycleMs = 3000; // Full breath cycle duration in ms
|
|||
|
|||
void setup() { |
|||
buttonState = 1; |
|||
pinMode(ledPin, OUTPUT); |
|||
pinMode(buttonPin, INPUT_PULLUP); |
|||
analogWrite(ledPin, 0); |
|||
|
|||
Serial.begin(9600); |
|||
} |
|||
|
|||
void loop() { |
|||
// --- Button debouncing ---
|
|||
int reading = digitalRead(buttonPin); |
|||
|
|||
if (reading != lastButtonState) { |
|||
lastDebounceTime = millis(); |
|||
} |
|||
|
|||
if ((millis() - lastDebounceTime) > debounceDelay) { |
|||
if (reading != buttonState) { |
|||
buttonState = reading; |
|||
if (buttonState == 0) { |
|||
Serial.println("B/true"); |
|||
} else { |
|||
Serial.println("B/false"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
lastButtonState = reading; |
|||
|
|||
// --- Serial command handling ---
|
|||
if (Serial.available() > 0) { |
|||
String command = Serial.readStringUntil('\n'); |
|||
command.trim(); |
|||
|
|||
if (command == "LED_ON") { |
|||
ledMode = LED_MODE_ON; |
|||
analogWrite(ledPin, 255); |
|||
} |
|||
else if (command == "LED_OFF") { |
|||
ledMode = LED_MODE_OFF; |
|||
analogWrite(ledPin, 0); |
|||
} |
|||
else if (command.startsWith("LED_DIM:")) { |
|||
int percent = command.substring(8).toInt(); |
|||
percent = constrain(percent, 0, 100); |
|||
int pwmValue = map(percent, 0, 100, 0, 255); |
|||
ledMode = LED_MODE_DIM; |
|||
analogWrite(ledPin, pwmValue); |
|||
} |
|||
else if (command == "LED_PULSE_ON") { |
|||
ledMode = LED_MODE_PULSE; |
|||
pulseStartTime = millis(); |
|||
} |
|||
else if (command == "LED_PULSE_OFF") { |
|||
ledMode = LED_MODE_OFF; |
|||
analogWrite(ledPin, 0); |
|||
} |
|||
else if (command.startsWith("CLEAR")) { |
|||
ledMode = LED_MODE_OFF; |
|||
analogWrite(ledPin, 0); |
|||
} |
|||
} |
|||
|
|||
// --- Pulse animation (non-blocking) ---
|
|||
if (ledMode == LED_MODE_PULSE) { |
|||
unsigned long elapsed = millis() - pulseStartTime; |
|||
unsigned long pos = elapsed % pulseCycleMs; |
|||
|
|||
// Sine wave: 0 -> 1 -> 0 over one full "breath" cycle
|
|||
float phase = (float)pos / (float)pulseCycleMs; |
|||
float brightness = sin(phase * PI); |
|||
brightness = brightness * brightness; // Squared for organic ease-in-out
|
|||
|
|||
// Min ~8 so LED never fully goes dark (subtle "alive" glow at trough)
|
|||
int pwmValue = 2 + (int)(brightness * 247.0); |
|||
analogWrite(ledPin, pwmValue); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue