From 8a8c8b922eba7335e18a1f027f991194a6e13b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cmatteoscrugli=E2=80=9D?= <“ma.”scrugli@gmail.com> Date: Sun, 7 Dec 2025 20:51:41 +0100 Subject: [PATCH] first commit --- .gitignore | 61 ++++++++ README.md | 305 +++++++++++++++++++++++++++++++++++++ src/src.ino | 422 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 788 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 src/src.ino diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..369a011 --- /dev/null +++ b/.gitignore @@ -0,0 +1,61 @@ +# Arduino build files +*.hex +*.eep +*.elf +*.map + +# Arduino IDE files +*.ino.bak +*.ino.tmp +*~ + +# Build directory +build/ +build-*/ + +# Compiled Object files +*.o +*.a + +# Debugging files +*.log +*.txt + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# IDE specific files +.vscode/ +.idea/ +*.sublime-* + +# Backup files +*~ +*.swp +*.swo +*.bak + +# Arduino libraries (if using external libraries, uncomment as needed) +# libraries/ + +# Documentation build +docs/_build/ + +# Python (if using any Python tools) +__pycache__/ +*.py[cod] +*.pyo +*.pyd +.Python +venv/ +env/ + +# Temporary files +*.tmp +*.temp diff --git a/README.md b/README.md new file mode 100644 index 0000000..137092b --- /dev/null +++ b/README.md @@ -0,0 +1,305 @@ +# Sistema Allarme Camper Ultra Low Power + +Sistema di allarme per camper ottimizzato per consumo energetico minimo, con rilevamento intelligente delle vibrazioni e controllo remoto via RF. + +## Caratteristiche + +- **Ultra Low Power**: ~3.5mA armato, autonomia 60+ giorni con batteria 12V 7Ah +- **Rilevamento Intelligente**: Conta N cambi di stato in finestra temporale per ridurre falsi positivi +- **Sleep Mode PWR_DOWN**: Sistema dorme il 99% del tempo (~0.1µA) +- **Interrupt-Driven**: Risposta immediata senza polling continuo +- **Watchdog Timer**: Lampeggio LED senza sprechi energetici +- **Configurabile**: Debug serial e tipo sensore via #define +- **Controllo RF**: Attivazione/disattivazione tramite telecomando 433MHz + +## Hardware Richiesto + +### Componenti Principali +- **Arduino Pro Mini 3.3V 8MHz** (consigliato per ultra low power) + - Dissaldare LED power sulla board (risparmio ~10mA) + - Mantenere regolatore di tensione onboard +- **RX480E-4** - Ricevitore RF 433MHz (⚠️ richiede 5V - vedi nota sotto) +- **Sensore vibrazione SW-420** - Modulo con switch vibrazioni + - Dissaldare LED power e LED signal dal modulo (risparmio ~15mA) + - Regolazione sensibilità tramite potenziometro onboard +- **Buzzer attivo** 3.3V-5V compatibile +- **LED** x2 (status + intrusione) +- **Resistenze** 1.5kΩ per LED (low power) + +**⚠️ Nota importante RF Receiver:** +Il RX480E-4 richiede alimentazione a 5V. Con Pro Mini 3.3V hai due opzioni: +1. Usare regolatore 5V separato per il solo ricevitore RF +2. Usare ricevitore RF compatibile 3.3V (es. RXB6, moduli superheterodyne) + +### Alimentazione +- Batteria 12V 7Ah (autonomia ~67 giorni) +- Oppure batteria 9V 500mAh (autonomia ~5 giorni) +- Regolatore step-down se necessario + +## Schema Collegamento + +``` +Arduino Pin → Componente +──────────────────────────── +Pin 2 → SW-420 D0 (INT0) +Pin 6 → RX480E-4 DATA (PCINT22) +Pin 9 → Buzzer +Pin 12 → LED intrusione +Pin 13 → LED status + +VCC (3.3V) → SW-420 VCC +VCC (5V) → RX480E-4 VCC (richiede regolatore separato) +GND → Tutti i GND comuni +``` + +## Configurazione Software + +### Parametri Configurabili + +Nel file `src/src.ino`, modifica le seguenti define: + +```cpp +// Debug Serial (disabilita in produzione) +#define DEBUG_SERIAL + +// Stato iniziale all'accensione +#define STARTUP_STATE 1 // 0=sempre disarmato, 1=sempre armato, 2=check RF + +// Rilevamento vibrazione intelligente +#define VIBRATION_WINDOW_MS 2000 // Finestra temporale (ms) +#define VIBRATION_THRESHOLD 80 // N° cambi di stato richiesti +#define VIBRATION_TIMEOUT_MS 3000 // Timeout inattività (ms) + +// Durate allarme +#define TRIGGER_DURATION_MS 5000 // Durata buzzer (ms) +#define ARMING_DELAY_MS 2000 // Delay armamento (ms) +``` + +### Modalità di Avvio + +| STARTUP_STATE | Comportamento | +|---------------|---------------| +| 0 | **ALWAYS_DISARMED** - Parte sempre disarmato (ignora RF) | +| 1 | **ALWAYS_ARMED** - Parte sempre armato (massima sicurezza) | +| 2 | **CHECK_RF** - Controlla stato RF all'avvio (default) | + +## Installazione + +### 1. Arduino IDE Setup + +``` +Tools → Board → Arduino Pro or Pro Mini +Tools → Processor → ATmega328P (3.3V, 8MHz) +Tools → Programmer → (seleziona il tuo FTDI/USB-Serial) +``` + +**Nota:** Il codice è compatibile con 8MHz. Le funzioni millis() e watchdog timer si adattano automaticamente alla frequenza del clock. + +### 2. Upload Codice + +1. Apri `src/src.ino` nell'Arduino IDE +2. Abilita `#define DEBUG_SERIAL` per test +3. Compila e carica (`Ctrl+U`) +4. Apri Serial Monitor (9600 baud) per vedere l'output + +### 3. Test Funzionalità + +**Con DEBUG_SERIAL abilitato:** +``` +Alarm Ready +(Premi telecomando) → Sistema si arma +(Scuoti sensore) → INTRUSIONE +``` + +### 4. Produzione + +1. Commenta `#define DEBUG_SERIAL` +2. Ricompila e carica +3. Sistema pronto per installazione + +## Funzionamento + +### Stati del Sistema + +``` +DISARMED (Disarmato) + ↓ (RF HIGH) +ARMING (Armamento - 2s) + ↓ +ARMED (Armato - lampeggio LED) + ↓ (Vibrazioni > soglia) +TRIGGERED (Allarme - buzzer 5s) + ↓ (Timeout o RF LOW) +DISARMED / ARMED +``` + +### Rilevamento Vibrazioni Intelligente + +Il sistema conta i **cambi di stato** del sensore in una finestra temporale: + +- **Soglia default**: 80 cambi in 2000ms +- **Vantaggio**: Filtra falsi positivi (vibrazioni stradali, vento) +- **Personalizzabile**: Regola `VIBRATION_THRESHOLD` e `VIBRATION_WINDOW_MS` + +**Esempio:** +``` +Vibrazione stradale leggera → 5 cambi in 2s → Ignorata ✓ +Intrusione reale → 80+ cambi in 2s → ALLARME! ✓ +``` + +## Consumo Energetico + +### Consumi per Stato + +| Stato | Consumo | Durata Tipica | +|-------|---------|---------------| +| **DISARMED** | ~3.0 mA | Continuo | +| **ARMING** | ~1.5 mA | 2 secondi | +| **ARMED** | ~3.5 mA | Continuo | +| **TRIGGERED** | ~32 mA | 5 secondi | + +### Autonomia Stimata + +**Con batteria 12V 7Ah:** +- Allarme armato continuo: **~67 giorni** +- Uso misto (8h armato/giorno): **~6 mesi** + +**Con batteria 9V 500mAh:** +- Allarme armato continuo: **~5 giorni** + +### Breakdown Consumo (Armato) + +``` +RX480E-4 (sempre on): 3.0 mA (86%) +LED lampeggio (media): 0.1 mA (3%) +ATmega328P (wake-up): 0.4 mA (11%) +───────────────────────────────── +TOTALE: 3.5 mA +``` + +## Preparazione Hardware + +### Arduino Pro Mini: Rimozione LED Power (Obbligatoria) + +**Risparmio: ~10mA** + +Il LED power sulla board Pro Mini consuma continuamente ~10mA e deve essere rimosso: + +1. Individua il LED sempre acceso sulla scheda (solitamente vicino al regolatore) +2. Dissalda il LED con saldatore a punta fine +3. Verifica con multimetro la riduzione di consumo + +### Sensore SW-420: Rimozione LED (Obbligatoria) + +**Risparmio: ~15mA** + +Il modulo SW-420 ha tipicamente 2 LED (power + signal) che consumano inutilmente: + +1. Individua i 2 LED sul modulo SW-420 +2. Dissalda entrambi i LED con saldatore a punta fine +3. Il sensore continuerà a funzionare normalmente via pin digitale D0 + +**Dopo rimozione LED:** Consumo totale sistema ridotto da ~28mA a ~3.5mA armato + +### Ottimizzazione Opzionale: RF con Switch MOSFET + +**Risparmio: ~3mA → autonomia >1 anno** + +Aggiungi MOSFET P-channel per accendere RX solo periodicamente: +- Complicato da implementare +- Latenza attivazione fino a 10 secondi +- Non consigliato per questo progetto + +## Calibrazione + +### Sensore SW-420: Regolazione Hardware + +Il modulo SW-420 ha un potenziometro per regolare la sensibilità fisica: + +1. Ruota il potenziometro completamente in senso orario (minima sensibilità) +2. Alimenta il modulo e osserva l'uscita digitale D0 +3. Ruota gradualmente in senso antiorario fino a rilevare vibrazioni medie +4. Evita di renderlo troppo sensibile (rileverà vibrazioni ambientali) + +**Obiettivo:** Rilevare vibrazioni da intrusione ma ignorare vibrazioni stradali/vento + +### Calibrazione Software Threshold + +Dopo aver calibrato il potenziometro hardware: + +1. Abilita `#define DEBUG_SERIAL` +2. Carica il codice +3. Arma il sistema +4. Prova diverse intensità di vibrazione +5. Osserva sul Serial Monitor quanti cambi vengono rilevati +6. Regola `VIBRATION_THRESHOLD` di conseguenza + +**Consigli:** +- Soglia troppo bassa → Troppi falsi positivi +- Soglia troppo alta → Sistema poco sensibile +- Default 80 cambi/2s → Buon compromesso con SW-420 + +### Misura Consumo + +Con multimetro in serie sulla linea VCC: +``` +Sistema DISARMED → Deve leggere ~3.0mA +Sistema ARMED → Deve leggere ~3.5mA (media) +LED lampeggia → Picchi fino a 5-6mA +``` + +## Troubleshooting + +### Sistema non si arma +- Verifica connessione RX480E-4 +- Controlla che telecomando trasmetta +- Abilita DEBUG_SERIAL per diagnostica + +### Troppi falsi positivi +- Aumenta `VIBRATION_THRESHOLD` +- Aumenta `VIBRATION_WINDOW_MS` +- Verifica montaggio sensore vibrazione + +### Consumo troppo alto +- Verifica che RX sia modello a basso consumo +- Rimuovi LED power da Pro Mini +- Controlla che DEBUG_SERIAL sia disabilitato + +### Serial Monitor non funziona +- Verifica baud rate 9600 +- Controlla che `#define DEBUG_SERIAL` sia attivo +- Verifica connessione FTDI (TX→RX, RX→TX) + +## Tecniche Low Power Implementate + +- ✅ **SLEEP_MODE_PWR_DOWN** - Consumo minimo 0.1µA +- ✅ **Interrupt esterni** - Wake-up istantaneo +- ✅ **Watchdog Timer** - Funziona in PWR_DOWN +- ✅ **Disabilitazione moduli** - ADC, TWI, SPI, Timer2, USART +- ✅ **Brown-out Detector disable** - Durante sleep +- ✅ **Pin non usati OUTPUT LOW** - Riduce leakage current +- ✅ **Eliminazione delay()** - Sostituiti con sleep +- ✅ **LED low current** - 2mA invece di 20mA + +## File del Progetto + +``` +camper/ +├── src/ +│ └── src.ino # Codice principale +├── README.md # Questo file +└── .gitignore # Git ignore per Arduino +``` + +## Licenza + +Questo progetto è rilasciato come open source. + +## Crediti + +Sviluppato per sistema allarme camper ultra low power. +Hardware target: Arduino Pro Mini 3.3V 8MHz (LED power dissaldato) + +--- + +**Autonomia target raggiunta: 60+ giorni con batteria standard 12V 7Ah** diff --git a/src/src.ino b/src/src.ino new file mode 100644 index 0000000..9057669 --- /dev/null +++ b/src/src.ino @@ -0,0 +1,422 @@ +// ========== ULTRA LOW POWER ALARM SYSTEM ========== +// Target: Arduino Pro Mini 3.3V 8MHz (ATmega328P, LED power dissaldato) +// Sensore: SW-420 vibration sensor (LED dissaldati) +// Sistema allarme camper ottimizzato per consumo minimo +// Rilevamento intelligente: conta N cambi di stato in finestra temporale +// Consumo atteso: ~3.5mA armato, autonomia 60+ giorni con 12V 7Ah + +// ========== CONFIGURAZIONI UTENTE ========== +// Decommentare per abilitare, commentare per disabilitare + +#define DEBUG_SERIAL // Serial debug (DISABILITA per produzione, risparmio ~500µA) + +// Stato iniziale allarme all'accensione del sistema +// Opzioni disponibili: +// 0 = ALWAYS_DISARMED - Parte sempre disarmato (ignora pin RF) +// 1 = ALWAYS_ARMED - Parte sempre armato (ignora pin RF) +// 2 = CHECK_RF - Controlla stato pin RF all'avvio (default) +#define STARTUP_STATE 1 + +// Parametri rilevamento vibrazione intelligente +#define VIBRATION_WINDOW_MS 2000 // Finestra temporale per conteggio vibrazioni (ms) +#define VIBRATION_THRESHOLD 80 // Numero minimo cambi di stato per allarme +#define VIBRATION_TIMEOUT_MS 3000 // Timeout inattività per reset contatore (ms) + +#define TRIGGER_DURATION_MS 5000 // Durata allarme intrusione (ms) +#define ARMING_DELAY_MS 2000 // Delay armamento (ms) + +// ========== INCLUSIONI ========== +#include +#include +#include +#include + +// ========== PIN DEFINITION ========== +const uint8_t vibPin = 2; // INT0 - SW-420 vibration sensor D0 output +const uint8_t buzzerPin = 9; // Output - Buzzer allarme +const uint8_t ledPin = 13; // Output - LED status (lampeggio quando armato) +const uint8_t ledIntrusionePin = 12; // Output - LED intrusione +const uint8_t rfChannel = 6; // PCINT22 - RX480E-4 CH1 + +// ========== STATE MACHINE ========== +enum AlarmState { + STATE_DISARMED, // Allarme disattivo (PWR_DOWN continuo, consumo ~3mA) + STATE_ARMING, // Armamento in corso (2 secondi, IDLE mode) + STATE_ARMED, // Armato e monitoraggio (PWR_DOWN + WDT lampeggio, ~3.5mA) + STATE_TRIGGERED // Intrusione rilevata (buzzer attivo 5 secondi) +}; + +volatile AlarmState currentState = STATE_DISARMED; + +// ========== FLAGS INTERRUPT (solo volatile bool) ========== +volatile bool rfStatoChanged = false; +volatile bool vibrationDetected = false; // Flag per interrupt vibrazione +volatile bool wdtFired = false; + +// ========== VARIABILI GLOBALI ========== +bool ledState = false; +unsigned long armingStartTime = 0; +unsigned long triggerStartTime = 0; + +// Tracciamento vibrazioni intelligente +volatile uint8_t vibrationCount = 0; // Contatore cambi di stato +volatile unsigned long firstVibrationTime = 0; // Timestamp prima vibrazione +unsigned long lastVibrationTime = 0; // Timestamp ultima vibrazione (per timeout) + +// ========== ISR - INTERRUPT SERVICE ROUTINES ========== +// IMPORTANTE: ISR devono essere atomiche e brevissime! +// Solo flag setting, nessun delay() o Serial.print() + +// Watchdog Timer Interrupt (lampeggio LED ogni 500ms) +ISR(WDT_vect) { + wdtFired = true; +} + +// External Interrupt 0 (vibrazione rilevata su pin 2) +// Conta i cambi di stato per rilevamento intelligente +ISR(INT0_vect) { + // ISR deve essere ATOMICA - solo operazioni minime! + // Il timestamp verrà gestito nel loop principale + vibrationCount++; + vibrationDetected = true; +} + +// Pin Change Interrupt 2 (RF ricevitore cambio stato su pin 6) +ISR(PCINT2_vect) { + rfStatoChanged = true; +} + +// ========== FUNZIONI LOW POWER ========== + +void disableUnusedPeripherals() { + // ADC - non usato (sensore è digitale) + ADCSRA &= ~(1 << ADEN); // Risparmio: ~200µA + power_adc_disable(); + + // TWI/I2C - non usato + power_twi_disable(); // Risparmio: ~10µA + + // SPI - non usato + power_spi_disable(); // Risparmio: ~5µA + + // Timer2 - non usato + power_timer2_disable(); // Risparmio: ~10µA + + // USART - disabilita se non DEBUG_SERIAL + #ifndef DEBUG_SERIAL + power_usart0_disable(); // Risparmio: ~100µA + #endif + + // Timer0 - MANTENERE attivo per millis() (usato per tracking vibrazioni) + // Timer1 - MANTENERE attivo (può servire per PWM buzzer) +} + +void setupPins() { + // Output pins + pinMode(buzzerPin, OUTPUT); + pinMode(ledPin, OUTPUT); + pinMode(ledIntrusionePin, OUTPUT); + digitalWrite(buzzerPin, LOW); + digitalWrite(ledPin, LOW); + digitalWrite(ledIntrusionePin, LOW); + + // Input pins + pinMode(vibPin, INPUT); // Sensore vibrazione switch digitale + pinMode(rfChannel, INPUT); // RF ricevitore + + // Pin non usati → OUTPUT LOW per ridurre leakage current + // Configurare tutti i pin non utilizzati + for (uint8_t i = 0; i < 20; i++) { + // Salta i pin che usiamo + if (i == vibPin || i == buzzerPin || i == ledPin || + i == ledIntrusionePin || i == rfChannel) { + continue; + } + + pinMode(i, OUTPUT); + digitalWrite(i, LOW); + } +} + +void setupInterrupts() { + cli(); // Disable interrupts durante setup + + // INT0 (vibrazione su pin 2) - ANY CHANGE per contare tutti i cambi di stato + EICRA |= (1 << ISC00); // Any logical change trigger + EICRA &= ~(1 << ISC01); // Clear ISC01 per ANY CHANGE mode + EIMSK |= (1 << INT0); // Enable INT0 + + // PCINT22 (RF su pin 6) - Any change + PCICR |= (1 << PCIE2); // Enable PCINT2 group (PCINT16-23) + PCMSK2 |= (1 << PCINT22); // Enable only PCINT22 (pin D6) + + sei(); // Re-enable interrupts +} + +void setupWatchdog_500ms() { + cli(); + MCUSR &= ~(1 << WDRF); // Clear watchdog reset flag + WDTCSR |= (1 << WDCE) | (1 << WDE); // Enter config mode + WDTCSR = (1 << WDIE) | // Interrupt enable (non reset mode) + (1 << WDP2) | (1 << WDP0); // Timeout 500ms (0b0101) + sei(); +} + +void disableWatchdog() { + cli(); + MCUSR &= ~(1 << WDRF); + WDTCSR |= (1 << WDCE) | (1 << WDE); + WDTCSR = 0x00; // Turn off WDT + sei(); +} + +void enterSleep(uint8_t mode) { + set_sleep_mode(mode); + sleep_enable(); + sleep_bod_disable(); // Risparmio ~20µA durante sleep + sei(); // Interrupt abilitati + sleep_cpu(); // *** ENTRA IN SLEEP MODE *** + // --- WAKE UP QUI quando interrupt viene triggerato --- + sleep_disable(); +} + +// ========== FUNZIONI RILEVAMENTO VIBRAZIONE INTELLIGENTE ========== + +void resetVibrationCounter() { + vibrationCount = 0; + firstVibrationTime = 0; + lastVibrationTime = 0; +} + +bool checkVibrationThreshold() { + if (vibrationCount == 0) { + return false; + } + + unsigned long now = millis(); + unsigned long elapsed = now - firstVibrationTime; + + // Se superata la soglia nella finestra temporale → INTRUSIONE! + if (vibrationCount >= VIBRATION_THRESHOLD && elapsed <= VIBRATION_WINDOW_MS) { + return true; + } + + // Se scaduta la finestra temporale senza superare soglia → reset + if (elapsed > VIBRATION_WINDOW_MS) { + resetVibrationCounter(); + return false; + } + + // Se troppo tempo dall'ultima vibrazione → timeout, reset + if (now - lastVibrationTime > VIBRATION_TIMEOUT_MS) { + resetVibrationCounter(); + return false; + } + + return false; +} + +// ========== STATE HANDLERS ========== + +void handleDisarmedState() { + // Check RF per attivazione + if (rfStatoChanged) { + rfStatoChanged = false; + if (digitalRead(rfChannel) == HIGH) { + // Attiva allarme + currentState = STATE_ARMING; + armingStartTime = millis(); + digitalWrite(ledIntrusionePin, LOW); + return; + } + } + + // Deep sleep continuo quando disarmato + // Consumo: ~3mA (dominato da RX480E-4) + enterSleep(SLEEP_MODE_PWR_DOWN); +} + +void handleArmingState() { + // Check timeout armamento (2 secondi) + if (millis() - armingStartTime >= ARMING_DELAY_MS) { + // Armato! + currentState = STATE_ARMED; + setupWatchdog_500ms(); // Avvia lampeggio LED + armingStartTime = 0; + return; + } + + // Check RF durante armamento (possibile disattivazione) + if (rfStatoChanged) { + rfStatoChanged = false; + if (digitalRead(rfChannel) == LOW) { + // Disarmato durante armamento + currentState = STATE_DISARMED; + armingStartTime = 0; + digitalWrite(ledPin, LOW); + return; + } + } + + // Sleep IDLE mode (Timer0 attivo per millis()) + enterSleep(SLEEP_MODE_IDLE); +} + +void handleArmedState() { + // Check vibrazione rilevata dall'interrupt + if (vibrationDetected) { + vibrationDetected = false; + unsigned long now = millis(); + lastVibrationTime = now; + + // Se è la prima vibrazione, inizializza timestamp + if (firstVibrationTime == 0) { + firstVibrationTime = now; + } + + // Controlla se abbiamo superato la soglia + if (checkVibrationThreshold()) { + // INTRUSIONE confermata! + currentState = STATE_TRIGGERED; + disableWatchdog(); // Stop lampeggio durante trigger + digitalWrite(ledPin, LOW); + triggerStartTime = millis(); + digitalWrite(ledIntrusionePin, HIGH); + digitalWrite(buzzerPin, HIGH); + + // Reset contatore vibrazioni + resetVibrationCounter(); + + #ifdef DEBUG_SERIAL + Serial.println(F("INTRUSIONE")); + #endif + + return; + } + } + + // Check timeout vibrazioni (anche se non c'è nuovo interrupt) + if (vibrationCount > 0) { + checkVibrationThreshold(); // Gestisce timeout e reset automatico + } + + // Check RF per disattivazione + if (rfStatoChanged) { + rfStatoChanged = false; + if (digitalRead(rfChannel) == LOW) { + // Disarma + currentState = STATE_DISARMED; + disableWatchdog(); + digitalWrite(ledPin, LOW); + digitalWrite(ledIntrusionePin, LOW); + resetVibrationCounter(); // Reset contatore quando disarma + return; + } + } + + // Lampeggio LED via Watchdog Timer + if (wdtFired) { + wdtFired = false; + ledState = !ledState; + digitalWrite(ledPin, ledState); + } + + // Sleep PWR_DOWN tra lampeggi + // Consumo: ~3.5mA medio (RX + lampeggio LED) + enterSleep(SLEEP_MODE_PWR_DOWN); +} + +void handleTriggeredState() { + // Check timeout trigger (5 secondi) + if (millis() - triggerStartTime >= TRIGGER_DURATION_MS) { + // Fine allarme + digitalWrite(buzzerPin, LOW); + digitalWrite(ledIntrusionePin, LOW); + triggerStartTime = 0; + + // Torna ad ARMED + currentState = STATE_ARMED; + setupWatchdog_500ms(); + return; + } + + // Check RF per disattivazione durante trigger + if (rfStatoChanged) { + rfStatoChanged = false; + if (digitalRead(rfChannel) == LOW) { + // Disarmato durante trigger + digitalWrite(buzzerPin, LOW); + digitalWrite(ledIntrusionePin, LOW); + triggerStartTime = 0; + currentState = STATE_DISARMED; + return; + } + } + + // Sleep IDLE durante trigger (millis() deve funzionare) + enterSleep(SLEEP_MODE_IDLE); +} + +// ========== ARDUINO CORE FUNCTIONS ========== + +void setup() { + // 1. Disabilita moduli non usati SUBITO + disableUnusedPeripherals(); + + // 2. Setup pin I/O + setupPins(); + + // 3. Setup interrupt + setupInterrupts(); + + // 4. Serial debug (solo se DEBUG_SERIAL) + #ifdef DEBUG_SERIAL + Serial.begin(9600); + Serial.println(F("Alarm Ready")); + #endif + + // 5. Imposta stato iniziale in base a STARTUP_STATE + #if STARTUP_STATE == 0 + // ALWAYS_DISARMED - Parte sempre disarmato + currentState = STATE_DISARMED; + + #elif STARTUP_STATE == 1 + // ALWAYS_ARMED - Parte sempre armato + currentState = STATE_ARMING; + armingStartTime = millis(); + + #else + // CHECK_RF - Controlla stato pin RF all'avvio (default) + bool rfHigh = digitalRead(rfChannel); + if (rfHigh) { + currentState = STATE_ARMING; + armingStartTime = millis(); + } else { + currentState = STATE_DISARMED; + } + #endif +} + +void loop() { + // State machine basata su interrupt + // Il sistema passa la maggior parte del tempo in sleep + // e si sveglia solo quando necessario + + switch(currentState) { + case STATE_DISARMED: + handleDisarmedState(); + break; + + case STATE_ARMING: + handleArmingState(); + break; + + case STATE_ARMED: + handleArmedState(); + break; + + case STATE_TRIGGERED: + handleTriggeredState(); + break; + } +}