|
|
View previous topic :: View next topic |
Author |
Message |
qoou
Joined: 28 Sep 2016 Posts: 14
|
Using a FVR for the ADC (pic16f1784) |
Posted: Wed Sep 28, 2016 10:13 pm |
|
|
PIC16F1784
I'm using an ADC to read temperature, and display it on an LCD.
Code: | setup_adc_ports(sAN7);
setup_adc(ADC_OFF);
..
..
setup_adc(ADC_CLOCK_INTERNAL); // Turn on ADC only when a reading takes place
set_adc_channel(7);
delay_us(20);
CTemp=((65520-read_adc())*0.1193)- 4024 + CalFactor; //Formula based on sensor's curve
setup_adc(ADC_OFF); |
The above code worked just fine, and outputs a temperature reading ("CTemp") dead on what I expected. However, I'm running off battery which voltage drops slowly over time, and it was affecting the reading. So I wanted to use the fixed voltage reference. I changed to below.
Code: | setup_vref(VREF_ON|VREF_ADC_2v048); // Setup FVR
setup_adc_ports(sAN7|VSS_FVR); // Note: I also tried (sAN7,VSS_FVR)
setup_adc(ADC_OFF);
..
..
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(7);
delay_us(20);
CTemp=((65520-read_adc())*0.1193)- 4024 + CalFactor;
setup_adc(ADC_OFF); |
My original battery voltage is around 4.6V. Changing the adc reference to the fvr, I expected my temperature reading to change drastically. It did not, it reads exactly the same as before.
Am I missing something and/or doing something stupid here? I feel like the ADC is still using Vss-Vdd as the reference.
Many thanks for any suggestions! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 28, 2016 10:37 pm |
|
|
Quote: | setup_adc_ports(sAN7|VSS_FVR); // Note: I also tried (sAN7,VSS_FVR) |
It absolutely must be as shown below, for it to work:
Code: | setup_adc_ports(sAN7, VSS_FVR); |
Also, this is how the 16F1784.h file says to do it.
Quote: | setup_adc(ADC_CLOCK_INTERNAL); |
What's the oscillator frequency of your PIC ? |
|
|
qoou
Joined: 28 Sep 2016 Posts: 14
|
|
Posted: Thu Sep 29, 2016 7:10 am |
|
|
PCM programmer wrote: | Quote: | setup_adc_ports(sAN7|VSS_FVR); // Note: I also tried (sAN7,VSS_FVR) |
It absolutely must be as shown below, for it to work:
Code: | setup_adc_ports(sAN7, VSS_FVR); |
Also, this is how the 16F1784.h file says to do it. |
I had seen suggestions here to try OR'ing them. Looking at the bits used, it seemed plausible.
https://www.ccsinfo.com/forum/viewtopic.php?t=50949
PCM programmer wrote: | Quote: | setup_adc(ADC_CLOCK_INTERNAL); |
What's the oscillator frequency of your PIC ? |
31 kHz Internal |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9250 Location: Greensville,Ontario
|
|
Posted: Thu Sep 29, 2016 8:50 am |
|
|
I have to ask WHY are you tunning the PIC so sloooooooooooow ??
All operations, especially the floating point math will take forever..
Not seeing what else you do in the program but over the past 2 decades I've always run the PIC fast to save energy while on batteries...
Jay |
|
|
qoou
Joined: 28 Sep 2016 Posts: 14
|
|
Posted: Thu Sep 29, 2016 9:09 am |
|
|
temtronic wrote: | I have to ask WHY are you tunning the PIC so sloooooooooooow ??
All operations, especially the floating point math will take forever..
Not seeing what else you do in the program but over the past 2 decades I've always run the PIC fast to save energy while on batteries...
Jay |
Saving energy on batteries was exactly the reason for using the low frequency clock. I would love to run a higher clock if possible.
This PIC has 3 internal oscillators: 16 MHz, 500 kHz, 31 kHz
I never tried the 500 kHz clock, but idle current draw at the others is:
@ 31 kHz = 24 uA
@ 16 MHz = 1,700 uA
This follows pretty closely to what's expected per the datasheet..
edit: Checking the datasheet, I would expect somewhere around 60uA for the 500 kHz internal. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9250 Location: Greensville,Ontario
|
|
Posted: Thu Sep 29, 2016 10:34 am |
|
|
You might want to 'do the math' or actual board level testing of slow clock speed vs fast clock speed with sleep mode.
While the faster clock ( 500* faster) does consume more current, since operation are faster, it spends less time doing them, so you could put the PIC to sleep. Depending on your code and application it could save you battery energy.
Microchip has an application note about this, probably 30 years old now but still applicable today. If I recall it's a PIC, an ADC measurement and sending data to PC as well as various batteries and energy used vs. PIC modes.
My well data loggers did this, fast clock + sleep, and power was saved.
Jay |
|
|
qoou
Joined: 28 Sep 2016 Posts: 14
|
|
Posted: Thu Sep 29, 2016 12:18 pm |
|
|
temtronic wrote: | You might want to 'do the math' or actual board level testing of slow clock speed vs fast clock speed with sleep mode.
While the faster clock ( 500* faster) does consume more current, since operation are faster, it spends less time doing them, so you could put the PIC to sleep. Depending on your code and application it could save you battery energy.
Microchip has an application note about this, probably 30 years old now but still applicable today. If I recall it's a PIC, an ADC measurement and sending data to PC as well as various batteries and energy used vs. PIC modes.
My well data loggers did this, fast clock + sleep, and power was saved.
Jay |
Keep in mind this PIC does not have an LCD driver allowed in sleep mode.
I assumed turning sleep mode on/off every 10ms wouldn't be practical. You're suggesting it would still be more power efficient to do that than run continuously at 32k?
Also, are you thinking that operating at 32 kHz is causing problems with setting the ADC reference voltage? |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Thu Sep 29, 2016 2:28 pm |
|
|
Quote: | This PIC has 3 internal oscillators: 16 MHz, 500 kHz, 31 kHz |
Take a look at page 68 in the datasheet - there are many frequency options in between. These are only actual oscillators.
My own experience is that the speed/current trade off usually ends up around 1MHz but this is not scientific advice and I also don't like things happening too sloooooooow as Temtronic said.
As for the FVR mystery please write the compiler version you're using and either check yourself or upload and we'll check the register contents. Most chances that for some reason the registers are not being setup correctly. |
|
|
qoou
Joined: 28 Sep 2016 Posts: 14
|
|
Posted: Thu Sep 29, 2016 10:43 pm |
|
|
guy wrote: | Quote: | This PIC has 3 internal oscillators: 16 MHz, 500 kHz, 31 kHz |
Take a look at page 68 in the datasheet - there are many frequency options in between. These are only actual oscillators. |
Ah, didn't see that. Thanks.
guy wrote: | As for the FVR mystery please write the compiler version you're using and either check yourself or upload and we'll check the register contents. Most chances that for some reason the registers are not being setup correctly. |
Version is 5.009
Need some more details/help on how to look at register contents.. Do I need a debugger for this? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Fri Sep 30, 2016 12:47 am |
|
|
guy wrote: | Quote: | This PIC has 3 internal oscillators: 16 MHz, 500 kHz, 31 kHz |
Take a look at page 68 in the datasheet - there are many frequency options in between. These are only actual oscillators.
My own experience is that the speed/current trade off usually ends up around 1MHz but this is not scientific advice and I also don't like things happening too sloooooooow as Temtronic said.
As for the FVR mystery please write the compiler version you're using and either check yourself or upload and we'll check the register contents. Most chances that for some reason the registers are not being setup correctly. |
Guy is spot on here.
As you change speeds, the CPU power consumption changes, but the peripheral consumption remains the same.
Now when you talk about 'displaying the data on an LCD'. What sort of LCD?. If this is an external LCD module, then you can put the PIC to sleep, and the LCD will keep displaying. Your chip doesn't have a direct LCD drive. So, imagine you are doing a job with 100000 instructions to be done (typical for anything involving FP maths). With the CPU at 32KHz, this takes over 3 seconds to do. For the whole of that three seconds, the peripherals, and CPU have to be on. Now switch to 1MHz, and the same operation takes just 1/10th second. Power consumption at 1MHz, will typically be perhaps 250uA with the ADC on, while at 32K, possibly around 50uA. However the chip only has to be 'on', for 1/30th the time. Result less total power drawn from the battery....
On most chips, the most efficient speed is around 1Mhz.
Now that having been said, your original problem is probably compiler version. 5.009, was a very early V5 compiler, and I'd say a 'beta' at best.
Can confirm it does not configure the ADC for Vref:
Code: |
#byte ADCON0=getenv("SFR:ADCON0")
#byte ANSEL0=getenv("SFR:ANSEL0")
setup_vref(VREF_ON|VREF_ADC_2v048); // Setup FVR
setup_adc_ports(sAN7, VSS_FVR); // Note: I also tried (sAN7,VSS_FVR)
ANSEL0=0;
bit_set(ADCON0,0);
bit_set(ADCON0,1);
|
This sets the bits to enable the internal Vref (and fixes one other register it is setting incorrectly). |
|
|
qoou
Joined: 28 Sep 2016 Posts: 14
|
|
Posted: Fri Sep 30, 2016 7:42 am |
|
|
Ttelmah wrote: | Guy is spot on here.
As you change speeds, the CPU power consumption changes, but the peripheral consumption remains the same.
Now when you talk about 'displaying the data on an LCD'. What sort of LCD?. If this is an external LCD module, then you can put the PIC to sleep, and the LCD will keep displaying. Your chip doesn't have a direct LCD drive. So, imagine you are doing a job with 100000 instructions to be done (typical for anything involving FP maths). With the CPU at 32KHz, this takes over 3 seconds to do. For the whole of that three seconds, the peripherals, and CPU have to be on. Now switch to 1MHz, and the same operation takes just 1/10th second. Power consumption at 1MHz, will typically be perhaps 250uA with the ADC on, while at 32K, possibly around 50uA. However the chip only has to be 'on', for 1/30th the time. Result less total power drawn from the battery....
On most chips, the most efficient speed is around 1Mhz. |
It's just a static LCD. I'm driving it using 24 I/O pins from the PIC.
I haven't done much with sleep modes before. My question earlier was... is it viable to turn sleep mode on for small increments between LCD toggles, about 10ms intervals? It doesn't seem like a great idea to me, but I don't know much about how fast it can sleep/wake up etc.
The entirety of this project is the temperature sensor, LCD, and 2 buttons. View high/low recorded temperature, and press both to enable a calibration mode. The temperature is refreshing about once every 2 seconds.
So far I've been able to run all of this with no noticeable delays at 32khz. Even the button presses react pretty much instantly as far as a human is concerned, so I'm not too worried about the clock speed. The consumption right now puts the battery life around 1.5 years under continuous operation.
You did mention "around 50uA" with the ADC on. Right now I'm seeing 24uA with ADC off, and around 350uA with it on. Is something else wrong here?
Ttelmah wrote: | Now that having been said, your original problem is probably compiler version. 5.009, was a very early V5 compiler, and I'd say a 'beta' at best.
Can confirm it does not configure the ADC for Vref:
Code: |
#byte ADCON0=getenv("SFR:ADCON0")
#byte ANSEL0=getenv("SFR:ANSEL0")
setup_vref(VREF_ON|VREF_ADC_2v048); // Setup FVR
setup_adc_ports(sAN7, VSS_FVR); // Note: I also tried (sAN7,VSS_FVR)
ANSEL0=0;
bit_set(ADCON0,0);
bit_set(ADCON0,1);
|
This sets the bits to enable the internal Vref (and fixes one other register it is setting incorrectly). |
Thanks! I'll give this a try later tonight. ..and I'll look into updating my compiler. |
|
|
qoou
Joined: 28 Sep 2016 Posts: 14
|
|
Posted: Mon Oct 03, 2016 12:45 pm |
|
|
Ttelmah wrote: | Can confirm it does not configure the ADC for Vref:
Code: |
#byte ADCON0=getenv("SFR:ADCON0")
#byte ANSEL0=getenv("SFR:ANSEL0")
setup_vref(VREF_ON|VREF_ADC_2v048); // Setup FVR
setup_adc_ports(sAN7, VSS_FVR); // Note: I also tried (sAN7,VSS_FVR)
ANSEL0=0;
bit_set(ADCON0,0);
bit_set(ADCON0,1);
|
This sets the bits to enable the internal Vref (and fixes one other register it is setting incorrectly). |
When trying to use ANSEL0, I get an error saying it's not a valid name.
Looking through the datasheet, the only things I found were the analog register selects for different ports, ANSELA, ANSELB, etc. For each of these, set to 0 for a digital input, or 1 for analog input. Unfortunately, I couldn't figure out what you were having me do with the "ANSEL0=0" line. Would you mind explaining a bit more?
Thanks again to all of you for taking your time to help me out.
Side note; in the datasheet there's sections for analog config ports A, B, and D. I can understand not having a section for C since there's no analog input ports there, but why isn't there a section for E? I happen to be using E2 (ch7). Using "ANSELE" in the compiler doesn't throw any errors, so it seems to recognize that it's valid... just a typo on datasheet? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Tue Oct 04, 2016 1:52 am |
|
|
You are typing something wrong.
I tested the code as posted on your compiler version:
Code: |
#include <16F1784.h>
#device ADC=12
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(internal=1000000)
#byte ADCON0=getenv("SFR:ADCON0")
#byte ANSELD=getenv("SFR:ANSELD")
void main()
{
setup_vref(VREF_ON|VREF_ADC_2v048); // Setup FVR
setup_adc_ports(sAN7, VSS_FVR);
setup_adc(ADC_CLOCK_DIV_2);
ANSELD=0;
bit_set(ADCON0,0);
bit_set(ADCON0,1);
while(TRUE)
{
//User Code
}
}
|
Remember '0', not 'O'.
If you look at the data sheet again, after the stuff for port's A, B & C, there is a separate section for the port D and port E registers with the comment "PIC 16(L)F1784/7 only". Has ANSELD and E.
The compiler does handle most of this for you. However with your rather early compiler it is possible that there are faults here. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9250 Location: Greensville,Ontario
|
|
Posted: Tue Oct 04, 2016 4:54 am |
|
|
just a couple of comments...
1) NEVER assume the 'default' settings for fuses is correct for your projects ! Someone at Microchip designed the hardware withe THEIR idea of default settings AND someone else at CCS decided on THEIR defaults. This isn't so much a problem with small PICs but the newer, bigger ones with more fuses than instructions it IS a huge problem. I now have an 'include' file for just fuses, a WORKING set, of every fuse (one per line) to ensure the PIC runs first time, every time. It also 'cleans up' the main program...one line not 30-40 lines for fuses AND not one mistyped entry.
2) consider a bigger battery for the power source. Doubling the battery physical size can get 4-10X the capacity and not cost a lot. Also the larger battery will be more stable over time (same output voltage). While the 'mantra' these days is 'smaller is better', I'm old school and like BIG batteries that WILL last a very. Very long time.
3) A 'static' LCD (direct drive, 8 pins per dgt) should NOT consume any real power while the PIC is asleep. It's the transitions (1>0, 0>1) that need energy. A PIC in sleep will 'keep' the last LCD reading on the LCD. Might be worth an hour's bench time to observe this...
just points to ponder.
Jay |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Tue Oct 04, 2016 10:05 am |
|
|
temtronic wrote: | A 'static' LCD (direct drive,8 pins per dgt) should NOT consume any real power while the PIC is asleep. |
The LCD itself might consume very little power, but maintaining a visible display requires AC drive signals - the driver chip, or the LCD drive peripheral of suitably equipped PICs needs to be continually clocked to keep the display "alive". DC driven LCDs, i.e. as if they were LEDs, don't work, and are very quickly damaged. CMOS takes power during transitions, and LCDs are capactive, that means LCD drivers draw low but non-negligable power all the time; I'd expect pretty much the same power regardless of whether the display is changing or not.
Sleeping the PIC inbetween LCD toggles sounds like a good idea, but I doubt you'd be able to sync to the LCD signal. I too feel "go faster, in shorter bursts" is the way to go. One project I did a lot of work on with power saving was a hand-held instrument with a Li-on polymer battery. It was ARM based, not PIC. It worked in bursts, triggered by data being available from a sensor. It had a relective segmented LCD display. The hardware gave me a choice of three viable clock speeds: 20, 40 and 60MHz. I found I could sleep between data bursts, and testing showed that 40MHz gave the best compromise and lowest overall power consumed. This, and other changes, mainly to a (relatively) high voltage bias generator, improved the battery life from about seven hours - less than a typical working shift, and hence no use at all, to a little over twenty-four, with no loss of performance or functionality.
Of course, by far the biggest eater of power in most LCDs is the back lighting. This can be turned off or dimmed, leaving the display itself alive, drawing much less than with the light full-on. Of course, reflective LCDs don't have a back-light, but these tend to be the very much older segmented types, though this seems to be the type being discussed here.
Pretty much all matrix type LCDs, whether colour or mono, have back lights and thus draw a lot of power, relatively speaking, in operation, even when the display is "black". OLED displays, on the other hand, draw power in proportion to the number and brightness of the active pixels.
My recommendation would also be to use a bigger battery if possible! In the case of my hand-held instrument, it simply wasn't possible as the casing had been effectively designed around the battery. |
|
|
|
|
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
|