Table of Contents

DC motor speed

Necessary knowledge: [HW] Motor Module, [AVR] Digital Inputs/Outputs, [LIB] Motors, [LIB] Delay

Theory

DC motor with wheel

Permanent magnet DC motors are very common in robotics and mechatronics. DC motors are relatively easy to control, both direction and speed. Motor rotation direction is determined by power supply polarity and H-bridge driver is often used when DC motor is controlled by microcontroller.

Even DC motor speed is easy to control there is no guarantee that required speed is also actually obtained. The reason is that the actual speed depends on several factors, primarily of the torque applied on the shaft, feeding current and other motor characteristics. The relationship between torque and speed of a ideal DC motor is linear, which means: the higher is the load on the shaft the lower is the speed of the shaft and the higher is the current through the coil. In reality it is not linear and can vary depending on the motor quite a lot.

Controlling the speed of DC motor can be realized either by analogous or digital signaling.

PWM signal examples for one period

In general, motor speed is dependent of the applied voltage. When powering motor with its nominal voltage, motor runs at its nominal speed at no load condition. When reducing the voltage motor speed and torque also decreases. This kind of speed control can be called as analogous motor speed control. This can be realized for example with one transistor.

In robotics DC motors are in most cases controlled by microcontrollers and as microcontrollers are digital devices it is much easier to control motor speed also digitally. To do that, instead of keeping transistor open partly, transistors need to be closed and opened constantly using pulse width modulation (PWM), so the total energy supplied to the motor is somewhere between motor switched off and motor running on full power. Opened time in the whole PWM period is called duty cycle, which is marked as percents. 0% means the transistor is closed constantly – it is not conducting current. 100% means the transistor is constantly open and is conducting current all the time. The frequency of the PWM has to be high enough to avoid vibrations in the shaft of the motor. At low frequencies the motor produces noise and due to that, modulation frequencies over 20 kHz are used quite often. On the other hand the efficiency of the transistors might not be so good at higher frequencies. Vibrating of the shaft of the motor is reduced by inertia of the rotor and the inductivity of the coils. Instead of using single transistor, H-bridge can be feed with the same PWM signal by controlling so motor speed and direction.

By using digital contorol, i.e. PWM signal to control the transistor and by this motor speed, there are several advantages over the analogous control. Most important ones for microcontroller driven systems are that speed can be controlled only by one single digital output (no need for complicated digital-analogous converter) and control is more effective (power dissipation are minimized).

Controlling motor speed with PWM

Simplified control schematics is shown on the figure. Control voltage Vc from microcontroller output pin turns on and off the transistor Q in approx. 20 kHz frequency. When Q is turned on (saturation), full current I flows freely through the motor M. In this state transistor acts as a closed switch and voltage on the transistor Vq is nearly 0 by leaving almost full Vdd across the motor. We can calculate the power dissipated by the transistor by using formula P = I × V. Applying this to Q:

P = I × Vq, and if Vq = 0 also P = 0 W

This means that almost no power is consumed by transistor when it is ON state. Similar situation is also when transistor is closed (OFF state). In this situation nearly no current flows through the motor and transistor. Calculating the power consumed by transistor once again:

P = I × Vq, and if I = 0 also P = 0 W

As a conclusion, when transistor operates only on and off states the efficiency can be very high as nearly no power is consumed by transistor itself. Compared with linear (analogous) control of the transistor when half of the power can be consumed by transistor in case motor is operated at half speed. However in practice, digital control (PWM) is also not totally lossless as transistors cannot be turned on and off instantaneously. Therefore little dissipation occurs in every transistor and every switching, by cousing bigger dissipation when frequency is higher.

Note: do not mix up RC Servo PWM signal with ordinary PWM signals.

Practice

The Motor module of the HomeLab includes motor board and DC motor equipped with integrated gearbox and encoder. Motor board allows connecting up to four DC motors. The schemes and instructions for connection are found in the chapter “Motors module”. Every motor is connected to H-bridge which is controlled with two digital output pins of the microcontroller. Motor speed is controlled by timers which are generating software PWM signal for H-bridge. Motor speed can be controlled by relative value between 0 to 255, where 0 means that motor is stopped and 255 that motor runs at maximum speed.

