Technical hardware documentation and register mapping for the L293D Motor Driver Shield (compatible with Arduino Uno R3 / Mega 2560, based on the Adafruit Motor Shield v1 architecture) used on the tracked_bot platform.
Reference Documentation:
Datasheet References:
Hardware Images:
The L293D Motor Driver Shield stacks directly onto an Arduino Uno R3 form-factor board. It integrates two dual H-bridge motor driver ICs and an 8-bit serial-in/parallel-out shift register to drive multiple motors while minimizing the required microcontroller GPIO count:

tracked_bot.tracked_bot.
By splitting Left and Right tracks onto separate physical L293D ICs (M3 on IC2, M1 on IC1), each motor utilizes an independent thermal package and power stage, eliminating thermal choking and maximizing available motor torque.| Parameter | Specification | Notes |
|---|---|---|
| Motor Supply Voltage ($V_{motor}$) | 4.5 V to 24 V DC | Absolute maximum rating up to 36 V per L293D datasheet |
| Logic Supply Voltage ($V_{logic}$) | 5.0 V DC | Supplied directly from Arduino 5 V rail |
| Continuous Output Current | 600 mA (0.6 A) per channel | Depends on ambient temperature and heat dissipation |
| Peak Output Current | 1.2 A per channel | Non-repetitive transient / stall current |
| DC Motor Capacity | Up to 4 bidirectional DC motors | Individual 8-bit speed selection via PWM |
| Stepper Motor Capacity | Up to 2 stepper motors | Unipolar or bipolar (connected to M1–M2 and M3–M4) |
| Servo Motor Capacity | Up to 2 hobby RC servos (5 V) | Dedicated headers with a 100 µF filter capacitor |
| Over-Temperature Protection | Internal thermal shutdown | Disables output stages under excessive junction heat |
| Internal Clamping Diodes | Built-in flyback suppression diodes | Protects against inductive back-EMF spikes |
The shield features a 2-pin screw terminal block labeled EXT_PWR and an adjacent 2-pin jumper header labeled PWR (or PWR_JMP).
[!WARNING] Short-Circuit Danger: Never connect an external power source to the
EXT_PWRterminals while thePWRjumper is installed and the Arduino is connected to a computer USB port or DC power jack. Leaving the jumper installed bridges the external motor supply directly to the Arduino’s 5V/VIN rail, which can permanently destroy the Arduino board, the shield, and the host computer’s USB port!
| Configuration | PWR Jumper State |
Motor Supply Source | Arduino Logic Supply | Recommended Use Case |
|---|---|---|---|---|
| Mode 1: Single Supply | INSTALLED (Closed) | Powered via Arduino DC barrel jack or VIN |
Same as motor supply | Prototyping with low-power motors (<9–12 V) where motor noise does not brown out the MCU. |
| Mode 2: Dual / Separate Supplies (Recommended) | REMOVED (Open) | External battery or power supply connected to EXT_PWR (4.5 V – 24 V) |
USB cable or independent battery/power bank | Standard for tracked_bot: Isolates MCU logic from motor current surges, voltage dips, and inductive brush noise. |
The shield occupies digital pins D3 through D12. Digital pins D0, D1, D2, D13 and all analog pins A0 through A5 remain completely untouched by the shield and are exposed for user hardware:

