Skip navigation
2015

A recent post appeared on the element14 community blog on the difference between different kind of motors led me to write this post. I am going to describe how to control a DC motor using Arduino UNO boards with a motor shield. There is a variety of methods to use an Arduino board to run a motor: they differ in complexity and cost. Using a motor shield makes running a motor relatively easy, even if it may be a bit expensive. However, the motor shield can drive other kind of motors and soon or later you will find it useful to have one of them.

 

DC motors have two wires: the wires must be connected to a DC voltage source to let the motor spin. They can rotate in both direction, depending how the wires are connected to the voltage source. Supposing you have a DC motor with a red and a green wire, if the motor rotates clockwise when the red wire is connected to the positive lead of a battery, it will rotate anticlockwise inverting the polarity.

 

DC motors usually work in a relatively wide range of voltages, usually between 9 and 12 V. It is important to avoid using voltages higher than recommended by the manufacturer, while if you use a voltage source that is too low, the motor does not get enough power to rotate. The speed at which the DC motor rotate depends on the voltage applied at its terminal. Hence, if the voltage is not constant, the speed will not be constant as well. Having some inertia, a DC motor will continue spinning for a while when the power is disconnected, so, if you connect and disconnect the external power rapidly, the motor will rotate at a speed that result from the weighted average of the speeds at 0 V and at the nominal voltage applied. The weighted depends clearly on the fraction of time the voltage is in fact applied to the motor leads: the higher the fraction the higher the speed.

 

Arduino boards provide a source of PWM signals that can be used to this aim. PWM stands for Pulse Width Modulation. In practice you can configure some of the Arduino pins to work as PWM pins on which a 5V signal is present only for a fraction of the time, the rest of the time being at 0V. The signal, then, appears as a square wave: the duration of the pulses ranging from 0 to T, where T is a characteristic time that may depend on the particular board used and its configuration (I will return on details about that in one of the next posts). Writing a 0 on a PWM pin results in having no signal at all on that pin, because the duration of the pin is 0. In this case we say that the duty cycle of the pin is 0. Setting the pin to 255, the pin stays at 5V 100% of the time T, hence we say that its duty cycle is 100%. Of course, any intermediate value can be used and putting the pin to 125 makes the pin to stay on for T/2 and off for the next T/2. In this case the duty cycle is 50% and the average voltage on that pin is 2.5V.

 

A DC motor cannot be directly connected to a PWM pin because it requires too much current. That's why we need a motor shield. An Arduino shield is a board that plugs on the Arduino one, in such a way it gets connected to all Arduino pins. The shield will use some of them, the others are left free to the user.

arduino motor shield

The motor shield I am using has two DC motor channel, called A and B. According to the documentation, both channels use 4 pins. In particular, channel A, uses the digital pins 3, 9 and 12 as PWM, brake and direction control, respectively, and the analog pin A0 for sensing the current driven by the motor.

 

The DC motor is connected to the + and - terminals corresponding to the A channel. Another pair of terminals are used to connect an external power source, such as a battery (labelled Vin and GND), while a second motor can be connected to another pair of terminals, labelled B (see the picture, where the terminals are highlighted by a red rectangle).

 

The PWM pin (pin 3) is used to regulate the speed of the motor. The maximum speed can be obtained setting this duty cycle at 100%, i.e. setting the pin at its maximum vale (255). The brake pin has two states: LOW and HIGH. When HIGH, the brake prevent the motor from moving. The direction pin, too, can be either LOW or HIGH: depending on the way in which the motor is connected to the terminals it set the direction of the rotation to be clockwise or anticlockwise.

 

Let's then look at the code to be deployed on the Arduino memory to use the motor, starting from the setup method.

#define ADIR 12
#define APWM 3
#define ABRAKE 9
#define ASENSE A0
void setup() {
  Serial.begin(9600);
  pinMode(ADIR, OUTPUT);
  pinMode(ABRAKE, OUTPUT);
}

 

