Anyone managed to get nanoWatt or nanoXatt XLP consumption from a PIC?.

Status
Not open for further replies.

Nigel Goodwin

Super Moderator
Most Helpful Member
Has anyone any tips on how to do this, I've never managed it yet over many years, on various different devices. Consumption in sleep is low, probably low enough, but no where near the claimed figures.

The specific device I've been trying today is the 18F26K22 - chosen for it's large memory (both ROM and RAM), fast speed, and dual serial ports (but that's a different story).

I've even scarcely populated a PCB this afternoon, it has the PIC, a 1uF ceramic capacitor across the supply, a 10K pullup on MCLR, and a reset switch - that's it. I built a minimum board to test, as the other board I was using had a SM I2C FRAM on it, which I couldn't easily disconnect.

So minimum hardware, and minimum software - set the clock up (at 64MHz as I've been using), set all I/O pins to outputs and low, turn off analogue inputs. The main program consists of an endless loop, with a sleep instruction inside - the second line, commented out here, was used to check if the device was sleeping or not, by checking RA0 with a scope.

Code:
while(1)
{
     SLEEP();
     //PORTAbits.RA0 = ~PORTAbits.RA0;
}

With the RAO line enabled, and sleep disabled, it consumes just over 9mA - obviously reducing the clock speed lowers that. With sleep enabled consumption drops to 21uA, which is pretty good - but no where near the claimed figures. I've tried turning peripherals off, and lowering the clock speed - rather stupidly as it happens, because the clock isn't running during sleep

The aim of the design will use a 32KHz crystal on tmr1, and wake up every second to run a clock and check if it's time to 'do something' yet, it'll also wake up in response to I/O interrupts and process those - but I'd like to get closer to the claimed figures before doing that.

So has anyone been here?, and managed to achieve what they claim?.
 
Last edited:
Hola Nigel,

From my readings in the last year I recall the "deep sleep" concept. It applies to the 18F and 24F family. Maybe to the new ones of the 16F?
But I suspect you know this already. Sorry if so.
 
So has anyone been here?, and managed to achieve what they claim?.
I think you have to turn off things like the ADC etc. (turn off Vref)
I don't do software so .... I am just making noise LOL
The little 8 pin and 6 pin PICs that we use have such a low power that there is no on/off switch. We ship with the watch battery connected.
 

I recall that you have to set all (most) IO to Outputs (low).

Also, the application note is below...
**broken link removed**
 
Last edited:
I recall that you have to set all (most) IO to Outputs (low).

All I/O pins are set low, I forgot to mention that, and it did make a small difference.

Also, the application note is below...
**broken link removed**

That refers to the USB capable devices, the 18F26K22 isn't one of those (but I'll have a read anyway) - I've got a 'Tricks and Tips' PDF, DS01146B, about low power use, but it doesn't tell me anything I'm not already doing.
 
OK, I've been studying further - and managed to find 'XLP BLE', a MicroChip program that allows you to estimate power usage and battery life for XLP processors. So I ran that, and found that the BOREN consumes up to 25uA (it claims 20nA otherwise) - further searching found that there's a mode where it can be active during running, and disabled during sleep 'BOREN = NOSLP' .

Tried turning BOREN to NOSLP, and it reduced consumption to 12uA - damn!! - still another 8uA saved.
 
Well, just to keep you updated, I'm currently working with the PIC16F18446, and this afternoon the consumption in sleep was 40uA (which to be fair, is probably low enough - but it didn't make me 'happy' ) - I tried disabling FVR, no change - so next I tried disabling ADCC, BIG change, consumption dropped to 2uA, and this includes the 3.3V regulator that feeds the PIC. This device also lets you totally disconnect any peripherals you're not using, so I've already got everything I don't need disconnected (including TMR2, which I struggled to add - then remembered I'd disconnected it).

As I assembled the board I did it in a bit of an 'unusual' order, specifically so I could monitor current consumption as I added parts - in particular so I could test the voltage regulator with nothing else onboard to affect it - if I remember correctly, it only took 1.6uA, which means the PIC is now drawing only 400nA. This does make me fairly happy

I might go back to the 18F26K22 at a later date?, for the moment the current project is more important - while they are connected to each other, the 18F26K22 is going to have a display, currently a 320x240 TFT, and the current that takes (about 100mA) makes nonsense of trying to save microamps from the processor.
 

The ADCC does not start disabled by default?

What are you using to measure the current anyways?
 
What does the second C in ADCC stand for. Not heard the term before.

Mike.
 
The ADCC does not start disabled by default?

It probably does, but I've already used it for measuring the battery voltage.

What are you using to measure the current anyways?

A multimeter, switching down from 200mA to 2mA when it goes to sleep - there is a 20uA range, but I'm not down to that yet.
 
Some nice progress, Nigel...