static pin dcmotor_pins[4][2] =
{
	{ PIN(B, 7), PIN(B, 4) },
	{ PIN(D, 1), PIN(D, 0) },
	{ PIN(D, 7), PIN(D, 6) },
	{ PIN(D, 5), PIN(D, 4) }
};
 
static int motorindex[4][2] =
{
	{ 0, 1 },
	{ 2, 3 },
	{ 4, 5 },
	{ 6, 7 }
};
 
// Initialize PWM for specified DC motor. 
void dcmotor_drive_pwm_init(unsigned char index, timer2_prescale prescaler)
{
  	unsigned char i, pwm;
 
	pin_setup_output(dcmotor_pins[index][0]);
	pin_setup_output(dcmotor_pins[index][1]);
 
	motor[index] = 1;
 
  	pwm = PWMDEFAULT;
 
  	for(i=0 ; i<CHMAX ; i++)      // initialize all channels
  	{
    	  compare[i] = pwm;           // set default PWM values
    	  compbuff[i] = pwm;          // set default PWM values
  	}
 
	// Timer 2 normal regime, set prescaler
	timer2_init_normal(prescaler);
  	// Timer 2 interrupts set enabled
	timer2_overflow_interrupt_enable(true);
 
  	// Enable global interrupts
	sei();
}
 
void dcmotor_drive_pwm(unsigned char index, signed char direction, unsigned char speed) 
{
	if(direction == -1)
	{
		compbuff[motorindex[index][0]] = 0x00;
		compbuff[motorindex[index][1]] = speed;
	}
	if(direction == 1)
	{
		compbuff[motorindex[index][0]] = speed;
		compbuff[motorindex[index][1]] = 0x00;
	} 
}

With the array dcmotor_pins in the library, the controlling pins of four motor-controllers are determined. Before controlling the motors and their speed, function dcmotor_drive_pwm_init with the number of the motor-controller (0 – 3) must be called out. It sets the pins as output. In addition prescaler - timer2_prescale prescaler have to be set as a second parameter. Prescaler sets PWM frequency and is important when using other timer based functions on the same time. If only motors are used TIMER2_NO_PRESCALE value is most suitable. If other timer based functions are used on the same time e.g. ultrasonic sensor TIMER2_PRESCALE_8 is recommended value. Bigger prescaler values are not suitable for DC motor speed control as vibration will be too high. However the same function can be used for example flashing the LED and in this case bigger prescaler values are important to consider.

For controlling motor speed the function dcmotor_drive_pwm is included into library. With this function three parameters are needed. First is motor index (0-3), second is direction -negative direction parameter is used to give to the motor one revolving direction and other direction with positive parameter, and 0 if the motor is stopped. Third parameter is speed where the value can be from 0 to 255. The speed value is not any specific rpm, but is relative value and the actual speed is depending on the motor and power supply. The precision of motor speed control is 8-bit, meaning that smallest controlling value is 1/255 of full speed.

The following is an example program which controls first DC motor (DC motor connector 0) so that motor speed is half of the full speed. The speed is modulated with PWM signal of controlling pin.

#include <homelab/delay.h>
#include <homelab/module/motors.h>
 
int main(void)
{
	// DC motor 0 init with no prescaler
  	dcmotor_drive_pwm_init(0, TIMER2_NO_PRESCALE);
 
  	while(1)
  	{   	
 		// DC motor drive with half of the nominal speed
		dcmotor_drive_pwm(0, 1, 128);			      
  	}
}

Another example program which controls first DC motor (DC motor connector 0) with potentiometer from Sensor module.

#include <homelab/delay.h>
#include <homelab/module/motors.h>
#include <homelab/adc.h>
 
int main(void)
{
	int speed;
 
	// Adjusting ADC
	adc_init(ADC_REF_AVCC, ADC_PRESCALE_8);
 
	// DC motor 0 init with no prescaler
  	dcmotor_drive_pwm_init(0, TIMER2_NO_PRESCALE);
 
  	while(1)
  	{
		// Potentiometer is connected to channel 3
		// Average of 4 samples are acquired
		speed = adc_get_average_value(3, 4);
 
		// DC motor drive with speed from potentiometer
		// As potentiometer has 10-bit output but DC motor drive 
		// function 8-bit input the adc output have to be converted 
		// to 8-bit e.g dividing the output with 4, or shifting bit 
		// 2 position >>2
		dcmotor_drive_pwm(0, 1, speed/4);
  	}
}