You are on page 1of 7

/*!!!!!!!!!!!!!!!!!! SPEED CONTROL OF DC MOTOR !!!!!!!!!!!!!!!!!!!!!!!!!

*/
/*** Including header files for C-Programming and 8051 Microcontroller Register
***/
#include <stdio.h>
#include <reg51.h>
int i,C,C1,COUNT=16,PrintVAL,col;
char PRNTC;
char* LINE1 ="NS=
NA=
";// NS denotes SetSpeed, NA denotes ActualSpeed (
in RPM)
char* LINE2 ="E=
DC=
";// E denotes Error, DC denotes Duty cycle (in pe
rcentage)
char* POINTER;
sbit led = P3^2;
ndow

// LED toggling to indicate speed measurement wi

sbit P20 = P2^0;


sbit P21 = P2^1;
sbit P22 = P2^2;

// LCD R/W (Read/Write) control bit


// LCD RS (Read Select) control bit
// LCD EN (Enable) control bit

sbit MotorDrive = P3^3;


t pin P3.3

// PWM Output applied to motor drive through Por

int Duty = 50,TON,TOFF;

// Duty Cycle initialised to 50%

// *****************************************************************************
// ***************************** MAIN PROGRAM ******************************
// *****************************************************************************
void main()
{
LCD();
led = 0;

// intitialize toggle LED to LOW

REFRESH1();
POINTER = LINE1;
PrintLine();
REFRESH2();
POINTER = LINE2;
PrintLine();

//Print two lines

TMOD = 0x51;
er
TON = 10*Duty;
TOFF =10*(100-Duty);

// Set Timer 0 as a Timer and Timer 1 as a Count

for(C1=0;C1<500;C1++)
{
MotorDrive = 1;
for(C=0;C<TON;C++)
MotorDrive = 0;

// Run Motor with initial duty cycle


;

for(C=0;C<TOFF;C++)

}
REFRESH6();
PrintVAL = Duty;
PrintDec();
while(1) // Endless while loop.
{
MandC();

// Measurement and Control Function

}
}
/*********** END of the MAIN Program ***************/
//***************************************************************
//**********************Previously Used Functions*************************
//***************************************************************
LCD() // Control Commands to configure and clear the LCD
{
P0 = 0XFF;
P1 = 0XFF;
P20=0;
//clear R/W
P21=0;
//clear RS
P22=0;
//clear EN
P0 = 0X30;
WRITE1();
P0 = 0X30;
WRITE1();
P0 = 0X38;
WRITE1();
P0 = 0X08;
WRITE1();
P0 = 0X03;
WRITE1();
P0 = 0X06;
WRITE1();
P0 = 0X0C;
WRITE1();
P0 = 0X80;
WRITE1();
CLRLCD();
}
WRITE1() // Send command to the LCD (WRITE CYCLE ROUTINE)
{
P20=0;
P21=0;
//MAKE RS,R/W,EN LOW
P22=0;
P22=0;
P22=1;
//MAKE EN HIGH
DELAY1();
P22=0;
P22=0;
P20=1;
P20=1;
// MAKE R/W HIGH
P20=0;

P20=0;
DELAY1();
}
DELAY1() // EN Pulse Width
{
for(C=0;C<2000;C++);
}
DELAY2()
{
for(C=0;C<500;C++);
}
DELAY3()
{
for(C=0;C<100;C++)
{
for(C=0;C<300;C++) ;
}
}
PRINTC() // Display a character on LCD
{
P0=PRNTC;
P21=1; //MAKE RS HIGH
P22=1; //MAKE EN HIGH
DELAY1(); //EN PULSE WIDTH
P22=0; //MAKE EN LOW
P20=1; //MAKE R/W HIGH
P21=0; //MAKE RS LOW
P20=0; //MAKE R/W LOW
P22=0;
}
REFRESH1() // Select First Line on LCD
{
P0=0X80;
WRITE1();
P20=0;
}
REFRESH2() // Select Second Line on LCD
{
P0=0XC0;
WRITE1();
P20=0;
}
REFRESH3() // Select First Line on LCD
{
P0=0X83;
WRITE1();
P20=0;
}
REFRESH4() // Select Second Line on LCD
{
P0=0X8C;
WRITE1();

P20=0;
}
REFRESH5() // Select Second Line on LCD
{
P0=0XC2;
WRITE1();
P20=0;
}
REFRESH6() // Select Second Line on LCD
{
P0=0XCC;
WRITE1();
P20=0;
}
/**************** *************/
CLRLCD() // Clear the LCD Display for Next page
{
P0=0X01;
WRITE1();
P20=0;
}
PrintDec() // Prints upto 4-digit decimal number
{
int D4,D31,D3,D21,D2,D1,A4,A3,A2,A1;
//***************** Decimal Value Extraction ******************/
D4 = PrintVAL/1000; // Most significant decimal digit
D31 = PrintVAL%1000;
D3 = D31/100; // Next significant decimal digit
D21 = D31%100;
D2 = D21/10; // Next significant decimal digit
D1 = D21%10; // Least significant decimal digit
//**********Decimal to ASCII Conversion ***************/
A4 = D4+48;
PRNTC = A4;
PRINTC();
A3 = D3+48;
PRNTC = A3;
PRINTC();
A2 = D2+48;
PRNTC = A2;
PRINTC();
A1 = D1+48;
PRNTC = A1;
PRINTC();
}
PrintLine() // Display one LINE (16 characters) of text
{
for (col=0;col<12;col++) // COUNT set to 16
{
PRNTC=*POINTER;
PRINTC();
POINTER++;
}
}

