DC motor with quadrature encoder (MO - SPG -30E)

Digital Fiber, Photoelectric, Laser Range, Optical, Temperature, Rotary Encoder, Ultrasonic, Gas, Gyro, Accelerometer, FlexiBend, Flexiforce, Compass......

DC motor with quadrature encoder (MO - SPG -30E)

Postby silveroblado » Thu Aug 25, 2011 10:41 pm

Hello members!!

I have a question regarding DC motor with quadrature encoder. I saw the video done by cytron controlling the dc motor with quadrature encoder, in which they are using the PID control. But the thing is that video the number of rotations of the shaft of the motor is already fixed.

I want to know how to get the number of rotations done by the dc motor with quadrature encoder. Only that nothing else, just the number of rotations or pulses generated. And it would be much better if it doesnt include PID control, because I cant understand it well. And I m using MD10C motor driver instead of L293.

I m using quadrature encoder with DC motor just to count the number of rotations or pulses to get the distance travelled....nothing else!! Please help as I am not able to get pass understanding how to do that. Thanks a lot!!
silveroblado
Apprentice
 
Posts: 32
Joined: Mon Aug 15, 2011 2:30 am
Location: Kuala Lumpur

Re: DC motor with quadrature encoder (MO - SPG -30E)

Postby silveroblado » Thu Aug 25, 2011 10:44 pm

silveroblado
Apprentice
 
Posts: 32
Joined: Mon Aug 15, 2011 2:30 am
Location: Kuala Lumpur

Re: DC motor with quadrature encoder (MO - SPG -30E)

Postby silveroblado » Thu Aug 25, 2011 10:44 pm

You can see the video above, the one posted by cytron!!they are controlling the dc motor using quadrature encoder.....I just want to know the number of rotations done by it, without setting any prefix value...whuich means my PIC should not know after how many rotations should my dc motor stop.....Just the value of rotations (counts) should be given to PIC nothing more!
silveroblado
Apprentice
 
Posts: 32
Joined: Mon Aug 15, 2011 2:30 am
Location: Kuala Lumpur

Re: DC motor with quadrature encoder (MO - SPG -30E)

Postby A380 » Fri Aug 26, 2011 3:14 pm

Hi,

For normal pulse counting encoder, it can measure the distance or rotation as well if the encoder moving in one direction only but it cant detect the rotation direction. Your PIC will count the pulse (pulse count increased) when it is rotated in both CW or CCW, so the count is incorrect to distance in this condition.

For quadrature encoder, your PIC has to monitor the pulses (two pulses) from quadrature encoder. These pulses are 90 degree different phase among each other. Since the direction of the rotation can be detected by these pulses, so the your PIC will decrease the count for reverse rotation.

More information about quadrature encoder, you can refer to the articles on Rohot Head to Toe Magazine Vol.7 and Vol.8
http://www.robothead2toe.com.my/
You can download it for free.

By the way, what kind of encoder you use in your project now?
User avatar
A380
Discoverer
 
Posts: 120
Joined: Tue May 19, 2009 2:44 pm
Location: Malaysia

Re: DC motor with quadrature encoder (MO - SPG -30E)

Postby silveroblado » Sat Aug 27, 2011 4:02 am

I m using the Quadrature encoder attached to DC motor (spur gear)...........Name is M0-SPG-30E.............

The code given by cytron is using PID control, which is quite confusing for me right now, I just need to know number of revolutions done by motor from going one place to another!!

In the sample program given by cytron (MO-SPG-30E), they have already told the PIC that motor has to turn 360 degrees or 720 degrees etc......but i dont want that, i need my PIC to just count the pulses, irrespective of the degree of rotation!!
silveroblado
Apprentice
 
Posts: 32
Joined: Mon Aug 15, 2011 2:30 am
Location: Kuala Lumpur

Re: DC motor with quadrature encoder (MO - SPG -30E)

Postby A380 » Sat Aug 27, 2011 1:18 pm

By referring to the sample code, the variable named as "CurrentPosition" is what you need.. that is the pulse count.. the real output rotation count is depending on your motor gear ratio due to the encoder is attached on motor shaft (before gear box). you can get its counting formula in the video I think. Hope this can help you..
User avatar
A380
Discoverer
 
Posts: 120
Joined: Tue May 19, 2009 2:44 pm
Location: Malaysia

Re: DC motor with quadrature encoder (MO - SPG -30E)

Postby silveroblado » Thu Sep 01, 2011 2:46 am

Here is code done by me to count number of 1's at A and B to count number of 11's!!Which helps me to know number of revolution!!right now I have not calculated how many 1's (counts) would be needed to make 360 degrees.........still this is just a basic code......Plz help me chk it and let me know if there is any room for improvement!!tq


#include <pic.h>
#include <htc.h>
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 20000000
#endif

//=============================================================================================================
__CONFIG (0x3F32 & HS & WDTDIS & BORDIS & LVPDIS);