The #define directives are used for convenience. This way we can identify the pin using a descriptive string rather than using integers, for which it can be difficult to remember the meaning. Sometimes you can find that this constants are not defined as above, but declaring global variables as

int ADIR = 12;
int PWM = 3;
int ABRAKE = 9;
int ASENSE = A0;

(I put the words "global variables" in italic, because being the Arduino programming language C++, they should be called members of the main class). This is not a very good idea, because variables takes space in memory and accessing them can result in a slower execution. If you define constants by directives as above, it helps in keeping the program shorter and faster.

 

The code above just tells to Arduino to consider both pin 12 and pin 9 as output digital pins. The Serial.begin(9600) statement is only needed if you want to write something on the serial monitor, as we are going to do below. We can then define a function (a method, using the appropriate language) to make the motor spin for a given time in a given direction with a given speed:

float go(int speed, int direction, int duration) {
  int count = 0;
  float averageCurrent = 0.;
  digitalWrite(ABRAKE, LOW);
  digitalWrite(ADIR, direction);
  int startTime = millis();
  int endTime = startTime + duration;
  analogWrite(APWM, speed);
  while (startTime < endTime) {
    averageCurrent += analogRead(ASENSE);
    count++;
    startTime = millis();
  }
  digitalWrite(ABRAKE, HIGH);
  return averageCurrent/count;
}


After setting to zero two variables (count and averageCurrent), this function release the brake and set the direction either LOW or HIGH. The direction is taken as a parameter and must be chosen by the programmer. It then put the current time in the startTime variable. In fact the time stored in this variable is given as the number of milliseconds elapsed since the beginning of the program, as returned by the millis() function. If the motor must stop rotating after duration milliseconds, the time at which we should stop the motor is given by startTime + duration. Setting the speed writing a number between 0 and 255 to the PWM pin the motor starts rotating (note that if speed is too low the motor may stay at rest).


We then start a loop in which we continuously measure since when the motor is running, such that when millis() returns a value higher than endTime we abandon the loop. Within the loop we also measure the current driven by the motor by means of analogRead(ASENSE), whose value is summed to averageCurrent. The count++ statement increments by one the counter called count.


When exiting the loop, the brake is activated, in such a way the motor stops. The method returns, then, the average value of the current reading (the average is the sum of the readings, divided by the number of them). It must be noted that what you measure with this statement is something that is related to the current required by the motor, but not as easy to use. First of all, the reading is a number between 0 and 1023 that correspond to a voltage between 0 and 5V. What you get from analogRead, then, is a voltage, not a current. Its value is the voltage drop across a resistor on the shield. Such a voltage raises when the PWM signal becomes on, remains constant while it stays on and decreases when it goes off, giving rise to a wave that is approximately rectangular. That means that what you measure with the above code is the average current driven by the motor in arbitrary units.


The loop() method looks like the following:

void loop() {
  float currentRequired = go(128, LOW, 3500);
  Serial.println(currentConsumption);
  delay(1000);
  currentRequired = go(128, HIGH, 3500);
  Serial.println(currentRequired);
  delay(1000);
}


When Arduino is powered, the motor starts rotating in one direction (say clockwise) at half of its maximum speed (128) for 3500 milliseconds. Then stops and we get the current required on average as the return value of the go() method. After showing the result on the serial monitor, we wait one second (delay(1000)), then restart the motor in the opposite direction (same speed, same duration).


Of course this is for demonstration purposes only. You can now use the go() method to let the motor rotate as you need. In the pictures below you can see my motor connected to the Arduino shield and to a 9V battery.


DC motor connected to Arduinoconnecting a DC motor to Arduino

The picture on the right shows how the connections are done on the motor shield.


