1
\$\begingroup\$

I was trying to simulate on proteus ADC with potentiometer and get the reading to control dc motor with PWM it's working but the problem is the ADC value not accurate. ADCH reach max value before potentiometer is 100%. I don't know why this behavior. Hope you can explain it to me.Here is the code.

#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
void pwm_init()
{
DDRB |= (1<<PB3);
TCCR0 |= (1<<WGM00) | (1<<WGM01) | (1<<COM01) | (1<<CS01);
OCR0 = 0x00;
}

void adc_init()
{
DDRA =0x00;
ADMUX |= (1<<REFS0);// AVCC ref
ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADLAR) | (1<<ADATE); // 1MHZ With 
prescaler 8 gives adc freq 125 khz
}

uint8_t adc_read()
{
ADCSRA |= (1<<ADSC);
while(!(ADCSRA && (1<<ADIF)));
ADCSRA |= (1<<ADIF);
return ADC;
}

int main(void)
{
pwm_init();
adc_init();
while (1) 
{
    OCR0 = adc_read();
}
}

You can also see in below picture duty cycle is almost 100% while potentiometer is just 12%. Simulation

\$\endgroup\$
  • \$\begingroup\$ Which board are you using? Are you sure that no other on-board devices/sensors are connected to the PA0 pin? \$\endgroup\$ – Ale..chenski Sep 8 '17 at 5:35
  • \$\begingroup\$ @Ali Chen iam not using any boards iam simulating it on proteus on atmega32 \$\endgroup\$ – user247954 Sep 8 '17 at 5:36
  • \$\begingroup\$ What voltages are on RV4(2), VCC and AVCC? Please show the whole circuit. \$\endgroup\$ – Bruce Abbott Sep 8 '17 at 5:52
  • \$\begingroup\$ Why do you do this logic AND operation: while(!(ADCSRA && (1<<ADIF))); instead of a bitwise AND: while( !( ADCSRA & (1<<ADIF)) ) ; ?? \$\endgroup\$ – G36 Sep 8 '17 at 16:28
2
\$\begingroup\$

If ADLAR = 1, then according to the datasheet, (section 26.8.4, see attachment), the ADC result is left aligned to the 16-bit couple ADCH-ADCL.

Your function adc_read() returns a 8-bit integer. Therefore it returns only the ADCL (see figure), because the upper 8 bits are lost in the conversion uint_16->uint_8.

In other words, if A0 or A1 are 1, you'll get a large duty value, because the value returned by adc_read() will be between 0x40 and 0xC0.

Solution: in your function adc_read() return ADCH only.

Also the potentiometer must be connected to a voltage source with AREF volt, where AREF is the ADC reference voltage. If you are using the internal reference, do not connect the potentiometer directly to the AREF pin, because such pin has a very small output current capability.

enter image description here

\$\endgroup\$
  • \$\begingroup\$ Thanks for pointing that out. I have edited the code so adc_read() returns ADCH only but unfortunately simulation showed duty cycle almost zero and no change happens to it when change the potentiometer value. \$\endgroup\$ – user247954 Sep 8 '17 at 5:42
  • \$\begingroup\$ Please then show the full schematics on your post! It's hidden by the scope! Beside, what's RV4(2) ? Is it a voltage equal to AREF? \$\endgroup\$ – next-hack Sep 8 '17 at 5:46
  • \$\begingroup\$ RV4 it is just a label for the potentiometer. \$\endgroup\$ – user247954 Sep 8 '17 at 5:48
  • \$\begingroup\$ You have to put a voltage generator with value AREF on the top pin of the potentiometer. Otherwise the voltage on PA0 will be always 0. \$\endgroup\$ – next-hack Sep 8 '17 at 5:53
  • \$\begingroup\$ This triangle above the potentiometer is the dc voltage supply with 5 v same as aref \$\endgroup\$ – user247954 Sep 8 '17 at 5:56
1
\$\begingroup\$

Thanks guys for your help

I found the problem.

I set the ADLAR in ADCSRA register and it should be set in ADMUX. I fixed that and all worked fine.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.