| Arduino Pin | AVR Pin | Shield Net / Function | Dedicated Usage on Shield | tracked_bot Status / Usage |
|---|---|---|---|---|
| D0 (RX) | PD0 |
Unused by shield | None | USART0 RX – Serial UART reception from Host (115200 8-N-1) |
| D1 (TX) | PD1 |
Unused by shield | None | USART0 TX – Serial UART telemetry transmission to Host (115200 8-N-1) |
| D2 | PD2 |
Unused by shield | None | FREE GPIO – External Interrupt 0 (INT0), sensors, encoders |
| D3 | PD3 |
PWM2B (OC2B) |
Motor 2 Speed / Enable (IC1 3,4EN) | Reserved (unused on tracked platform) |
| D4 | PD4 |
DIR_CLK |
74HC595 Shift Clock | 74HC595 Clock Line |
| D5 | PD5 |
PWM0B (OC0B) |
Motor 4 Speed / Enable (IC2 3,4EN) | Reserved (formerly Right Track) |
| D6 | PD6 |
PWM0A (OC0A) |
Motor 3 Speed / Enable (IC2 1,2EN) | Left Track PWM Speed (Timer0 Fast PWM) |
| D7 | PD7 |
DIR_EN |
74HC595 Output Enable (active LOW) | 74HC595 Output Enable (~OE) |
| D8 | PB0 |
DIR_SER |
74HC595 Serial Data Input | 74HC595 Serial Data (SER) |
| D9 | PB1 |
PWM1A (OC1A) |
Servo 2 PWM Control (SERVO_2) |
Reserved / Free for pan-tilt servo |
| D10 | PB2 |
PWM1B (OC1B) |
Servo 1 PWM Control (SER1) |
Reserved / Free for pan-tilt servo |
| D11 | PB3 |
PWM2A (OC2A) |
Motor 1 Speed / Enable (IC1 1,2EN) | Right Track PWM Speed (Timer2 Fast PWM) |
| D12 | PB4 |
DIR_LATCH |
74HC595 Storage Latch Clock | 74HC595 Latch Line (RCLK) |
| D13 | PB5 |
Unused by shield | Arduino Uno onboard LED | FREE GPIO / SPI SCK / Built-in LED |
| A0 | PC0 |
Analog Breakout | None | Battery Voltage Sense (resistive voltage divider) |
| A1 | PC1 |
Analog Breakout | None | HC-SR04 Ultrasonic Trigger / Analog Sensor |
| A2 | PC2 |
Analog Breakout | None | HC-SR04 Ultrasonic Echo / Analog Sensor |
| A3 | PC3 |
Analog Breakout | None | FREE GPIO / Analog Input |
| A4 (SDA) | PC4 |
Analog Breakout | None | I2C SDA – IMU/Gyro (MPU-6050) or OLED display |
| A5 (SCL) | PC5 |
Analog Breakout | None | I2C SCL – IMU/Gyro (MPU-6050) or OLED display |
The 74HC595 shift register deserializes an 8-bit word clocked in from the microcontroller into the 8 direction control signals feeding the L293D H-bridges.
flowchart LR
subgraph MCU ["<b>ATmega328P (Control Pins)</b>"]
D4["<b>D4 (PD4)</b><br/>Shift Clock"]
D7["<b>D7 (PD7)</b><br/>Output Enable"]
D8["<b>D8 (PB0)</b><br/>Serial Data"]
D12["<b>D12 (PB4)</b><br/>Storage Latch"]
end
subgraph ShiftReg ["<b>74HC595 (8-Bit Shift Register)</b>"]
SH_CP["<b>SH_CP</b><br/>Shift Clock"]
OE["<b>~OE</b><br/>Output Enable"]
DS["<b>DS</b><br/>Serial Data In"]
ST_CP["<b>ST_CP</b><br/>Storage Latch"]
OUTPUTS["<b>Outputs Q0..Q7</b><br/>Direction Demux Bus"]
end
subgraph HBridge ["<b>Dual L293D H-Bridges</b>"]
M1_DIR["<b>Motor 1 Direction</b><br/>Right Track"]
M2_DIR["<b>Motor 2 Direction</b><br/>Auxiliary"]
M3_DIR["<b>Motor 3 Direction</b><br/>Left Track"]
M4_DIR["<b>Motor 4 Direction</b><br/>Auxiliary"]
end
D4 -->|"CLK"| SH_CP
D7 -->|"EN (~OE)"| OE
D8 -->|"SER"| DS
D12 -->|"LATCH"| ST_CP
SH_CP & OE & DS & ST_CP --> OUTPUTS
OUTPUTS -->|"Q2, Q3"| M1_DIR
OUTPUTS -->|"Q1, Q4"| M2_DIR
OUTPUTS -->|"Q5, Q7"| M3_DIR
OUTPUTS -->|"Q0, Q6"| M4_DIR
classDef mcuPin fill:#0c4a6e,stroke:#38bdf8,stroke-width:2px,color:#ffffff;
classDef regPin fill:#4338ca,stroke:#818cf8,stroke-width:2px,color:#ffffff;
classDef hBridge fill:#831843,stroke:#f472b6,stroke-width:2px,color:#ffffff;
class D4,D7,D8,D12 mcuPin;
class SH_CP,OE,DS,ST_CP,OUTPUTS regPin;
class M1_DIR,M2_DIR,M3_DIR,M4_DIR hBridge;
style MCU fill:none,stroke:#38bdf8,stroke-width:2px,stroke-dasharray: 4 4
style ShiftReg fill:none,stroke:#818cf8,stroke-width:2px,stroke-dasharray: 4 4
style HBridge fill:none,stroke:#f472b6,stroke-width:2px,stroke-dasharray: 4 4
| Shift Register Bit | Constant Identifier | L293D IC & Pin | Target Channel | Function |
|---|---|---|---|---|
| Bit 0 | SHIFT_BIT_MOTOR4_A |
IC2 Pin 10 (3A) |
Motor 4 | Direction A |
| Bit 1 | SHIFT_BIT_MOTOR2_A |
IC1 Pin 2 (1A) |
Motor 2 | Direction A |
| Bit 2 | SHIFT_BIT_MOTOR1_A |
IC1 Pin 10 (3A) |
Motor 1 | Direction A (Right Track) |
| Bit 3 | SHIFT_BIT_MOTOR1_B |
IC1 Pin 15 (4A) |
Motor 1 | Direction B (Right Track) |
| Bit 4 | SHIFT_BIT_MOTOR2_B |
IC1 Pin 7 (2A) |
Motor 2 | Direction B |
| Bit 5 | SHIFT_BIT_MOTOR3_A |
IC2 Pin 2 (1A) |
Motor 3 | Direction A (Left Track) |
| Bit 6 | SHIFT_BIT_MOTOR4_B |
IC2 Pin 15 (4A) |
Motor 4 | Direction B |
| Bit 7 | SHIFT_BIT_MOTOR3_B |
IC2 Pin 7 (2A) |
Motor 3 | Direction B (Left Track) |
Transmission of an 8-bit direction byte from ATmega328P follows this sequence:
DIR_LATCH (PB4 / D12) LOW to prepare the storage register.DIR_CLK (PD4 / D4) LOW.DIR_SER (PB0 / D8).DIR_CLK HIGH (data is shifted into the 74HC595 on the rising clock edge).DIR_LATCH HIGH (latches the internal 8-bit shift buffer onto output pins Q0–Q7).DIR_EN (PD7 / D7) LOW to keep the outputs enabled (active LOW).sequenceDiagram
autonumber
participant MCU as ATmega328P (Firmware)
participant LATCH as DIR_LATCH (PB4 / D12)
participant CLK as DIR_CLK (PD4 / D4)
participant SER as DIR_SER (PB0 / D8)
participant REG as 74HC595 (Shift Register)
participant OUT as L293D Inputs (Q0..Q7)
Note over MCU,LATCH: Step 1: Open Storage Register
MCU->>LATCH: Pull LOW (ST_CP)
loop Step 2: Shift 8 Bits (MSB Bit 7 down to LSB Bit 0)
MCU->>CLK: Pull LOW (SH_CP)
MCU->>SER: Set Bit Data Level (DS)
MCU->>CLK: Pull HIGH (Rising Edge)
REG->>REG: Shift bit into internal stage
end
Note over MCU,LATCH: Step 3: Latch Parallel Outputs
MCU->>LATCH: Pull HIGH (ST_CP)
REG->>OUT: Update outputs Q0..Q7 simultaneously
Serial Shift Timing Diagram:
DIR_LATCH (PB4) ---\___________________________________________/--- (ST_CP)
Bit 7 Bit 6 Bit 0
DIR_CLK (PD4) ___/---\___/---\___/---\___ ... _____/---\________ (SH_CP)
DIR_SER (PB0) ===< D7 >===< D6 >=================< D0 >====== (DS)
Outputs (Q0..Q7): [Previous Latch State Held] [New State Output]
See implementation in shift_reg.c and shift_reg.h.
Speed regulation is performed by driving the L293D enable inputs (1,2EN) with hardware Pulse Width Modulation (PWM):
flowchart LR
subgraph MCU_CTRL ["<b>Microcontroller & Shift Register</b>"]
PWM_M3["<b>PD6 / OC0A</b><br/>Timer0 Fast PWM"]
DIR_M3_A["<b>74HC595 Q5</b><br/>Dir A - M3_A"]
DIR_M3_B["<b>74HC595 Q7</b><br/>Dir B - M3_B"]
PWM_M1["<b>PB3 / OC2A</b><br/>Timer2 Fast PWM"]
DIR_M1_A["<b>74HC595 Q2</b><br/>Dir A - M1_A"]
DIR_M1_B["<b>74HC595 Q3</b><br/>Dir B - M1_B"]
end
subgraph IC2 ["<b>L293D IC2 (Left Track Actuation)</b>"]
EN_IC2["<b>1,2EN (Pin 1)</b><br/>PWM Speed Enable"]
A1_IC2["<b>1A (Pin 2)</b><br/>Half-Bridge 1"]
A2_IC2["<b>2A (Pin 7)</b><br/>Half-Bridge 2"]
OUT_M3["<b>M3 Channels</b><br/>Pins 3 & 6"]
EN_IC2 & A1_IC2 & A2_IC2 --> OUT_M3
end
subgraph IC1 ["<b>L293D IC1 (Right Track Actuation)</b>"]
EN_IC1["<b>1,2EN (Pin 1)</b><br/>PWM Speed Enable"]
A1_IC1["<b>1A / 3A</b><br/>Half-Bridge 1"]
A2_IC1["<b>2A / 4A</b><br/>Half-Bridge 2"]
OUT_M1["<b>M1 Channels</b><br/>Pins 11 & 14"]
EN_IC1 & A1_IC1 & A2_IC1 --> OUT_M1
end
subgraph Motors ["<b>Track Actuators</b>"]
LEFT_TRACK["<b>Left Track Motor (M3)</b>"]
RIGHT_TRACK["<b>Right Track Motor (M1)</b>"]
end
PWM_M3 -->|"PWM Duty Cycle"| EN_IC2
DIR_M3_A -->|"Direction Bit"| A1_IC2
DIR_M3_B -->|"Direction Bit"| A2_IC2
OUT_M3 ==>|"Bidirectional Drive"| LEFT_TRACK
PWM_M1 -->|"PWM Duty Cycle"| EN_IC1
DIR_M1_A -->|"Direction Bit"| A1_IC1
DIR_M1_B -->|"Direction Bit"| A2_IC1
OUT_M1 ==>|"Bidirectional Drive"| RIGHT_TRACK
classDef mcuStyle fill:#0c4a6e,stroke:#38bdf8,stroke-width:2px,color:#ffffff;
classDef hBridge fill:#831843,stroke:#f472b6,stroke-width:2px,color:#ffffff;
classDef motorStyle fill:#701a75,stroke:#e879f9,stroke-width:2px,color:#ffffff;
class PWM_M3,DIR_M3_A,DIR_M3_B,PWM_M1,DIR_M1_A,DIR_M1_B mcuStyle;
class EN_IC2,A1_IC2,A2_IC2,OUT_M3,EN_IC1,A1_IC1,A2_IC1,OUT_M1 hBridge;
class LEFT_TRACK,RIGHT_TRACK motorStyle;
style MCU_CTRL fill:none,stroke:#38bdf8,stroke-width:2px,stroke-dasharray: 4 4
style IC2 fill:none,stroke:#f472b6,stroke-width:2px,stroke-dasharray: 4 4
style IC1 fill:none,stroke:#f472b6,stroke-width:2px,stroke-dasharray: 4 4
style Motors fill:none,stroke:#e879f9,stroke-width:2px,stroke-dasharray: 4 4
Fast PWM Waveform Timing Diagram:
TCNT0 / TCNT2 (Counters)
^
255 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TOP
| /| /| /| /|
OCR | - - - - - / | - - - - - / | - - - - - / | - - - - - / | - - - - - OCR0A / OCR2A
| / | / | / | / |
0 +---------+---+---------+---+---------+---+---------+---+---------> Time
Output Pins: PD6 (OC0A, M3 Left) / PB3 (OC2A, M1 Right)
1 |=========| |=========| |=========| |=========| |
0 +---------+---+---------+---+---------+---+---------+---+--------->
|<--Duty->| |<--Duty->| |<--Duty->| |<--Duty->| |
|<------ Period ~1.024ms (976 Hz) ------->|
Timer0: 8-bit counter for Motor 3 (Left Track) on OC0A (PD6, pin D6).Timer2: 8-bit counter for Motor 1 (Right Track) on OC2A (PB3, pin D11).WGM = 3, 8-bit counter, TOP = 0xFF / 255).CS01 = 1, CS00 = 1 -> $f_{PWM} = \frac{16\,000\,000\,\text{Hz}}{64 \times 256} \approx 976.56\,\text{Hz}$CS22 = 1 -> $f_{PWM} = \frac{16\,000\,000\,\text{Hz}}{64 \times 256} \approx 976.56\,\text{Hz}$OCR0A: Duty cycle for Motor 3 (Left Track), range 0 (0% OFF) to 255 (100% full speed).OCR2A: Duty cycle for Motor 1 (Right Track), range 0 (0% OFF) to 255 (100% full speed).A frequency of ~976 Hz balances low acoustic motor whine with minimal switching losses in the bipolar L293D output transistors.
The tracked platform utilizes Motor 3 on IC2 for the left track drive and Motor 1 on IC1 for the right track drive:
| Channel | Desired Motion | PWM Duty (OCRxx) |
Dir A (74HC595) |
Dir B (74HC595) |
Output Terminals | Resulting State |
|---|---|---|---|---|---|---|
| M3 (Left Track, IC2) | Forward | 1 .. 255 |
MOTOR3_A (bit 5) = 1 |
MOTOR3_B (bit 7) = 0 |
Out 1 = HIGH, Out 2 = LOW | Track drives forward |
| Reverse | 1 .. 255 |
MOTOR3_A (bit 5) = 0 |
MOTOR3_B (bit 7) = 1 |
Out 1 = LOW, Out 2 = HIGH | Track drives reverse | |
| Dynamic Brake | 1 .. 255 |
MOTOR3_A (bit 5) = 0 |
MOTOR3_B (bit 7) = 0 |
Out 1 = LOW, Out 2 = LOW | Active dynamic braking | |
| Coast / Off | 0 |
Don’t care (X) |
Don’t care (X) |
High-Z floating | Track coasts freely | |
| M1 (Right Track, IC1) | Forward | 1 .. 255 |
MOTOR1_A (bit 2) = 1 |
MOTOR1_B (bit 3) = 0 |
Out 1 = HIGH, Out 2 = LOW | Track drives forward |
| Reverse | 1 .. 255 |
MOTOR1_A (bit 2) = 0 |
MOTOR1_B (bit 3) = 1 |
Out 1 = LOW, Out 2 = HIGH | Track drives reverse | |
| Dynamic Brake | 1 .. 255 |
MOTOR1_A (bit 2) = 0 |
MOTOR1_B (bit 3) = 0 |
Out 1 = LOW, Out 2 = LOW | Active dynamic braking | |
| Coast / Off | 0 |
Don’t care (X) |
Don’t care (X) |
High-Z floating | Track coasts freely |
Firmware driver references:
While tracked_bot primarily uses DC gearmotors on M3 and M4, the shield natively supports other actuator types:
[GND, +5V, Signal] pinout.SER1 (Servo 1): Arduino pin D10 (PB2 / Timer1 OC1B).SERVO_2 (Servo 2): Arduino pin D9 (PB1 / Timer1 OC1A).PWR jumper and power the Arduino logic separately via a 5 V USB power bank.| Symptom | Probable Cause | Corrective Action |
|---|---|---|
| Motors do not rotate | Power jumper missing or no voltage on EXT_PWR |
Check LED indicator. Verify external battery voltage and connection polarity on EXT_PWR. |
| MCU reboots on motor startup | Voltage sag / brownout on shared power rail | Remove PWR jumper and power Arduino via dedicated USB supply. |
| One track rotates backwards | Inverted motor polarity or shift register bit order | Swap the motor wires on the M3/M4 screw terminal, or invert direction flags in l293d_shield.c. |
| Motor hums but cannot move | PWM duty cycle is below the motor deadband | Increase OCR0x starting threshold (typically duty cycle > 25–30% is needed to overcome gearbox friction). |
| Servo twitches / jitters | Insufficient 5 V current or supply ripple | Use an external 5 V BEC/regulator for servos or avoid powering heavy servos from the Arduino 5 V pin. |