Connect with us

16f877a DC encoder motor control help!!!!!!!

Discussion in 'Microcontrollers, Programming and IoT' started by wildarms, May 28, 2021.

Scroll to continue with content
  1. wildarms

    wildarms

    1
    0
    May 28, 2021
    Hello everyone. I was trying to control the encoder dc motor using pic 16f877a. I couldn't use the #INT_RB interrupt. can you help me with my code. Angle value due to INT_RB interrupt is always zero, I need to increase it somehow, please help.

    Code:
    #include <16F877A.h>
    #device adc=10 //set the bit value of adc
    #FUSES XT, NOWDT, NOPROTECT, NOBROWNOUT, NOLVP, NOPUT, NODEBUG, NOCPD
    #use delay(crystal=4000000)
    #include <lcd.c>
    
    unsigned int16 last_read,quad;
    
    #INT_RB // RB port interrupt on change
    void RB_IOC_ISR(void)
    {
    int8 encoderRead;
    encoderRead = input_b() & 0x30;
    if(encoderRead == last_read)
    return;
    
    if(bit_test(encoderRead, 4) == bit_test(last_read, 5))
    quad -= 1;
    else
    quad += 1;
    last_read = encoderRead;
    }
    
    signed long EncoderGet(void)
    {
    signed long value = 1;
    
    while(quad >= 4)
    {
    value += 1;
    quad -= 4;
    }
    while(quad <= -4)
    {
    value -= 1;
    quad += 4;
    }
    return value;
    }
    
    signed long PWM,error = 0,change = 0,realPosition = 0,angle = 0.0f;
    
    void main()
    {
    unsigned int8 temp;
    unsigned int16 rev,kp;
    unsigned long int16 referance; //variable for ADC reading value from AN0
    
    lcd_init();
    delay_ms(10);
    
    set_tris_c(0x00); //set all portb pins as output
    set_tris_b(0x00);
    port_b_pullups(TRUE);
    delay_ms(10);
    temp = input_b(); // Add these 4 lines
    enable_interrupts(INT_RB);
    clear_interrupt(INT_RB);
    enable_interrupts(GLOBAL);
    setup_ccp1(CCP_PWM); //4kHz PWM signal output at CCP1 pin 17
    setup_timer_2(T2_DIV_BY_16, 255, 1);
    setup_adc_ports(ALL_ANALOG); //A0A1 A2 A3 A5 E0 E1 E2 analog pins
    setup_adc(ADC_CLOCK_DIV_32); //enable ADC and set clock FOR ADC
    
    WHILE(1)
    {
    set_adc_channel(0); // next analog reading will be from channel 0
    delay_us(10); //allow time after channel selection and reading
    referance =read_adc(); //start and read A/D
    referance=referance*250;
    referance=referance/1023;
    referance=referance+20;
    set_adc_channel(1); // next analog reading will be from channel 1
    delay_us(10); //allow time after channel selection and reading
    kp = 50+(read_adc()*10/1023); //start and read A/D
    delay_ms(200);
    
    
    change = EncoderGet();
    if(change)
    {
    realPosition += change;
    }
    rev = realPosition/360.0f; // Here 360 represents the encoder pulses per revolution
    angle = ((int16)(rev*360))%360; // Real time angle is determined in this line
    
    
    error=referance-angle;
    PWM=error*kp;
    if (PWM>=1023)
    PWM=1023;
    else if (PWM<=0)
    PWM=0;
    set_pwm1_duty(PWM);
    
    
    printf(LCD_PUTC,"\fref=%lu",referance);
    printf(LCD_PUTC," kp=%lu",kp);
    printf(LCD_PUTC,"\npos=%lu",rev);
    lcd_gotoxy(8,2);
    printf(LCD_PUTC,"PWM=%lu",PWM);
    delay_ms(700);
    }
    }
    Moderators note : used code tags for pieces of code
     
    Last edited by a moderator: May 28, 2021
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-