![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
berlin vince joe V S
Joined: 26 Jun 2015 Posts: 16
|
i need to convert adc output to corresponding voltage |
Posted: Fri Jun 26, 2015 12:54 am |
|
|
Code: |
#include <16F676.H>
#device adc=10
#fuses INTRC_IO, NOWDT, NOPROTECT, BROWNOUT, PUT
#use delay(clock = 4000000)
void main()
{
//int x;
float c,x;
while(1)
{
setup_adc_ports(sAN3);
set_adc_channel(3);
setup_adc(ADC_CLOCK_INTERNAL);
c=read_adc();
delay_ms(1000);
x=(5*c)/1023;//the loop work according to this value
delay_ms(100);
if(x>4.00)
{
output_high(pin_c4);
delay_ms(1);
output_low(pin_c5);
delay_ms(1);
}
if(x<3.00)
{
output_high(pin_c5);
delay_ms(1000);
output_low(pin_c4);
delay_ms(1000);
}
}
}
|
please help me to solve it i am using ccs compiler _________________ Thanks |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Fri Jun 26, 2015 1:40 am |
|
|
First:
setup_adc(ADC_CLOCK_INTERNAL);
Look at the chip's data sheet. Is this recommended at your clock rate?. Look at the note under the table "Tad vs. DEVICE OPERATING FREQUENCIES".
Then, _why_.
While it sounds nice to be working with 'volts', it is the sign of idiocy when it comes to a microprocessor.
Chips like the PIC, take an _age_ to do float arithmetic, and the code is bulky. There is rarely any good reason to actually use floating point numbers for something like this. Especially since your accuracy (using the supply as the reference), is unlikely to be better than quite a few mV. Why waste code space, and processor time doing maths that is beyond the accuracy of the hardware?.
Then find out why /1023, is not the right conversion. The chip manufacturers _deliberately_ design the conversion ramp of the ADC, to reduce the maths involved in the conversion. Take advantage of their work.
Remember AN3 is port A4.
Then, you don't actually tell us what is not working in your code?.
Though it won't work 'well', or 'efficiently', it will sort of work.
Code: |
#include <16F676.H>
#device adc=10
#fuses INTRC_IO, NOWDT, NOPROTECT, BROWNOUT, PUT
#use delay(clock = 4000000)
#define FLOAT_TO_ADC(x) (int16)((x*204.8)+0.5)
void main()
{
int16 adc_count;
setup_adc_ports(sAN3, VSS_VDD);
set_adc_channel(3);
setup_adc(ADC_CLOCK_DIV_8);
//setup only wants to be done _once_
while(TRUE)
{
delay_ms(1000);
//you _must_ delay before taking an ADC reading.
//since you have this long delay in your loop, use it for the required
//delay.
adc_count=read_adc();
if(adc_count>FLOAT_TO_ADC(4.0))
{
output_high(pin_c4);
delay_ms(1);
output_low(pin_c5);
delay_ms(1);
}
if(adc_count<FLOAT_TO_ADC(3.0))
{
output_high(pin_c5);
delay_ms(1000);
output_low(pin_c4);
delay_ms(1000);
}
}
}
|
Now, this does it a completely different way. Though there appears to be 'float' maths still in the define 'FLOAT_TO_ADC', _this is done at compile time by the PC_. So it takes the number '4.0', and converts this into the value expected from the ADC, when the code is compiled. This way the PIC doesn't actually have to do anything. So for '4', the integer '819' is substituted at compile time, and the test just becomes adc_count>819. Even if done at 'run' time with a variable, this is much more efficient. A float multiply, takes less than half the time of a division. Similarly the actual _comparison_ is done using an integer value rather than a float (about 30* faster...). The code size also plummets (drops from 60% code size, to 12%....).
What the code does though seems fairly pointless. If the voltage is greater than 4v, C4 goes high, then C5 goes low 1mSec later. This repeats every 1.002 seconds (though since the pins are left high/low, you will never see this). If the voltage is below 3v, C5 goes high, and then C4 goes low 1 second later. This repeats every 3 seconds (same comment applies though that you won't see any further changes). If you want to see something happen, you need to turn the pins off after the function.... |
|
![](templates/subSilver/images/spacer.gif) |
berlin vince joe V S
Joined: 26 Jun 2015 Posts: 16
|
|
Posted: Fri Jun 26, 2015 2:53 am |
|
|
actually i was tried to monitor the battery level using pic16f676 and i set the upper cut as 4v and lower cut as 3v
and tried to calculate analogue voltage on that pin using this formula
(Resolution of ADC * System Voltage)/(ADC Reading/Analogue Voltage Measured)
once again thanks for your advice..... ![Cool](images/smiles/icon_cool.gif) _________________ Thanks |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Fri Jun 26, 2015 4:48 am |
|
|
OK.
As a bit of 'explanation'. The first part comes as the old 'fence posts versus fence panels' thing. So historically when the first ADC's came out, a 10bit ADC, gave 1024 'levels', but 1023 'risers', and the calculation would be /1023. Then something like 30 years ago, Texas were doing a chip and trying to reduce the work needed on a very early processor. So they deliberately adjusted the way their ADC worked, so it behaved as if it had one more count than it actually 'had', and reached the top count a little below the reference. result they could use /256 (it was an 8bit ADC). It behaved as if it actually counted to 256, but just got to 255 and stopped.
The PIC ADC's generically do this. So the ADC on your PIC behaves as if it actually counted to 1024, but just gets to 1023, 1.5 counts 'below' the reference, voltage and stops. Microchip publish transfer diagrams for their various ADC's that show this. A few of the earliest PIC ADC's, don't do this, but they are 'exotica', like some of the early PIC14's.
On the maths, on your PIC, just the code to perform the float division, used about 40% of the ROM of the chip. One of the key things is to 'think integer', and look at things like (for instance) using an integer 'mV' value, rather than working in float 'volts'. Floats though they 'sound nice', bring lower accuracy (a 4byte FP number, has a 'precision' only equivalent to a 23.5bit integer, yet take at least twice as long to handle as a 32bit integer..). The 'point' about floats is they bring a huge range of values, which can be useful when dealing with things that may cover such a range, but something like volts, from 0 to 5, doesn't have such a range. 'Think integer', should be a motto for people working on embedded systems. ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9170 Location: Greensville,Ontario
|
|
Posted: Fri Jun 26, 2015 5:07 am |
|
|
As Mr T points out floating point is not fast in a PIC!
Here's another way to think about it.
5V = ADC max of 1024 bits. This assumes you have a 1% voltage divider on the battery to PIC ADC input pin.
4v = +- 800 bits (4/5*1000) rough math....it's early here !
3V - +- 600 bits
So you can define a variable as 'battery_4V_level' 800, and one as 'battery_3V_level' 600.
Then it's very fast and easy for the PIC to compare.
You will of course need to use DVM to get a closer value for # of bits=4.00 volts but 800 seems reasonable to me, at least for a starting point.
Jay |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|