2
\$\begingroup\$

I wrote a code that takes an analog input from a potentiometer and controls the frequency of a clock pulse. So, the idea is to increase the frequency when I increase the pot and decrease the frequency when I decrease the pot. It should change at a constant rate.

The problem:

When I change the pot, the frequency changes, but not in a constant rate. For example, when I increase the pot, the frequency may decrease and if I increase the pot more, it may increase again. And so on.

Here are some examples of when I keep ONLY INCREASING the pot: enter image description here enter image description here enter image description here

The Config:

#pragma config FOSC = INTRCCLK  
#pragma config WDTE = OFF       
#pragma config PWRTE = OFF      
#pragma config MCLRE = OFF       
#pragma config BOREN = ON       
#pragma config CP = OFF         
#pragma config CPD = OFF

The Code:

#include <xc.h>
#include "config.h"
#define _XTAL_FREQ 4000000

void delay(unsigned char freq){
    for(int i = 0; i < (int)freq; i++){
        __delay_ms(1);
    }
}

void dClock(unsigned char freq){
    GPIO1 = 1;
    delay(freq);
    GPIO1 = 0;
    delay(freq);
}

void InitADC(){
    ANSEL = 0x11;
    ADCON0 = 0b00000001;
    CMCON = 0x7;
    VRCON = 0;
}

unsigned char GetADCValue(){
    ADCON0 = 0b00000011;
    while(GO_nDONE);
    return ADRESL;
}

void main(void) {
    TRISIO0 = 1; //analog input
    TRISIO1 = 0; //output
    TRISIO2 = 0;
    TRISIO3 = 1; //mode
    TRISIO5 = 1; //pulse_button

    char pressed = 0;
    GPIO1 = 0;

    InitADC();

    while(1){
        if(GPIO3 == 0){
            GPIO2 = 1;
            unsigned char freq = GetADCValue();
            dClock(freq);
        }
        else{
            GPIO2 = 0;
            if(GPIO5 == 1 && pressed == 0){
                GPIO1 = 1;
                __delay_ms(500);
                GPIO1 = 0;
                pressed = 1;
            }
            else if(GPIO5 == 0 && pressed == 1){
                pressed = 0;
            }
        }
    }
    return;
}

Other than that, everything works fine. Could someone help me with that? Thank you.

\$\endgroup\$
  • \$\begingroup\$ Please share the datasheet of your potentiometer. Note that only ideal potetiometers have an ideal linear relationship. \$\endgroup\$ – Huisman Jul 9 at 18:08
  • \$\begingroup\$ Measure the adc input with a multimeter and scope (both) and verify whether it corresponds to the frequency you measure on the scope. \$\endgroup\$ – Huisman Jul 9 at 18:09
  • \$\begingroup\$ @Huisman The whole circuit is made on proteus simulation, including the pot. So, the pot shouldn't be faulty. \$\endgroup\$ – Ali Abo Shady Jul 9 at 19:04
  • \$\begingroup\$ I have no experience with proteus, but the word simulation suggest it would even easier to deduce. Write down the values of the ADC and the frequency and try to identify whether there is a pattern. \$\endgroup\$ – Huisman Jul 9 at 19:15
  • \$\begingroup\$ What's CMCON = 0x7; doing in the ADCinit() ? \$\endgroup\$ – Huisman Jul 9 at 19:47
5
\$\begingroup\$

The ADC is only returning the least significant bits with return ADRESL;.
So, if the pot was in such position the returned ADC value was 0b011, "increasing the pot" will return 0b000 as next step.

enter image description here

You should either return ADRESH; or set ADCON0 = 0b**1**0000001; or change freq to an unsigned int and return (ADRESH<8) & ADRESL

\$\endgroup\$
  • \$\begingroup\$ Yes that's it!! It was overflowing as you said. Thank you so much. \$\endgroup\$ – Ali Abo Shady Jul 9 at 20:22

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.