ATMega328p/Arduino Interupt enabled pins?
-
Good thing with gw.wait is that it calls process so if you got an incoming message you dont miss that. Or you can use the normal software debounce and check millis() and dont do a reading for the first 250-500 milliseconds... its the same i think because process is called then. What you dont want to use is delay().
@sundberg84 said:
What you dont want to use is delay().
Thank you for making aware of this. I will be using gt.wait (500) I think.
Back onto the subject of the interupt pins, so do you advice i use INT0 and INT1? I have potentially 3 switchs to put into this node, so i could do with another one. What needs to be done for the PCINT pins, like I said earlier, the state needs to be saved while it sleeps. I will be saving the state of the pin anyway for the switch to work, surly? My switch will be a normal light switch push-on push-off style (Just one button that you depress to toggle the light). Either way, if I monitor the switch in terms of saving the switch state to a variable each time it is changed then surly i would be good to just use any PCINT enabled pins?
I'm assuming the above based on the extract of the following from the AVRFreaks forum thread I posted earlier.
"While on modern AVRs most (all?) IO are PCINT. So there's far more interrupt sources but you cannot specify when the interrupt occurs. It just happens on every low-high or high-low transition so you have to keep track of the previous state of pins to know which way it just changed. Also they are grouped in 8's so all 8 pins on a PORT just cause a single PCINT vector/handler to be called. It's then up to you to work out which of the 8 caused the change.
Oh and whatever else you do, do not make the mistake of using them to read switches/buttons. That's a mistake almost all beginners make as they don't know about contact bounce." -
@samuel235 If a node goes into sleep mode using gw.sleep(0), then the radio is powered of as well. So the radio will NOT be able to wake the node via INT.
There are ways to put the processor to sleep and keep the radio alive, but that would eat the battery very quickly. The Mysensors lib does not provide for this scenario at this moment.
Maybe someone can extend the MySensor SLEEP function with an additional parameter to indicate the type of sleep (all peripherals, only processor and I2C, only processor and SPI/radio, only processor).
-
I like that idea.
For the ATmega328, sleeping the mcu saves about 15mA, which is on the same level as the nrf in receive mode (14mA). So such a mode would "only" double the battery life. Other mcus (ESP8266?) might have larger differences though, resulting in higher gains.
-
Ahh okay, thats useful information to know. Thank you @GertSanders!
I'm currently having a read through this PDF, more specifically page 15 reads:
External Interrupts
Pins:
INT0 and INT1 – range of event options
INT0 – PORT D [2]
INT1 – PORT D [3]
PCINT[23:0] – any signal change (toggle)
PCINT[7:0] – PORT B [7:0]
PCINT[14:8] – PORT C [6:0]
PCINT[23:16] – PORT D [7:0]
Pulses on inputs must be slower than I/O clock rateSo, would you advise me attaching the 3 switches to pins INT0, INT1 and any pin on that port B range. Then if i ever needed 4 switches, I could then go to any pin in port C range. Because the PCINT pins are inside of different port ranges from each other, as long as save the state of the switch/pin in a variable I should have no issue with it waking the uC up when the switch is toggled?
I hope i'm understanding your information correctly guys :)
-
hi.
just want to add my piece too :)
just a little OT about waking up with radio int. For nrf, you can't as it's power hungry , but for rfm69 you can. Guys at lowpowerlab have already made it, and it seems to consumes uA. but it is not implemented in Mysensors yet. It is a matter of RX ON/OFF timings and ATC Rssi. It is one thing I am interested in, and is on my big todolist :persevere:For PCINT, you understand right if I understand you well too lol!
For PCINT, I have already played with this for my knowledge months ago. I did the same way @mflakvidd has linked (by playing directly with registers and setting/checking bits).
And yes, it would be better to make a software debounce. Something like:
-set your interrupts- go to sleep
- if wake up: in interrupt routine, save state or what you want. check the interrupt "mask" meaning check the bit according to your pin in the right register. disable PCINT on your pin. Disable PCINT for your pin only could be in case your isr could be re-fired.
- then in your main loop, just after your gw.sleep, do a software debounce like guys advised you. Use millis or gw.wait for instance easier and test state pin. It is better to do this there, not in isr, your isr has to be short (you don't want to spend time in an interrupt)
- then re-enable PCINT and go to sleep.
Like you are reading in docs, you will need to handle the pin state. For using registers, it is just a matter of setting the right bits to enable or disable, and in your isr routine checking the right bits to know which pin has fired. That's all. I would advise you to test this in a separate sketch (not a mysensors one) to debug easier (fo instance testing some online already made sketch to see how it works for you.
My tests were not mysensors related, so it's useless I give you dirty things as others already gave you good links. I began with examples too ;)
Another docs for interrupt, but maybe you already read it:
http://www.gammon.com.au/interrupts
http://www.gammon.com.au/forum/?id=11091 -
hi.
just want to add my piece too :)
just a little OT about waking up with radio int. For nrf, you can't as it's power hungry , but for rfm69 you can. Guys at lowpowerlab have already made it, and it seems to consumes uA. but it is not implemented in Mysensors yet. It is a matter of RX ON/OFF timings and ATC Rssi. It is one thing I am interested in, and is on my big todolist :persevere:For PCINT, you understand right if I understand you well too lol!
For PCINT, I have already played with this for my knowledge months ago. I did the same way @mflakvidd has linked (by playing directly with registers and setting/checking bits).
And yes, it would be better to make a software debounce. Something like:
-set your interrupts- go to sleep
- if wake up: in interrupt routine, save state or what you want. check the interrupt "mask" meaning check the bit according to your pin in the right register. disable PCINT on your pin. Disable PCINT for your pin only could be in case your isr could be re-fired.
- then in your main loop, just after your gw.sleep, do a software debounce like guys advised you. Use millis or gw.wait for instance easier and test state pin. It is better to do this there, not in isr, your isr has to be short (you don't want to spend time in an interrupt)
- then re-enable PCINT and go to sleep.
Like you are reading in docs, you will need to handle the pin state. For using registers, it is just a matter of setting the right bits to enable or disable, and in your isr routine checking the right bits to know which pin has fired. That's all. I would advise you to test this in a separate sketch (not a mysensors one) to debug easier (fo instance testing some online already made sketch to see how it works for you.
My tests were not mysensors related, so it's useless I give you dirty things as others already gave you good links. I began with examples too ;)
Another docs for interrupt, but maybe you already read it:
http://www.gammon.com.au/interrupts
http://www.gammon.com.au/forum/?id=11091@scalz - Thank you for this information.
I'm not sure I completely get your example method, however I will do some reading of those links you provided at some point today when I have a spare 5 minutes at work, hoping to futher understand how you meant certain things.
When you say "Set your interrupts" i'm assuming you meant that I need to assign the interrupt pins:
digitalPinToInterrupt(2) digitalPinToInterrupt(3)Is this what you meant?
I will then need to have two variables saved, say sw1 and sw2, write the state of the respecting pins to those variables.
Once i have done that, I then send the node to sleep.What do you mean by disable PCINT? (sorry)
Perform a gw.wait(500)
Enable PCINT
Then go back to sleep.Did i understand that process correctly?
I will be performing all of this on a arduino to make sure i understand the processes and the ordering of what to do what, then I'll get it attached to Rev2 board, once i have finished designing and ordering the PCB that is.
-
@samuel235: maybe I should have said "init your interrupt" or attach it. it was late lol. It was related to the External interrupt pins(PCINT). It seems digitalpinToInterrupt is new to me, I didn't know it, I used to attachInterrupt and registers when needed. I will look at digitalPintoInterrupt.
So when I said disable PCINT I was meaning to detach it in the interrupt routine and do your debouncing in loop.Yep you have understood the global process. of course you will need to run some tests as what I said is not complete I think, just a way to go.
- init/ attach your interrupt(pin x)
- sleep mode
- on wake up, you will be in your ISR (interrupt service routine). Save state and detach your interrupt for the concerned pin.
- after the isr is executed, you will be redirected just after the gw.sleep of course. So after this line, do your debouncing by testing pin state for instance, with millis and gw.wait. Maybe you will need to adapt the delay you check pin state with millis because debouncing will depend on your switch. But this should not be a big delay, maybe 5 to 20ms, maybe more it depends on your switch. When I say delay, it is not delay() of course! but the time you use millis()
-
@mfalkvidd: thx ;) I am already reading it, too curious :)
-
@samuel235: maybe I should have said "init your interrupt" or attach it. it was late lol. It was related to the External interrupt pins(PCINT). It seems digitalpinToInterrupt is new to me, I didn't know it, I used to attachInterrupt and registers when needed. I will look at digitalPintoInterrupt.
So when I said disable PCINT I was meaning to detach it in the interrupt routine and do your debouncing in loop.Yep you have understood the global process. of course you will need to run some tests as what I said is not complete I think, just a way to go.
- init/ attach your interrupt(pin x)
- sleep mode
- on wake up, you will be in your ISR (interrupt service routine). Save state and detach your interrupt for the concerned pin.
- after the isr is executed, you will be redirected just after the gw.sleep of course. So after this line, do your debouncing by testing pin state for instance, with millis and gw.wait. Maybe you will need to adapt the delay you check pin state with millis because debouncing will depend on your switch. But this should not be a big delay, maybe 5 to 20ms, maybe more it depends on your switch. When I say delay, it is not delay() of course! but the time you use millis()
@scalz - Right okay, i think i understand this pretty clearly now on the method to go about enabling interrupt to wake the uC.
I have just realized that there is a example sketch that uses sleep function for 2 switches, i can use this and modify it to work for 3 when needed. I shall be studying this sketch along with your links later on tonight hopefully.
Once i have sent off my deigns to get my Rev2 remade i will focus my attention to making sure i completely understand the method of this sleep with interrupt function.
Thank you for your help guys!