I read quite a bit of the other posts on this but was soon lost in the weeds.
I want to use an attiny 85 for space & power reasons.
The idea is :
The processor is asleep. I press a button and the LED comes on, stays on for 6 minutes, then goes off, and the processor goes back to sleep.
But if I press the same button during that 6 minutes, the LED goes off and, back to sleep.
As I understand it, the Attiny 85 has one external interrupt, and 5 reset interrupts.
Could I use interrupt 1 to turn it on, then, when pressed during the 6 minutes,
Well I am lost.
Obviously I am not ready to code yet because I don't even know where I'm going.
May I have some help ?
I have an IF ELSE in my INT0 ISR. It looks at whether the LED is high or low. IF low, turn ON LED and count 6 min worth of millis, then turn it OFF, end ISR, go to sleep.
ELSE If LED is high, turn it OFF, end ISR, go to sleep.
ATTiny85 has 1 external interrupt, INT0. It also has PCINT (pin change interrupt) on all pins.
Note that only a low level interrupt on INT0 can be used while the '85 is sleeping - PCINTs can be used to wake the t85 on pin level change.
What you've asked for sounds straightforward...
I'd have an empty ISR, turn the interrupt on before sleeping, turn it off after waking (I would also wait until the user releases the button and give it some time for debouncing before going to sleep (so the PCINT doesn't trigger when it's released) and waking (since you don't want the pressed button to confuse the rest of the application)) Use blink-without-delay techniques for the 6 minute delay, and check the button state normally - and then call the sleep routine if the time is up or the button is pressed.
ISRs should run as quickly as possible. delay() doesn't work in an ISR, and millis() doesn't advance since interrupts are off.
u = ASCII / quick type replacement of µ (same as with capacitors) = micro
C => controller
uC => micro controller
And that would be a very bad design. Never ever wait in a ISR.
But you don't even need to do anything in a ISR. Just let the ISR wake up the uC and just go on. You know that the piece after sleep_cpu() is executed once the CPU is somehow woken up ;p Just wake up, save millis() and keep waiting until it's time to sleep again.
Septillion -
yes, I think I follow you, and it makes sense, but how is shutting it OFF if already ON handled ?
DrAzzy -
I have read your response three times, and I think I am beginning to get it (I will have to block diagram it out). I can understand that delay doesn't work in an ISR (since it stops normal operation), but I don't quite get what you mean about millis not advancing. Is it the same deal ? or just a bad idea to do it in an ISR ?
pratto:
DrAzzy -
I have read your response three times, and I think I am beginning to get it (I will have to block diagram it out). I can understand that delay doesn't work in an ISR (since it stops normal operation), but I don't quite get what you mean about millis not advancing. Is it the same deal ? or just a bad idea to do it in an ISR ?
Interrupts are disabled while in an ISR (you can re-enable them, but this opens a real can of worms). millis() is advanced by an interrupt (specifically timer0 overflow interrupt), so if interrupts are disabled, millis() won't advance. So, you can't wait in an ISR by monitoring millis() - it won't ever change. But - you should never wait in an ISR, ISR's should run as quickly as possible, preferably just a few lines to set a flag or something - for waking from sleep, you'll often have an empty ISR.
With well-written interrupts this is fine - if the timer overflow happens while another ISR is running, the interrupt will run after that ISR returns, and millis() won't be thrown off. But if the ISR takes more than around 1ms to run (which is a long time for an ISR), the timer will overflow multiple times, but it's interrupt will only be run the one time.
AS long as you don't turn off the led it will be on. So there was indeed a pseudo step missing in my pseudo code (fixed it).
While the led is on (and the uC awake), didn't you wanted to be able to turn it off with a button? Then simply detect is the button became pressed and put the uC to bed
pratto:
I read quite a bit of the other posts on this but was soon lost in the weeds.
I want to use an attiny 85 for space & power reasons.
The idea is :
The processor is asleep. I press a button and the LED comes on, stays on for 6 minutes, then goes off, and the processor goes back to sleep.
But if I press the same button during that 6 minutes, the LED goes off and, back to sleep.
As I understand it, the Attiny 85 has one external interrupt, and 5 reset interrupts.
Could I use interrupt 1 to turn it on, then, when pressed during the 6 minutes,
Well I am lost.
Obviously I am not ready to code yet because I don't even know where I'm going.
May I have some help ?
The idea is:
The Idea is not clear to me. Is it like:
The MCU has gone to sleep mode.
An external interrupt signal, generated by an interrupting device (K1), has arrived at the
INT0-pin of MCU.
The MCU has waken.
The LED is ON.
(Configure K1 as an input device.)
if (6-Minute has elapsed) // by polling the TOV1 flag of TC1
{
OFF the LED.
Send the MCU to sleep mode.
}
If (K1 is closed) // by polling the Logic Value of INT0-pin.
{
OFF the LED.
Reconfigure K1 as interrupting device.
Send the MCU to sleep mode.
}
We may try to implement all the above steps using ArduinoUNO to obtain working codes.
Once the working codes are found, they could be mapped into ATTiny85 architecture.
The 6-Minute time delay could be generated using Timer-1 of ATmega328 of ArduinoUNO.
septillion:
Or more simple, by using the higher level millis(). Same for the rest, no porting needed Long life HAL
Thanks for the information of the alternating way of generating time delay. But, I am reluctant to call the millis() function being afraid that it might have been implemented using T0 interrupt in the background.
septillion:
So? What's the problem with it using timer0?
If I decide to go in my prescribed way, I would be polling the K1 while delay is being generated by repeated interrupts of T0. I clearly see that there exists a 'software racing' between two routines; I am again afraid that I might not be able (due to my own limitations) to manage the situation in case there is a collision.
ok. I get it. I actually think I get it. And the code is so clean and concise. I have been trying to figure this out for years. A guy wrote me a sketch to do it, but it is about 80 lines long, and I never understood it (WDT, Flags, MCUCR, detachInterrupt, atomic library, and more.
I am going to try and remember how to program an attiny, and breadboard this up.
A couple of things : instead of ON for 6 minutes then off, I want ON for 6 hours. But it doesn't have to be accurate. 1/2 hour each side will be fine. Will using millis() still work ?
The other thing is, I am trying to really get the power consumption down (when the LED is OFF) by turning the ADC off, and using Power Down. Will my interrupt bring me out of power down ?
septillion:
So? What's the problem with it using timer0?
If I decide to go in my prescribed way, I would be polling K1 while the time delay is being generated by repetitive interrupts of T0. I clearly see that there might exist a 'Software Racing' between two routines. I am again afraid that I might not be able to manage (due to my own limitations) the situation in case there is a collision. Moreover, I have seen some Forum Members terming it 'Notorious interrupt if could not be managed properly.'
If you write it from scratch (aka, not use all the Arduino functions/libaries) it might indeed look a bit more scary
pratto:
A couple of things : instead of ON for 6 minutes then off, I want ON for 6 hours. But it doesn't have to be accurate. 1/2 hour each side will be fine. Will using millis() still work ?
Millis() will probably have less error then the 8% you suggested so as long as you don't expect a period of 50 days (and I don't mean you can have the Arduino of for 50days, just a simple led blink should be less then 50 days) you're fine!
pratto:
The other thing is, I am trying to really get the power consumption down (when the LED is OFF) by turning the ADC off, and using Power Down. Will my interrupt bring me out of power down ?
There are multiple sites which have that info including the datasheet But on the top of my mind I think the external interrupt can wake all modes of sleep.
@GolamMostafa, But why do the polling with a timer? Why not just poll as damn many times as the uC can? (aka, just do it in loop)
Or, use millis() to time the polling as well. That's why there is such a higher level function for timing in the first place