/////////////////////////////////////////////////////////////////////
//****************************************************************
// *************************** NEW Function*****************************
//****************************************************************
MandC()
{
int ActualSpeed,SetSpeed,Error,K;// Speed and control parameters
int CPH,CPL;
// Count values for HIGH and LOW durations of th
e PWM output
// Choose CPH + CPL = 2560, giving PWM time period TPWM = 2560/(11MHz/12) = 2.8
ms approx.
int T1Gate,PulseCount,countC;
// Count Encoder pulses by Timer1, Gated through a time window T1Gate in the ran
ge 1-5 sec,
// generated by counting PWM pulses for a count PulseCount = T1Gate/TPWM = 358*T
1Gate)
SetSpeed = 1500;
in the range 900-4500)
K = 10;
n the range 1-20)

// Default value in RPM (choose multiples of 100


// PI Control Parameter (choose integer values i

CPH = Duty/10;
//
pulse = 256*CPH
CPL = 10 - CPH;
//
pulse = 256*CPL
T1Gate = 3;
//
the range 1-5)
PulseCount = 358*T1Gate;//

Timer0 count for the HIGH duration of the PWM


Timer0 count for the LOW duration of the PWM
Timer1 Gate in sec (choose integer values in
(11MHz/12)/2560 = 358

/**************** Run Timer1 to count the Encoder output pulses ****************


***/
TH1 = 0x00;
TL1 = 0x00;
TR1 = 1;
for(countC = PulseCount; countC
dow T1Gate
{
/**************** Generate PWM waveform
***/
TH0 = 0xFF - CPH;
TL0 = 0xFF;
6*CPH
MotorDrive = 1;
TR0 = 1;
while(!TF0);
TF0 = 0;
if it is not equal to 1
TR0 = 0;
g the LOW interval
TH0 = 0xFF - CPL;
TL0 = 0xFF;
6*CPL

// Initialize Timer1 as a counter


// Start Timer1
> 0; countC--) // Create the gating win
using Timer0 as a timer ****************
// Set Timer0 for a timing interval = 25
// HIGH interval of PWM starts
// Start Timer 0
// If TF0 = 1 stop Timer0
//Checking Timer0 flag register
// Clear the Timer0 Flag bit for startin
// Set Timer0 for a timing interval = 25

MotorDrive = 0;
// Low interval of PWM starts
TR0 = 1;
// Start Timer 0
while(!TF0);
// Checking Timer0 flag register if it i
s not equal to 1
TR0 = 0;
// If TF0 = 1 stop the timer
TF0 = 0;
// Clear the Timer0 Flag bit for the nex
t PWM cycle
}
/****************************** Measure speed**********************************/
TR1 = 0;
// Stop Timer1 to hold measured value
ActualSpeed = 15*(256*TH1 + TL1)/T1Gate; // Speed in RPM = 15*Encoder pu
lse frequency
/******************** Compute, Update PWM Duty cycle and Display ***************
*/
Error = (ActualSpeed - SetSpeed)/(SetSpeed/100);//Percentage error in sp
eed
Duty = Duty - Error/K;
// Correction made in Duty cycle
// Restricting Duty cycle in the range of (10%-90%)
if(Duty>90)
{
Duty=90;
}
if(Duty<10)
{
Duty=10;
}
/////// Print Set Speed(NS) and Actual Speed (NA)
REFRESH3();
PrintVAL = SetSpeed;
PrintDec();
REFRESH4();
PrintVAL = ActualSpeed;
PrintDec();
/// Check and Print Error (E)
REFRESH5();
if(Error<0)
{
Error = Error * -1;
PRNTC = 45;
PRINTC();
PrintVAL = Error;
PrintDec();
Error = Error * -1;
}
else
{
PRNTC = 32;
PRINTC();
PrintVAL = Error;
PrintDec();
}

// Print '-' sign

// Print Space

///// Print Duty cycle (DC)


REFRESH6();
PrintVAL = Duty;
PrintDec();
led= ~ led;
}
/*!!!!!!!!!!!!!!!!!! End of the Program !!!!!!!!!!!!!!!!!!!!!!!!!*/

You might also like