As usual this blog post will appear on my personal web page, and its content will be part of the Scientific Arduino e-book: a freely available e-book in PDF that can be used as a standalone manual or as an addendum to Scientific Programming, a textbook to learn how to program in C for scientists published by World Scientific (available in Italian from Pearson).


During the past days I was busy with the preparation of a scientific exhibition that opened on September 25 for the European Research Night. The year 2015 is the International Year of the Light, as declared by the UN, hence the theme of the exhibition is the Light and its scientific applications.

We were working on a Newton's disc, when I came to the idea that one can easily build an electronic version of such a device. A Newton's disc is a disc divided in segments, each of which has a different color. When the disc spins rapidly, the coloured segments fade and the disc appears to be white. The Newton's disc is used to demonstrate that white light is in fact the superposition of light beams of different colours.

The reason for which the disc appears to be white is that images collected by our eyes persists on the retina for a while (1/20 of a second). When the disc spins and you look at a given sector, the coloured light coming from that sector enters you eye and 'remains' on its surface for such short time. However, if the disc spins rapidly enough, the light coming from the same place rapidly changes color and light of different colours hits the same portion of the retina in less than 1/20 of a second. The eye then receives a series of different signals in a short time window and our brain interprets all these signals as a single image providing the illusion that the disc is white.

We can do the same using an RGB LED.

A RGB LED is a LED capable of emitting three colours with different intensities: red, green and blue. Weighting the light of each color allows us to produce light of mostly any color. Instead of mixing three colours at the same time, one can switch on and off each color at the time. If the switching time is low enough you can easily distinguish the sequence: red, green, blue, red, green, blue, etc.. However, if each color is on for a very short time, the eye detect each color in less than its persistence time and interprets the sequence of the three colours as just their sum: white.

RGB LED's exist in two flavours: common cathode and common anode. Both have four pins and contain, in fact, three coloured LED's. In the common cathode pins, the longest one is the cathode to be connected to the ground. Putting a voltage on the other three pins, a current flows through the appropriate LED and the device emits light of the corresponding color. In common anode LED's, the longest pin is the anode to be connected to the voltage source. Connecting the other pins to ground let the current flow.

In this example, I used a common cathode LED with an Arduino board: the longest pin was connected to the Arduino GND pin, while the other to pins 9, 10 and 11 (the PWM ones) by means of a resistor, to limit the current flowing.

Operating such a device is very simple. Just define the used pin as output pins and put them to zero in the setup:

 

void setup() {    
  // set pins as output pins
  pinMode( 9,   OUTPUT);  
  pinMode(10, OUTPUT);  
  pinMode(11,  OUTPUT);  

  // switch off all LED's
  digitalWrite( 9,   LOW);  
  digitalWrite(10, LOW);  
  digitalWrite(11,  LOW);  
}  

In the loop, you can just put each pin to an appropriate value in sequence. For example:

void loop() {
 int i = 9;
 while (i < 12) {
    // switch on a given color
    analogWrite(i, 125);
    // wait d milliseconds
    delay(500);
    // switch off that color
    analogWrite(i, 0);
    // go to next color
    i++;
  }
}

With this code you switch on a color for 0.5 s, then switch it off and repeat the sequence on each color. Reducing the delay to 50 milliseconds you can no more distinguish the single colours. The switching between them is so fast that what you can see is just white light.

The movie above shows my Arduino Newton's disc looping such that the time for which each color lasts is progressively reduced until the eye can no more see the single colours switching. In the end, the LED appears as white.

RGB LED's, in fact, is yet another applications of the Newton's theory of light that can be either interpreted in the wave theory. What happens in an RGB LED is that lights of three colours and different intensities sum up and the result is light whose color is the "sum" of the three beams. Modern TV's and computer monitors, as well as phone screens and similar devices works the same way: the screen is divided in pixels, each of which is made of three tiny light sources of three colours (red, green and blue). Switching on and off with the appropriate intensity each of the sub-pixels results in the image on the screen.

Filter Blog

By date: By tag: