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 CCS Technical Support

PWM control with input from ADC

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
adhemp



Joined: 05 Apr 2007
Posts: 3

View user's profile Send private message

PWM control with input from ADC
PostPosted: Thu Apr 05, 2007 6:06 pm     Reply with quote

Hey guys, I'm currently working on temperature sensing project where I would like to alter the duty cycle coming from my PIC (16F877) based on the temperature read from a thermistor. I have the thermistor as one leg of a voltage divider circuit who's voltage output is sent to an op-amp for buffering, then to the ADC of the PIC.

I'm not sure if I'm missing something simple in my ADC code or what, but if you could take a look and offer any suggestions then I'd be most appreciative...thanks!



Code:

#include <16F877.h>
#device adc=10
#fuses HS,NOWDT,NOPROTECT,NOLVP,BROWNOUT, PUT
#use delay(clock=4000000)      //4MHz

void init_ADC(void);

void main() {
   int16  value, voltage;         //8bit value for ADC reading
   
   set_tris_a(0b11111111);      //designate port A for thermistors as all  inputs from thermistors
   init_ADC();

  while(TRUE)
  {
      delay_ms(10);                         
      output_low(PIN_C2);                  // Set CCP1 output low
      setup_ccp1(CCP_PWM);              // Configure CCP1 as a PWM
      setup_timer_2(T2_DIV_BY_16, 156, 1); // 400 Hz

        value = read_ADC();               //read in voltage from thermistor
   voltage=1024/value;

      if (voltage>3)                          //switching voltage in voltage divider circuit
         set_pwm1_duty(117);            // 75% duty cycle on pin C2
      if (voltage<3)               
         set_pwm1_duty(78);            // 50% duty cycle on pin C2
   } 


void init_ADC(void)
{
  setup_adc_ports( A_ANALOG );      //A0 A1 A2 Ref=Vdd
  setup_adc( ADC_CLOCK_INTERNAL ); 
  set_adc_channel( 0 );            //Sets A_to_D input to channel 0 (Pin 2 on PIC)
  delay_us(10);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 05, 2007 11:26 pm     Reply with quote

Here is a link to a demo program that shows how to read the A/D
and display the result as a voltage.
http://www.ccsinfo.com/forum/viewtopic.php?t=28842&start=7
That program isn't 100% applicable to your problem, but it might help.

Here's a better idea. You're running the A/D in 10-bit mode, and
presumably your board is running at +5v. So the A/D value read
for a +5v input will be 1023. For a 0 volt input, it will be 0.
For 3 volts, it will be (3/5) * 1023 = approximately 614.

You don't need to convert the raw A/D value to a single digit "volts"
value. You already know that if you read 614, it's at 3.0 volts.
So you can define a constant that represents the 3v level. Then use
that constant in your code:
Code:
#define ADC_3_VOLTS  614

Code:

value = read_adc();

if(value > ADC_3_VOLTS)
  {
    // Do something.
  }


Also, you need to look a bit more closely at your logic in the code
that sets the PWM duty cycle. What if the voltage is exactly 3 volts ?
Your code doesn't handle that state.

What if the voltage changes slightly every few milliseconds, due to
noise ? What if one moment it's 2.95 volts, and then it's 3.01 volts, etc.
Your program would constantly do fairly large changes in duty cycle.
You need to look into the concept of "hysteresis".

Lastly, do you really need 10 bits of resolution ? It's possible that the
bottom one or two bits might be noise, anyway. It might be better to
use the A/D in 8-bit mode and just read a value from 0 to 255 from it.
I don't know your requirements, so that's just a suggestion.
adhemp



Joined: 05 Apr 2007
Posts: 3

View user's profile Send private message

PostPosted: Fri Apr 06, 2007 3:35 pm     Reply with quote

Thanks for your help...I'm now able to switch between duty cycles based on changing voltage in the divider network. I ran into another problem today that I couldn't quite understand. The input into the ADC on the PIC is initially ~3.8 V, measured with an oscilloscope.

If I run the following code:

Code:

if (voltage>=ADC_4_VOLTS)            //switching voltage in voltage divider circuit
         set_pwm1_duty(117);            // 75% duty cycle on pin C2
if (voltage<ADC_4_VOLTS  && voltage>=ADC_3_VOLTS)               
         set_pwm1_duty(78);            // 50% duty cycle on pin C2
 if (voltage<ADC_3_VOLTS)               
         set_pwm1_duty(20);            // 15% duty cycle on pin C2



then I would expect to have a duty cycle of 50% shown initially. However, the duty cycle begins at 75% and then switches to 50% at approximately 3.4 V. Oddly, the transition between the 50 and 15% duty cycles occurs at 3 V, as expected.

Do you know why this initial duty cycle would be off but the second transition at 3 V would not be?

Thanks!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 06, 2007 4:25 pm     Reply with quote

1. Post the #define statements for those constants.

2. Verify that the oscilloscope is calibrated properly by checking the
A/D input voltage with a voltmeter (assuming it's a DC voltage).

3. Measure the Vdd voltage for your PIC with a voltmeter. Is it 5.0v ?
adhemp



Joined: 05 Apr 2007
Posts: 3

View user's profile Send private message

PostPosted: Sat Apr 07, 2007 3:23 pm     Reply with quote

Figured it out...silly mistake on my part in how I defined my constants. Thanks for your help.
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