Intro
The Ultimate Guide to using Motors in Robotics (including ROS, Raspberry Pi)
A layered solution
Basic power, motor drivers
- First layer- DC motor with appropriate supply voltage
- ex) 12V DC motor connected to 12V battery with a switch
Motor Driver
- Motor Driver: Need a way to change the speed and direction, and control it remotely
Pulse Width Modulation (PWM)
- 30% Duty Cycle = 60% of max voltage
- Motor driver takes PWM input and amplifies it (PWM output)
Motor Controllers (open and closed loop)
- Motor controllers- A way to generate the PWM input signal
- takes in target speed/direction as input
Open-loop control
- A map between input and output signal
Close-loop control
- Need a way to measure live motor speed and feed it back to the motor controller and make sure the speed is right
PID Control
-
Look at how far we are away from where we want to be and adjust our signal accordingly (bigger changes for bigger errors)
-
Encoders
Pi as motor controller
- Why separate motor controller?
- Modularity (easier to swap)
- Allocation of compute resources
Comms layer
-
If motor controller is on same board as robot controller (e.g. raspberry pi), it makes it easier; otherwise, need a way to communicate
-
Onboard computer (rpi) transmit target speed (speed request)
-
Motor controller feed info back (speed, positions, currents, temps, etc)
-
Comms will often be a type of serial line
- Also CAN, I2C, PWM
- In this case we have a pi communicating to an Arduino using serial over USB
Robot controller and software driver
-
The overall control software for the robot needs to do 2 things:
- Calculate the speeds it wants the motor to go
- Needs to transmit those speeds, using appropriate protocol, to the motor controller
-
Robot Controller and “Driver” software
- In normal ROS, this can be 2 different nodes communicating over topics
- If using ros2_control
- robot controller is ros2 controller
- Driver- hardware interface- a separate library it loads to communicate with motors

Demo circuit overview
- Raspberry pi running a driver node in ROS- communicates over serial over USB to the motor controller giving it the speeds
- Instead of having the robot controller on board a real robot, this demo just has another ROS node running on the Dev machine with a GUI
- It will send the data over ROS topics over Wi-Fi

Wiring the motor driver
-
L298N Motor Driver
- Max 2A current per motor with 3A spikes
- Very cheap, but has a large voltage drop- ex) with a 12V battery it will only get 9-10V out (running 75% speed)
-
Wiring
- Bottom terminals: 12V in to power motors, 5V in to power the chip, and a common ground
- In this case, 5V terminal is left empty
- Pair of terminals on each side to supply power to the motors
- Onboard jumper enables a 5V regulator (he removed b/c doesn’t want conflicts with his own 5V power supply)
- 6 pins bottom right: control the motors
- Outer pairs: control speed
- Inner pairs: control direction
- Bottom terminals: 12V in to power motors, 5V in to power the chip, and a common ground
Making the motor controller, open-loop test

- Arduino nano
- Would like to redo the controller with a raspberry pi pico
- Instead of powering the nano over 5V, will power over USB
- Using a USB hub- minimize the amount of current drawn from the pi
- The 5V from arduino is piggybacked into the motor driver

Arduino firmware
- Upload the ros_arduino_bridge code to the Arduino
Test serial comms
- Install miniterm
sudo apt install python3-serial- start miniterm
miniterm -e /dev/ttyUSB0 57600- Check current encoder values (0 if not plugged in)
e0 0
Note: 255 = 1111 111 in binary
The largest 1 byte number
- Run both motors at full speed in open-loop raw PWM mode
o 255 255- Run motor 2 in reverse
o 0 -150Closed-loop with encoders
Set up ROS driver
- Want to interact with it from a higher level
- Raspberry pi connected to Arduino
Demo
- See Serial Motor Demo
- 2 ROS nodes
- 1 node running on the pi listening for motor speeds on a topic and sending them to the controller
- A GUI node on dev machine to send commands in a more user-friendly interface




