CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

i need to convert adc output to corresponding voltage

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
berlin vince joe V S



Joined: 26 Jun 2015
Posts: 16

View user's profile Send private message

i need to convert adc output to corresponding voltage
PostPosted: Fri Jun 26, 2015 12:54 am     Reply with quote

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
Ttelmah



Joined: 11 Mar 2010
Posts: 19327

View user's profile Send private message

PostPosted: Fri Jun 26, 2015 1:40 am     Reply with quote

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....
berlin vince joe V S



Joined: 26 Jun 2015
Posts: 16

View user's profile Send private message

PostPosted: Fri Jun 26, 2015 2:53 am     Reply with quote

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
_________________
Thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19327

View user's profile Send private message

PostPosted: Fri Jun 26, 2015 4:48 am     Reply with quote

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
temtronic



Joined: 01 Jul 2010
Posts: 9161
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jun 26, 2015 5:07 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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