I've been using the PMD (Peripheral Module Disable) on my 16F15xxx projects, too, but I'm really disappointed that XC8 won't evaluate my constant expressions to a constant. That is, XC8 generates a whole bunch of bit-shift code for statements like this;

Code:
     PMD4 = 1<<UART2MD |    // UART2 module off
            1<<UART1MD |    // UART1 module off
            1<<MSSP1MD |    // MSSP1 module off
            1<<CWG1MD;      // CWG1 module off
 
Last edited:

Are you using the free version of XC8?, it does tend to generate some fairly poor code.
 

Why do you think that w/r SFR bits are a constant?
 
Well, here's an excerpt from the p16F15325.inc file (in C:\Program Files (x86)\Microchip\MPLABX\v4.05\mpasmx\);
Code:
;----- PMD4 Bits -----------------------------------------------------
CWG1MD           EQU  H'0000'
MSSP1MD          EQU  H'0004'
UART1MD          EQU  H'0006'
UART2MD          EQU  H'0007'

But now that you mention it, XC8 coughs and chokes when I try to use a bit index constant even in an ASM instruction;

Code:
     asm("movlb PORTC/2                            ");
     asm("btfsc PORTC,RC0                          ");

** 16f15325_oled.c:271: error: (800) undefined symbol "RC0"

Why wouldn't the bit index constants from the \mpasmx\ include file be recognized?
 
Last edited:
XC8 is very disappointing. The free version stores intermediate values from calculations and then reloads them. I knew the problem with constants being 8 bit but didn't know about the bit shift constant nonsense.

Mike.
 
It seems XC8 is using different include files where those bit index constants are actually defined as structure elements. There also seems to be bit index constants associated with the register bits;

Code:
// Register: PMD4
#define PMD4 PMD4
extern volatile unsigned char           PMD4                __at(0x79A);
#ifndef _LIB_BUILD
asm("PMD4 equ 079Ah");
#endif
// bitfield definitions
typedef union {
    struct {
        unsigned CWG1MD                 :1;
        unsigned                        :3;
        unsigned MSSP1MD                :1;
        unsigned                        :1;
        unsigned UART1MD                :1;
        unsigned UART2MD                :1;
    };
} PMD4bits_t;
extern volatile PMD4bits_t PMD4bits __at(0x79A);
// bitfield macros
#define _PMD4_CWG1MD_POSN                                   0x0
#define _PMD4_CWG1MD_POSITION                               0x0
#define _PMD4_CWG1MD_SIZE                                   0x1
#define _PMD4_CWG1MD_LENGTH                                 0x1
#define _PMD4_CWG1MD_MASK                                   0x1
#define _PMD4_MSSP1MD_POSN                                  0x4
#define _PMD4_MSSP1MD_POSITION                              0x4
#define _PMD4_MSSP1MD_SIZE                                  0x1
#define _PMD4_MSSP1MD_LENGTH                                0x1
#define _PMD4_MSSP1MD_MASK                                  0x10
#define _PMD4_UART1MD_POSN                                  0x6
#define _PMD4_UART1MD_POSITION                              0x6
#define _PMD4_UART1MD_SIZE                                  0x1
#define _PMD4_UART1MD_LENGTH                                0x1
#define _PMD4_UART1MD_MASK                                  0x40
#define _PMD4_UART2MD_POSN                                  0x7
#define _PMD4_UART2MD_POSITION                              0x7
#define _PMD4_UART2MD_SIZE                                  0x1
#define _PMD4_UART2MD_LENGTH                                0x1
#define _PMD4_UART2MD_MASK                                  0x80
Ok, I tried it and XC8 generates the two instructions I'm lookin' for but, gads, that's an ugly way to do things (sigh!)...
Code:
     PMD4 = 1<<_PMD4_UART2MD_POSN |    // UART2 module off
            1<<_PMD4_UART1MD_POSN |    // UART1 module off
            1<<_PMD4_MSSP1MD_POSN |    // MSSP1 module off
            1<<_PMD4_CWG1MD_POSN;      // CWG1 module off
Code:
   663                           ;x_16f15325_oled.c: 266: PMD4 = 1<<0x7 |;x_16f15325_oled.c: 267: 1<<0x6 |;x_16f15325_ole
      +                          d.c: 268: 1<<0x4 |;x_16f15325_oled.c: 269: 1<<0x0;
   664  0729  30D1                   movlw    209
   665  072A  009A                   movwf    26    ;volatile
 
Last edited:
XC8 is very disappointing. The free version stores intermediate values from calculations and then reloads them. I knew the problem with constants being 8 bit but didn't know about the bit shift constant nonsense.

Mike.

It's not nonsense, when you use a define'd constant it works as expected.
 

XC8 was trying to tell you something but you weren't listening.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…