Alarmă de curent PRO cu ATtiny85 (USB 5V)
Dispozitiv compact care anunță căderea sau revenirea curentului de la rețea prin buzzer și LED-uri. Alimentare de la un încărcător USB 5V, logică pe ATtiny85, comutator pentru moduri (Fail / Off / Return).
Descriere & cum funcționează
Dispozitivul monitorizează prezența tensiunii de 5V furnizată de un încărcător USB. La căderea alimentării, trece automat pe modul alimentat din acumulator și declanșează o alertă acustică continuă (configurabilă în firmware). La revenirea alimentării, emite o secvență de 3 beep-uri și semnalizează vizual prin LED-uri. Un comutator cu trei poziții permite selectarea rapidă a modului:
- FAIL – alarmează la cădere de curent (beep continuu).
- OFF – dispozitivul rămâne inactiv (fără semnale).
- RETURN – alarmează la revenirea curentului (3 beep-uri).
Conectorul USB-C este cablat ca UFP/Sink, cu rezistențe de 5.1 kΩ pe liniile CC pentru negocirea standard (VBUS 5V). Microcontrolerul ATtiny85 gestionează logica de stare, anti-debouncing pentru comutator și modelele de semnalizare. LED-urile indică rapid starea, iar buzzerul poate fi pasiv (prin driver tranzistor) sau activ (direct la 5V).
Schemă electronică
Bill of Materials (BOM)
Orientativ — ajustează după componentele tale finale.
| RefDes | Componentă | Specificații | Cant. | Note |
|---|---|---|---|---|
| U1 | ATtiny85-20SU | MCU 8-bit, 5V, SOIC-8/TSSOP-8 | 1 | Frecv. internă; ISP prin header 2×3 |
| J1 | USB-C Receptacle | UFP/Sink, doar alimentare (VBUS + CC) | 1 | CC1/CC2 cu Rd = 5.1 kΩ |
| R1, R2 | Rezistențe CC | 5.1 kΩ ±1% | 2 | Rd pentru CC1/CC2 → GND |
| C1, C2 | Decuplare | 100 nF, 10 µF / 16V | 2 | Lângă U1 și VBUS |
| D1 | TVS VBUS | SMBJ5.0A sau USB ESD | 1 | Protecție ESD/Surge |
| F1 | Siguranță PTC | Resetabilă 0.5–1.0 A | 1 | Protecție la scurt |
| SW1 | Comutator 3 poziții | ON-OFF-ON (SPDT) | 1 | Moduri: FAIL / OFF / RETURN |
| LED1, LED2 | LED status | Verde / Roșu + R serie | 2 | R ~1–2 kΩ la 5V |
| BZ1 | Buzzer | 5V activ sau pasiv | 1 | Pasiv → driver tranzistor (Q1) |
| Q1, Rb | Driver buzzer (opțional) | NPN + 1–4.7 kΩ | 1+1 | Pentru buzzer pasiv |
| J2 | Header ISP | 2×3, 2.54 mm | 1 | Programare USBasp/UNO-as-ISP |
Video demonstrativ
Galerie
Firmware ATtiny85
Vezi codul complet
// ATtiny85 (ATTinyCore): 0->PB0, 1->PB1, 2->PB2, 3->PB3, 4->PB4
const uint8_t BUZZ_PIN = 0; // PB0 (HIGH = ON prin MOSFET)
const uint8_t LED_GREEN = 1; // PB1 (ACTIVE-LOW: LOW = ON)
const uint8_t NET_SENSE = 2; // PB2 (LM393: HIGH=curent prezent, LOW=pană)
const uint8_t SW_ON1 = 3; // PB3 (ON=LOW) -> CĂDERE
const uint8_t SW_ON2 = 4; // PB4 (ON=LOW) -> REVENIRE
inline void led_on(uint8_t p){ digitalWrite(p, LOW); } // active-low
inline void led_off(uint8_t p){ digitalWrite(p, HIGH); }
const uint16_t DEBOUNCE_MS = 50;
// --- Parametri sunet ---
const uint16_t OUTAGE_ON_MS = 400; // model intermitent cât timp e pană (ON)
const uint16_t OUTAGE_OFF_MS = 300; // model intermitent cât timp e pană (OFF)
const uint16_t BEEP_MS_EVENT = 180; // pentru „revenire” (3 bipuri)
const uint16_t BEEP_MS_PAUSE = 120;
// --- Stări ---
bool net_present=false, net_prev=false;
// pentru modelul intermitent la pană
bool buzz_state = false;
unsigned long buzz_t0 = 0;
bool in_outage_pattern = false;
bool read_net_debounced(){
static bool stable=false; static unsigned long t0=0;
bool raw = digitalRead(NET_SENSE); // HIGH=prezent
if (raw != stable){
if (millis()-t0 >= DEBOUNCE_MS){ stable = raw; t0 = millis(); }
} else { t0 = millis(); }
return stable;
}
inline void buzz_on() { digitalWrite(BUZZ_PIN, HIGH); buzz_state = true; }
inline void buzz_off() { digitalWrite(BUZZ_PIN, LOW); buzz_state = false; }
void triple_beep(){
for (uint8_t i=0; i<3; i++){
buzz_on(); delay(BEEP_MS_EVENT);
buzz_off(); delay(BEEP_MS_PAUSE);
}
}
// Rulează modelul intermitent non-blocking cât timp e pană (ON-1 activ)
void outage_buzz_tick(){
static uint16_t current_slice = OUTAGE_ON_MS; // durata segmentului curent
if (!in_outage_pattern){
// inițializare la intrarea în mod
in_outage_pattern = true;
buzz_on();
buzz_t0 = millis();
current_slice = OUTAGE_ON_MS;
}
unsigned long now = millis();
if (now - buzz_t0 >= current_slice){
// schimbă starea și durata
if (buzz_state){
buzz_off();
current_slice = OUTAGE_OFF_MS;
} else {
buzz_on();
current_slice = OUTAGE_ON_MS;
}
buzz_t0 = now;
}
}
void reset_outage_buzz(){
in_outage_pattern = false;
buzz_off();
}
void setup(){
pinMode(BUZZ_PIN, OUTPUT); buzz_off();
pinMode(LED_GREEN, OUTPUT); led_off(LED_GREEN);
pinMode(NET_SENSE, INPUT);
pinMode(SW_ON1, INPUT_PULLUP); // ON=LOW (centrul la GND)
pinMode(SW_ON2, INPUT_PULLUP);
net_prev = net_present = digitalRead(NET_SENSE);
if (net_present) led_on(LED_GREEN); else led_off(LED_GREEN);
}
void loop(){
const bool on1 = (digitalRead(SW_ON1)==LOW); // ON-1: cădere
const bool on2 = (digitalRead(SW_ON2)==LOW); // ON-2: revenire
const bool off_mode = (!on1 && !on2) || (on1 && on2);
net_prev = net_present;
net_present = read_net_debounced();
// LED verde (prezent curent)
if (net_present) led_on(LED_GREEN);
else led_off(LED_GREEN);
// LED roșu e hardware via comparator (nu-l comandăm din cod)
// Edge-uri
const bool fell = (net_prev && !net_present); // a căzut curentul
const bool rose = (!net_prev && net_present); // a revenit curentul
if (off_mode){
reset_outage_buzz(); // mut în OFF
} else {
// ON-1: pană -> intermitent permanent
if (on1){
if (!net_present){
outage_buzz_tick(); // rulează modelul non-blocking
} else {
reset_outage_buzz(); // dacă a revenit
}
}
// ON-2: revenire -> 3 bipuri scurte (o singură dată pe eveniment)
if (on2){
if (rose){
// ne asigurăm că nu rămâne moștenită starea din modelul de pană
reset_outage_buzz();
triple_beep();
}
// în rest, tăcem
}
}
delay(2); // mic respiro
}