Module 10: Motors & Movement
Level: 🟡 Intermediate
Board: Arduino Uno
Prerequisites: Modules 5, 7
Estimated time: 70–90 minutes
Goal: Control different types of motors safely and understand their electrical demands.
What You'll Learn
Motors turn electrical energy into physical movement. They're also the most electrically demanding components you'll work with: they draw high current, generate noise, and produce voltage spikes that can reset or damage your Arduino. In this module, you'll learn to control three types of motors (servo, DC, stepper), understand why each needs careful power management, and build a precision turntable.
10.1 Servo Motors: Precise Position Control
What Is a Servo?
A servo motor moves to a specific angle and holds it. Inside the housing: a DC motor, a gear train (for torque), and a feedback potentiometer (so the servo knows its current angle). You tell it "go to 90°" and it goes there and stays.
How Servo Control Works
Servos are controlled by a specific kind of PWM signal, but it's not the same as analogWrite() PWM.
| Parameter | Servo PWM | analogWrite PWM |
|---|---|---|
| Frequency | 50 Hz (20 ms period) | ~490 Hz or ~980 Hz |
| Pulse width range | 1 ms–2 ms | 0 ms–2 ms (at ~490 Hz) |
| What it controls | Angular position (0°–180°) | Average voltage (0–5V) |
The servo reads the pulse width:
- 1 ms pulse → 0° (full left)
- 1.5 ms pulse → 90° (center)
- 2 ms pulse → 180° (full right)
This happens 50 times per second. The Arduino Servo library handles all the timing.
Never use
analogWrite()for servos. The wrong frequency and pulse range will cause erratic behavior or damage.
Using the Servo Library
/*
* Module 10: Basic Servo Control
*
* Circuit:
* - Servo signal (orange/white) → pin 6
* - Servo VCC (red) → EXTERNAL 5V supply
* - Servo GND (brown/black) → GND (shared with Arduino)
*
* Board: Arduino Uno
*/
#include <Servo.h>
const int SERVO_PIN = 6;
Servo myServo;
void setup() {
myServo.attach(SERVO_PIN);
myServo.write(90); // Start at center
delay(500);
}
void loop() {
// Sweep from 0° to 180°
for (int angle = 0; angle <= 180; angle++) {
myServo.write(angle);
delay(15); // Give the servo time to reach the position
}
// Sweep back
for (int angle = 180; angle >= 0; angle--) {
myServo.write(angle);
delay(15);
}
}
Servo Power: Revisiting Module 5
From Module 5: servos need external power. The SG90 micro servo draws 100–250 mA when moving, with peaks up to 500 mA under load. That exceeds the Arduino's USB supply headroom.
Always:
- Power the servo from an external 5V supply (or 6V for standard servos; check the datasheet)
- Connect the external supply's GND to the Arduino's GND
- Add a 470µF electrolytic capacitor across the servo's power leads to absorb current spikes
- Only the signal wire connects to an Arduino pin
Potentiometer-Controlled Servo
const int POT_PIN = A0;
const int SERVO_PIN = 6;
Servo myServo;
void setup() {
myServo.attach(SERVO_PIN);
}
void loop() {
int potValue = analogRead(POT_PIN);
int angle = map(potValue, 0, 1023, 0, 180);
myServo.write(angle);
delay(15);
}
Servo Types
| Type | Rotation | Use Case |
|---|---|---|
| Standard servo | 0°–180° | Robotic arms, pan/tilt, gates |
| Continuous rotation servo | Full 360° | Wheels, winches (speed control, not position) |
| High-torque servo | 0°–180° | Heavy loads, larger mechanisms |
For continuous rotation servos, write(90) = stop, write(0) = full speed one direction, write(180) = full speed other direction.
10.2 DC Motors: Speed and Direction
The Simplest Motor
A DC motor spins when you apply voltage. Reverse the voltage, it spins the other way. Change the voltage, it changes speed. Simple concept, but driving one from an Arduino requires extra hardware.
Why You Can't Just Connect a DC Motor to a Pin
- Current: Even small DC motors draw 200–500 mA. Arduino pins max out at 40 mA.
- Back-EMF: When a motor stops, its inertia generates a reverse voltage spike that can damage electronics.
- Direction: Reversing a motor requires swapping the polarity of the power connections, and a single pin can't do that.
The H-Bridge: Motor Driver
An H-bridge is a circuit with four switches arranged in an "H" pattern. By closing different pairs of switches, current flows through the motor in either direction.
You don't build H-bridges from scratch; you use driver ICs or modules.
L298N Motor Driver Module
The L298N is the most common motor driver for Arduino projects. It can drive two DC motors independently.
L298N Specs:
- Motor supply: 5V–35V
- Output current: up to 2A per channel
- Logic voltage: 5V
- Built-in 5V regulator (can power your Arduino if motor supply is 7–12V)
L298N Pin Connections
| L298N Pin | Connection | Function |
|---|---|---|
| VCC (12V) | External motor power supply | Motor voltage (5V–35V) |
| GND | Arduino GND + power supply GND | Shared ground |
| 5V | Can supply 5V to Arduino (or leave NC if using USB) | Onboard regulator output |
| IN1 | Arduino digital pin | Motor A direction control |
| IN2 | Arduino digital pin | Motor A direction control |
| ENA | Arduino PWM pin | Motor A speed (PWM) |
| IN3 | Arduino digital pin | Motor B direction control |
| IN4 | Arduino digital pin | Motor B direction control |
| ENB | Arduino PWM pin | Motor B speed (PWM) |
| OUT1, OUT2 | Motor A terminals | Motor A power |
| OUT3, OUT4 | Motor B terminals | Motor B power |
Direction and Speed Control Logic
| IN1 | IN2 | Motor A |
|---|---|---|
| HIGH | LOW | Forward |
| LOW | HIGH | Reverse |
| LOW | LOW | Stop (coast) |
| HIGH | HIGH | Stop (brake) |
Speed is controlled by the PWM signal on ENA: analogWrite(ENA, 0–255).
Code: DC Motor Control
/*
* Module 10: DC Motor with L298N
*
* Circuit:
* - L298N IN1 → pin 7, IN2 → pin 8, ENA → pin 9 (PWM)
* - L298N VCC → external motor power supply (e.g., 9V)
* - L298N GND → Arduino GND + power supply GND
* - Motor connected to OUT1, OUT2
* - Potentiometer on A0 for speed control
*
* Board: Arduino Uno
*/
const int IN1 = 7;
const int IN2 = 8;
const int ENA = 9; // Must be PWM pin
const int POT_PIN = A0;
void setup() {
Serial.begin(9600);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(ENA, OUTPUT);
}
void motorForward(int speed) {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
analogWrite(ENA, speed);
}
void motorReverse(int speed) {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
analogWrite(ENA, speed);
}
void motorStop() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
analogWrite(ENA, 0);
}
void motorBrake() {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
analogWrite(ENA, 255);
}
void loop() {
int potValue = analogRead(POT_PIN);
// Center position (around 512) = stop
// Below center = reverse, above center = forward
if (potValue > 562) {
int speed = map(potValue, 562, 1023, 0, 255);
motorForward(speed);
Serial.print("Forward: ");
Serial.println(speed);
} else if (potValue < 462) {
int speed = map(potValue, 462, 0, 0, 255);
motorReverse(speed);
Serial.print("Reverse: ");
Serial.println(speed);
} else {
motorStop();
Serial.println("Stopped");
}
delay(50);
}
Flyback Diodes: Protecting Your Electronics
When a motor is suddenly disconnected (or when switching direction), the collapsing magnetic field in the motor coils generates a voltage spike (back-EMF). This spike can be 50–100V and will damage your driver IC and Arduino.
Flyback diodes (also called freewheeling diodes) provide a safe path for this current. The L298N module has built-in flyback diodes for its output. If you're building your own H-bridge with discrete transistors, you must add them yourself (1N4007 across each motor terminal, cathode toward the positive supply).
10.3 Stepper Motors: Precision Rotation
What Makes Steppers Different
A stepper motor moves in discrete steps, typically 1.8° per step (200 steps per revolution). You control exactly how many steps it takes, giving precise position control without a feedback sensor.
Types of Stepper Motors
| Type | Wires | Common Models |
|---|---|---|
| Bipolar | 4 | NEMA 17 |
| Unipolar | 5 or 6 | 28BYJ-48 |
The 28BYJ-48 with its ULN2003 driver board is the most common beginner stepper. It's cheap, comes with a driver, and is perfect for learning. It's also slow and weak; for real projects, you'll want a NEMA 17 with an A4988 or DRV8825 driver.
28BYJ-48 + ULN2003 Driver
Specs:
- Operating voltage: 5V
- Steps per revolution: 2048 (in half-step mode with built-in gear reduction)
- Current draw: ~240 mA
- Speed: ~15 RPM max at full torque
Wiring:
| ULN2003 Pin | Arduino Pin |
|---|---|
| IN1 | D8 |
| IN2 | D9 |
| IN3 | D10 |
| IN4 | D11 |
| VCC | External 5V (NOT Arduino 5V; too much current) |
| GND | Arduino GND + external supply GND |
Step Modes
Full step (4 steps per cycle): Strongest torque, coarser positioning.
| Step | IN1 | IN2 | IN3 | IN4 |
|---|---|---|---|---|
| 1 | HIGH | LOW | LOW | LOW |
| 2 | LOW | HIGH | LOW | LOW |
| 3 | LOW | LOW | HIGH | LOW |
| 4 | LOW | LOW | LOW | HIGH |
Half step (8 steps per cycle): Smoother movement, double the resolution.
The half-step sequence interleaves single-coil and dual-coil energizations, giving 8 positions per cycle instead of 4.
Code: Stepper with AccelStepper Library
The built-in Stepper library works but lacks acceleration control. The AccelStepper library is much better for smooth motion.
Install AccelStepper from the Library Manager.
/*
* Module 10: Stepper Motor with AccelStepper
*
* Circuit:
* - ULN2003: IN1→D8, IN2→D10, IN3→D9, IN4→D11
* (Note: pin order for AccelStepper is IN1, IN3, IN2, IN4)
* - ULN2003 VCC → External 5V supply
* - ULN2003 GND → Arduino GND + external GND
*
* Library: AccelStepper
* Board: Arduino Uno
*/
#include <AccelStepper.h>
// For 28BYJ-48 with ULN2003, use HALF4WIRE mode
// Pin order: IN1, IN3, IN2, IN4 (not sequential!)
AccelStepper stepper(AccelStepper::HALF4WIRE, 8, 10, 9, 11);
void setup() {
Serial.begin(9600);
stepper.setMaxSpeed(1000); // Steps per second
stepper.setAcceleration(500); // Steps per second²
Serial.println("Stepper ready");
}
void loop() {
// Rotate one full revolution (2048 half-steps for 28BYJ-48)
stepper.moveTo(2048);
// Run until target reached
while (stepper.distanceToGo() != 0) {
stepper.run();
}
delay(500);
// Return to start
stepper.moveTo(0);
while (stepper.distanceToGo() != 0) {
stepper.run();
}
delay(500);
}
Pin order warning: The AccelStepper library expects pins in the order IN1, IN3, IN2, IN4 for the 28BYJ-48. This is not a typo; it matches the coil activation sequence. If your motor vibrates but doesn't turn, the pin order is wrong.
Holding Torque and Power
When a stepper holds position, it continuously draws current through its coils to maintain torque. This means:
- The motor and driver get warm even when not moving
- Continuous current draw (240 mA for the 28BYJ-48)
- If you don't need to hold position, disable the outputs to save power:
// Release all coils — motor can spin freely, draws no current
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
10.4 Why Motors Need Separate Power
This topic was introduced in Module 5, but it's so critical for motor projects that we reinforce it here.
The Three Motor Power Problems
1. Current spikes: Motors draw much more current when starting or reversing than when running at steady speed. A motor rated for 300 mA might spike to 1A for a fraction of a second. If powered from the Arduino's 5V rail, this drops the voltage and resets the board.
2. Electrical noise: Motor brushes (in DC motors) create electromagnetic interference that appears as voltage spikes on the power line. These can corrupt sensor readings, cause I2C communication failures, and trigger false interrupts.
3. Back-EMF: When a motor is disconnected or suddenly stops, the collapsing magnetic field generates a reverse voltage that can damage driver ICs and the Arduino.
Protection Strategy
For every motor project, follow this checklist:
- External power supply for motor(s), rated for peak current + 30% margin
- Shared ground between Arduino and external supply
- 470µF–1000µF electrolytic capacitor across motor power leads
- 0.1µF ceramic capacitor across motor terminals (directly on the motor)
- Flyback diodes if not using a driver with built-in protection
- Separate power wiring (keep motor power wires physically away from signal wires)
Motor Shields vs. Discrete Drivers
| Approach | Pros | Cons |
|---|---|---|
| Motor shield (e.g., Adafruit Motor Shield) | Clean stacking, integrated design, library support | Expensive ($15–25), fixed pin usage |
| Discrete driver module (L298N, A4988) | Cheap ($2–5), flexible pin choice | More wiring, needs external power setup |
| Discrete transistors / MOSFETs | Cheapest, fully custom | Most complex, must add own protection |
For learning, discrete driver modules are the best balance of cost and simplicity. For polished projects, shields are cleaner.
Module Project: Motorized Turntable
Objective
Build a stepper-motor-driven turntable that rotates an object at a speed controlled by a potentiometer. An OLED display shows the current angle and speed. Pressing a button resets the position to 0°.
Components Needed
| Component | Quantity | Notes |
|---|---|---|
| Arduino Uno | 1 | |
| USB-B cable | 1 | |
| Breadboard | 1 | |
| 28BYJ-48 stepper motor + ULN2003 driver | 1 set | |
| SSD1306 OLED (128×64, I2C) | 1 | |
| Potentiometer (10kΩ) | 1 | Speed control |
| Pushbutton | 1 | Position reset |
| External 5V/2A power supply | 1 | For stepper motor |
| 470µF electrolytic capacitor | 1 | Motor power smoothing |
| Jumper wires | 10+ |
The Code
/*
* Module 10 Project: Motorized Turntable
*
* Stepper motor turntable with:
* - Potentiometer speed control (center = stop, left = CCW, right = CW)
* - OLED showing angle and speed
* - Button to reset position to 0°
*
* Circuit:
* - Stepper: ULN2003 IN1→D8, IN3→D10, IN2→D9, IN4→D11
* - ULN2003 power: EXTERNAL 5V (not Arduino!)
* - OLED: SDA→A4, SCL→A5 (I2C)
* - Potentiometer: wiper→A0, ends→5V/GND
* - Button: pin 7 (INPUT_PULLUP)
* - 470µF cap across external 5V supply
* - All GNDs connected together
*
* Libraries: AccelStepper, Adafruit SSD1306
* Board: Arduino Uno
*/
#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
// --- Pins ---
const int POT_PIN = A0;
const int BUTTON_PIN = 7;
// --- Stepper (28BYJ-48 with ULN2003) ---
AccelStepper stepper(AccelStepper::HALF4WIRE, 8, 10, 9, 11);
const int STEPS_PER_REV = 2048; // Half-step mode
// --- OLED ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// --- State ---
long currentSteps = 0;
float currentAngle = 0;
float currentSpeedRPM = 0;
bool isRunning = false;
// --- Debounce ---
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
// --- Display timing ---
unsigned long lastDisplayUpdate = 0;
const unsigned long DISPLAY_INTERVAL = 200;
void setup() {
Serial.begin(9600);
// Stepper setup
stepper.setMaxSpeed(800);
stepper.setAcceleration(400);
// Button
pinMode(BUTTON_PIN, INPUT_PULLUP);
// OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED not found");
while (1);
}
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
// Splash screen
display.setTextSize(2);
display.setCursor(10, 10);
display.println("Turntable");
display.setTextSize(1);
display.setCursor(10, 40);
display.println("Module 10 Project");
display.display();
delay(2000);
Serial.println("Turntable ready");
}
void updateDisplay() {
display.clearDisplay();
// Title
display.setTextSize(1);
display.setCursor(0, 0);
display.print("TURNTABLE");
// Running indicator
display.setCursor(80, 0);
display.print(isRunning ? "[RUN]" : "[STOP]");
display.drawLine(0, 10, 127, 10, SSD1306_WHITE);
// Angle (large)
display.setTextSize(2);
display.setCursor(0, 14);
char angleStr[10];
dtostrf(currentAngle, 6, 1, angleStr);
display.print(angleStr);
display.setTextSize(1);
display.setCursor(80, 14);
display.print("deg");
// Visual angle indicator (circle with line)
int centerX = 106;
int centerY = 22;
int radius = 10;
display.drawCircle(centerX, centerY, radius, SSD1306_WHITE);
float rad = currentAngle * PI / 180.0;
int lineX = centerX + radius * sin(rad);
int lineY = centerY - radius * cos(rad);
display.drawLine(centerX, centerY, lineX, lineY, SSD1306_WHITE);
// Speed
display.setTextSize(1);
display.setCursor(0, 36);
display.print("Speed: ");
display.print(currentSpeedRPM, 1);
display.print(" RPM");
// Direction
display.setCursor(0, 48);
if (currentSpeedRPM > 0.1) {
display.print("Direction: CW");
} else if (currentSpeedRPM < -0.1) {
display.print("Direction: CCW");
} else {
display.print("Direction: ---");
}
// Steps counter
display.setCursor(0, 57);
display.print("Steps: ");
display.print(stepper.currentPosition());
display.display();
}
void handleButton() {
unsigned long now = millis();
int reading = digitalRead(BUTTON_PIN);
if (reading != lastButtonState) {
lastDebounceTime = now;
}
if ((now - lastDebounceTime) > 50) {
static int buttonState = HIGH;
if (reading != buttonState) {
buttonState = reading;
if (buttonState == LOW) {
// Reset position
stepper.setCurrentPosition(0);
currentAngle = 0;
Serial.println("Position reset to 0°");
}
}
}
lastButtonState = reading;
}
void loop() {
unsigned long now = millis();
// --- Read potentiometer ---
int potValue = analogRead(POT_PIN);
// Dead zone in the center (stop zone)
if (potValue > 480 && potValue < 544) {
// Stop
stepper.setSpeed(0);
isRunning = false;
currentSpeedRPM = 0;
} else {
// Map pot to speed: left half = negative (CCW), right half = positive (CW)
float speed;
if (potValue >= 544) {
speed = map(potValue, 544, 1023, 0, 700);
} else {
speed = map(potValue, 480, 0, 0, -700);
}
stepper.setSpeed(speed);
isRunning = true;
// Convert steps/sec to RPM
currentSpeedRPM = (speed / STEPS_PER_REV) * 60.0;
}
// --- Run stepper ---
if (isRunning) {
stepper.runSpeed();
}
// --- Calculate angle ---
long pos = stepper.currentPosition();
currentAngle = fmod((pos * 360.0 / STEPS_PER_REV), 360.0);
if (currentAngle < 0) currentAngle += 360.0;
// --- Handle button ---
handleButton();
// --- Update display ---
if (now - lastDisplayUpdate >= DISPLAY_INTERVAL) {
lastDisplayUpdate = now;
updateDisplay();
}
}
Circuit Diagram (SVG)
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 500" font-family="monospace" font-size="11">
<!-- Arduino -->
<rect x="30" y="100" width="140" height="310" fill="#1a7a8a" stroke="#333" stroke-width="2" rx="8"/>
<text x="100" y="128" text-anchor="middle" fill="white" font-size="14" font-weight="bold">Arduino Uno</text>
<!-- Pins -->
<rect x="170" y="150" width="22" height="14" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
<text x="181" y="160" text-anchor="middle" fill="white" font-size="8">5V</text>
<rect x="170" y="170" width="22" height="14" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
<text x="181" y="180" text-anchor="middle" fill="white" font-size="8">GND</text>
<rect x="170" y="210" width="22" height="14" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
<text x="181" y="220" text-anchor="middle" fill="white" font-size="8">A0</text>
<rect x="170" y="240" width="22" height="14" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
<text x="181" y="250" text-anchor="middle" fill="white" font-size="8">A4</text>
<rect x="170" y="260" width="22" height="14" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
<text x="181" y="270" text-anchor="middle" fill="white" font-size="8">A5</text>
<rect x="170" y="300" width="22" height="14" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
<text x="181" y="310" text-anchor="middle" fill="white" font-size="8">D7</text>
<rect x="170" y="330" width="22" height="14" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
<text x="181" y="340" text-anchor="middle" fill="white" font-size="8">D8</text>
<rect x="170" y="350" width="22" height="14" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
<text x="181" y="360" text-anchor="middle" fill="white" font-size="8">D9-11</text>
<!-- External Power -->
<rect x="620" y="100" width="120" height="55" fill="#cc4444" stroke="#333" stroke-width="2" rx="6"/>
<text x="680" y="122" text-anchor="middle" fill="white" font-size="11" font-weight="bold">External</text>
<text x="680" y="140" text-anchor="middle" fill="white" font-size="10">5V / 2A</text>
<rect x="755" y="115" width="35" height="18" fill="none" stroke="#333" stroke-width="1.5" rx="3"/>
<text x="773" y="128" text-anchor="middle" font-size="7">470µF</text>
<!-- Shared GND -->
<line x1="192" y1="177" x2="750" y2="177" stroke="blue" stroke-width="2" stroke-dasharray="6,3"/>
<text x="460" y="172" text-anchor="middle" font-size="9" fill="blue" font-weight="bold">SHARED GND</text>
<!-- ULN2003 + Stepper -->
<rect x="500" y="230" width="120" height="80" fill="#ff9933" stroke="#333" stroke-width="2" rx="6"/>
<text x="560" y="255" text-anchor="middle" font-size="11" font-weight="bold" fill="white">ULN2003</text>
<text x="560" y="275" text-anchor="middle" font-size="9" fill="white">+ 28BYJ-48</text>
<text x="560" y="295" text-anchor="middle" font-size="8" fill="#ffddaa">Stepper Motor</text>
<!-- Stepper control wires -->
<line x1="192" y1="337" x2="500" y2="250" stroke="orange" stroke-width="1.5"/>
<text x="340" y="280" font-size="8" fill="orange">IN1-IN4 (D8-D11)</text>
<!-- Stepper power from external -->
<line x1="680" y1="155" x2="680" y2="240" stroke="red" stroke-width="2"/>
<line x1="680" y1="240" x2="620" y2="240" stroke="red" stroke-width="2"/>
<text x="655" y="230" font-size="8" fill="red">EXT 5V</text>
<!-- OLED Display -->
<rect x="350" y="360" width="130" height="70" fill="#222" stroke="#333" stroke-width="2" rx="6"/>
<rect x="363" y="370" width="104" height="42" fill="#000" stroke="#555" stroke-width="1" rx="3"/>
<text x="415" y="390" text-anchor="middle" fill="#00ccff" font-size="10">123.5° CW</text>
<text x="415" y="404" text-anchor="middle" fill="#00ccff" font-size="8">5.2 RPM</text>
<text x="415" y="425" text-anchor="middle" fill="white" font-size="9">SSD1306 OLED</text>
<line x1="192" y1="247" x2="350" y2="385" stroke="#cc8800" stroke-width="1.5"/>
<text x="260" y="320" font-size="8" fill="#cc8800">SDA (A4)</text>
<line x1="192" y1="267" x2="350" y2="400" stroke="#008800" stroke-width="1.5"/>
<text x="260" y="340" font-size="8" fill="#008800">SCL (A5)</text>
<!-- Potentiometer -->
<rect x="350" y="100" width="80" height="40" fill="#ddd" stroke="#333" stroke-width="1.5" rx="4"/>
<text x="390" y="122" text-anchor="middle" font-size="9">10kΩ POT</text>
<line x1="192" y1="217" x2="350" y2="120" stroke="green" stroke-width="1.5"/>
<text x="265" y="165" font-size="8" fill="green">Wiper (A0)</text>
<!-- Button -->
<rect x="350" y="160" width="70" height="30" fill="none" stroke="#333" stroke-width="1.5" rx="4"/>
<text x="385" y="179" text-anchor="middle" font-size="9">Reset BTN</text>
<line x1="192" y1="307" x2="350" y2="175" stroke="purple" stroke-width="1.5"/>
<text x="265" y="238" font-size="8" fill="purple">D7</text>
</svg>
Circuit Schema (JSON)
{
"module": 10,
"project": "Motorized Turntable",
"board": "Arduino Uno",
"schematic": {
"components": [
{
"id": "U1", "type": "arduino_uno",
"pins_used": {
"5V": "net_arduino_vcc", "GND": "net_gnd",
"A0": "net_pot_wiper", "A4": "net_sda", "A5": "net_scl",
"D7": "net_button", "D8": "net_in1", "D9": "net_in2", "D10": "net_in3", "D11": "net_in4"
}
},
{ "id": "PS1", "type": "power_supply", "value": "5V", "max_current": "2A",
"pins": { "positive": "net_ext_vcc", "negative": "net_gnd" } },
{ "id": "C1", "type": "capacitor_electrolytic", "value": "470", "unit": "uF",
"pins": { "positive": "net_ext_vcc", "negative": "net_gnd" } },
{ "id": "DRV1", "type": "uln2003_driver",
"pins": { "in1": "net_in1", "in2": "net_in2", "in3": "net_in3", "in4": "net_in4",
"vcc": "net_ext_vcc", "gnd": "net_gnd" } },
{ "id": "MOT1", "type": "stepper_motor", "model": "28BYJ-48",
"steps_per_rev": 2048, "current_draw": "240mA",
"connection": "Connected to ULN2003 output via ribbon cable" },
{ "id": "OLED1", "type": "ssd1306", "protocol": "I2C", "address": "0x3C",
"pins": { "vcc": "net_arduino_vcc", "gnd": "net_gnd", "sda": "net_sda", "scl": "net_scl" } },
{ "id": "POT1", "type": "potentiometer", "value": "10000", "unit": "ohm",
"pins": { "pin1": "net_arduino_vcc", "wiper": "net_pot_wiper", "pin3": "net_gnd" } },
{ "id": "SW1", "type": "pushbutton",
"pins": { "pinA": "net_button", "pinB": "net_gnd" } }
],
"nets": [
{ "name": "net_gnd", "description": "Shared ground", "nodes": ["U1.GND", "PS1.negative", "C1.negative", "DRV1.gnd", "OLED1.gnd", "POT1.pin3", "SW1.pinB"] },
{ "name": "net_arduino_vcc", "nodes": ["U1.5V", "OLED1.vcc", "POT1.pin1"] },
{ "name": "net_ext_vcc", "description": "External 5V for motor", "nodes": ["PS1.positive", "C1.positive", "DRV1.vcc"] },
{ "name": "net_sda", "nodes": ["U1.A4", "OLED1.sda"] },
{ "name": "net_scl", "nodes": ["U1.A5", "OLED1.scl"] },
{ "name": "net_pot_wiper", "nodes": ["U1.A0", "POT1.wiper"] },
{ "name": "net_button", "nodes": ["U1.D7", "SW1.pinA"] },
{ "name": "net_in1", "nodes": ["U1.D8", "DRV1.in1"] },
{ "name": "net_in2", "nodes": ["U1.D9", "DRV1.in2"] },
{ "name": "net_in3", "nodes": ["U1.D10", "DRV1.in3"] },
{ "name": "net_in4", "nodes": ["U1.D11", "DRV1.in4"] }
],
"power": {
"usb": { "voltage": 5.0, "used_ma": 90, "note": "Arduino + OLED + pot" },
"external": { "voltage": 5.0, "used_ma": 240, "note": "Stepper motor" }
}
},
"code": { "filename": "module10_turntable.ino", "language": "cpp" },
"validation": {
"expected_behavior": "Pot controls speed and direction. OLED shows angle, RPM, direction. Button resets to 0°. Motor powered externally — no Arduino resets.",
"common_mistakes": [
"Motor vibrates but doesn't turn: AccelStepper pin order wrong — use IN1, IN3, IN2, IN4",
"Arduino resets when motor moves: motor drawing from Arduino 5V — use external supply",
"Motor runs in wrong direction: swap any two adjacent input pins",
"OLED flickers when motor runs: add 0.1µF cap near OLED, keep motor wires away from I2C lines",
"Speed unresponsive: pot center dead zone too wide or too narrow — adjust 480/544 values"
]
}
}
Self-Check: Module 10
Before moving to Module 11, make sure you can:
- Explain the difference between servo PWM and analogWrite PWM
- Wire and control a servo motor with external power
- Wire a DC motor with an L298N H-bridge for direction and speed control
- Explain back-EMF and why flyback diodes are needed
- Wire and control a stepper motor with a ULN2003 driver
- Choose between full-step and half-step modes
- Implement proper power isolation for all motor types
- Build the turntable project with smooth speed control and display
Key Terms Glossary
| Term | Definition |
|---|---|
| Servo motor | Motor with built-in feedback for precise angle control (0°–180°) |
| DC motor | Continuous rotation motor. Speed depends on voltage, direction on polarity |
| Stepper motor | Motor that moves in discrete steps for precise position control |
| H-bridge | Circuit that allows reversing motor polarity for bidirectional control |
| L298N | Common dual H-bridge motor driver module |
| Back-EMF | Voltage spike generated by a motor's collapsing magnetic field |
| Flyback diode | Diode that safely absorbs back-EMF energy |
| ULN2003 | Darlington transistor array commonly used to drive stepper motors |
| AccelStepper | Library for smooth stepper control with acceleration/deceleration |
| Holding torque | Force a stepper applies while stationary to hold position |
| NEMA 17 | Standard bipolar stepper motor size used in 3D printers and CNC |
| Half-step | Stepper mode that doubles resolution by interleaving coil activations |
| Continuous rotation servo | Modified servo that rotates 360°. Speed control, not position |
Previous: ← Module 9: Sound & Audio Next: Module 11: Arduino Nano & Compact Builds →