 |
 |
| View previous topic :: View next topic |
| Author |
Message |
Gabriel
Joined: 03 Aug 2009 Posts: 1082 Location: Panama
|
| Sleep Currents |
Posted: Sat Jun 27, 2026 9:43 am |
|
|
Hi all,
Im developing a Temperature LORA sensor.
I have a custom board with a PIC18F47Q84, EEPROM, and RTC to wake up via EXT INT.
The board is powered by 3x 18650s (paralleled) through a MCP1700 LDO.
Im using the RYLR896 radio and BME280 as the sensor.
I cant get sleep Current under 0.100mA which is absurd - or maybe i hit my boards limit? i refuse to belive this, and battery life obviously sucks when i have such a large bank.
Edit: also ive taken care of checking every pull up on the board, to ensure none are kept low during sleep, this was happening with botht the RTCs interrupt pins... huge current gains obviously.
Edit_2: fuses
| Code: | #include <18F47Q84.h>
#device PASS_STRINGS=IN_RAM
#device adc=8
#fuses MCLR
#fuses NOWDT
#fuses NOLVP
#fuses NOXINST
#fuses NODEBUG
#fuses NOBROWNOUT
#fuses NOLPBOR
#fuses NOPROTECT
#fuses HS
#fuses RSTOSC_EXT_PLL
#use delay(clock=64MHz) |
CODE:
| Code: |
disable_interrupts(INT_RDA);
sleep(SLEEP_FULL|REG_LOW_POWER);
delay_ms(2);
setup_oscillator(OSC_EXTOSC_PLL|OSC_CLK_DIV_BY_1|OSC_PLL_ENABLED|OSC_EXTOSC_READY);
delay_ms(1);
|
this is my sleep "method".
ive taken particular care to disable everything i can think of. i even have a function called "Disable_Everthing();"
PIN BY PIN!
| Code: |
void Disable_Everything()
{
setup_wdt(WDT_OFF);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
setup_ccp3(CCP_OFF);
setup_counters(RTCC_OFF,RTCC_DIV_1);
setup_timer_0(T0_OFF);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,0);
setup_timer_3(T3_DISABLED);
setup_timer_4(T4_DISABLED,0,0);
setup_timer_5(T5_DISABLED);
setup_timer_6(T6_DISABLED,0,0);
setup_pwm1(PWM_DISABLED);
setup_pwm2(PWM_DISABLED);
setup_pwm3(PWM_DISABLED);
setup_pwm4(PWM_DISABLED);
setup_spi(SPI_DISABLED);
setup_clc1(CLC_DISABLED);
setup_clc2(CLC_DISABLED);
setup_clc3(CLC_DISABLED);
setup_clc4(CLC_DISABLED);
setup_clc5(CLC_DISABLED);
setup_clc6(CLC_DISABLED);
setup_clc7(CLC_DISABLED);
setup_clc8(CLC_DISABLED);
setup_smt1(SMT_DISABLED);
setup_smt2(SMT_DISABLED);
setup_dsm(DSM_DISABLED);
#ifdef VERSION_1
input(BAT_SENS); //A0
#endif
#ifdef VERSION_2
setup_comparator(NC_NC_NC_NC);
setup_vref(VREF_OFF);
setup_dac(DAC_OFF);
output_low(PIN_A2);
#endif
//output_low(PIN_A0); //LECTURA DE BAT
output_low(PIN_A1);
//output_low(PIN_A2); //OFF EN V.2 y INPUT en V.1
output_low(PIN_A3);
output_low(PIN_A4);
output_low(PIN_A5);
//output_low(PIN_B0); //INTERRUPT
//output_low(PIN_B1); //INTERRUPT
output_low(PIN_B2);
output_high(PIN_B3); //LORA RESET
//output_low(PIN_B4); //LORA UART
//output_low(PIN_B5); //LORA UART
output_low(PIN_B6);
output_low(PIN_B7);
output_low(PIN_C0); //FTDI
output_low(PIN_C1); //FTDI
output_low(PIN_C2);
//output_low(PIN_C3); //I2C
//output_low(PIN_C4); //I2C
output_low(PIN_C5);
output_low(PIN_C6);
output_low(PIN_C7);
output_low(PIN_D0);
output_low(PIN_D1);
#ifndef USE_DS
output_low(PIN_D2);
output_low(PIN_D3);
#endif
output_low(PIN_D4);
output_low(PIN_D5);
output_low(PIN_D6);
output_low(PIN_D7);
output_low(BAT_SENS_ENABLE); //E0/enable in V.1
output_low(PIN_E1);
output_low(PIN_E2);
}
|
im on my second revision of the board, the previous used an opamp and internal DAC to check the 18650 voltage indirectly... that was costing me about 0.400mA! - thats gone now - i managed to get that board revision down to 0.250mA.
still crazy sleep currents.
what am i missing? getting down to 0.050mA would be a huge win a this point.
thanks,
G _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20100
|
|
Posted: Sat Jun 27, 2026 11:11 am |
|
|
What commands are you sending to the LoRa module to put it to sleep????
If it is staying awake, it'd explain a lot of this. You need to send the
sleep command to the module.
Also the MCP1700, is a low power regulator, but is a linear regulator. So
will waste you quite a lot of power.
Also you don't show how you are programming the BME. If it is left in
continuous sample mode, as opposed to being put back into sleep mode
it'll draw a lot more current.
How is the PIC being woken up?. What interrupt are you using?.
Remember interrupts need to be cleared before you sleep, or the chip
won't sleep but will awake immediately. |
|
 |
