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

ADC and PWM Problem
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

ADC and PWM Problem
PostPosted: Wed Jun 23, 2010 2:57 am     Reply with quote

Guys im new at ccs. I downloaded the demo version of ccs which is on the official website. Version is 4.102. I was using some other compiler but i had to change my compiler for this project.

I need to use ADC and PWM in my code. I work at 4Mhz with 16F877A. I use AN0 as analog input just to read voltage value by the help of the potentiometer. Voltage can vary between 0-5V. What i want to do is, get that ADC value (8bit ADC) and use it (8 bit) PWM channel. By looking at the position of a switch i need to give PWM signal to the chosen led.

On the pcb i can read only a few voltage values at AN0 pin. For example i keep turning potentiometer but it jumps from 500mV to 5V. Why is this happening? Can you please tell me how adc settings are done ?

I use those setting lines:
Code:

   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_DIV_32);
   //setup_adc ( ADC_CLOCK_INTERNAL );
   set_adc_channel(0);

....
//and the code is simply like that

do{

value = read_adc() ;  //this variable is defined like this-> long value;
....

if (condition1 occurs){
               setup_ccp1(CCP_PWM);
               set_pwm1_duty(led_res);
               Delay_ms(100);
}
if (condition2 occurs){
               setup_ccp2(CCP_PWM);
               set_pwm2_duty(led_res);
               Delay_ms(100);
}
}while(1);
Ttelmah



Joined: 11 Mar 2010
Posts: 19383

View user's profile Send private message

PostPosted: Wed Jun 23, 2010 3:43 am     Reply with quote

You leave out some bits 'needed' to see what may be happening. Timer2 setup, is 'critical', since this sets the available resolution on the PWM.
Do you have a #device ADC= line?. (You don't need it, since it'll default to 8bit, but if there is one present, it'll affect things).
You do realise that the loop speed will change radically when conditions are 'met'. This will make the response somewhat erratic.
ADC_CLOCK_DIV_32, is unnecessarily 'slow' for 4MHz operation. Recommended value is /8. This will degrade the ADC accuracy, and make the conversion take longer than it should.

Best Wishes
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Wed Jun 23, 2010 4:10 am     Reply with quote

Here u can see timer settings. I dont use timer0 so i made command line.

Code:
void main()
{

   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_DIV_8);  // Here u can see -> i made it 8us
   //setup_adc ( ADC_CLOCK_INTERNAL );
   set_adc_channel(0);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   //setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_16,124,1);
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   set_pwm1_duty(0);
   set_pwm2_duty(0);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   // TODO: USER CODE!!
   
   output_a(0x00);   
   output_b(0x00);
   output_c(0x00);
   output_d(0x00);
   output_e(0x00);
   


Also about 8 bit ADC, programme created header file itself. Here is the content of file :

#include <16F877A.h>
#device adc=8

#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES RESERVED //Used to set the reserved FUSE bits

#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
Ttelmah



Joined: 11 Mar 2010
Posts: 19383

View user's profile Send private message

PostPosted: Wed Jun 23, 2010 5:24 am     Reply with quote

OK.
Now first thing, you talk about a PWM resolution of '8bits'. This is not what you have.
The PWM, has a range from 0 to ((Timer2_max+1)*4)-1 counts. So with 124 in the timer2 setup, 0 to 499. Not '8 bits'.
To get an 8bit Timer2 resolution, needs 63 in the second value of the timer2 setup.
You don't need to reselect the CCP as PWM, when you change the duty. Once setup, it stays setup.
What you describe should work with:
Code:

do{

value = read_adc() ;  //this variable is defined like this-> long value;
....

if (switch1){
               set_pwm1_duty(value);
}
else {
               set_pwm2_duty(value);
}
delay_ms(100);
}while(1);


Best Wishes
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Wed Jun 23, 2010 6:44 am     Reply with quote

Ok. I wrote 63 instead of 124. But i think that my problem is in adc. I created a new project and tried only adc.

Code:

  #include <ctype.h>
  #include <float.h>
  #include <stddef.h>
  #include <stdlib.h>
 
  int value=0;
  unsigned led_res=0;

void main()
{
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_DIV_8);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   // TODO: USER CODE!!
   output_a(0x00);   
   output_b(0x00);
   output_c(0x00);
   output_d(0x00);
   output_e(0x00);

do {   
       checkpoint:
       value = adc_done();
       if (value==1) {
       delay_us(10);
       led_res = read_adc();
       output_D(led_res);
       }
       else goto checkpoint; 
   }while(1);

}


Here is the header file content :

Code:
#include <16F877A.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES RESERVED                 //Used to set the reserved FUSE bits

