|
|
View previous topic :: View next topic |
Author |
Message |
samiceng
Joined: 23 Oct 2018 Posts: 5
|
PIC16F913 Sleep With LCD |
Posted: Mon Sep 19, 2022 12:47 pm |
|
|
hello. I tried to make my post as short as possible, but I couldn't do it, So here it is:
I am working on a counter project that will use a 3V coin battery and an segment LCD. It will be in sleep most of the time, and the LCD must stay ON to display the count during sleep.
I was using:
* PIC16F913
* CCS V 5.071
* 3V coin battery with a 2V regulator (Idle current for the regulator is 1uA).
* Clock is a low power 32.768kHz crystal
* LCD (2V 1/4 duty 1/3 bias) with three 1M res for LCD biasing.
* 330K Res pull up at the MCLR pin.
* PIN-B0 was pulled down to GND through a 1M Res, and will be connected
to 2V supply using a bush button to wake up from sleep.
The code is: ( to demonstrate the idea I Just use an 8bit int variable for the count value)
Code: |
#include <16F913.h>
#fuses LP, NOWDT, PUT, MCLR, NOBROWNOUT, NOFCMEN, NOIESO
#use delay(clock=32768)
int count1 = 8; // 1st digit
int count2 = 8; // 2nd digit
int count3 = 8; // 3rd digit
int count4 = 8; // 4th digit
int count5 = 8; // 5th digit
/////////////////////////////////////////////////////////////////////////////////////////
// LCD Configuration //
/////////////////////////////////////////////////////////////////////////////////////////
// Digit segments A B C D E F G DP
// b7 b6 b5 b4 b3 b2 b1 b0
#define DIGIT1 COM0+13, COM1+13, COM2+13, COM3+13, COM2+14, COM0+14, COM1+14, COM3+14
#define DIGIT2 COM0+3, COM1+3, COM2+3, COM3+3, COM2+2, COM0+2, COM1+2, COM3+2
#define DIGIT3 COM0+1, COM1+1, COM2+1, COM3+1, COM2+8, COM0+8, COM1+8, COM3+8
#define DIGIT4 COM0+9, COM1+9, COM2+9, COM3+9, COM2+10, COM0+10, COM1+10, COM3+10
#define DIGIT5 COM0+11, COM1+11, COM2+11, COM3+11, COM2+6, COM0+6, COM1+6, COM3+6
// ComX+Y is combination of Backplan0-3 and Segment0-SegmentXX
////////////////////////////////////////////////////////////////////////////////////////
// character 0 1 2 3 4 5 6 7 8 9 Null
byte const Digit_Map_1[11] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6,0x00};
#define blank 10
//////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
// Segments Initilization
// Seg15 Seg14 Seg13 Seg12 Seg11 Seg10 Seg9 Seg8 Seg7 Seg6 Seg5 Seg4 Seg3 Seg2 Seg1 Seg0
// 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1
// if bit_SegX is 1, SegX is set as Segment Output. Otherwise
/////////////////////////////////////////////////////////////////////////////////////////
#define Segments 0x6f4e // Initialize LCD SegmentX
////////////////////////////////////////////////////////////////////////////////////////
void Display()
{
lcd_symbol (Digit_Map_1[count1], DIGIT1); // from left to right
lcd_symbol (Digit_Map_1[count2], DIGIT2); // from left to right
lcd_symbol (Digit_Map_1[count3], DIGIT3); // from left to right
lcd_symbol (Digit_Map_1[count4], DIGIT4); // from left to right
lcd_symbol (Digit_Map_1[count5], DIGIT5); // from left to right
}
///////////////////////////////////////////////////////////////////////////////
void main()
{
set_tris_a (0xff); // avoid floating
set_tris_b (0xff); // avoid floating
set_tris_c (0xff); // avoid floating
set_tris_e (0xff); // avoid floating
output_high(pin_A0); // Make all unused pins to High
output_high(pin_A1);
output_high(pin_A4);
output_high(pin_A5);
output_high(pin_A6);
output_high(pin_A7);
output_high(pin_E3);
setup_counters (T0_EXT_L_TO_H, T0_DIV_1); // // disable timer 0 ??????
setup_timer_1 (T1_DISABLED); // disable timer 1
setup_timer_2 (T2_DISABLED,0,1); // disable timer 2
setup_vref (FALSE); // disable Voltage reference
setup_adc (ADC_OFF); // disable ADC
setup_wdt (WDT_OFF); // disable Watch Dog Timer
setup_ccp1 (CCP_OFF); // disable compare/capture
setup_comparator (NC_NC_NC_NC); // disable comparators
setup_spi(SPI_DISABLED);
#byte VRCON = 0x009D // VR control register
VRCON = 0x00; // VR is disabled
#byte CMCON0 = 0x009C // Comparator configuration register
CMCON0 = 0x0007; // Comparator is disabled
#byte ANSEL = 0x0091 // Analog select register
ANSEL = 0x00; // Digital I/O
#byte ADCON0 = 0x001F // A/D control register
ADCON0 = 0x00; // A/D is shut off
ext_int_edge(L_TO_H); // init interrupt triggering for button press
clear_interrupt(INT_EXT);
disable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
setup_lcd(LCD_MUX14|LCD_INTRC,7, Segments); // set segments
// initial start up
count5 = 8;
count4 = 8;
count3 = 8;
count2 = 8;
count1 = 8;
Display ();
delay_ms(1000);
count5 = 0;
count4 = 0;
count3 = 0;
count2 = 0;
count1 = 0;
Display ();
while (TRUE)
{
while (!input (PIN_B0))
{
Display ();
clear_interrupt(INT_EXT);
disable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
sleep();
delay_ms(50);
}
while (input (PIN_B0))
{
Display ();
count1++;
if (count1 >=10)
{
count1=0;
}
delay_ms(1000);
}
}
}
|
Now I got a current of 9.5uA during sleep, since my regulator draw 1uA, that mean the PIC draw 8.5uA during sleep. But the data sheet says it can go below 100nA. I know that LCD will draw some current but isn't around 8.5uA too much for LCD.
I write a test code that turn OFF everything and go to sleep just to see how low can I got. I reached 1.7uA( 0.7uA for the PIC).
Here is this code.
Code: |
#include <16F913.h>
#fuses LP, NOWDT, PUT, MCLR, NOBROWNOUT, NOFCMEN, NOIESO
#use delay(clock=32768)
void main()
{
set_tris_a (0xff); // avoid floating
set_tris_b (0xfe); // avoid floating
set_tris_c (0xfc); // avoid floating
set_tris_e (0xff); // avoid floating
output_high(pin_A0);
output_high(pin_A1);
output_high(pin_A2);
output_high(pin_A3);
output_high(pin_A4);
output_high(pin_A5);
output_high(pin_A6);
output_high(pin_A7);
output_high(pin_B0);
output_high(pin_B1);
output_high(pin_B2);
output_high(pin_B3);
output_high(pin_B4);
output_high(pin_B5);
output_high(pin_B6);
output_high(pin_B7);
output_high(pin_C0);
output_high(pin_C1);
output_high(pin_C2);
output_high(pin_C3);
output_high(pin_C4);
output_high(pin_C5);
output_high(pin_C6);
output_high(pin_C7);
output_high(pin_E3);
setup_counters (T0_EXT_L_TO_H, T0_DIV_1); // disable timer 0 ????????
setup_timer_1 (T1_DISABLED); // disable timer 1
setup_timer_2 (T2_DISABLED,0,1); // disable timer 2
setup_vref (FALSE); // disable Voltage reference
setup_adc (ADC_OFF); // disable ADC
setup_wdt (WDT_OFF); // disable Watch Dog Timer
setup_ccp1 (CCP_OFF); // disable compare/capture
setup_comparator (NC_NC_NC_NC); // disable comparators
setup_spi(SPI_DISABLED);
#byte VRCON = 0x009D // VR control register
VRCON = 0x00; // VR is disabled
#byte CMCON0 = 0x009C // Comparator configuration register
CMCON0 = 0x0007; // Comparator is disabled
#byte ANSEL = 0x0091 // Analog select register
ANSEL = 0x00; // Digital I/O
#byte ADCON0 = 0x001F // A/D control register
ADCON0 = 0x00; // A/D is shut off
ext_int_edge(L_TO_H); // init interrupt triggering for button press
enable_interrupts (INT_EXT); // turn on interrupts
setup_lcd(LCD_DISABLED);
while (TRUE)
{
while (!input (PIN_B0))
{
output_low(pin_C1);
clear_interrupt(INT_EXT);
disable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
sleep();
delay_cycles(1);
}
while (input (PIN_B0))
{
output_toggle(pin_C1);
delay_ms(1000);
}
}
}
|
I was using:
* PIC16F913
* CCS V 5.071
* 3V coin battery with a 2V regulator (Idle current for the regulator is 1uA).
* Clock is a low power 32.768kHz crystal
* PIN-C1 is connected to LED with 47K Res connected to GND.
* 330K Res pull up at the MCLR pin.
* PIN-B0 was pulled down to GND through a 1M Res, and will be connected
to 2V supply using a push button to wake up from sleep. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 19, 2022 3:03 pm |
|
|
I guess you want to know why the first program uses more current than
the 2nd program.
I couldn't find a spec in the 16F913 data sheet for current usage by
the LCD module when it's enabled. I think the excess current might
be used by the LCD module. To test this, turn it on in your 2nd program.
Change this:
Quote: | setup_lcd(LCD_DISABLED); |
to this:
Code: | setup_lcd(LCD_MUX14|LCD_INTRC,7, Segments); |
How much current does the 2nd program now use ? |
|
|
samiceng
Joined: 23 Oct 2018 Posts: 5
|
|
Posted: Tue Sep 20, 2022 12:50 pm |
|
|
PCM programmer, I found something.
I tried what you suggest ( had to add this line too: "#define Segments 0x6f4e"). I got 2.9uA while sleep. But there is no LCD resistors attached to PIN C0 to C2. So to make it fair I add them and test two codes: one with LCD enabled and the other is not.
So using this arrangement:
* PIC16F913
* CCS V 5.071
* 3V coin battery with a 2V regulator (Idle current for the regulator is 1uA).
* Clock is a low power 32.768kHz crystal
* LCD (2V 1/4 duty 1/3 bias) with three 1M res for LCD biasing.
* 330K Res pull up at the MCLR pin.
* PIN-B0 was pulled down to GND through a 1M Res, and will be connected
to 2V supply using a bush button to wake up from sleep.
and code :
Code: |
#include <16F913.h>
#fuses LP, NOWDT, PUT, MCLR, NOBROWNOUT, NOFCMEN, NOIESO
#use delay(clock=32768)
int count1 = 8; // 1st digit
int count2 = 8; // 2nd digit
int count3 = 8; // 3rd digit
int count4 = 8; // 4th digit
int count5 = 8; // 5th digit
/////////////////////////////////////////////////////////////////////////////////////////
// LCD Configuration //
/////////////////////////////////////////////////////////////////////////////////////////
// Digit segments A B C D E F G DP
// b7 b6 b5 b4 b3 b2 b1 b0
#define DIGIT1 COM0+13, COM1+13, COM2+13, COM3+13, COM2+14, COM0+14, COM1+14, COM3+14
#define DIGIT2 COM0+3, COM1+3, COM2+3, COM3+3, COM2+2, COM0+2, COM1+2, COM3+2
#define DIGIT3 COM0+1, COM1+1, COM2+1, COM3+1, COM2+8, COM0+8, COM1+8, COM3+8
#define DIGIT4 COM0+9, COM1+9, COM2+9, COM3+9, COM2+10, COM0+10, COM1+10, COM3+10
#define DIGIT5 COM0+11, COM1+11, COM2+11, COM3+11, COM2+6, COM0+6, COM1+6, COM3+6
// ComX+Y is combination of Backplan0-3 and Segment0-SegmentXX
////////////////////////////////////////////////////////////////////////////////////////
// character 0 1 2 3 4 5 6 7 8 9 Null
byte const Digit_Map_1[11] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6,0x00};
#define blank 10
/////////////////////////////////////////////////////////////////////////////////////////
// Segments Initilization
// Seg15 Seg14 Seg13 Seg12 Seg11 Seg10 Seg9 Seg8 Seg7 Seg6 Seg5 Seg4 Seg3 Seg2 Seg1 Seg0
// 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1
// if bit_SegX is 1, SegX is set as Segment Output. Otherwise
/////////////////////////////////////////////////////////////////////////////////////////
#define Segments 0x6f4e // Initialize LCD SegmentX
////////////////////////////////////////////////////////////////////////////////////////
void Display()
{
lcd_symbol (Digit_Map_1[count1], DIGIT1); // from left to right
lcd_symbol (Digit_Map_1[count2], DIGIT2); // from left to right
lcd_symbol (Digit_Map_1[count3], DIGIT3); // from left to right
lcd_symbol (Digit_Map_1[count4], DIGIT4); // from left to right
lcd_symbol (Digit_Map_1[count5], DIGIT5); // from left to right
}
///////////////////////////////////////////////////////////////////////////////
void main()
{
set_tris_a (0xff); // avoid floating
set_tris_b (0xff); // avoid floating
set_tris_c (0xff); // avoid floating
set_tris_e (0xff); // avoid floating
output_high(pin_A0); //////////////////////////////////
output_high(pin_A1); //
output_high(pin_A2); //
output_high(pin_A3); //
output_high(pin_A4); //
output_high(pin_A5); //
output_high(pin_A6); //
output_high(pin_A7); //
//
output_high(pin_B1); //
output_high(pin_B2); //
output_high(pin_B3); //
output_high(pin_B4); // set all the ports to high state
output_high(pin_B5); //
output_high(pin_B6); //
output_high(pin_B7); //
//
output_high(pin_C0); //
output_high(pin_C1); //
output_high(pin_C2); //
output_high(pin_C3); //
output_high(pin_C4); //
output_high(pin_C5); //
output_high(pin_C6); //
output_high(pin_C7); //
//
output_high(pin_E3); //////////////////////////////////
setup_counters (T0_EXT_L_TO_H, T0_DIV_1); // // disable timer 0 ??????
setup_timer_1 (T1_DISABLED); // disable timer 1
setup_timer_2 (T2_DISABLED,0,1); // disable timer 2
setup_vref (FALSE); // disable Voltage reference
setup_adc (ADC_OFF); // disable ADC
setup_wdt (WDT_OFF); // disable Watch Dog Timer
setup_ccp1 (CCP_OFF); // disable compare/capture
setup_comparator (NC_NC_NC_NC); // disable comparators
setup_spi(SPI_DISABLED); // disable SPI
#byte VRCON = 0x009D // VR control register
VRCON = 0x00; // VR is disabled
#byte CMCON0 = 0x009C // Comparator configuration register
CMCON0 = 0x0007; // Comparator is disabled
#byte ANSEL = 0x0091 // Analog select register
ANSEL = 0x00; // Digital I/O
#byte ADCON0 = 0x001F // A/D control register
ADCON0 = 0x00; // A/D is shut off
ext_int_edge(L_TO_H); // init interrupt triggering for button press
clear_interrupt(INT_EXT);
disable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
//! setup_lcd(LCD_DISABLED); // once test with LCD disabled
setup_lcd(LCD_MUX14|LCD_INTRC,7, Segments); // once test with LCD enabled
while (TRUE)
{
while (!input (PIN_B0))
{
set_tris_a (0xff); // avoid floating
set_tris_b (0xff); // avoid floating
set_tris_c (0xff); // avoid floating
set_tris_e (0xff); // avoid floating
output_high(pin_A0); //////////////////////////////////
output_high(pin_A1); //
output_high(pin_A4); //
output_high(pin_A5); // set all the un used ports to high state
output_high(pin_A6); //
output_high(pin_A7); //
output_high(pin_E3); //////////////////////////////////
clear_interrupt(INT_EXT);
sleep();
delay_cycles(1);
}
while (input (PIN_B0))
{
count1++;
delay_ms(1000);
}
}
}
|
I got : with LCD disabled the current was 6.2uA
with LCD enabled the current was 11.2uA
Also note I just enabled the LCD and did not display anything yet.
Now I had a look at the 16F913.h file and found that I can use "LCD_BIAS_PINS" in set up the LCD. So using it
Code: |
setup_lcd(LCD_MUX14|LCD_BIAS_PINS|LCD_INTRC,7, Segments);
|
The current dropped to 3.7uA. ( still display nothing)
And when I turn ON all the segments before sleep the current become 4.3uA.
Note: All the current readings above are from the battery. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Fri Sep 23, 2022 7:46 am |
|
|
It is one of the old 'adages' that when you want to reduce the power you
have to turn off everything. The LCD falls into this category...
Controlling the bias to reduce the current does seem to be a very good way
to go. At least you now have a good idea as to what is causing the problem.
Classic 'PCM' sensible solution. |
|
|
|
|
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
|