buongiorno a tutti,ho finito di fare il mio primo programma , grazie ad un utente in un precedente post.
ora vorrei mettere la funzione sleep in un modulo che usa solo un atmega328 ed un rf24.
in poche parole,visto che non conosco ancora bene i termini, quando il modulo con lcd(lo chiamo tx)
viene acceso si accende anche il modulo (fatto dal solo atmega328)chiamato rx. e di conseguenza funziona secondo il programma che ho fatto.
ho cercato di capire qualcosa ma non ne sono venuto a capo, se possibile avrei bisogno di un po di aiuto,
grazie mille
tx_lcd.txt (7.02 KB)
tx_lcd.txt (7.02 KB)
ce qualcosa dove posso leggere qualcosa??
Ciao, sono ancora io! 
Sei sicuro di questo? non è il RX che ha LCD?
si ho sbagliato a scrivere il nome del file e di conseguenza ho sbagliato a scrivere la domanda....questa quarantena mi da un po' alla testa

Non sono un esperto in materia, ma posso darti qualche idea.
Secondo me bisogna trovare un equilitrio tra il tempo da tenere il TX in sleep mode e la sua reattività nell uscirne nel caso in cui il RX sia pronto da ricevere i dati inviando un meggaggio preciso.
Penso che watchdog possa venirti in aiuto: svegliare il TX ogni x sec per dargli la possibilità di ricevere questo messaggio dal RX. Nel caso positivo eseguire il codice da te già fatto se no ritornare in sleep mode.
e di conseguenza anche il modulo rf24 va il sleep?o ci vuole il suo comando adatto?.
perche' ho cercato in merito ma non ho trovato
nulla
Cercando un po ho trovato una funzione powerdown nella libreria rf24. Non l'ho mai usata ma visto il suo nome forse è quello che cerchi.
forse ho trovato qualcosa
https://www.youtube.com/watch?v=MvjpmsH2wKI&t=2s
http://forcetronic.blogspot.com/2015/
in basso alla pagina ce un listato
allora vedo di capire il watchdog
questo puo'andare bene....non riesco ancora a prenderci il verso
qualcosa ho capito,ma resta in sleep 8 secondi(che poi cambiero') va un poco e ritorna va in sleep.
ora non riesco ancora bene a capire dove sbaglio.
se non mi sbaglio,dovrebbe stare in sleep ,controllare se myRadio.available,se si andare il loop altrimenti sleep
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#include <SPI.h>
#include <RF24.h>
#include <DHT.h>
RF24 myRadio (10, 9);
#define DHTPIN 5
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
volatile int f_wdt=1;
ISR(WDT_vect)
{
if(f_wdt == 0)
{
f_wdt=1;
}
else
{
Serial.println("WDT Overrun!!!");
}
}
byte addresses[6] = {"00001" };//[][6] = {"00001" , "00002"};
//------------creo 2 operazioni ogni tot tempo----------
unsigned long letturaMillis = 0; //memorizzerà l'ultima volta che il LED è stato aggiornato
unsigned long interval1 = 5000; //intervallo a cui lampeggiare (millisecondi)
unsigned long secondiMillis = 0;
unsigned long interval2 = 990;
//----------- dati in arrivo----------
struct Ricezione
{
boolean accensione; // comando accensione quadro
boolean avvio; //comando avvio motorino avviamento
int id ;
int tensione ;
float ampere = 0;
char text[150] ;
};
struct Ricezione ricezione;
unsigned long dopo;
unsigned long t_olio;
//------------dati in uscita-----------
struct Data
{
boolean mar; //sensore marcia
boolean freno ; //freno a mano
boolean candel ; //candelette
boolean olio ; //sensore olio
int secondo;
int minuto;
boolean conf_acc ; //conferma ricevuto comando accensione quadro
boolean conf_avv; //conferma ricevuto comando accensione avviamento
float humidithy ;
float temperature ;
};
struct Data data;
// ---variabili per timer on/off timer quadro ----
unsigned long oldMillis ;// variabile tempo quadro
#define T_MIN 3000 // tempo di inibizione pulsante
#define T_OFF 200000 // tempo di quadro acceso
bool Ing_quadro = false;
// ---variabili per timer avvio----
bool ing_cand = false;
bool ing_olio = false;
bool ing_sen = false;
bool Ing_avv = false;
unsigned long motore ;
int button = 0;
bool ing_mar = false;
int secondi = 0;
int minuti = 0;
void enterSleep(void)
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN); /* EDIT: could also use SLEEP_MODE_PWR_DOWN for lowest power consumption. */
sleep_enable();
/* Now enter sleep mode. */
sleep_mode();
/* The program will continue from here after the WDT timeout*/
sleep_disable(); /* First thing to do is disable sleep. */
/* Re-enable the peripherals. */
power_all_enable();
}
void setup()
{
MCUSR &= ~(1<<WDRF);
/* In order to change WDE or the prescaler, we need to
* set WDCE (This will allow updates for 4 clock cycles).
*/
WDTCSR |= (1<<WDCE) | (1<<WDE);
/* set new watchdog timeout prescaler value */
WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */
/* Enable the WD interrupt (note no reset). */
WDTCSR |= _BV(WDIE);
Serial.println("Initialisation complete.");
delay(100); //Allow for serial print to complete.
dht.begin();
Serial.begin(115200);
pinMode(2, INPUT_PULLUP); // freno a mano
pinMode(4, INPUT_PULLUP); // pulsante quadro
pinMode(8, OUTPUT); // rele' avviamento
pinMode(7, OUTPUT); // led dati
pinMode(6, OUTPUT); // rele' quadro
pinMode(14, INPUT_PULLUP); //pulsante avviamento
pinMode(15, INPUT_PULLUP); //sensore marcia 1
pinMode(16, INPUT_PULLUP); //sensore marcia 2
pinMode(17, INPUT_PULLUP); // candelette
pinMode(18, INPUT_PULLUP);
myRadio.begin();
myRadio.setChannel(115);
myRadio.setPALevel(RF24_PA_MIN);
myRadio.setDataRate( RF24_250KBPS ) ;
myRadio.openWritingPipe( addresses); //( addresses[0]);
myRadio.openReadingPipe(1, addresses);//(1, addresses[1]);
}
void loop() {
myRadio.startListening();
while (myRadio.available()) {
dopo = millis(); //memorizzo tempo dopo
digitalWrite(7, HIGH);
myRadio.read(&ricezione, sizeof(ricezione));
}
delay(5);
myRadio.stopListening();
digitalWrite(7, LOW);
myRadio.write(&data, sizeof(data));
delay(5);
data.secondo = secondi;
data.minuto = minuti;
if((myRadio.available()) )
{
/*
/* Re-enter sleep mode. */
enterSleep();
}
else
{
/* Do nothing. */
lettura();
ricez();
if (millis() - dopo >= 3000) { // se millis e inferiore a
digitalWrite(6, LOW); //spengo tutto
}
}
}
void lettura() {
if (millis() - secondiMillis > interval2) { //azioni da fare
secondiMillis = millis(); //ogni interval2=1000 ms
secondi = secondi + 1;
if (secondi >= 60) {
secondi = 0;
minuti = minuti + 1;
}
if (minuti >= 99) {
minuti = 0;
}
} //faccio una lettura ogni interval1
if (millis() - letturaMillis > interval1) { //azioni da fare
letturaMillis = millis(); //ogni interval1=5000 ms
data.humidithy = dht.readHumidity();// leggo temperatura
data.temperature = dht.readTemperature();
}
}
void ricez() {
//----------azoni accensione quadro-------------
//pin 4 accensione quadro ricezione.accensione comando remoto
// leggo pin 4 e variabile ricezione.accensione almeno 1 true
Ing_quadro = (ricezione.accensione == 1 || digitalRead(4) == LOW );
// La pressione del pulsante inverte lo stato dell'uscita
if (Ing_quadro && millis() - oldMillis > T_MIN) {
oldMillis = millis();
// Toogle (funzione passo passo)
digitalWrite(6, !digitalRead(6)); //accendo/spengo quadro
}
// Dopo secondi t_off spengo comunque il LED (se acceso)
if ( (millis() - oldMillis > T_OFF) && digitalRead(6)) {
digitalWrite(6, LOW); //spengo quadro
}
if (digitalRead(6) == HIGH) { //spengo quadro
(data.conf_acc = 1); //invio dato lcd
}
else {
(data.conf_acc = 0); //invio dato lcd
}
//-------------- azioni avviamento----------
//if (Ing_avv) { // se tasto // se sensore marcia HIGH
//if (!ing_mar || digitalRead(2) == HIGH ) {
// digitalWrite(6, LOW);
//}
//}
if (digitalRead(2) == LOW) { //se freno a mano low
data.freno = true; //invio dato lcd 1
}
else { //altrimenti
data.freno = false; //invio dato lcd 0
}
if (ing_mar == true ) { // se leggo variabile sensore folle 1
data.mar = true; //invio dato lcd 1
}
else { //altrimenti
data.mar = false; //invio dato lcd 0
}
//pin 14 (A0) pin avvio ricezione.avvio comando remoto avvio
//se almeno 1 e vera e true qundi 1
Ing_avv = (digitalRead(14) == LOW || (ricezione.avvio == true));
// associo freno a mano e quadro entrambi vere true
ing_sen = (digitalRead(2) == LOW && digitalRead(6) == HIGH);
//associo pin con sensori folle
ing_mar = (digitalRead(15) == LOW && digitalRead(16) == LOW);
//se 6 e' on e ing_avv=1 e !ing_mar e (2) == HIGH
if (digitalRead(6) == HIGH) { // quadro on
if (Ing_avv == 1 ) // se tasto
if (!ing_mar|| digitalRead(2) == HIGH ) {
// se sensore folle e marcia high
digitalWrite(6, LOW); // quadro off spengo tutto
}
}
if ( millis() - t_olio >= 500 ) {
if (!ing_mar|| digitalRead(2) == HIGH )
digitalWrite(6, LOW);
}
//associo button con sensori e variabili
// La pressione del pulsante =low
button = Ing_avv && ing_sen && ing_mar && ing_cand && ing_olio;
if (button == LOW) { //se tutte e 5 sono vere 1
digitalWrite(8, LOW); //avviamento off
(data.conf_avv = false); //invio dato lcd
//Azzera motoretempo avviamento con timer
motore = millis();
} //se tempo corrente -tempo motore
else if ( millis() - motore <= 2500 ) {
digitalWrite(8, HIGH); //avviamento on
(data.conf_avv = true); //invio dato lcd
}
else {
digitalWrite(8, LOW); //avviamento off
(data.conf_avv = false); //invio dato lcd
}
//-------------- candelette----------||
Serial.println(t_olio);
ing_cand = (digitalRead(17) == LOW); //se low valore ing_cand=1
if ( ing_cand == true) {
(data.candel = false);
}
else {
(data.candel = true);
}
//-------------- sensore olio----------||
ing_olio = (digitalRead(18) == LOW); // se low valore ing_olio=1
if ( ing_olio == true) {
t_olio=millis();
(data.olio = true);
}
else {
(data.olio = false);
}
}
Il tuo codice, non so dove l'hai trovato, è della serie: "perché fare semplice quando si può fare complicato!". ;D
Questa pagina web che ho trovato spiega bene come usare il watchdog.
Questa per lo sleep.
Ricordati pero' che non puoi usare un interrupt per svegliare il tuo CPU.
Quello che devi fare è ascoltare (per qualche sec o meno) se c'è un messaggio proveniente dal tu RX. Se c'è eseguire il tuo loop e se non c'è ritornare nello stato di sleep. Tutto questo nel setup. fai attenzione a quello che ti dice Leonardo( quello del primo sito che ti ho dato) nell'ultima parte del suo tuto ( [important] ).
Ne loop aggiungerai un piccolo timeout, nel caso in cui il RX non risponde piu' per tot sec, dove riattiverai il watchdog e rimetterai la CPU in sleep.
Questa è l'idea che mi sono fatto. Ripeto: non ho mai utilizzato queste cose, quindi a prendere con le pinzette.
per iniziare cosi sarebbe corretto?
[
code]void loop() {
myRadio.startListening();
while (myRadio.available()) {
dopo = millis(); //memorizzo tempo dopo
digitalWrite(7, HIGH);
myRadio.read(&ricezione, sizeof(ricezione));
}
delay(5);
myRadio.stopListening();
digitalWrite(7, LOW);
myRadio.write(&data, sizeof(data));
delay(5);
if(!myRadio.available()) {
delay(200);
wdt_enable(WDTO_4S);
}
mmmm... pas bien!! (direbbero i francesi!)
Dammi una rinfrescatina: RX invia un messaggio dopo aver ricevuto i dati?
La ricezione del messaggio di ritorno del RX non arriva ad effetto immediato. Puo' arrivare dopo alcuni loop.
Se il buffer di ricezione non è vuoto, bisogna svuotarlo ogni volta che si riceve qualche cosa se no !myRadio.available rimarrà sempre false.
si,pero' posso anche inviare un messaggio dedicato da rx(quello con lcd) verso il tx
non ci arrivo,lo sono abbastanza ignorante ,ma cerco di informarmi e arrivo al punto che faccio un minestrone ed non ne esco piu' vivo!!
non ne esco piu'
beh, questo un po tutti in questo periodo! 
non ci arrivo,lo sono abbastanza ignorante
Questa cosa me l'hai già detta e poi ci sei riuscito! ci abbiamo messo 100 posts ma alla fine ci sei riuscito.
Fai un programma che farà solo questo. Poi lo integri nell'altro.
Dai, siamo tutti qui a farti il tifo (non la malattia!!!)
con questo esempio,credo di aver fatto qualcosa, se il pin e' basso scrive solo setup altrimenti conta fino a 10 e poi va in sleep
usando una board uno e alimentando con 5vcc da ingresso Vin ho 28mA attivo e 19mA in sleep e corretto?
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
void enterSleep(void) {
digitalWrite(13, LOW);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
/* Il programma riprende qui. */
sleep_disable();
}
void setup() {
wdt_disable();
wdt_enable(WDTO_8S);
Serial.begin(115200);
pinMode(3, INPUT);
pinMode(13, OUTPUT);
Serial.println("Setup: ok");
digitalWrite(13, HIGH);
}
int secondi=0;
void loop() {
delay(1000);
secondi++;
boolean flag = true;
do {
if (digitalRead(3) == HIGH) {
flag = false;
}
} while (flag);
wdt_reset();
Serial.print("Attivo da ");
Serial.print(secondi, DEC);
Serial.println(" s.");
if(secondi == 10) {
Serial.println("Sleep!");
delay(200);
secondi = 0;
enterSleep();
}
}
qui invece conta fino a 10 poi va in sleep
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
void enterSleep(void) {
digitalWrite(13, LOW);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
/* Il programma riprende qui. */
sleep_disable();
}
void setup() {
wdt_disable();
wdt_enable(WDTO_8S);
Serial.begin(115200);
pinMode(3, INPUT);
pinMode(13, OUTPUT);
Serial.println("Setup: ok");
digitalWrite(13, HIGH);
}
int secondi = 0;
void loop() {
delay(1000);
secondi++;
boolean flag = true;
do {
if (secondi <= 10) {
flag = false;
}
} while (flag);
wdt_reset();
Serial.print("Attivo da ");
Serial.print(secondi, DEC);
Serial.println(" s.");
if (secondi == 10) {
Serial.println("Sleep!");
delay(200);
secondi = 0;
enterSleep();
}
}
5vcc da ingresso Vin
Sei sicuro di questo?
28mA attivo e 19mA in sleep e corretto
pensavo a meno!!
Come ripeto non ho mai utilizzato lo sleep, comunque mi sembra OK!
si ho messo un alimentatore regolabile impostato a 5 vcc, saranno gli altri chip, che alzano il consumo, credo quello della seriale il led etc, lunedi mi dovrebbe arrivare l'ìatmega328 nudo e crudo e vediamo il consumo.
meno male ora devo aggiungerlo al mio codice....vediamo cosa ne esce
ho provato cosi ma non e' corretto,quale e' il mio errore ora?
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#include <SPI.h>
#include <RF24.h>
#include <DHT.h>
RF24 myRadio (10, 9);
#define DHTPIN 5
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
byte addresses[6] = {"00001" };//[][6] = {"00001" , "00002"};
//------------creo 2 operazioni ogni tot tempo----------
unsigned long letturaMillis = 0; //memorizzerà l'ultima volta che il LED è stato aggiornato
unsigned long interval1 = 5000; //intervallo a cui lampeggiare (millisecondi)
unsigned long secondiMillis = 0;
unsigned long interval2 = 990;
//----------- dati in arrivo----------
struct Ricezione
{
boolean accensione; // comando accensione quadro
boolean avvio; //comando avvio motorino avviamento
int id ;
int tensione ;
float ampere = 0;
char text[150] ;
};
struct Ricezione ricezione;
unsigned long dopo;
unsigned long t_olio;
//------------dati in uscita-----------
struct Data
{
boolean mar; //sensore marcia
boolean freno ; //freno a mano
boolean candel ; //candelette
boolean olio ; //sensore olio
int secondo;
int minuto;
boolean conf_acc ; //conferma ricevuto comando accensione quadro
boolean conf_avv; //conferma ricevuto comando accensione avviamento
float humidithy ;
float temperature ;
};
struct Data data;
// ---variabili per timer on/off timer quadro ----
unsigned long oldMillis ;// variabile tempo quadro
#define T_MIN 3000 // tempo di inibizione pulsante
#define T_OFF 200000 // tempo di quadro acceso
bool Ing_quadro = false;
// ---variabili per timer avvio----
bool ing_cand = false;
bool ing_olio = false;
bool ing_sen = false;
bool Ing_avv = false;
unsigned long motore ;
int button = 0;
bool ing_mar = false;
int secondi = 0;
int minuti = 0;
int sleep = 0;
int old_sleep = 0;
void enterSleep(void) {
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
/* Il programma riprende qui. */
sleep_disable();
}
void setup()
{
wdt_disable();
wdt_enable(WDTO_8S);
dht.begin();
Serial.begin(115200);
pinMode(2, INPUT_PULLUP); // freno a mano
pinMode(4, INPUT_PULLUP); // pulsante quadro
pinMode(8, OUTPUT); // rele' avviamento
pinMode(7, OUTPUT); // led dati
pinMode(6, OUTPUT); // rele' quadro
pinMode(14, INPUT_PULLUP); //pulsante avviamento
pinMode(15, INPUT_PULLUP); //sensore marcia 1
pinMode(16, INPUT_PULLUP); //sensore marcia 2
pinMode(17, INPUT_PULLUP); // candelette
pinMode(18, INPUT_PULLUP);
myRadio.begin();
myRadio.setChannel(115);
myRadio.setPALevel(RF24_PA_MIN);
myRadio.setDataRate( RF24_250KBPS ) ;
myRadio.openWritingPipe( addresses); //( addresses[0]);
myRadio.openReadingPipe(1, addresses);//(1, addresses[1]);
}
void loop() {
myRadio.startListening();
while (myRadio.available()) {
dopo = millis(); //memorizzo tempo dopo
digitalWrite(7, HIGH);
myRadio.read(&ricezione, sizeof(ricezione));
}
delay(5);
myRadio.stopListening();
digitalWrite(7, LOW);
myRadio.write(&data, sizeof(data));
delay(5);
data.secondo = secondi;
data.minuto = minuti;
lettura();
ricez();
if (millis() - dopo >= 3000) { // se millis e inferiore a
digitalWrite(6, LOW); //spengo tutto
}
boolean flag = true;
do {
if (myRadio.available()) {
flag = false;
}
} while (flag);
wdt_reset();
if (!myRadio.available()) {
enterSleep();
}
}
void lettura() {
if (millis() - secondiMillis > interval2) { //azioni da fare
secondiMillis = millis(); //ogni interval2=1000 ms
secondi = secondi + 1;
if (secondi >= 60) {
secondi = 0;
minuti = minuti + 1;
}
if (minuti >= 99) {
minuti = 0;
}
} //faccio una lettura ogni interval1
if (millis() - letturaMillis > interval1) { //azioni da fare
letturaMillis = millis(); //ogni interval1=5000 ms
data.humidithy = dht.readHumidity();// leggo temperatura
data.temperature = dht.readTemperature();
}
}
void ricez() {
//----------azoni accensione quadro-------------
//pin 4 accensione quadro ricezione.accensione comando remoto
// leggo pin 4 e variabile ricezione.accensione almeno 1 true
Ing_quadro = (ricezione.accensione == 1 || digitalRead(4) == LOW );
// La pressione del pulsante inverte lo stato dell'uscita
if (Ing_quadro && millis() - oldMillis > T_MIN) {
oldMillis = millis();
// Toogle (funzione passo passo)
digitalWrite(6, !digitalRead(6)); //accendo/spengo quadro
}
// Dopo secondi t_off spengo comunque il LED (se acceso)
if ( (millis() - oldMillis > T_OFF) && digitalRead(6)) {
digitalWrite(6, LOW); //spengo quadro
}
if (digitalRead(6) == HIGH) { //spengo quadro
(data.conf_acc = 1); //invio dato lcd
}
else {
(data.conf_acc = 0); //invio dato lcd
}
//-------------- azioni avviamento----------
//if (Ing_avv) { // se tasto // se sensore marcia HIGH
//if (!ing_mar || digitalRead(2) == HIGH ) {
// digitalWrite(6, LOW);
//}
//}
if (digitalRead(2) == LOW) { //se freno a mano low
data.freno = true; //invio dato lcd 1
}
else { //altrimenti
data.freno = false; //invio dato lcd 0
}
if (ing_mar == true ) { // se leggo variabile sensore folle 1
data.mar = true; //invio dato lcd 1
}
else { //altrimenti
data.mar = false; //invio dato lcd 0
}
//pin 14 (A0) pin avvio ricezione.avvio comando remoto avvio
//se almeno 1 e vera e true qundi 1
Ing_avv = (digitalRead(14) == LOW || (ricezione.avvio == true));
// associo freno a mano e quadro entrambi vere true
ing_sen = (digitalRead(2) == LOW && digitalRead(6) == HIGH);
//associo pin con sensori folle
ing_mar = (digitalRead(15) == LOW && digitalRead(16) == LOW);
//se 6 e' on e ing_avv=1 e !ing_mar e (2) == HIGH
if (digitalRead(6) == HIGH) { // quadro on
if (Ing_avv == 1 ) // se tasto
if (!ing_mar || digitalRead(2) == HIGH ) {
// se sensore folle e marcia high
digitalWrite(6, LOW); // quadro off spengo tutto
}
}
if ( millis() - t_olio >= 500 ) {
if (!ing_mar || digitalRead(2) == HIGH )
digitalWrite(6, LOW);
}
//associo button con sensori e variabili
// La pressione del pulsante =low
button = Ing_avv && ing_sen && ing_mar && ing_cand && ing_olio;
if (button == LOW) { //se tutte e 5 sono vere 1
digitalWrite(8, LOW); //avviamento off
(data.conf_avv = false); //invio dato lcd
//Azzera motoretempo avviamento con timer
motore = millis();
} //se tempo corrente -tempo motore
else if ( millis() - motore <= 2500 ) {
digitalWrite(8, HIGH); //avviamento on
(data.conf_avv = true); //invio dato lcd
}
else {
digitalWrite(8, LOW); //avviamento off
(data.conf_avv = false); //invio dato lcd
}
//-------------- candelette----------||
Serial.println(t_olio);
ing_cand = (digitalRead(17) == LOW); //se low valore ing_cand=1
if ( ing_cand == true) {
(data.candel = false);
}
else {
(data.candel = true);
}
//-------------- sensore olio----------||
ing_olio = (digitalRead(18) == LOW); // se low valore ing_olio=1
if ( ing_olio == true) {
t_olio = millis();
(data.olio = true);
}
else {
(data.olio = false);
}
}