LoganX & OhmGuru
OhmGuru OhmGuru
Hey, I’ve been building a small alarm board that flashes a LED at a very specific interval and I think we could tweak it into a personal alarm system. The blinking pattern could act like a signal for a threat and the buzzer can be a quick deterrent. Want to help me fine‑tune the firmware?
LoganX LoganX
Fine, but only if the board sits in a room with an odd number of windows. Give me the sketch and the current timing code, and I’ll cut the interval down a notch. Once you’re sure the LED blinks fast enough to catch a threat, hand it back, don’t touch the pins like a fool, and run. That's it.
OhmGuru OhmGuru
Here’s a stripped‑down sketch that uses a timer interrupt for the LED blink, so the main loop stays clean. The LED is on pin 13, the buzzer on pin 12. I’m starting the interval at 800 ms, and you can cut it by 200 ms per tweak. Once the window count is odd, the board will be armed. ```cpp // Basic alarm board sketch const int LED_PIN = 13; const int BUZZER_PIN = 12; const int WINDOW_COUNT = 5; // must be odd for armed state volatile unsigned long blinkInterval = 800; // ms volatile unsigned long lastBlink = 0; bool ledState = false; bool armed = false; void setup() { pinMode(LED_PIN, OUTPUT); pinMode(BUZZER_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); digitalWrite(BUZZER_PIN, LOW); // Only arm if window count is odd if (WINDOW_COUNT % 2 == 1) { armed = true; } } void loop() { if (!armed) return; // nothing to do if not armed unsigned long now = millis(); if (now - lastBlink >= blinkInterval) { lastBlink = now; ledState = !ledState; digitalWrite(LED_PIN, ledState ? HIGH : LOW); if (ledState) { // When LED turns on, buzz briefly digitalWrite(BUZZER_PIN, HIGH); delay(50); // 50 ms buzz digitalWrite(BUZZER_PIN, LOW); } } // Your main code would go here, but we keep it idle } ``` **How to cut the interval:** Just change the `blinkInterval` constant from 800 to 600, 400, 200, or whatever feels right. The LED will flash that fast, and the buzzer will sound each time the LED turns on. Feel free to copy it, upload, and give it a spin. Don’t touch the pins—this board is already a mess in a good way. When you’re happy, hand it back and let it run.
LoganX LoganX
Alright, you got the right idea. Cut the interval by 200 and watch the LED speed up. But that `delay(50)` in the middle will choke the timer—use a second interrupt for the buzzer if you want true real‑time. Keep the board in a room with an odd number of windows, set the window count to 5 or 7, and make sure you lock the case. Once you’re sure the blink looks like a warning, hand the board over, don’t touch it again, and let it run. If it goes off, I’ll fix it from the back of the room.
OhmGuru OhmGuru
Got it, here’s the updated sketch with a separate ISR for the buzzer so the LED timing stays clean. I’ve left the window count at 5—feel free to swap 7 if you want more odds. The case lock is a good idea, just make sure the pin headers stay exposed for the buzz. ```cpp // Alarm board with dual interrupts #include <avr/io.h> #include <avr/interrupt.h> const int LED_PIN = 13; const int BUZZER_PIN = 12; const int WINDOW_COUNT = 5; // odd number to arm volatile unsigned long blinkInterval = 600; // ms, cut by 200 volatile unsigned long lastBlink = 0; volatile bool ledState = false; volatile bool armed = false; // Buzzer ISR: toggles buzzer for 50 ms when triggered ISR(TIMER2_COMPA_vect) { static unsigned long buzzStart = 0; if (digitalRead(BUZZER_PIN) == LOW) { digitalWrite(BUZZER_PIN, HIGH); buzzStart = millis(); } else if (millis() - buzzStart >= 50) { digitalWrite(BUZZER_PIN, LOW); // disable this compare interrupt until next trigger TIMSK2 &= ~(1 << OCIE2A); } } void setup() { pinMode(LED_PIN, OUTPUT); pinMode(BUZZER_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); digitalWrite(BUZZER_PIN, LOW); // arm only if windows count is odd if (WINDOW_COUNT % 2 == 1) { armed = true; } // Configure Timer1 for LED blink TCCR1B |= (1 << WGM12); // CTC mode OCR1A = 15624; // 1 s @ 16 MHz, prescaler 64 TCCR1B |= (1 << CS11) | (1 << CS10); // prescaler 64 TIMSK1 |= (1 << OCIE1A); // enable compare interrupt // Configure Timer2 for buzzer ISR TCCR2B |= (1 << WGM21); // CTC mode OCR2A = 249; // 1 kHz compare at 16 MHz, prescaler 64 TCCR2B |= (1 << CS22) | (1 << CS21); // prescaler 64 // keep compare interrupt disabled until LED triggers sei(); // enable global interrupts } ISR(TIMER1_COMPA_vect) { if (!armed) return; unsigned long now = millis(); if (now - lastBlink >= blinkInterval) { lastBlink = now; ledState = !ledState; digitalWrite(LED_PIN, ledState ? HIGH : LOW); if (ledState) { // trigger buzzer ISR TIMSK2 |= (1 << OCIE2A); } } } void loop() { // everything handled in interrupts; keep loop idle } ``` Upload this, lock the case, and let it run. I’ll pick it up from the back of the room if anything goes off.
LoganX LoganX
Looks solid. Just test that the LED really flips every 600 ms and that the buzzer lights for 50 ms each time the LED goes on. Keep the case locked but leave the header rows exposed for the buzz. If it blows a warning, hand it back to me from the back of the room and I’ll take it from there. Done.
OhmGuru OhmGuru
Sure thing, I’ll spin it up and watch the 600 ms blink and 50 ms buzz in real time. Locked case, headers exposed—no surprises. I’ll hand it back from the back if anything sparks. Done.
LoganX LoganX
Good. Keep it running, keep the case tight. If it goes off, bring it to the back and let me see what’s wrong. No tricks, no drama. That's all.
OhmGuru OhmGuru
All right, case locked, headers exposed, timer running. If it lights up or buzzes wrong, you’ll find me at the back with the board. No drama.
LoganX LoganX
Alright, keep your hands off it. I’ll monitor from the back. If it lights or buzzes wrong, bring it over, no nonsense.