This project aims to measure the RPM
and controls the speed of motor. There is a wide range of cheap low-voltage
motors available, running at maximum no-load speeds ranging from 3600 RPM to
18,000 RPM or more. Torque may be anything between 3g-cm for the cheaper
versions and over 60g-cm for the slightly more expensive motors. Many
applications require slower speeds with correspondingly greater torque, and
there are several different plastic gearboxes available for the model maker to
use. There are also motor-driven devices such as cooling fans and water pumps
that can be controlled by this project.
If controlling motors is of no interest to you, perhaps you might like to use
the circuit for controlling the brightness of a filament .In this D.C. Motor controller
project, it is possible to control the speed of a motor by simply wiring a
resistor in series with it. Apart from the inefficiency of such a system, there
is the need for a heavy-duty variable resistor (potentiometer). A typical d.c. motor requires several hundred
milliamps to drive it. If the motor is taking say 300mA and the variable
resistor is dropping say 3V, the power dissipated in the resistor is 0•9W. The typical variable
potentiometer is rated at only 0•25W, so something much more robust is required
costing three or more times as much required. Another factor is that motors do
not run well on less than their full rated voltage. They fail to start turning
when current is switched on and have a tendency to stall when extra load is
applied. The motor speed can be controlled from 30rps to 180 rps. It measures
revolutions per minute in rpm mode from 2000 rpm to 15000 rpm. Another factor
is that motors do not run well on less than their full rated voltage. They fail
to start turning when current is switched on and have a tendency to stall when
extra load is applied.
ICs working on +5v are
1. ATMEGA
16
2. MOC7811
The motor works on +5v.
Hardware Design
The circuit is designed using ATMEGA family
of microcontroller .The required clock is generated internally. The reset will
contain the resistance. The speed is controlled using PWM techniques. PWM pulse
is the on-off (low or high pulse) given to the motor driver circuit. The MOSFET
(IRFZ44) is used for driving the DC Motor. The optical sensor will be used for
sensing the speed. The output of the optical sensor will be given to the
microcontroller The RPM will be displayed on the 16X2 LCD. Input voltage is
varied by potentiometer of 10KΩ. This voltage is applied to pin no.A0 of Microcontroller.
By varying the value of potentiometer we are controlling the Speed of DC motor.
Microcontroller used is of atmega family.
We have used atmega 16. The input voltage from pot is in analog form but microcontroller
needs it to be in digital form. So we give this voltage at port pin A because
port A is input to Analog to Digital Converter (ADC). ADC converts this voltage
into 10 bit digital data. It is stored in ADC register. From this value we can
calculate the ON&OFF period as below
If input data = 100
As it is 10 bit ADC & register
inside are only 8 bits, we have to divide ADC output by 4 to get Ton.
Ton = 100%4 = 25
Toff = 255-25 = 230 as register is 8 bit
After calculating Ton &
Toff, we are checking the status of pin 4(OCO).
If pin 4 = logic ‘1’ then Ton is
loaded in timer register.
If pin 4 = logic ‘0’ then Toff
is loaded in timer register.
This will generate the Pulse Width
Modulation signal at pin 4(OCO). This PWM signal is given to the MOSFET (IRFZ44).
We are using MOSFET to drive the motor. For controlling the speed of motor,
motor is connected at the drain terminal of the MOSFET.PWM signal from
microcontroller is applied to the MOSFET. Depending on the gate voltage, MOSFET
will produce the drain current. This drain current is used to control the speed
of the motor. For measurement of speed of DC motor, we are using the optical
sensor (MOC 7811). It is selected because it gives +5v when one rotation is
complete. This sensor is connected across the motor. The output of sensor is
connected to pin 16(INT0) of the microcontroller. For this Clear Timer ON
compare Match mode (TCL) is used. We are counting number of pulses in 0.5
second. Using timer & counter the RPM & RPS are calculated as follows
RPS = 2*(0.5 sec)*count
RPM = 2*60*(0.5 sec)*count
RPM & RPS values are displayed on
LCD
LCD we have used is 16x2. This LCD has
8-bit parallel interface. It is possible to use all 8 bits plus 3 control signals
or 4 bits plus the control signals. It requires +5V to operate. It is connected
to port C & D of microcontroller. It acts as an output to microcontroller.
It uses ASCII values to display the characters.
ALGORITHM
i. Initialization.
ii. Defined
functions.
iii. Initialize
Port A as input Port.
iv. Initialize
Port B as output Port.
v. Scan
the analog input coming from the potentiometer.
vi. Convert
this analog input into digital form.
vii. Calculate
‘ON’ & ‘OFF’ period.
viii. Load
the count depending on status of pin OCo .
1. If
OCo = 1, load Ton as count value.
2. Else,
load Toff as count value.
ix. Count
the pulses on the pin INTo for 0.5 seconds.
x. Calculate
RPS & RPM as follows
1. RPS=2*0.5*count
value.
2. RPM=2*0.5*60*count
value.
xi. Display
RPS & RPM on LCD.
xii. Repeat
the procedure from step 5.
PROGRAM CODE
//ADC
#ifndef INTERNAL_ADC_H
#define INTERNAL_ADC_H
void adc_init(void);
void adc_chan0(void);
#endif
//LCD
fndef lcd_H
#define lcd_H
#define line1 0x80
#define line2 0xC0
#define EN 7
#define RW 6
#define RS 5
#define RW_INIT () {PORTD|= (1<<RW); PORTD&=~ (1<<RS);
DDRC&=PORTC&=~ (1<<7) ;}
void lcd_config(void);
void lcd_init(void);
void lcd_en_tgl (void);
void lcd_cmd(unsigned char letter);
void lcd_char(unsigned char letter);
void lcd_nibble(unsigned char
nib,unsigned char rs);
void lcd_clr_line(unsigned char line);
void lcd_string(unsigned char
*senpoint, unsigned char line);
lcd_single_char(unsigned char
*senpoint,unsigned char line,unsigned char position);
#endif
//ADC
#ifndef INTERNAL_ADC_C
#define INTERNAL_ADC_C
#include "internal_adc.h"
#include <avr\io.h>
void adc_init(void)
{
adc_chan0 (); //Aref,internal
turned off,right adjust,channel 0 selected
ADCSRA=0x86; //single conversion
with conversion disabled ps =64
return;
}
void adc_chan0(void)
{
ADMUX&=0x00; //select adc0
channel (temperature 1)
ADCSRA=0xC6;
}
#endif
//SPEED CONTROL & SPEED
MEASUREMENT
#include <avr\io.h>
#include <util\delay.h>
#include <avr\interrupt.h>
#include "lcd.h"
#include "internal_adc.h"
#define FCPU = 1000000UL
#define JTAG_DISABLE() {MCUCSR|=0x80;MCUCSR|=0x80;}//JTAG disabled
static unsigned char t_on=0,t_off=0;
static unsigned int
pulse_count,pulse_buff;
void calculate(unsigned int
data,unsigned char *t_value,unsigned char line);
unsigned int adc_scan(void);
void pwm_init(void);
void intrpt0_init(void);
void timer1_init(void);
ISR (INT0_vect)
{
SREG=0x00;
pulse_count++;
SREG=0x80;
return;
}
ISR (TIMER0_COMP_vect)
{
SREG=0x00; //disable global interrupt
if(bit_is_set(PINB,3))
OCR0=t_on;
else
OCR0=t_off;
SREG=0x80; //enable global interrupt
return;
}
ISR (TIMER1_OVF_vect) //0.5 second timer1
{
SREG=0x00;
pulse_buff=pulse_count; //pulse_buff*2 gives rps , pulse_buff*2*60
gives rpm
pulse_count=0;
TCNT1H=0xE1;
TCNT1L=0x7A;
SREG=0x80;
return;
}
void main(void)
{
unsigned char proj_str[2][16] =
{" Motor control ","SpeedMeasurement"};
unsigned int m_value;
unsigned char data_str[16];
JTAG_DISABLE();
DDRA=0x00; //port a as i/p
PORTA=0x00; //high impedance
DDRB=0xFF; //set port B as o/p
lcd_init();
adc_init();
intrpt0_init();
timer1_init();
pwm_init();
lcd_clr_line(1);
lcd_clr_line(2);
lcd_string(proj_str[0],1);
lcd_string(proj_str[1],2);
_delay_ms(2000);
lcd_clr_line(1);
lcd_clr_line(2);
while(1)
{
adc_chan0();
m_value=adc_scan();
calculate(t_on,data_str,2); //display rps
lcd_clr_line(2);
lcd_string(data_str,2);
calculate(pulse_buff*120,data_str,1);
//display rpm
lcd_clr_line(1);
lcd_string(data_str,1);
t_on=m_value/4; //load t_on and t_off values
t_off=255-t_on;
_delay_ms(1);
}
}
unsigned int adc_scan(void)
{
while(!bit_is_set(ADCSRA,4));
ADCSRA|=(1<<ADIF);
return ADC;
}
void calculate(unsigned int
data,unsigned char *t_value,unsigned char line)
{
unsigned int temp;
t_value[0]=(data/10000)+0x30;
temp=(data%10000);
t_value[1]=(temp/1000)+0x30;
temp%=1000;
t_value[2]=(temp/100)+0x30;
temp%=100;
t_value[3]=(temp/10)+0x30;
t_value[4]=(temp%10)+0x30;
if(line==1)
{
t_value[5]='r';
t_value[6]='p';
t_value[7]='m';
}
if(line==2)
{
t_value[5]='r';
t_value[6]='p';
t_value[7]='s';
}
t_value[8]=0;
return;
}
void pwm_init(void)
{
TCCR0=0x1B; //CTC mode, toggle OCO (pin4),prescalar divide by 64
TIMSK|=(1<<1); //set interrupt for o/p compare
SREG=0x80; //start global interrupt
TCNT0=0x00; //counter set to zero
return;
}
void intrpt0_init(void)
{
MCUCR|=0x03; //interrupt0 falling edge detect
GICR|=0x40; //interrupt detect enable
SREG=0x80; //start global interrupt
return;
}
void timer1_init(void)
{
//0.5 second timer
//timer 1 and timer 0 share same pre
scalar
//so timer 1 is working with 64 pre
scalar
TCNT1H=0xE1;
TCNT1L=0x7A;
TIMSK|=0x04; //timer0 interrupt enable
TCCR1A|=0x00;
TCCR1B|=0x03; //pre scalar (counter starts)
SREG=0x80; //start global interrupt
return;
}
//LCD
Interfacing
#ifndef lcd_C
#define lcd_C
#include <avr\io.h>
#include <stdio.h>
#include <util\delay.h>
#include "lcd.h"
void lcd_config(void)
{
DDRD=0b11100000;
DDRC=0b11110000;
//lower nibble of uC port is connected to higher nibble of lcd
PORTD&=~(1<<RW);
return;
}
void lcd_init(void)
{
lcd_config();
_delay_ms(30); // wait after power up
lcd_nibble(0x03,0); / send 03h 3 times to initialize
lcd_en_tgl();
_delay_ms(5);
lcd_en_tgl();
_delay_us(160);
lcd_en_tgl();
_delay_ms(5);
lcd_nibble(0x02,0); // enable 4 bit mode
_delay_us(160);
lcd_cmd(0x28); //set 4-bit mode and 2 lines @ 5x7
_delay_us(160);
lcd_cmd(0x10); //cursor move & shift left
_delay_us(160);
lcd_cmd(0x06); //entry mode = increment
_delay_us(160);
lcd_cmd(0x0C); //display on - cursor blink on
_delay_us(160);
lcd_cmd(0x01); //clear display ram
_delay_ms(2);
return;
}
void lcd_en_tgl (void)
{
PORTD|=(1<<EN);
PORTD&=~(1<<EN); //Enable pin
return;
}
void lcd_cmd(unsigned char letter)
{
// Command Function
//The RS is set to 0 to signify this
is a command
unsigned
char temp; // temp Variable
temp=letter; //move letter to temp
temp=temp>>4; //shift temp to right by 4
lcd_nibble(temp,0); //send out higher nibble
temp=letter; //move letter to temp
temp=temp&0x0F;
lcd_nibble(temp,0); //send out lower nibble
_delay_us(10);
return;
}
void lcd_char(unsigned char letter)
{
//TData Function
//The RS is set to 1 to signify this
is a command
unsigned char temp; // temp Variable
temp=letter; //move letter to temp
temp=temp>>4; //shift temp to right by 4
lcd_nibble(temp,1); //send out higher nibble
temp=letter; //move letter to temp
temp=temp&0x0F;
lcd_nibble(temp,1); //send out lower nibble
_delay_us(10);
return;
}
void lcd_nibble(unsigned char
nib,unsigned char reg_sel)
{
//unsigned char i,x;
if(reg_sel)
PORTD|=(1<<RS); // Set RS Pin (defined in header
file)
else
PORTD&=~(1<<RS);
nib=(nib<<4);
PORTC=nib;
_delay_us(5);
lcd_en_tgl(); // Toggle E pin (defined in
header file)
RW_INIT();
while(bit_is_set(PINC,7)); //busy check
lcd_config(); //reconfigure lcd i/o pins
return
}
void lcd_clr_line(unsigned char line)
{
// clear line command.
char tline;
// The line to clear variable
char x;
// loop variable
if(line==1) // Set the variable
value based on line
tline=0x80;
// 1 = Line 1
if(line==2)
tline=0xC0; //
2 = Line 2
lcd_cmd(tline); // Send command to jump to beggining
of line (1/2)
_delay_us(160)
for(x=0x00;x<0x14;x++)
{ // Loop through all 20 chars of line (even
tho 16 are viewabl
lcd_char(0x20);
// Send Blank Character
_delay_us(160);
}
lcd_cmd(tline);
// Go back to beggining of line
_delay_us(160);
return;
}
void lcd_string(unsigned char
*senpoint, unsigned char line)
{
if(line==1)
lcd_cmd(line1);
if(line==2)
lcd_cmd(line2);
while(*senpoint != '\0')
// While we havent seen a \0 (esc) go on
{
lcd_char(*senpoint); // Send 1st char to our char
function
senpoint++; // Send next
}
return;
}
lcd_single_char(unsigned char
*senpoint,unsigned char line,unsigned char position)
{
unsigned
char pos;
pos=position;
lcd_cmd(0x03); //return cursor to home position
if(line==1)
lcd_cmd(line1);
if(line==2)
lcd_cmd(line2);
while(pos!=0)
//first position or home position is 0 and last position is 15
lcd_cmd(0x14); //move to right
pos--;
}
while(*senpoint!='/0')
{
lcd_char(*senpoint); // send the character to be
displayed
senpoint++;
}
return;
}
#endif
it is a nice project to be understood and will you post the simulation circuit diagram for better understanding.
ReplyDeleteplz upload simulation of this project
ReplyDeletepls upload diagram. thx
ReplyDeletepease upload simulation of thi. thanks :)
ReplyDelete