//=============================================================================================================

#define DIRM1 RC3
#define PWMM1 RC1
#define DIRM2 RD0
#define PWMM2 RC2

#define buzzer RA3

#define A RA0 //present on motor M1
#define B RA1 //present on motor M1

//=============================================================================================================

void delay(unsigned long data);

void run_cwM1(unsigned char speed);
void run_ccwM1(unsigned char speed);
void stopM1 (unsigned char data);

void run_cwM2(unsigned char speed);
void run_ccwM2(unsigned char speed);
void stopM2 (unsigned char data);

//==============================================================================================================

bit initA, initB, stopA, stopB;
unsigned long countAB;

//==============================================================================================================


void main(void)
{
TRISA = 0b00000011; //configure PORTA I/O direction
TRISB = 0b00000000; //configure PORTB I/O direction
TRISC = 0b00000000;
TRISD = 0b00000000;
TRISE = 0b00000000;

PORTA = 0; //clearing all ports before use
PORTB = 0;
PORTC = 0;
PORTD = 0;
PORTE = 0;

CMCON = 0x07; //disable all the comparators
ADCON1 = 0x06; //configure PORTA as digital I/O

CCP1CON = 0b00001100;
CCP2CON = 0b00001100;
PR2 = 0xFF; //PWM Period Setting (4.88KHz)
T2CON = 0b00000101; //Timer2 On, prescale 4

while(1)
{
run_cwM1(0xff);
run_ccwM2(0xff);
initA = A; //get current A value
initB = B; //get current B value

if(A==1 && B==1)
{
countAB++;

if(countAB==10)
{
buzzer=1;
stopM1(1000);
stopM2(1000);
run_ccwM1(0xff);
run_cwM2(0xff);
countAB--;

if(countAB==0)
{
buzzer=1;
stopA;
stopB;
stopM1(1000);
stopM2(1000);
}
}
}
}
}

//======================================================================================================================
// BASIC MOTOR FUNCTION
//======================================================================================================================

void run_cwM1 (unsigned char speed) //run motor in clockwise direction
{

// Setup CCP2 as PWM.
CCP2M3 = 1;
CCP2M2 = 1;

DIRM1 = 1;
CCPR2L = 0xFF;
}

void run_ccwM1 (unsigned char speed) //run motor in counter clockwise direction
{

// Setup CCP2 as PWM.
CCP2M3 = 1;
CCP2M2 = 1;

DIRM1 = 0;
CCPR2L = 0xFF;
}

void stopM1 (unsigned char data) //brake or stop the motor motion
{

// Setup CCP2 as PWM.
CCP2M3 = 1;
CCP2M2 = 1;

DIRM1 = 0;
CCPR2L = 0x00;
delay(data);
}

//=========================================================================================================================

void run_cwM2 (unsigned char speed) //run motor in clockwise direction
{

// Setup CCP1 as PWM.
CCP1M3 = 1;
CCP1M2 = 1;

DIRM2 = 1;
CCPR1L = 0xFF;
}

void run_ccwM2 (unsigned char speed) //run motor in counter clockwise direction
{
// Setup CCP1 as PWM.
CCP1M3 = 1;
CCP1M2 = 1;

DIRM2 = 0;
CCPR1L = 0xFF;
}

void stopM2 (unsigned char data) //brake or stop the motor motion
{
// Setup CCP1 as PWM.
CCP1M3 = 1;
CCP1M2 = 1;

DIRM2 = 0;
CCPR1L = 0x00;
delay(data);
}

//===========================================================================================================================

void delay(unsigned long data) //delay function, the delay time
{
for( ;data>0;data--); //depend on the given value
}
silveroblado
Apprentice
 
Posts: 32
Joined: Mon Aug 15, 2011 2:30 am
Location: Kuala Lumpur

Re: DC motor with quadrature encoder (MO - SPG -30E)

Postby A380 » Thu Sep 01, 2011 3:52 am

Hi, you cant count on "11" state in while loop as you wrote. For encoder, we have to monitor the edge (raising or failing edge) but not the state.

If your code like this in while loop:
if(A==1 && B==1)
{
countAB++;
.........
}
your PIC has possibility to count more than once due to the "11" state stay too long time there and your count is totally wrong. Normally we use external interrupt pins to monitor the signal edge.

I think the sample code given by Cytron (Robot Head to Toe Magazine) is a good sample code. May be you can try to refer and modify it from there.
What PIC do you use?
User avatar
A380
Discoverer
 
Posts: 120
Joined: Tue May 19, 2009 2:44 pm
Location: Malaysia

Re: DC motor with quadrature encoder (MO - SPG -30E)

Postby silveroblado » Thu Sep 01, 2011 5:13 pm

I use PIC 16f877a!
silveroblado
Apprentice
 
Posts: 32
Joined: Mon Aug 15, 2011 2:30 am
Location: Kuala Lumpur

