DC motor with encoder
In this article we will make a simple construction to understand the operation of the encoder in a DC motor.
The materials we will need to implement our construction are
- an Arduino Uno ,
- a DC power supply for the motor,
- an engine drive controller ,
- and a DC motor with an encoder adapted to its construction.
- an Arduino UNO Shield, blank perforated board
- some connection materials, thin wires in different colors
All the necessary connections will be made on the blank board. The board wiring I present below is a good guide to construction.
In the photo below you can see the DC motor I chose to use. As you can see it has a built-in encoder. It is up to you whether you want to use it as a simple DC motor or if you want to use the encoder or finally use the motor and the encoder together.
Engine
JGB37-520 DC motor with mechanical gearbox and encoder.
It is mainly used in variable speed cars, self-balancing cars (with two wheels), racing cars, monitoring car, robots and other related constructions.
The speed encoder operates using the Hall effect .
Engine wiring:
1, red: motor power supply + (polarity to white reverses motor drive)
2, black: encoder power supply -
3, yellow: signal line, (A)
4, green: signal line, (B )
5, blue: encoder power supply +
6, white: motor power supply - (alternating polarity with red reverses motor drive)
In our first construction we will use only the engine encoder to understand its operation. As you can see in the image below, the motor power cables, which are Red and White, are not connected. Only the encoder cables are connected. We will rotate the motor shaft by hand and monitor the signals generated.
An encoder works by observing changes in the magnetic field generated by a magnet attached to the motor shaft. Here you will find the principle of operation of the sensor based on the HALL effect .
As the motor rotates the encoder outputs will be activated periodically. When the magnet is rotated clockwise, output "A" will be activated first and when rotated counterclockwise, output "B" will be activated first. This way you know exactly when the motor shaft rotates. This can be very convenient for cases where we need to control the forward or backward movement of a DC motor.
The following diagram shows the phase difference between outputs A and B of the encoder. We will programmatically exploit this phase difference to control the motor movement.
The following figure shows the wiring for two identical engines on an Arduino UNO board. Other equipment will be connected to this board later. We will use in our example only the encoder from one engine.
It can be seen that there are two connectors for each motor, one for Motor A and one for encoder A. In this example we will only use the Encoder A
connector. Four connectors are connected to this connector. The two ends are for powering the encoder, GND and VCC. The two middle ones are connected one to pin D2 and the other to pin D10. Note here that pins D2 and D3 are the only ones used to create interrupts on the Arduino UNO board. We will encounter this when writing the program.
Let's write a very simple program to understand how a coder works and how to read the coder outputs.
To read the encoder, we will connect the encoder output pins to the Arduino terminals 2 and 10. Pin 2 is an interrupt pin. The encoder power cables will be connected to the Arduino 5V and GND.
//Author : Manolis Aristovoulidis
//Περιστρέφω το μοτέρ με το χέρι και μετράω και τυπώνω
// την ταχύτητα και την κατεύθυνση της κίνησης
//θετικοί αριθμοί συμβολίζουν κίνηση δεξιόστροφη,
//αρνητικοί αριθμοί συμβολίζουν αριστερόστροφη κίνηση
const byte encoder_pinA = 2; //A pin -> the interrupt pin 2
const byte encoder_pinB = 10; //B pin -> the digital pin 10
int pulses; //the number of the pulses
boolean Direction; //the rotation direction
void setup()
{
Serial.begin(57600); //Initialize the serial port
EncoderInit(); //Initialize the module
}
void loop()
{
Serial.print("Direction:");
if(Direction){
Serial.print("Forword ");
}else{
Serial.print("Backword ");
}
Serial.print("Pulses:");
Serial.println(pulses);
pulses = 0;
delay(100);
}
void EncoderInit()
{
Direction = true; //default -> Forward
pinMode(encoder_pinB,INPUT);
attachInterrupt(digitalPinToInterrupt(encoder_pinA), wheelSpeed, RISING );
}
void wheelSpeed()
{
int val = digitalRead(encoder_pinB);
if(val == LOW ){
Direction = false; //Reverse
pulses--;
}else{
Direction = true; //Forward
pulses++;
}
}
In the monitoring of the serial port we observe the following results.
From here you can download the program for the construction
Direction:Forword Pulses:0
Direction:Forword Pulses:0
Direction:Forword Pulses:0
Direction:Forword Pulses:3
Direction:Forword Pulses:17
Direction:Forword Pulses:38
Direction:Forword Pulses:63
Direction:Forword Pulses:85
Direction:Forword Pulses:102
Direction:Forword Pulses:112
Direction:Forword Pulses:117
Direction:Forword Pulses:112
Direction:Forword Pulses:98
Direction:Forword Pulses:86
Direction:Forword Pulses:74
Direction:Forword Pulses:64
Direction:Forword Pulses:53
Direction:Forword Pulses:42
Direction:Forword Pulses:33
Direction:Forword Pulses:25
Direction:Forword Pulses:17
Direction:Forword Pulses:8
Direction:Forword Pulses:0
Direction:Backword Pulses:-3
Direction:Backword Pulses:-17
Direction:Backword Pulses:-39
Direction:Backword Pulses:-54
Direction:Backword Pulses:-67
Direction:Backword Pulses:-79
Direction:Backword Pulses:-88
Direction:Backword Pulses:-92
Direction:Backword Pulses:-97
Direction:Backword Pulses:-89
Direction:Backword Pulses:-77
Direction:Backword Pulses:-66
Direction:Backword Pulses:-56
Direction:Backword Pulses:-45
Direction:Backword Pulses:-35
Direction:Backword Pulses:-27
Direction:Backword Pulses:-19
Direction:Backword Pulses:-12
Direction:Backword Pulses:-6
Direction:Backword Pulses:0
Direction:Backword Pulses:0
Direction:Backword Pulses:0
When it starts the program correlates the wheelSpeed () function with the interrupt that will occur in pin 2.
This interrupt will occur whenever the pulse in pin 2 rises (from 0 to 5V) whereupon the wheelSpeed () function will be executed. The signal line A of the encoder is connected to pin 2.
The first thing the wheelSpeed () function does is read the value of pin 10, ie the signal line B of the encoder. If its value is 0 (LOW) it means that the signal A precedes the B, that is, the movement is forward. At the same time it increases the value of the pulses by one unit.
In the other case where B precedes A the Direction variable becomes false and the pulse value decreases by one unit. For this reason we have negative values for the pulses when the motion is reversed.
The loop executed by the program (ie the loop function) every 100 msec sends the direction and pulse values to the serial port and resets the pulses.
So as we turn the engine by hand, the values we see in the table below are generated. These are snapshots of the engine condition per 100 msec.