problems with c code for pic (adc and pwm) - Page 1
Forum section: electronics / beginners

author: little_carlos
author_rank: Regular Contributor
timestamp: April 02, 2016, 02:22:15 am
content: hey, so, i made a code to control pwm output with a pot on adc chanel (AN2), i run it on proteus and it works perfect, just as i wanted, but in the actual real circuit it doesnt behave like that, the change on the duty cycle is small, why is not acting like on proteus?the pic is 16f887 btwhere is the codeunsigned adc;void Initmain() {ANSEL = 0x04;ANSELH = 0;TRISA = 1;TRISC = 0;PORTC = 0;C1ON_bit = 0; // Disable comparatorsC2ON_bit = 0;PWM1_Init(5000);}void main(){Initmain();adc = 0;PWM1_Start();PWM1_Set_Duty(adc);while (1) {adc = ADC_READ(2);PWM1_Set_Duty(adc);}delay_ms(5);}

author: danadak
author_rank: Super Contributor
timestamp: April 02, 2016, 11:20:27 am
content: Is the ADC result a right justified 10 bit result in a 16 bit word ?I assume your PWM is 16 bits, so you should do the following ifresult is right justified -PWM1_Set_Duty( adc << 6 );This assumes A/D result is unsigned.Regards, Dana

author: little_carlos
author_rank: Regular Contributor
timestamp: April 02, 2016, 01:35:14 pm
content: Quote from: danadak on April 02, 2016, 11:20:27 amand if the pwm is 8 bit?

author: ProAce
author_rank: Contributor
timestamp: April 04, 2016, 08:41:35 am
content: I assume it isn't working because you are trying to fit an int(adc) into char(duty ratio).From MikroC lib: void PWM1_Set_Duty(unsigned short duty_ratio);Sets PWM duty ratio. Parameter duty takes values from 0 to 255, where 0 is 0%, 127 is 50%, and 255 is 100% duty ratio. Other specific values for duty ratio can be calculated as (Percent*255)/100.

author: Philfreeze
author_rank: Regular Contributor
timestamp: April 04, 2016, 10:13:04 am
content: ADC_READ() returns for this PIC a 10bit value (0-1023). You want to give this to a PWM where 0=0% and 255=100%. It looks like PWM1_Set_Duty() has a 16bit parameter (unsigned short) for some reason.You will get an unexpected behaviour if you just give the 10bit value to PWM1_Set_Duty() because it should only get values <256.This means you probably have to perform:Code:adc = ADC_READ(2) >> 2; // shift by 2 is equal to /4PWM1_Set_Duty(adc);This way the maximum value of adc is now 255 (1023/4 round up).

author: little_carlos
author_rank: Regular Contributor
timestamp: April 04, 2016, 11:05:54 pm
content: Quote from: ProAce on April 04, 2016, 08:41:35 amThanks, but how could I implement it to my code?

author: rstofer
author_rank: Super Contributor
timestamp: April 05, 2016, 01:13:42 am
content: unsigned adc;adc = ADC_READ(2); /* reading channel 2 */PWM1_Set_Duty((unsigned char) (adc >> 2)) /* assuming 10 bit ADC. If 12 bit, adc >> 4 */or you could write it in one statement like:PWM1_Set_Duty((unsigned char) (ADC_READ(2) >> 2));

author: ProAce
author_rank: Contributor
timestamp: April 05, 2016, 05:05:44 am
content: Indeed. Don't let the shifting bits cofuse you. By shifting the (binary) value you are simply dividing it to fit 8bit (255 in decimals) duty ratio as Philfreeze already said. Check this out:http://www.eevblog.com/wiki/index.php?title=Embedded_Programming_Tips_and_Tricks_for_Beginners