Re: DC motor with quadrature encoder (MO - SPG -30E)

Postby silveroblado » Thu Sep 01, 2011 5:17 pm

This is the code Cytron used for SPG - encoder.......code is given under the MO-SPG -30E.......I tried to modify it from there!!

// Author : Cytron Technologies Sdn Bhd
// Project : Sample code demonstration for Cytron DC Geared Motor with Encoder (MO-SPG-30E-XXXK)
// Project description : Demonstrate the usage of the Encoder at the motor
// Version : 1.0 Sep 2010
//
//==========================================================================


#include<pic.h>
__CONFIG (0x3F32);

#define rs RC3
#define e RC5
#define lcd_data PORTB
#define ButA RA0
#define ButB RA1
#define LEDRED RA3
#define LEDGREEN RA4

#define IN3 RC4
#define IN4 RC7
#define EN2 CCPR2L

#define A RA5
#define B RA2


void send_config(unsigned char data);
void delay(unsigned long data);
void send_char(unsigned char data);
void lcd_goto(unsigned char data);
void lcd_clr(void);
void send_string(const char *s) ;
void run_cw(unsigned char speed);
void run_ccw(unsigned char speed);
void stop (unsigned char data);
void motor_run(unsigned char speed, unsigned long degree);
void motor_run_overshoot(unsigned char speed, unsigned long degree);

bit initA, initB, stopA, stopB,end;
unsigned long bigdegree;
unsigned long desire_angle;
unsigned long smalldegree;
unsigned long limit;
unsigned long countAB;
unsigned long countover;
unsigned long countstop;
unsigned char gear_ratio;




void main(void)
{
TRISA = 0b11100111; //configure PORTA I/O direction
TRISB = 0b00000000; //configure PORTB I/O direction
TRISC = 0b00000000;

ADCON1 = 0b10000110; //configure PORTA as digital I/O

send_config(0b00000001); //clear display at lcd
send_config(0b00000010); //lcd return to home
send_config(0b00000110); //entry mode-cursor increase 1
send_config(0b00001100); //display on, cursor off and cursor blink off
send_config(0b00111000);

CCP2CON = 0b00001100;
PR2 = 0xFF; //PWM Period Setting (4.88KHz)
T2CON = 0b00000101; //Timer2 On, prescale 4
LEDRED=1;
LEDGREEN=1;

//================================================================
// By pressing button A, motor will rotate to the desired location
// and the overshoot occur on each and every time the motor rotates

// By pressing on button B, motor will rotates to the desired location
// with overshoot for the 1st time. If the load and the speed remain
// the motor will rotate and reach at the specified angle accurately
// after the 1st rotation.The idea is to pass the overshoot error to
// the next and compensate it to archieve better precision.
while(1)
{
if (ButA==0) //button A pressed?
{
while(ButA==0); //waiting for release
motor_run(254,360); //run motor at speed 254 for 360 degree
}
else if (ButB==0) //button B pressed?
{
while(ButB==0); //waiting for release
motor_run_overshoot(254,360); //run motor at speed 254 for angle 360degree
lcd_goto(0); //set lcd cursor to location 0
send_string("overshoot = "); //print string
lcd_goto(12); //set lcd cursor to location 12
send_char(countover/10 +0x30); //print tens digit of the overshoot counter
lcd_goto(13); //set lcd cursor to location 13
send_char(countover%10 +0x30); //print units digit of the overshoot counter
delay(50000);
}
else
stop(500); //motor not running
}
}
//==========================================================
// SAMPLE FUNCTION WITHOUT OVERSHOOT COMPENSATION
//==========================================================
void motor_run(unsigned char speed, unsigned long degree)
{
desire_angle = degree;
//in this case gear ratio is 1:20
gear_ratio = 20;
//convert the desired agle to the total angle at the rear shaft (multiply gear ratio)
smalldegree = desire_angle *gear_ratio;
//12 count per revolution at the rear shaft
//meaning each count represent 30 degree
//to calculate how many counts needed for the desire angle
//we divide total angle at the rear shaft with 30 degree
limit = smalldegree/30;

countAB=0; //reset the counter
lcd_clr(); //clear lcd screen
while(countAB < limit) //while counter is in the limit
{ //motor will overshoot because it can not sudden stop
initA = A; //get current A value //overshoot depends on load and speed of the motor
initB = B; //get current B value
do
{
run_cw(speed); //run motor in clockwise direction with user defined speed
}while(initA ==A && initB ==B); //continue run until state change
countAB++; //increment counter for each state change
}
//once program exit the previous while loop
//meaning that the motor has reached the desired angle
stop(1000);
}
silveroblado
Apprentice
 
Posts: 32
Joined: Mon Aug 15, 2011 2:30 am
Location: Kuala Lumpur

Next

Return to Sensor

Who is online

Users browsing this forum: No registered users and 17 guests

cron