Buongiorno a tutti;
Ho un arduino nano (master) che tramite un modulo HC-12 e 4 pulsanti invia comandi ai dispositivi slave (sensori finestre) e funziona correttamente.
L'hardware dello slave è questo:
Modulo 4056 per la carica della batteria
ATTiny84 1MHz (ATTiny-Core)
Buzzer pilotato da un transistor bc547 e diodo di protezione
Contatto reed
Modulo HC-12 (FU2, B1200)
Connettore SPI per gli aggiornamenti
Con la versione base del codice tutto funziona e lo slave alimentato con una batteria 18650 3.7V 2200 mA ha un consumo energetico di 2.5 mA
voglio ridurre il consumo e aggiungo al codice il deep sleep e il consumo si riduce a 0.5 mA (fantastico) eseguo i test e noto che riceve e invia i dati tramite HC-12 correttamente, come fa a funzionare se è in deep sleep? e perché il resto del codice nel loop() non funziona più?.
Ho provato ad inserire un'interrupt che si attiva al cambio di stato del contatto reed ma purtroppo va in conflitto con la SoftwareSerial, ho provato neoSWSerial, AltSoftSerial ma per le mie limitate conoscenze non sono riuscito a farle funzionare.
prima di scrivere qui ho passato 2 giorni a dialogare con l'AI di Copilot e Gemini ma non c'è stato niente da fare quindi ho deciso di chiedere a voi.
il codice che allego è la versione con deep sleep ma senza interrupt, chiedo a voi un grande aiuto.
Amedeo Di Vito
hc12_slave.ino (4.3 KB)
Mi dispiace non poterti aiutare, non ho conoscenze nella direzione che ti interessa
rimango però qui in ascolto, chissà mai
comunque, si può vedere il codice della parte interrupt (che hai omesso)?
Non metterlo come file.ino, non riesco a vederlo dal furbofono
mettilo in chiaro nel messaggio
Grazie
questo è il codice con interrupt
#include <Arduino.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <SoftwareSerial.h>
// Definizioni dei pin
#define REED_PIN 0
#define ALARM_ON 10
#define LED_PIN 3
#define HC12_SET_PIN 7
#define HC12_RX_PIN PA2
#define HC12_TX_PIN PA1
// Inizializzazione della seriale software
SoftwareSerial hc12(HC12_RX_PIN, HC12_TX_PIN);
// Variabili globali
volatile bool wakeUpFlag = false; // Flag per gestione wake-up
bool enabled = false;
bool alarmActive = false;
unsigned long timerVolt;
const float LOW_BATT = 3.0;
uint8_t device = 1;
uint8_t delayRead = 100;
uint8_t delayAlarm = 100;
void setup() {
// Inizializzazione della comunicazione seriale
hc12.begin(1200);
// Configurazione dei pin
pinMode(ALARM_ON, OUTPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(REED_PIN, INPUT_PULLUP);
pinMode(HC12_SET_PIN, OUTPUT);
digitalWrite(HC12_SET_PIN, HIGH);
// Indicazione di avvio
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(LED_PIN, LOW);
// Pulizia del buffer seriale
clearBuffer();
// Inizializzazione del timer per il controllo della tensione
timerVolt = millis();
checkVolt();
// Configura l'interrupt per il REED switch (Pin Change Interrupt)
PCMSK0 |= (1 << PCINT0); // Abilita l'interrupt sul REED_PIN (PA0)
GIMSK |= (1 << PCIE0); // Abilita il Pin Change Interrupt
sei(); // Abilita gli interrupt globali
}
ISR(PCINT0_vect) {
wakeUpFlag = true; // Imposta il flag di risveglio
}
void loop() {
// Controllo del wake-up
if (wakeUpFlag) {
wakeUpFlag = false; // Resetta il flag
if (enabled) {
alarmActive = true;
beep(3); // Emesso un segnale acustico di allarme
}
}
// Gestione dell'allarme
if (alarmActive) {
digitalWrite(ALARM_ON, HIGH);
delay(delayAlarm);
digitalWrite(ALARM_ON, LOW);
delay(delayAlarm);
} else {
digitalWrite(ALARM_ON, LOW);
}
// Controllo della batteria ogni 5 minuti
if (millis() - timerVolt > 300000L) {
timerVolt = millis();
checkVolt();
}
// Lettura dei dati dalla seriale
if (hc12.available() > 0) {
dataRead();
}
// Modalità sleep per risparmiare energia
enterSleepMode();
}
void enterSleepMode() {
cli(); // Disabilita gli interrupt per preparare il sonno
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sei(); // Riabilita gli interrupt globali
sleep_mode(); // Entra in modalità sleep
sleep_disable(); // Ritorna qui dopo il wake-up
}
void dataRead() {
char cmd;
char dev;
char buf[3];
if (hc12.available() > 0) {
cmd = hc12.read();
delay(delayRead);
if (cmd != '#') {
clearBuffer();
return;
}
dev = hc12.read();
delay(delayRead);
}
if ((uint8_t)dev == device + 48) {
clearBuffer();
if (enabled) {
enabled = false;
alarmActive = false;
beep(2);
} else {
enabled = true;
beep(1);
}
sprintf(buf, "%d%d", device, enabled);
hc12.println(buf);
}
}
void clearBuffer() {
while (hc12.available() > 0) {
hc12.read();
}
}
void beep(uint8_t num) {
for (int i = 0; i < num; i++) {
digitalWrite(ALARM_ON, HIGH);
delay(20);
digitalWrite(ALARM_ON, LOW);
delay(80);
}
}
void checkVolt() {
float batteryVoltage = readVcc();
if (batteryVoltage <= LOW_BATT) {
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(LED_PIN, LOW);
}
}
float readVcc() {
ADMUX = _BV(MUX5) | _BV(MUX0);
delay(2);
ADCSRA |= _BV(ADSC);
while (bit_is_set(ADCSRA, ADSC));
uint16_t low = ADCL;
uint8_t high = ADCH;
long vcc = (high << 8) | low;
return (1125300.0 / vcc) / 1000.0;
}
Non posso prometterti nulla
Ma domani ci guardo