Hi,
I have to realize aproject with Arduino Mini, powered by battery, that when the window is opened more then 10 minutes send a message with NRF24l01 to an Arduino Nano that switch off the boiler. When the window is closed, send another message and if all windows are closed switch on the boiler.
To save the battery, I think to sleep Arduino, when the switch connected to the window change (on to off or viceversa) by interrupt wake up Arduino Mini, send a message to the Arduino Nano connected to the boiler then go to sleep.
My first test is to sleep Arduino and when a button switch off the first time or switch on the second time, by interrupt wake up Arduino.
I try to use this example:
#include <avr/sleep.h>
#include <avr/wdt.h>
byte i, adcsra, mcucr1, mcucr2;
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup()
{
Serial.begin(9600);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
EICRA = 0x00; //pin2 richiesta interrupt a livello low
}
void loop()
{
sleep_enable(); //abilita sleep
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //modalità sleep massima
adcsra = ADCSRA; //memorizza ADC e Stato Registro A
ADCSRA = 0; //disabilita ADC
cli(); //disabilita interrupts
EIMSK |= _BV(INT0); //abilita INT0
mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //spegne il brown-out detector
mcucr2 = mcucr1 & ~_BV(BODSE);
MCUCR = mcucr1;
MCUCR = mcucr2;
sei(); //abilita interrupts per potersi svegliare
Serial.println("Goodnigth...");
delay(500);
sleep_cpu(); //sleep qua
Serial.println("Wake up");
delay(500);
sleep_disable(); //sveglia quì
ADCSRA = adcsra; //ripristina ADCSRA
//inserire qui il codice
if (EICRA == 0x00) {
digitalWrite(13, HIGH);
Serial.println("Pull down...");
} else {
digitalWrite(13, LOW);
Serial.println("Pull up...");
}
delay(500);
delay(50);
EICRA = ~EICRA; //pin2 richiesta interrupt a livello low/high
}
ISR(INT0_vect)
{
EIMSK &= ~_BV(INT0); //interrupt int0 per svegliarsi
}
I insert the delay(500) to be sure that the println appear.
Problem:
I see the led switch on when I push the button and switch off the I release the button but I see only the string "Goodnigth".
My personal impression is that the led status change only for the mechanical action of the button and not for the interrupt
Hi,
no one has experience with interrupts?
I put the explanation of my complete design for clarity. I know how to make each part of the project except the management of interrupt and I'm trusting in the experience of someone more expert then me ...
I hope I explained clearly enough: my English is so poor...
Most of us have experience with interrupts. It's only now I can kind of read the code. The indentation is mangled (press ctrl+t and have a look) and the comments are in a language I don't master.
But, couple of things.
What do you plan to do with WDT?
Why don't you just use the Arduino functions (HAL) \
What's the messing with MCUCR suppose to do?
And you don't need to clear the interrupt flag yourself.
And did you had a look at the datasheet about what interrupt is able to wake what sleep mode?
And if English is to hard, maybe try the subboard in your language (Italian?).
septillion:
Most of us have experience with interrupts. It's only now I can kind of read the code. The indentation is mangled (press ctrl+t and have a look) and the comments are in a language I don't master.
I see correctly the code. Ctrl+t open another window in thr browser! I do not understand what's going on.
Yes, I copyed and modified an example from a tutorial written in Italian (for this reason some comments are in Italian. I'm sorry but I don't know some instruction and I'm not able to translate them)
septillion:
But, couple of things.
What do you plan to do with WDT?
Why don't you just use the Arduino functions (HAL) \
What's the messing with MCUCR suppose to do?
And you don't need to clear the interrupt flag yourself.
And did you had a look at the datasheet about what interrupt is able to wake what sleep mode?
I'm not using WDT
I don't now the Arduino functions (HAL), I'm trying to generate a source code with basic instruction. I will read a tutorial for the HAL if you tell me is necessary
ok, if is not necessary to clear the interrupt I don't do it
I read the datasheet about interrupt. I understood there are some way to activate the interrupt. I think to attivate the interrupt when the switch change state (I see is possible to call a function when the pin 2 change state: attachInterrupt(0, interrupttrigger, CHANGE); )
septillion:
And if English is to hard, maybe try the subboard in your language (Italian?).
I written here because in the English forum there are many people and is major the probability that someone already had my problem
I should have told you, but Ctrl+T in the Arduino IDE of course..
Copying and modifying an example is a terrible way to go. Way better to learn from it and write your own code. Two pro's to that, 1) You really know what it does, 2) it really does what you want
Why do you include WDT then?
You do know Arduino functions. digitalWrite, Serial.print() etc are all Arduino functions that handle HAL (Hardware Abstraction Layer). Aka, functions that helps you so you don't have to mess with the hardware and registers behind it. For external interrupts there is attachInterrupt() and digitalPinToInterrupt()
In sleep mode Power-down you can only wake it with a level interrupt (see page 39 of the datasheet), aka HIGH or LOW, no CHANGE, FALLING or RISING.
septillion:
I should have told you, but Ctrl+T in the Arduino IDE of course..
I'm sorry... now I understand
septillion:
Copying and modifying an example is a terrible way to go. Way better to learn from it and write your own code. Two pro's to that, 1) You really know what it does, 2) it really does what you want
You have reason!
septillion:
Why do you include WDT then?
Included for error...
septillion:
You do know Arduino functions. digitalWrite, Serial.print() etc are all Arduino functions that handle HAL (Hardware Abstraction Layer). Aka, functions that helps you so you don't have to mess with the hardware and registers behind it. For external interrupts there is attachInterrupt() and digitalPinToInterrupt()
In sleep mode Power-down you can only wake it with a level interrupt (see page 39 of the datasheet), aka HIGH or LOW, no CHANGE, FALLING or RISING.
Now I tried with attachInterrupt, but when I push button or release, I don't see the debug string and I don't see the correct action on the led...
thanks to all for the tips.
Combining your suggestions to some news found thanks to St. Google, now I'm able to send Arduino to sleep and wake up it when I push or release a button.
Now I have to manage the debouncing because sometime the final state of the led is not the state aspected.
hoping not to abuse too much of the patience of the forum users, I wonder: it works, but is there a better way to implement this example?
#include <avr/sleep.h>
const byte ledPin = 6;
const byte interruptPin = 2;
volatile byte state = LOW;
byte i, adcsra, mcucr1, mcucr2;
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}
void loop() {
delay(50);
digitalWrite(ledPin, state);
sleep_enable(); //enable sleep
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //maximum sleep mode
adcsra = ADCSRA; //store ADC e Status Register A
ADCSRA = 0; //disable ADC
cli(); //disable interrupts
EIMSK |= _BV(INT0); //enable INT0
mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //switch off il brown-out detector
mcucr2 = mcucr1 & ~_BV(BODSE);
MCUCR = mcucr1;
MCUCR = mcucr2;
sei(); //enable interrupts to wake up Arduino
Serial.println("Goodnigth");
delay(100);
sleep_cpu(); //sleep here
Serial.println("wake up");
delay(100);
sleep_disable(); //Wake up
ADCSRA = adcsra; // ADCSRA
// insert your code from here...
EICRA = ~EICRA; //pin2 interrupt
}
void blink() {
state = !state;
}
#include <avr/sleep.h>
const byte LedPin = 13;
const byte InterruptPin = 2;
void setup() {
Serial.begin(115200);
// disable ADC
ADCSRA = 0;
pinMode(LedPin, OUTPUT);
pinMode(InterruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(InterruptPin), wakeUp, FALLING);
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //maximum sleep mode
}
void loop() {
Serial.println("Goodnight");
Serial.flush();
noInterrupts();
sleep_enable(); //enable sleep
// turn off brown-out enable in software
MCUCR = bit (BODS) | bit (BODSE); // turn on brown-out enable select
MCUCR = bit (BODS); // this must be done within 4 clock cycles of above
interrupts();
sleep_mode();
Serial.println("wake up");
digitalToggle(LedPin);
delay(100); //Let's stay away to debounce
}
void wakeUp() {
}
void digitalToggle(byte pin){
digitalWrite(pin, !digitalRead(pin));
}
But having a LED turned on while in sleep is like isolating your house but put the heater outside... The led will take wayyyyyy more current then the micro, even with it running.
// turn off brown-out enable in software
MCUCR = bit (BODS) | bit (BODSE); // turn on brown-out enable select
MCUCR = bit (BODS); // this must be done within 4 clock cycles of above
But having a LED turned on while in sleep is like isolating your house but put the heater outside... The led will take wayyyyyy more current then the micro, even with it running.
You are right, but this is only for the example.
In my project, I have to:
opening the window (down button), wake up Arduino, send a string via rf to another Arduino (instead of switch on the led), then go back to sleep
closing the window (up button), wake up Arduino, send a string via rf to another Arduino (instead of switch off the led), then go back to sleep
I have to manage debouncing (I don't switch manually a button but I have the same problem because when I open or close the window I change the state of the switch)
In my project, I don't use leds and all component are in power down mode (if I made it correctly).
Makes sens. But then I think my code is a perfect starting place Don't forget to put the RF is a ultra-low power setting as well
And about debouncing, I think this is one of the cases a delay() aka a blocking function is appropriate. No matter how you turn it, you want to block the uC from going to sleep and do nothing. So yeah...
I also thought that a delay() is enough to avoid the debouncing, but I'm not so expert and I wasn't sure this is a correct way to solve the problem.
If you confirm me is correct, I avoid the debouncing with a delay()
Uhmmm... you have reason, to save battery I have to put the RF to a minimum power setting necessary. I don't know how to do. I Have to read the datasheet...
Now I'm also reading how to use timer interrupt to understand if is possible to check sometime the state of switch (in case of black-out, wen the power supply restart I don't know the state of the switch)