Gabriel
Joined: 03 Aug 2009 Posts: 1082 Location: Panama
|
|
Posted: Sat Jun 27, 2026 12:05 pm |
|
|
hi Ttelmah!
for the lora im just using the AT command sleep:
| Code: | | fprintf(LORA,"AT+MODE=%u\r\n",LORA_SLEEP); |
LORA_SLEEP is defined as 1 - mode 1 is sleep.
im using EXT and EXT1 to wake up.
for context: the RTC has a Minute alarm, and a seconds alarm.
I wake up every minute, go back to sleep for random amount of seconds, and then transmit... as a transmission overlap avoidance method (i have multiple of these sensors laying around).
ext1 on the minute alarm, ext on the seconds.
for the BME its in single shot mode - however i have this code setup to work with S17021, DS18B20, and BME280 (i like having choices) - same issue across the sensor line - witht the DS18B20 i even go as far a removing power with a dedicated pin - same issue.
I am NOT clearing the interrupts, thank you for that.
i will test and report!
thank you!
G _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20100
|
|
Posted: Mon Jun 29, 2026 12:48 am |
|
|
As one extra comment, the instruction after the sleep, should be
delay_cycles(1); not the delay_ms you have. This needs to be a NOP
instruction, and this is what delay_cycles gives. The delay_ms will
probably be putting the wrong code at this point.
The point here is that the following instruction, has been already fetched
when the processor goes to sleep. It must be a 'do nothing' instruction,
or problems can result. |
|
 |
jeremiah
Joined: 20 Jul 2010 Posts: 1421
|
|
Posted: Mon Jun 29, 2026 7:41 am |
|
|
Besides turning off the registers, have you looked into the PMD (Peripheral Module Disable)? I don't know pic18s well, but on pic24's this disconnects the modules from power (meaning if you enable them, you need to re-init the registers again).
In our low power boards we generally disable everything we can, even stuff we plan to use, then turn off the disable when we are about to use the peripherals and disable them after we are done.
Also, what is the value of your VREGPM register? that has a huge impact on your sleep current (see section 50.3.3 of the data sheet) |
|
 |
