| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| azykazy 
 
 
 Joined: 05 Oct 2011
 Posts: 11
 Location: South Africa
 
 
			      
 
 | 
			
				| adc help |  
				|  Posted: Thu Nov 03, 2011 7:03 am |   |  
				| 
 |  
				| Hi All, 
 I am trying to measure the voltage across a battery using the adc using a voltage divider network. Pic 18f4550 +Vref is +5v -Vref is ground. My ADC is not working any ideas whats wrong?
 
 
  	  | Code: |  	  | 
 #include<18f4550.h>
 #device adc=10
 #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
 #use delay(clock=4000000)
 
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
 
 void main(void)
 {
 int16 adc_value;
 float32 volts;
 
 setup_adc_ports(ALL_ANALOG);
 setup_adc(ADC_CLOCK_DIV_4);
 set_adc_channel(0);
 delay_us(20);
 
 do{
 read_adc(ADC_START_ONLY);
 adc_value = read_adc(ADC_READ_ONLY);
 volts = (float)(adc_value * 5)/1023.0;
 
 if (volts > 12) output_high(PIN_D0);
 if (volts < 12 && volts > 11){
 output_high(PIN_D1);
 output_low(PIN_D0);
 };
 if(volts < 11)   {
 output_high(PIN_D2);
 output_low(PIN_D1);
 };
 }while(TRUE);
 }
 
 | 
 
 Compiler version is 4.093.
 
 Thanks,
 Azmat
 |  | 
	
		|  | 
	
		| SherpaDoug 
 
 
 Joined: 07 Sep 2003
 Posts: 1640
 Location: Cape Cod Mass USA
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Nov 03, 2011 7:13 am |   |  
				| 
 |  
				| 1) Check the voltage on the A/D pin with a voltmeter to see if it is what you expect. 
 2) Print the A/D counts you get from read_adc() to make sure they are what you expect.
 
 3)  Tell us what results you expect and what results you are getting.  "My ADC is not working" is not very helpful.
 
 4)  I suspect your line:
 volts = (float)(adc_value * 5)/1023.0;
 
 should be:
 volts = ((float)adc_value * 5)/1023.0;
 
 I suspect (adc_value * 5) is overflowing before it gets converted to a float.
 _________________
 The search for better is endless.  Instead simply find very good and get the job done.
 |  | 
	
		|  | 
	
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9588
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Nov 03, 2011 7:15 am |   |  
				| 
 |  
				| several things.... 
 1) the ADC will NOT tolerate +12 volts on it !! In fact the PIC will NOT be happy and you may destroy it.
 You MUST design and install a voltage divider to reduce the +12 to no more than +5 volts.The max the PIC ADC can read is +5,so the divider will allow the PIC to 'think' a +5 reading is your +12, +2.5 will be +6,etc.
 
 When you design the voltage divider, be sure to use the MAXIMUM the battery will be. '12 volt' batteries usually are anywhere from 13.2 to 14.6 depending on the type they are.
 
 2) your equation for calulating the battery voltage will have to be 'tweaked' by the ratio of the voltage divider to all it to display the real voltage.
 
 3) your IF statements will require 12.0 not 12, 11.0 not 11. The compiler may think 12 is an integer not a float.
 |  | 
	
		|  | 
	
		| azykazy 
 
 
 Joined: 05 Oct 2011
 Posts: 11
 Location: South Africa
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Thu Nov 03, 2011 7:49 am |   |  
				| 
 |  
				| I need to measure the battery voltage. 
 I have the appropriate voltage divider network in place and when the battery is at its peak 14V the voltage on adc is +5V.
 
 How do I get a read out on the adc values?
 |  | 
	
		|  | 
	
		| Battery David 
 
 
 Joined: 01 Feb 2010
 Posts: 25
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Nov 03, 2011 8:46 am |   |  
				| 
 |  
				| What resistor values are you using for your voltage divider? If they are too high, the ADC can't read it properly. There are a bunch of posts on that topic you can search for. 
 Something you didn't ask for but I'll volunteer anyway:
 Rather than doing floating point math, figure out what ADC value you would get for the voltages you're interested in. Use those to compare, rather than the floating points. The code savings and speed improvements will be considerable.
 |  | 
	
		|  | 
	
		| sahu77 
 
 
 Joined: 08 Sep 2011
 Posts: 202
 
 
 
			    
 
 | 
			
				| Re: adc help |  
				|  Posted: Thu Nov 03, 2011 10:32 am |   |  
				| 
 |  
				|  	  | azykazy wrote: |  	  | Hi All, 
 I am trying to measure the voltage across a battery using the adc using a voltage divider network. Pic 18f4550 +Vref is +5v -Vref is ground. My ADC is not working any ideas whats wrong?
 
 
  	  | Code: |  	  | 
 #include<18f4550.h>
 #device adc=10
 #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
 #use delay(clock=4000000)
 
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
 
 void main(void)
 {
 int16 adc_value;
 float32 volts;
 
 setup_adc_ports(ALL_ANALOG);
 setup_adc(ADC_CLOCK_DIV_4);
 set_adc_channel(0);
 delay_us(20);
 
 do{
 read_adc(ADC_START_ONLY);
 adc_value = read_adc(ADC_READ_ONLY);
 volts = (float)(adc_value * 5)/1023.0;
 
 if (volts > 12) output_high(PIN_D0);
 if (volts < 12 && volts > 11){
 output_high(PIN_D1);
 output_low(PIN_D0);
 };
 if(volts < 11)   {
 output_high(PIN_D2);
 output_low(PIN_D1);
 };
 }while(TRUE);
 }
 
 | 
 
 Compiler version is 4.093.
 
 Thanks,
 Azmat
 | 
 hi all what say for this
 
  	  | Code: |  	  | int1 done;                      // Put local variable at beginning of code block int x;                        // Number of times to average ADC value
 int32 temp_result;
 
 set_adc_channel(0); // Select AN0
 
 // Average ADC value
 temp_result = 0;
 for (x=1; x<=ADC_AVERAGE_COUNT; x++)
 {
 delay_ms(ADC_DELAY);          //Charge capacitor
 read_adc(ADC_START_ONLY);       //Do A/D conversion
 
 done == adc_done();
 
 while(!done) {
 done = adc_done();
 }
 
 temp_result += read_adc();          // Read A/D register .  Pin A0 in an input
 delay_ms(ADC_2TAD);               // Wait 2 TADs before doing another A/D conversion
 }
 
 ADC_Value = temp_result / ADC_AVERAGE_COUNT;
 
 tlong = (int32)ADC_Value*5000;    //Convert the result in millivolts
 tlong = tlong/1023;              // 0..1023 -> 0-5000mV
 ch = tlong/1000;                      // Extract volts (thousands of millivolts
 volts =ch*fx                       // fx= voltage divider network factor
 | 
 now  Ur requirement code
 
 
  	  | Code: |  	  | if (volts > 12) output_high(PIN_D0); if (volts < 12 && volts > 11){
 output_high(PIN_D1);
 output_low(PIN_D0);
 };
 if(volts < 11)   {
 output_high(PIN_D2);
 output_low(PIN_D1);
 | 
 _________________
 sahu
 |  | 
	
		|  | 
	
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Nov 03, 2011 11:01 am |   |  
				| 
 |  
				|  	  | Quote: |  	  | do{ read_adc(ADC_START_ONLY);
 adc_value = read_adc(ADC_READ_ONLY);
 
 | 
 This is unnecessary.   You can replace it with:
 
  	  | Code: |  	  | adc_value = read_adc();
 
 | 
 
 
 
  	  | Quote: |  	  | volts = (float)(adc_value * 5)/1023.0; 
 | 
 read_adc() will produce values from 0 to 1023.
 Therefore, the maximum value the equation above will produce is 5.0 volts.
 
 
 
  	  | Quote: |  	  | if (volts > 12) output_high(PIN_D0); if (volts < 12 && volts > 11){
 
 | 
 Here you are comparing volts, which can be 5.0 max, to 12.
 This code will never set Pin D0 to a high level.
 |  | 
	
		|  | 
	
		| azykazy 
 
 
 Joined: 05 Oct 2011
 Posts: 11
 Location: South Africa
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Fri Nov 04, 2011 2:22 am |   |  
				| 
 |  
				| Thanks for the advice people. 
 PCM thanks for pointing that volts error out to me. Brilliant!
 
 I am using the corresponding adc values to compare so the pic doesnt have to do unnecessary math calculations.
 
 Thanks for the help guys much appreciated!
     
 Azmat
 |  | 
	
		|  | 
	
		|  |