Hello everyone..
Im going to build a project about controlling brushed dc motor with feedback from encoder disk. im using 16F877A and XC8 Compiler for this project. THe encoder disk is from old printer and it has like 8000 steps. about one year ago ,i build that project via Arduino and it worked fine but now im tring to build that project via PIC microcontroller. the code same as arduino's code but its not working for now !
im using a brushed dc motor(max current is about 0.5 amps) and l293n (max current is 2 Amps) for driving motor. connections of driver and pic is fine. but there is a problam.
for example when i forced to motor's rotor through the CCW direction, the pic is giving expected pwm signal but when i set free the rotor , there are two possible action happening.
first possible action is rotor start turning through the CW direction as i expected but its not stopping.
second possible action is rotor start turning through the CW direction as i expected but its missing steps and stopping somewhere after the setpoint.
but same condition is not valid to other direction. its working fine and stopping expected point everytime.
i found the reason ;
when the rotor turning throught the CW direction , interrupt service routine is stop working or missing steps.
the other thing that i should ask ; when motor turning fast , imean when the frequency of encoder is 35kHz , interrupt service routine is missing steps but i dont want to miss any steps.
what should i do ??
My codes are down below.there are also PWM.c ,PWM.h files and pwm signals from my oscillascope .
need some help here.
thanks for assist and have a great day for all of you guys .
My Main C code is here
this is header fie of pwm
this is my pwm.c codes
Im going to build a project about controlling brushed dc motor with feedback from encoder disk. im using 16F877A and XC8 Compiler for this project. THe encoder disk is from old printer and it has like 8000 steps. about one year ago ,i build that project via Arduino and it worked fine but now im tring to build that project via PIC microcontroller. the code same as arduino's code but its not working for now !
im using a brushed dc motor(max current is about 0.5 amps) and l293n (max current is 2 Amps) for driving motor. connections of driver and pic is fine. but there is a problam.
for example when i forced to motor's rotor through the CCW direction, the pic is giving expected pwm signal but when i set free the rotor , there are two possible action happening.
first possible action is rotor start turning through the CW direction as i expected but its not stopping.
second possible action is rotor start turning through the CW direction as i expected but its missing steps and stopping somewhere after the setpoint.
but same condition is not valid to other direction. its working fine and stopping expected point everytime.
i found the reason ;
when the rotor turning throught the CW direction , interrupt service routine is stop working or missing steps.
the other thing that i should ask ; when motor turning fast , imean when the frequency of encoder is 35kHz , interrupt service routine is missing steps but i dont want to miss any steps.
what should i do ??
My codes are down below.there are also PWM.c ,PWM.h files and pwm signals from my oscillascope .
need some help here.
thanks for assist and have a great day for all of you guys .
My Main C code is here
Code:
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#include <xc.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 16000000L
#include "pwm.h"
#define STEP_MARGIN 3 //Allowıng 3 missed steps from encoder disk.
#define sensorStatusA PORTBbits.RB6 //Photo sensor 1
#define sensorStatusB PORTBbits.RB7 //Photo sensor 2
#define MotY_DIRECTION PORTDbits.RD0 //Direction output motor
#define MotY_PWM PORTCbits.RC2 //PWM output motor
int stepStatus = 0;
//int stepStatusOld = 0;
int oldSensorStatusA = 0;
int dutyCycle = 0;
signed long setPoint = 0;
int actualPoint = 0;
void __interrupt () isr (){
if (RBIF==1){
if(MotYSensor02 == 0 && MotYSensor01 == 0){
if(MotYStep == 1){
MotYIsPoint--;
}
if(MotYStep == 3){
MotYIsPoint++;
}
MotYStep = 0;
}
if(MotYSensor02 == 1 && MotYSensor01 == 0){
if(MotYStep == 0){
MotYIsPoint++;
}
if(MotYStep == 2){
MotYIsPoint--;
}
MotYStep = 1;
}
if(MotYSensor02 == 1 && MotYSensor01 == 1){
if(MotYStep == 3){
MotYIsPoint--;
}
if(MotYStep == 1){
MotYIsPoint++;
}
MotYStep = 2;
}
if(MotYSensor02 == 0 && MotYSensor01 == 1){
if(MotYStep == 2){
MotYIsPoint++;
}
if(MotYStep == 0){
MotYIsPoint--;
}
MotYStep = 3;
}
RBIF=0;
}
void main(void) {
TRISB=0XF0;
//-----interrupt registers-----//
GIE=1;
INTEDG=1;
RBIF=0;
RBIE=1;
//-------------------------//
while(1){
if(abs(MotYSetPoint - MotYIsPoint) < STEP_MARGIN){ // Actualpoint=Setpoint
TRISC2=1;
MotY_DIRECTION= 0;
MotYStepDone = 1;
MotYDutyCycle = MIN_DUTYCYCLE;
}
else{
if(MotYIsPoint < MotYSetPoint){ // CW diection
MotY_DIRECTION= 1;
PWM_Init(0);
PWM_Start(0);
PWM_SetDutyCycle(0,100); //16kHz pwm freq and %40 of dutycycle
}
if(MotYIsPoint > MotYSetPoint){ //CCW direction
MotY_DIRECTION= 0;
PWM_Init(0);
PWM_Start(0);
PWM_SetDutyCycle(0,50); //16kHz freq of pwm and %20 of dutycycle
}
}
} }
this is header fie of pwm
Code:
#ifndef _PWM_H_
#define _PWM_H_
#include "stdutils.h"
/*************************************************************************************************
Function Prototypes
*************************************************************************************************/
void PWM_Init(uint8_t channel);
void PWM_SetDutyCycle(uint8_t channel,uint8_t dutyCycle);
void PWM_Start(uint8_t channel);
void PWM_Stop(uint8_t channel);
/*************************************************************************************************/
#endif
this is my pwm.c codes
Code:
#include <pic16f877a.h>
#include "pwm.h"
#pragma warning push
#pragma warning disable 752 // Suppress warnings related to size of variables(conversion to shorter data type).
void PWM_Init(uint8_t channel)
{
switch (channel)
{
case 0 :
CCP1CON = 0x0F; // Select the PWM mode.
PR2 = 500; // 16kHz freq of pwm.
CCPR1L = 50; // By default set the dutycycle to 50
TRISC2=0; // Make the PWM pin(PC.2) Output
break;
case 1 :
CCP2CON = 0x0F; // Select the PWM mode.
PR2 = 100; // Set the Cycle time to 100 for varying the duty cycle from 0-100
CCPR2L = 50; // By default set the dutycycle to 50
TRISC1=0; // Make the PWM pin(PC.1) Output
break;
}
}
void PWM_SetDutyCycle(uint8_t channel,uint8_t dutyCycle)
{
switch (channel)
{
case 0 :
CCPR1L = dutyCycle;
break;
case 1 :
CCPR2L = dutyCycle;
break;
}
}
void PWM_Start(uint8_t channel)
{
TMR2ON = 1; //Start the Timer for PWM generation
}
void PWM_Stop(uint8_t channel)
{
switch (channel)
{
case 0 :
CCP1CON = 0x00; //Disable the CCP Module from generating PWM
break;
case 1 :
CCP2CON = 0x00; //Disable the CCP Module from generating PWM
break;
}
}