asmallri
Joined: 12 Aug 2004 Posts: 1670 Location: Perth, Australia
|
| Re: Sleep Currents |
Posted: Tue Jun 30, 2026 2:11 am |
|
|
| Gabriel wrote: | Hi all,
Im developing a Temperature LORA sensor.
I have a custom board with a PIC18F47Q84, EEPROM, and RTC to wake up via EXT INT.
The board is powered by 3x 18650s (paralleled) through a MCP1700 LDO.
Im using the RYLR896 radio and BME280 as the sensor.
I cant get sleep Current under 0.100mA which is absurd - or maybe i hit my boards limit? i refuse to belive this, and battery life obviously sucks when i have such a large bank.
Edit: also ive taken care of checking every pull up on the board, to ensure none are kept low during sleep, this was happening with botht the RTCs interrupt pins... huge current gains obviously.
Edit_2: fuses
| Code: | #include <18F47Q84.h>
#device PASS_STRINGS=IN_RAM
#device adc=8
#fuses MCLR
#fuses NOWDT
#fuses NOLVP
#fuses NOXINST
#fuses NODEBUG
#fuses NOBROWNOUT
#fuses NOLPBOR
#fuses NOPROTECT
#fuses HS
#fuses RSTOSC_EXT_PLL
#use delay(clock=64MHz) |
CODE:
| Code: |
disable_interrupts(INT_RDA);
sleep(SLEEP_FULL|REG_LOW_POWER);
delay_ms(2);
setup_oscillator(OSC_EXTOSC_PLL|OSC_CLK_DIV_BY_1|OSC_PLL_ENABLED|OSC_EXTOSC_READY);
delay_ms(1);
|
this is my sleep "method".
ive taken particular care to disable everything i can think of. i even have a function called "Disable_Everthing();"
PIN BY PIN!
| Code: |
void Disable_Everything()
{
setup_wdt(WDT_OFF);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
setup_ccp3(CCP_OFF);
setup_counters(RTCC_OFF,RTCC_DIV_1);
setup_timer_0(T0_OFF);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,0);
setup_timer_3(T3_DISABLED);
setup_timer_4(T4_DISABLED,0,0);
setup_timer_5(T5_DISABLED);
setup_timer_6(T6_DISABLED,0,0);
setup_pwm1(PWM_DISABLED);
setup_pwm2(PWM_DISABLED);
setup_pwm3(PWM_DISABLED);
setup_pwm4(PWM_DISABLED);
setup_spi(SPI_DISABLED);
setup_clc1(CLC_DISABLED);
setup_clc2(CLC_DISABLED);
setup_clc3(CLC_DISABLED);
setup_clc4(CLC_DISABLED);
setup_clc5(CLC_DISABLED);
setup_clc6(CLC_DISABLED);
setup_clc7(CLC_DISABLED);
setup_clc8(CLC_DISABLED);
setup_smt1(SMT_DISABLED);
setup_smt2(SMT_DISABLED);
setup_dsm(DSM_DISABLED);
#ifdef VERSION_1
input(BAT_SENS); //A0
#endif
#ifdef VERSION_2
setup_comparator(NC_NC_NC_NC);
setup_vref(VREF_OFF);
setup_dac(DAC_OFF);
output_low(PIN_A2);
#endif
//output_low(PIN_A0); //LECTURA DE BAT
output_low(PIN_A1);
//output_low(PIN_A2); //OFF EN V.2 y INPUT en V.1
output_low(PIN_A3);
output_low(PIN_A4);
output_low(PIN_A5);
//output_low(PIN_B0); //INTERRUPT
//output_low(PIN_B1); //INTERRUPT
output_low(PIN_B2);
output_high(PIN_B3); //LORA RESET
//output_low(PIN_B4); //LORA UART
//output_low(PIN_B5); //LORA UART
output_low(PIN_B6);
output_low(PIN_B7);
output_low(PIN_C0); //FTDI
output_low(PIN_C1); //FTDI
output_low(PIN_C2);
//output_low(PIN_C3); //I2C
//output_low(PIN_C4); //I2C
output_low(PIN_C5);
output_low(PIN_C6);
output_low(PIN_C7);
output_low(PIN_D0);
output_low(PIN_D1);
#ifndef USE_DS
output_low(PIN_D2);
output_low(PIN_D3);
#endif
output_low(PIN_D4);
output_low(PIN_D5);
output_low(PIN_D6);
output_low(PIN_D7);
output_low(BAT_SENS_ENABLE); //E0/enable in V.1
output_low(PIN_E1);
output_low(PIN_E2);
}
|
im on my second revision of the board, the previous used an opamp and internal DAC to check the 18650 voltage indirectly... that was costing me about 0.400mA! - thats gone now - i managed to get that board revision down to 0.250mA.
still crazy sleep currents.
what am i missing? getting down to 0.050mA would be a huge win a this point.
thanks,
G |
A have done a lot of work in this area building a Wildland Fire (Bush Fire) warning system as detailed here -> www.thingy-iot.au. If you would like to share your schematic I will review it for you. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
 |