#use delay(clock=4000000)




Here u can download isis file and see potentiometer problem:

http://www.2shared.com/file/i_0ZknVs/adc_design.html
http://rapidshare.com/files/401986155/adc_design.rar.html
Ttelmah



Joined: 11 Mar 2010
Posts: 19383

View user's profile Send private message

PostPosted: Wed Jun 23, 2010 7:17 am     Reply with quote

You originally said you had 'value' declared as long. You now have it declared as an int. This changes _everything_ change it to long. The PWM function _changes the way it works according to the type of the number used_.
Don't test adc_done. Not wanted/needed. You don't even trigger the conversion till you call read_adc....
Leave the delay in the loop. The ADC needs time to charge between samples.

Best Wishes
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Wed Jun 23, 2010 7:31 am     Reply with quote

Also can u plz tell me how can i see adcon1 register bits in ccs ?
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Wed Jun 23, 2010 7:46 am     Reply with quote

I'm sorry i was trying those and i forgot them before copying. I have changed the code as u told me. Here is the new one :

Code:
  #include <ctype.h>
  #include <float.h>
  #include <stddef.h>
  #include <stdlib.h>
 
  int value=0;
  long led_res=0;

void main()
{
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_DIV_8);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   // TODO: USER CODE!!
   output_a(0x00);   
   output_b(0x00);
   output_c(0x00);
   output_d(0x00);
   output_e(0x00);

do {   
       //checkpoint:
       //value = adc_done();
       //if (value==1) {
       delay_us(10);
       led_res = read_adc();
       output_D(led_res);
       //}
       delay_ms(100);
       //else goto checkpoint; 
   }while(1);
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Wed Jun 23, 2010 8:20 am     Reply with quote

I realize that my potentiometer is the problem. When i apply any voltage level to AN0 pin without potentiometer, there is no problem with adc. But with pot, it doesnt apply linear voltage level and adc is converting applied voltage level correctly. Why does it happening? It does the same thing in pcb too
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 23, 2010 10:16 am     Reply with quote

What is the resistance value of your trimpot in ohms ?
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Wed Jun 23, 2010 1:56 pm     Reply with quote

I am using 1k but I saw the same problem at 10k and 500 ohms too
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 23, 2010 2:16 pm     Reply with quote

Quote:

output_a(0x00);
output_b(0x00);
output_c(0x00);
output_d(0x00);
output_e(0x00);

I just looked at your code. You're clobbering PortA and any other Ports
that you're using, such as the UART. You are setting the TRIS to all
outputs on all the ports. Don't do this. Delete those lines.

Get rid of this stuff too. It's Wizard code and it doesn't do anything
useful, and it can do some harm. For example, the setup_spi()
statement is actually configuring the SPI module. You don't need it.
Delete all these lines.
Quote:

setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Fri Jun 25, 2010 3:12 am     Reply with quote

Thank you very much PCM programmer. My problem is solved at isis Very Happy Today ill try it on hardware i hope there wont be a problem too Smile

By the way what does clobbering means? I didn't understand that. Can you please explain its meaning Question

Also i thought that following lines are using for clearing ports. Am i wrong ? Are those lines assigning tris values ?

Quote:
output_a(0x00);
output_b(0x00);
output_c(0x00);
output_d(0x00);
output_e(0x00);
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Fri Jun 25, 2010 5:28 am     Reply with quote

I tried it in hardware. ADC works Cool Then i tried my first code ADC+PWM. That code was actually driving leds with pwm. I saw there little pwm duration increasement but it happens very rarely. Then i deleted delay lines and tried again. I saw led doesn't blink anymore.

In conclusion i think that delay_ms or delay_us commands affect pwm. Is that true Question I'll use buttons in my code. Because of debounce issue i need delay command there. Also for ADC conversion time i need too. What do u suggest me ? Should i use nop as writing asm ? Is that gonna be a solution ?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jun 25, 2010 11:51 am     Reply with quote

Quote:
Also i thought that following lines are using for clearing ports. Am i wrong ? Are those lines assigning tris values ?

output_a(0x00);
output_b(0x00);
output_c(0x00);
output_d(0x00);
output_e(0x00);

Yes, in Standard I/O mode (the default mode), the compiler also sets
the TRIS to be all outputs when you use the output_x() functions.

Quote:

By the way what does clobbering means?

"Clobbered" means damaged or destroyed or hurt. In this case, it
means the contents of the TRIS registers have been changed, so the
CCS library code may not work anymore.

Quote:
I saw led doesn't blink anymore.

Post a very short compilable program that shows the problem.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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