Arduino Development
Senior 6 · ICT
Arduino Development
Lesson 4 of 5
25 min
A sensor on its own only reports. To open a gate, sound an alarm, pump water or move a robot arm, the Arduino must drive an actuator. Some actuators, such as a small LED, can run directly from a pin. Most cannot: a motor or a pump needs far more current than a pin's 20 mA, and must be switched through a transistor, a motor driver or a relay. This lesson covers the actuators you will use most, how to control how much they do, and how to position a servo motor precisely.
Definition
Pulse-width modulation (PWM): switching a digital pin on and off very fast, so that the average voltage depends on the fraction of time it is on. On the Uno, analogWrite(pin, value) with value 0 to 255 does this on the pins marked ~.
Duty cycle: the fraction of each period that the signal is HIGH, .
Servo motor: a motor with a built-in gearbox, position sensor and control circuit that turns its output shaft to the angle set by a control pulse. A typical hobby servo such as the SG90 turns through about 180°.
Relay: an electrically operated switch that lets a small control signal switch a separate, larger circuit.
| Actuator | Control from the Uno | Note |
|---|---|---|
| LED | digitalWrite on/off, or analogWrite for brightness | Always with a series resistor |
| Active buzzer | digitalWrite: sounds at one fixed pitch | Check its current; larger ones need a transistor |
| Passive buzzer | tone(pin, frequency, ms): any pitch | tone() stops PWM on pins 3 and 11 while it plays |
| Servo motor | The Servo library on any digital pin | Using it disables analogWrite on pins 9 and 10 |
| DC motor | Through a transistor or a motor-driver board (for example an L298N), with PWM for speed | Never directly from a pin |
| Pump, fan, lamp on a separate supply | A relay module's IN pin | Low-voltage (for example 12 V) loads only in school |
A pin can only be at 0 V or 5 V. PWM switches it about 490 times a second (about 980 times on pins 5 and 6), and the LED or motor responds to the average:
An LED switching 490 times a second looks steadily lit, just dimmer. This sketch fades an LED on PWM pin 9 and beeps a passive buzzer on pin 7 at full brightness:
// Fade an LED on PWM pin 9 up and down; beep a passive buzzer on pin 7 at full brightness
const int LED_PIN = 9; // must be a ~ (PWM) pin
const int BUZZER_PIN = 7;
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
for (int level = 0; level <= 255; level += 5) { // brighter
analogWrite(LED_PIN, level);
delay(20);
}
tone(BUZZER_PIN, 880, 200); // 880 Hz for 200 ms
for (int level = 255; level >= 0; level -= 5) { // dimmer
analogWrite(LED_PIN, level);
delay(20);
}
}
Worked example 1: duty cycle and average voltage
Find the duty cycle and the average voltage for analogWrite(9, 64), and the value that gives an average of about 3.0 V.
A servo is controlled by a pulse sent about 50 times a second (every 20 ms). The width of the pulse sets the angle: roughly 1 ms for one end of the range and 2 ms for the other, with exact values that vary between models. The Arduino Servo library generates these pulses for you; by default it uses 544 µs for 0° and 2400 µs for 180°. You only call attach(pin) once and then write(angle).
An SG90 has three wires: brown to GND, red to 5 V and orange to the signal pin. (Other servos use black, red and white or yellow.)
// Turn a potentiometer on A0 to set the angle of a servo on pin 9
#include <Servo.h>
const int POT_PIN = A0;
const int SERVO_PIN = 9;
Servo arm;
void setup() {
arm.attach(SERVO_PIN); // the library makes the control pulses
Serial.begin(9600);
}
void loop() {
int reading = analogRead(POT_PIN); // 0 to 1023
int angle = map(reading, 0, 1023, 0, 180); // 0 to 180 degrees
arm.write(angle);
Serial.print("Angle: ");
Serial.println(angle);
delay(15); // give the servo time to move
}
Turning the knob changes the voltage at A0 from 0 to 5 V; map turns the reading 0 to 1023 into an angle 0 to 180, and the servo follows.
Worked example 2: angle from the knob, and pulse width
The potentiometer reads 682. Find the angle, and estimate the pulse width the library sends.
A relay module contains a relay, a transistor to drive its coil, and usually an indicator LED. Its IN pin takes the Arduino's signal; its COM, NO (normally open) and NC (normally closed) screw terminals switch the separate circuit, for example a 12 V pump with its own battery. This sketch, which would water a plant pot when a soil sensor on A2 reads dry, shows the pattern:
// Switch a small 12 V pump through a relay module on pin 6 when the soil is dry
const int SOIL_PIN = A2; // analog soil-moisture sensor: higher reading = drier
const int RELAY_PIN = 6; // relay module IN pin
const int DRY_LEVEL = 600; // threshold found by testing
const int RELAY_ON = HIGH; // many modules switch on with LOW: if so, write LOW here
const int RELAY_OFF = (RELAY_ON == HIGH) ? LOW : HIGH;
void setup() {
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, RELAY_OFF); // pump off at start
Serial.begin(9600);
}
void loop() {
int soil = analogRead(SOIL_PIN);
bool dry = soil > DRY_LEVEL;
digitalWrite(RELAY_PIN, dry ? RELAY_ON : RELAY_OFF);
Serial.print("Soil: ");
Serial.print(soil);
Serial.println(dry ? " pump ON" : " pump off");
delay(1000);
}
Many relay modules are active low: the relay switches on when IN is LOW. The constant RELAY_ON lets you change that in one place. All the sketches in this lesson were compiled for the Uno with arduino-cli without errors.
Science Buddies: Control a Positional Servo Motor with an Arduino (Lesson #10). Watch the servo's three wires being connected and the Servo library's attach and write commands; compare with the wiring diagram above.
Warning
Motors and mains are not pin loads. Never connect a DC motor, pump or relay coil directly to a pin: the current will damage the board, and a motor's back-voltage needs a diode to absorb it (motor drivers and relay modules include this). Power more than one servo, or any larger motor, from a separate 5 V supply, with its GND joined to the Arduino's GND. Never wire a relay to mains electricity (230 V in Rwanda) in school: it can kill. Use low-voltage loads only.
Tip
Check the pin's timer before you plan. On the Uno, the Servo library takes over pins 9 and 10 for PWM, and tone() affects pins 3 and 11. If you need a servo, a fading LED and a buzzer together, put the servo on 9, the LED on 5 or 6, and the buzzer on any spare pin.
knob_servo. Check that the angle printed matches the servo.Check: the barrier never moves while a car is under it, closes 3 seconds after the car leaves, and the LEDs always match its position.
Practice
analogWrite(5, 200).map(300, 0, 1023, 0, 180) give?Sources and credits
This lesson adapts CC BY-SA material and is shared under CC BY-SA 4.0.