Gabriel
Joined: 03 Aug 2009 Posts: 1082 Location: Panama
|
|
Posted: Tue Jun 30, 2026 12:55 pm |
|
|
Hi,
Clearing the interrupts, both inside the ISR and again right before the sleep instruction did not change anything.
Ive also added the delay_cycles(1); right after the sleep instrucction but i still at 0.110ish mA.
I read the comment about the VREGPM and i belive this is addressed by the ORed option here:
| Code: | | sleep(SLEEP_FULL|REG_LOW_POWER); | specifically the REG_LO_POWER - am i wrong to assume this?
I frankly do not know how to operate the PMD.
does CCS have any instructions for this? i searched the manual, no mention of PMD _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
 |
newguy
Joined: 24 Jun 2004 Posts: 1943
|
|
Posted: Tue Jun 30, 2026 4:57 pm |
|
|
| Look in the data sheet of your processor. If it has peripheral module disable capability, it will be detailed there. |
|
 |
asmallri
Joined: 12 Aug 2004 Posts: 1670 Location: Perth, Australia
|
|
Posted: Tue Jun 30, 2026 6:23 pm |
|
|
I realise you want to reduce the sleep current. But aside from that, for a very low power device, why are you running the clock so fast?
From the code snippet, there are lots of I/O lines that are not initialised because they are commented out. By default, non initialised I/O are inputs and if they are left floating, can result in higher currents. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
 |
jeremiah
Joined: 20 Jul 2010 Posts: 1421
|
|
Posted: Wed Jul 01, 2026 7:29 am |
|
|
| asmallri wrote: | I realise you want to reduce the sleep current. But aside from that, for a very low power device, why are you running the clock so fast?
|
That's definitely worth considering. I will say from my own experience: if you spend significantly more time in sleep vs awake, then the clock speed will be a negligible factor (just due to the relative weights of sleep vs awake time). We do a full current draw analysis to verify for each project. Most all of our projects run at either 32 MHz or 22.1184 MHz and we get average sleep draws in the single digit microamp amp range.
BUT we do have a much larger sleep cycle than awake time, so there is that to consider.
Last edited by jeremiah on Wed Jul 01, 2026 7:43 am; edited 1 time in total |
|
 |
