Tero's Arduino Blog

Using Arduino with Ada

Running a Motor with Motorshield and Pulse Width Modulation (PWM)

Required parts:

Optional parts:

Setup

Using a motor from Arduino is somewhat complex since you cannot directly connect the motor to the pins Arduino. Instead, for motor control you need to either build required circuit by yourself or use a motor shield.

Personally, I used Seeedstudio's motor shield. In addition, I soldered crimp connectors to the wires of the motor so it is easier to plug into the shield or to a breadboard.

Once you have the motor shield and the motor, connecting them is easy, as shown in the picture above. The Seeedstudio motor shield can control two motors, I connected my motor into M1 (motor 1) pins.

Code

To run motor at various speeds, you need to use Pulse Width Modulation (PWM) feature of Arduino. While AVR-Ada provides some support for PWM, I found it easier to do my own configuration.

The M1 pins on the Seeedstudio motor shield are controlled by digital pins 8, 9, and 11 of Arduino. The digital pins 8 and 11 control the direction and pin 9 controls the speed using PWM. Wiki page has a table and description for the control logic.

The pins 8 and 11 can be programmed simply with True or False values, but pin 9 needs to be adjusted via Timer 1 since we want to use PWM. The timer 1 control is handled by writing some values to TCCR1A and TCCR1B registers (the atmega328p datasheet tells the details).

We want 8-bit fast PWM with no prescaling and it happens by setting WGM13 and WGM10 bits to False, WGM11 and WGM12 bits to True, CS11 and CS12 bits to False and CS10 bit to True. Also, COM1A1 is set to True and COM1A0 to False to clear OC1A register on the compare match:

TCCR1A_Bits := (COM1A1_Bit => True,
                COM1A0_Bit => False,
                WGM10_Bit  => True,
                WGM11_Bit  => False,
                others => False);
TCCR1B_Bits := (WGM12_Bit => True,
                WGM13_Bit => False,
                CS10_Bit => True,
                CS11_Bit => False,
                CS12_Bit => False,
                others => False);

After this we can write the speed value to OCR1A register:

MCU.OCR1A := 16#D2#;

The complete code is here:

with AVR;
with AVR.MCU;
with AVR.Timer1;

use AVR;

procedure Motor is
   use AVR.MCU;

   IN_1 : Boolean renames MCU.PORTB_Bits (0); -- digital pin 8
   IN_2 : Boolean renames MCU.PORTB_Bits (3); -- digital pin 11
   EA_1 : Boolean renames MCU.PORTB_Bits (1); -- digital pin 9

begin
   MCU.DDRB_Bits (0) := DD_Output;
   MCU.DDRB_Bits (1) := DD_Output;
   MCU.DDRB_Bits (3) := DD_Output;

   -- Clockwise rotation
   IN_1 := False;
   IN_2 := True;

   MCU.PRR_Bits (MCU.PRTIM1_Bit) := Low;
   TCCR1A_Bits := (COM1A1_Bit => True,
                   COM1A0_Bit => False,
                   WGM10_Bit  => True,
                   WGM11_Bit  => False,
                   others => False);
   TCCR1B_Bits := (WGM12_Bit => True,
                   WGM13_Bit => False,
                   CS10_Bit => False,
                   CS11_Bit => True,
                   CS12_Bit => False,
                   others => False);

   MCU.OCR1A := 16#b2#;
   loop
      null; -- busylooping
   end loop;
end Motor;

As usual, the code can be found from Sourcehut Mercurial repository: motorshield. AVR-Ada 1.2 is required.


Copyright © 2012, 2013 Tero Koskinen - Theme Skeleton; Blogging engine Pelican; Powered by Python