In my Beeping Clock I was looking at a way to reduce the power consumption and extend the battery life. Something similar to "Sleep" but without the hassle of setting a timer or using the watchdog to wake the device after a few cycles.
As ever, whilst I was trying to sleep, an idea hit me. Why not switch the PIC to a low frequency clock, wait for a few cycles and then switch back to full speed? I tried this with the reduced frequency set to 100kHz, and with a "SleepTime" set to 500mS the idling current drain went from a measured 3.8mA (at 32MHz) to 1.9mA (at 125kHz), a halving of the current. As the clock spends most of the time doing very little, this should extend the battery life by a decent amount.
The routine sets the frequency of the device to 32kHz, performs the delay while running at 32kHz, once the delay has expired the frequency is set to 32MHz. If you are running your device at another frequency, the "exit" frequency will need to be changed.
Here's the code.
SubSleepTime(InSnoozeAsWord)
#DefineFrq0032'32kHz
#DefineFrq0064'62kHz
#DefineFrq015'125kHz
#DefineFrq057'500kHz
#DefineFrq111'1MHz
#DefineFrq212'2MHz
#DefineFrq413'4MHz
#DefineFrq814'8MHz
#DefineFrq1615'16MHz
#DefineFrq3230'32MHzDimSnoozeTimeAsWordLetSnoozeTime=0SetFreq(Frq003)'32kHzDoRepeat10'With other commands included, this should is ~10 mS at 32kHzNOPEndRepeatLetSnoozeTime=SnoozeTime+1LoopUntilSnoozeTime>=SnoozeSetFreq(Frq32)'32MHzNOP'May take a cycle or two to get back up to speedEndSubSubSetFreq(InFreqAsByte)IfFreq.0=1ThenSetIRCF0OnElseSetIRCF0OffEndIfIfFreq.1=1ThenSetIRCF1OnElseSetIRCF1OffEndIfIfFreq.2=1ThenSetIRCF2OnElseSetIRCF2OffEndIfIfFreq.3=1ThenSetIRCF3OnElseSetIRCF3OffEndIfIfFreq.4=1ThenSetSPLLENOnElseSetSPLLENOffEndIfEndSub
The Routine "SleepTime" is called with the parameter that sets the amount of low power snoozing you want. The value is a Word value, SleepTime(1) gives a delay time of close to 10mS.
The chip I used was a 16F1829, other devices might need the frequency constants adjusting to reflect the frequency registers in the specific device. I used nearly the same code in a 12F1840 so I am assuming that this range of devices will work without modification.
Realised that because I hadn't used 32kHz or 64kHz in the original white noise generator, I hadn't included them here. Tweaked to use 32kHz instead of 125kHz, updated frequency constant list to include 32kHz and 64kHz. I've not measured the saving in current consumption lowering down from 100kHz to 32kHz.
Last edit: mkstevo 2021-02-06
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Well, the code as written is for PIC. It certainly works on the 12F1840 and 16F1829. I used this to change the speed "on the fly" in my white noise generator sleeping aid (12F1840). It seems to work on the Beeping Clock which is where the code above came from (16F1829).
I imagined that the PicAxe used similar to allow changing frequency "on the fly" which is what often happened before/after issuing serial in/out commands to ensure the serial communication ran at the correct speed. That gave me the original inspiration to try it on the white noise generator.
Can you address the frequency registers on an AVR directly? If so, this technique might work.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I can only use what is in gcb help/forums...I am rubbish at data sheets.
It would be handy to change the clock freq when wanted... but this is first
I've heard of.
I use a touch display with #chip mega328p,16 and it works with hwspi.
I use same touch display with #chip LGT328p32 and it does not work with hwspi
only software spi....because it's too fast.
So changing clock could an answer.. but I'm just speculating.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Try something like this: {Absolutely UNTESTED - if it all goes wrong and you can't reprogram your AVR, don't blame me!}
It is suggested that you need to issue both commands consecutively. To return it, you would need both commands, with the second one set to the original value.
'Code "borrowed" from diy0t.com'LetCLKPR=0x80'1000 0000 enable change in clock frequency'LetCLKPR=0x01'0000 0001 use clock division factor 2 to reduce the frequency from 16 MHz to 8 MHz'
It might work? You'd have to check quite what CLKPR should be for standard operation so you can return it to the correct frequency.
Last edit: mkstevo 2021-02-06
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I can only say that #chip LGT328p,16 works mega328p programs ok.
at 32 it does hwspi glcd very fast.
I've posted glcd demos and they are faster on LGT.
Not mentioned is interrupts work the same as mega328.
which is not inferred to in the interrupt lgt demo...like it's special.
What test like moving ram? I don't know how to write code that writes
xxxx bytes from address zzzz to address yyyy.
is copying arrays the same?.... as a test.
I tested your demos, except speaker,,, and all ok
Can't you do the necessary speed tests for the techy stuff? :)
I'll run any code you want as a comparison.... but it is a faster chip "in many ways"
useful ways I hope.
Why can't hwspi pins be defined and software spi pins be defined and swap them
in program?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
stevo --- The "CLKPR" code was from an Arduino site so might be relevant?
gcb uses different stuff to arduino. lot of gcb is there but unknown sorted of hidden.
avr interrupts and the calculator link .
cheers
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I've slightly updated my SleepTime routine so that it is now called with the time in tens of mS and the exit frequency. This way if you are running your device at 16MHz you could call SleepTime thus:
SleepTime(100, Frq16)
This will perform a low power sleep for one second (100 x 10mS) and then set the PIC operation to 16MHz once complete.
Longer delays are not timed accurately. A five minute delay I was using ended up at around five minutes and 30 seconds.
For me, the power saving is superb, far and away better than I had hoped. Using this to sleep for 500ms, every 500 mS has nearly doubled the battery life compared to the same circuit with no power saving.
In my Beeping Clock I was looking at a way to reduce the power consumption and extend the battery life. Something similar to "Sleep" but without the hassle of setting a timer or using the watchdog to wake the device after a few cycles.
As ever, whilst I was trying to sleep, an idea hit me. Why not switch the PIC to a low frequency clock, wait for a few cycles and then switch back to full speed? I tried this with the reduced frequency set to 100kHz, and with a "SleepTime" set to 500mS the idling current drain went from a measured 3.8mA (at 32MHz) to 1.9mA (at 125kHz), a halving of the current. As the clock spends most of the time doing very little, this should extend the battery life by a decent amount.
The routine sets the frequency of the device to 32kHz, performs the delay while running at 32kHz, once the delay has expired the frequency is set to 32MHz. If you are running your device at another frequency, the "exit" frequency will need to be changed.
Here's the code.
The Routine "SleepTime" is called with the parameter that sets the amount of low power snoozing you want. The value is a Word value, SleepTime(1) gives a delay time of close to 10mS.
The chip I used was a 16F1829, other devices might need the frequency constants adjusting to reflect the frequency registers in the specific device. I used nearly the same code in a 12F1840 so I am assuming that this range of devices will work without modification.
Realised that because I hadn't used 32kHz or 64kHz in the original white noise generator, I hadn't included them here. Tweaked to use 32kHz instead of 125kHz, updated frequency constant list to include 32kHz and 64kHz. I've not measured the saving in current consumption lowering down from 100kHz to 32kHz.
Last edit: mkstevo 2021-02-06
i didn't know you could set the clock in code while running. Does this work on avr?
Well, the code as written is for PIC. It certainly works on the 12F1840 and 16F1829. I used this to change the speed "on the fly" in my white noise generator sleeping aid (12F1840). It seems to work on the Beeping Clock which is where the code above came from (16F1829).
I imagined that the PicAxe used similar to allow changing frequency "on the fly" which is what often happened before/after issuing serial in/out commands to ensure the serial communication ran at the correct speed. That gave me the original inspiration to try it on the white noise generator.
Can you address the frequency registers on an AVR directly? If so, this technique might work.
I can only use what is in gcb help/forums...I am rubbish at data sheets.
It would be handy to change the clock freq when wanted... but this is first
I've heard of.
I use a touch display with #chip mega328p,16 and it works with hwspi.
I use same touch display with #chip LGT328p32 and it does not work with hwspi
only software spi....because it's too fast.
So changing clock could an answer.. but I'm just speculating.
Try something like this: {Absolutely UNTESTED - if it all goes wrong and you can't reprogram your AVR, don't blame me!}
It is suggested that you need to issue both commands consecutively. To return it, you would need both commands, with the second one set to the original value.
It might work? You'd have to check quite what CLKPR should be for standard operation so you can return it to the correct frequency.
Last edit: mkstevo 2021-02-06
LGTs are different from PICs and the registers are very different.
I have asked Stan, via email, to so some frequency tests. We need to know what frequencies work, and, this can be done easily on the #chip line.
Once we have confirmed the frequency then we can sort the library.
The "CLKPR" code was from an Arduino site so might be relevant?
I can only say that #chip LGT328p,16 works mega328p programs ok.
at 32 it does hwspi glcd very fast.
I've posted glcd demos and they are faster on LGT.
Not mentioned is interrupts work the same as mega328.
which is not inferred to in the interrupt lgt demo...like it's special.
What test like moving ram? I don't know how to write code that writes
xxxx bytes from address zzzz to address yyyy.
is copying arrays the same?.... as a test.
I tested your demos, except speaker,,, and all ok
Can't you do the necessary speed tests for the techy stuff? :)
I'll run any code you want as a comparison.... but it is a faster chip "in many ways"
useful ways I hope.
Why can't hwspi pins be defined and software spi pins be defined and swap them
in program?
stevo --- The "CLKPR" code was from an Arduino site so might be relevant?
gcb uses different stuff to arduino. lot of gcb is there but unknown sorted of hidden.
avr interrupts and the calculator link .
cheers
I'd meant that it may be relevant for the AVR (Atmel) processor range, I should have said that in retrospect.
I've slightly updated my SleepTime routine so that it is now called with the time in tens of mS and the exit frequency. This way if you are running your device at 16MHz you could call SleepTime thus:
SleepTime(100, Frq16)
This will perform a low power sleep for one second (100 x 10mS) and then set the PIC operation to 16MHz once complete.
Longer delays are not timed accurately. A five minute delay I was using ended up at around five minutes and 30 seconds.
For me, the power saving is superb, far and away better than I had hoped. Using this to sleep for 500ms, every 500 mS has nearly doubled the battery life compared to the same circuit with no power saving.