What's wrong with my DC motor !?

Thread Starter

josephgebran

Joined Jun 5, 2011
10
Hello all, i am working on a simple DC motor control in 1 direction only. I will attach the code written in HITECH C Compiler for PIC16F887.
Rich (BB code):
#include <htc.h>
#include <stdlib.h>
#define _XTAL_FREQ 8000000
#define  TMR2_PRESCALER 4

__CONFIG(0x28C4);    // config word 1
__CONFIG(0x3eff);    // config word 2 (in sequence)


#define byte unsigned char
#define word unsigned int
#define dword unsigned long


typedef union _word_VAL
{
    word Val;
    struct { byte LB; byte HB; } byte1;
} word_VAL;

byte x1,x2,x3,speed;
byte ccpr1l_copy,ccpr2l_copy;
void PWM1_Init(word x),PWM1_Set_Duty(byte x),PWM1_Start(),PWM1_Stop();
void PWM2_Init(word x),PWM2_Set_Duty(byte x),PWM2_Start(),PWM2_Stop();
void init();

void Move_Forward(int speed);
void Clutch();

void main()
{
	init();
    while(1)
    {speed=1;
    Move_Forward(speed);
    __delay_ms(2000);
	Clutch();
	__delay_ms(2000);
    speed=3;
    Move_Forward(speed);
    __delay_ms(2000);
    Clutch();
	__delay_ms(2000);
}  
}           // End main program

void init()
{
OSCCON=0b01110001;   //frequency = 8M
ANSEL=0b1110000;     //Enable PortA Analog Input,AN4,AN5,AN6
ANSELH=0;            //Disable PortB Analog Input
C1ON=0;              //turn off
C2ON=0;              //comparators
TRISA=0b11110000;	 //RA0,RA1,RA2,RA3 Digital Outputs for stepper motor of Camera,AN4 Analog Input for Light Sensor
TRISB=0b11101011;    //RB2,RB4 Digital Outputs for Horn and Flashlight
TRISC=0b11110000;    //RC0,RC3 Digital Outputs for DC motor, CCP1,CCP2 for PWM Output
TRISD=0b11000000;    //RD0,RD1,RD2,RD3 Digital Outputs for stepper motor of Robot ,RD4 Digital Output for Camera,RD5 Digital Output for Clutch
T2CON=0b00000001;    // prescaler=4
CCP1CON=0b00001100;
CCP2CON=0b00001100;
CCPR1H=CCPR1L=CCPR2H=CCPR2L=0;
ccpr1l_copy=ccpr2l_copy=0;
PWM1_Init(5000);   //Initialize PWM modules at
PWM2_Init(5000);   //5KHz frequency
RCSTA=0b10010000;
TXSTA=0b00100100;
BAUDCTL=0b00000000;
SPBRG=207;
}

void Move_Forward(int speed)
{ byte current_duty;
        switch(speed)
        { case 1:
            current_duty = 20;
            break;
          case 2:
            current_duty = 127;
            break;
          case 3:
            current_duty = 240;
            break;
          case 0:
            RC0=0;
            PWM1_Stop();
            break; }
   if (current_duty!=0)      
   
	{PWM1_Set_Duty ( current_duty );
   PWM1_Start();
   RC0=1; }
} 

 void Clutch()
 { RD5=1;
   RC0=0;
   RC3=0;
   PWM1_Stop();
   PWM2_Stop();
   }
 
void PWM1_Init(word x)
{
PR2=((_XTAL_FREQ/(4*TMR2_PRESCALER))/x)-1;
}

void PWM1_Set_Duty(byte x)
{
ccpr1l_copy=x*(PR2+1)/100;
}


void PWM1_Start()
{   
CCPR1L=ccpr1l_copy; 
}
   
void PWM1_Stop()
{
CCPR1L=0;  
}
   
void PWM2_Init(word x)
{
PR2=(500000/x)-1;   
}

void PWM2_Set_Duty(byte x)
{
ccpr2l_copy=x*(PR2+1)/100;
}


void PWM2_Start()
{
CCPR2L=ccpr2l_copy; 
}
   
void PWM2_Stop()
{
CCPR2L=0;     
}
I Connected the circuit, and the motor is rotating for 2 seconds, stops for 2 seconds, and then rotates again for 2 seconds but i can't feel any difference in its rotation speed ! Help. Thank You
 

#12

Joined Nov 30, 2010
18,224
You might get better results by posting this in "Embedded systems and microcontrollers". The people who watch that forum would likely be able to read your code.
 

stahta01

Joined Jun 9, 2011
133
The first problem is that you are trying to put a value bigger that 255 into a single byte like ccpr2l_copy.

Tim S.

Rich (BB code):
ccpr2l_copy=x*(PR2+1)/100;
20 * 5 = 100
240 * 5 = 0x4B0 (0xB0 is 176)
These are rough guesses on the values, the difference 100 and 176 might not be noticeable.
 

#12

Joined Nov 30, 2010
18,224
Excellent! Old farts like me lurk in the Chat and Projects section. We can be very good with beginners, but several of us haven't learned microprocessors. Glad to see this getting some work done.

good luck!
 

stahta01

Joined Jun 9, 2011
133
Lookup CCPR1L and CCPR1H (or CCPR2L and CCPR2H) in the datasheet.
Use Division and Modulus "%" to separate the 16 bit result.

Tim S.
 

ErnieM

Joined Apr 24, 2011
8,415
can u help me with the equation? i mean if i want to seperate the 16 bits into two 8 bits, i will divide the number by what?!
I am unfamiliar with the Hitech C compiler, I've done something similar with the Sourceboost C compiler. You may need to translate this to work.

What I have is a 10 bit number residing in PWMset, defined as unsigned short (16 bit unsigned number). We need the least significant bit into the DC1B0 bit of CCP1CON, the next bit into the DC1B1 bit of CCP1CON, and the next 8 bits into CCPR1L. The individual bits are each coppied one at a time, then the 8 bits are found by shifting over the 2 places and assigning, like so:

Rich (BB code):
        unsigned short    PWMset;
...

        ccp1con.DC1B0 = PWMset.0;    // first change 2 LSB's
        ccp1con.DC1B1 = PWMset.1;
        ccpr1l = PWMset>>2;          // now copy over MSB
 
Top