jeremiah
Joined: 20 Jul 2010 Posts: 1421
|
|
Posted: Wed Jul 01, 2026 7:39 am |
|
|
| Gabriel wrote: |
I frankly do not know how to operate the PMD.
does CCS have any instructions for this? i searched the manual, no mention of PMD |
Our .h defines:
| Code: |
// Memory Architecture Variables for disabling to save power
// PMD = Peripheral Module Disable
#bit TIMER1_PMD = getenv("BIT:T1MD") // Timer Module
#bit TIMER2_PMD = getenv("BIT:T2MD")
#bit TIMER3_PMD = getenv("BIT:T3MD")
#bit TIMER4_PMD = getenv("BIT:T4MD")
#bit TIMER5_PMD = getenv("BIT:T5MD")
#bit U1_PMD = getenv("BIT:U1MD") // UART Module
#bit SPI1_PMD = getenv("BIT:SPI1MD") // SPI Module
#bit ADC1_PMD = getenv("BIT:ADC1MD") // ADC Module
#bit DAC_PMD = getenv("BIT:DAC1MD") // DAC Module
#bit CLC1_PMD = getenv("BIT:CLC1MD") // CLC Module
#bit CLC2_PMD = getenv("BIT:CLC2MD")
#bit CLC3_PMD = getenv("BIT:CLC3MD")
#bit CLC4_PMD = getenv("BIT:CLC4MD")
#word PMD1 = getenv("SFR:PMD1")
#word PMD2 = getenv("SFR:PMD2")
#word PMD3 = getenv("SFR:PMD3")
#word PMD4 = getenv("SFR:PMD4")
#word PMD5 = getenv("SFR:PMD5")
#word PMD6 = getenv("SFR:PMD6")
#word PMD7 = getenv("SFR:PMD7")
#word PMD8 = getenv("SFR:PMD8")
// Disable Masks, invert and & to enable
#define PMD1_TIMER1_MASK 0x0800 ///< Peripheral Module Disable mask for Timer1
#define PMD1_SPI1_MASK 0x0008 ///< Peripheral Module Disable mask for SPI1
#define PMD3_DAC_MASK 0x0040 ///< Peripheral Module Disable mask for DAC
|
Then in our initialization code, we disable everythng BUT the stuff we need running all the time (here a timer, SPI, and DAC). Everything else is manually enabled/disabled as it is used
| Code: |
// Disable all unnecessary modules
PMD1 = 0xffff & (~PMD1_TIMER1_MASK) & (~PMD1_SPI1_MASK);
PMD2 = 0xffff;
PMD3 = 0xffff & (~PMD3_DAC_MASK);
PMD4 = 0xffff;
PMD5 = 0xffff;
PMD6 = 0xffff;
PMD7 = 0xffff;
PMD8 = 0xffff;
|
Here's an example of functions we use to enable and disable peripherals:
| Code: |
void Connection_Interface_Enable(void)
{
// Clear the bit for the PMD (peripheral module disable)
U1_PMD = 0;
setup_uart(SYSTEM_BAUD_RATE, STREAM_UART);
}
void Connection_Interface_Disable(void)
{
setup_uart(FALSE, STREAM_UART);
// Set the bit for the PMD (peripheral module disable)
U1_PMD = 1;
}
|
We call those functions before we use the UART and after we are done with it. Similar for our ADC usage. |
|
 |
Gabriel
Joined: 03 Aug 2009 Posts: 1082 Location: Panama
|
|
Posted: Wed Jul 01, 2026 5:48 pm |
|
|
ive reduced the processor speed - didnt expect any gains but did anyways.
the 18F47Q84 is my swiss army knife so i copy and paste a lot of code.
that oscillator config just works... no brainer.
on this same line i switched to internal RC at 16MHz to see if mabye my crystal or anything related was pulling current. no change.
the pins that i dont intentionally drive low are being used by the app.
like B0 and B1 are inputs used by the RTC interrupts. so thats why they are commented. ive explicitly set them as inputs, no change in current still.
these are pins with pullups, which ive verified are high during sleep.
The only "wierd" thing ive noticed is that my lora module, brings its TX line low during sleep.
Since i have my pins configured as UART, maybe the PPS or uart module has an internal pull up that does not get killed by Port_x_Pullups(FALSE);?!?!
this would explain the high current draw.
That RX Pin is the only thing i cant account for since it seems its the lora module drive it low. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|