Skip to content

Robot Arm - Embedded Rust Project

Robot Arm

A learning journey into embedded Rust development - This project explores the Embassy async runtime framework to control a physical robot arm using a Raspberry Pi Pico microcontroller.

Overview

This is a hands-on learning project that combines:

  • Embedded Rust development with the Embassy framework
  • Hardware control of servo motors and sensors
  • Real-time systems programming
  • Physical computing with microcontroller platforms

Hardware Requirements

Core Components

  • Raspberry Pi Pico (or Pico W for wireless features)
  • Debug Probe (or second Pico configured as debug probe)
  • EEZYbotARM MK1 robot arm with 5 servo motors
  • USB Cable for programming and power

Optional Hardware

  • Potentiometers for manual control input
  • Additional sensors (ultrasonic, infrared, etc.)
  • Power supply for servo motors (separate from Pico power)

Software Architecture

Embassy Framework

The project uses the Embassy async runtime, which provides:

  • Async/await syntax for embedded development
  • Hardware abstraction layers (HAL) for Pico peripherals
  • Real-time task scheduling
  • Interrupt handling and device drivers

Key Components

// Core Embassy setup
use embassy_rp::gpio::{Input, Output, Pull};
use embassy_rp::pwm::Pwm;
use embassy_time::{Duration, Timer};
// Servo control with PWM
let mut pwm = Pwm::new_output_a(pio, pin, config);
pwm.set_duty(duty_cycle);

Getting Started

Development Environment Setup

Terminal window
# Install Rust with embedded target
rustup target add thumbv6m-none-eabi
# Install probe-rs for debugging
cargo install probe-rs --features cli
# Install elf2uf2 for UF2 binary creation
cargo install elf2uf2

Building and Flashing

Terminal window
# Build the project (automatically flashes if Pico is connected)
cargo build
# Manual flash if needed
cargo build --release
elf2uf2 -d target/thumbv6m-none-eabi/release/robot-arm
# Then copy the UF2 file to the Pico's RPI-RP2 drive

Hardware Connections

Pico GPIO 0-4 → Servo signal pins
Pico GPIO 5-9 → Sensor inputs (optional)
Pico GPIO 10-14 → LED indicators (optional)
Pico GND → Common ground
Pico VBUS → 5V power for servos

Learning Objectives

Embedded Rust

Master async programming in resource-constrained environments

PWM Control

Learn pulse-width modulation for servo motor control

Real-time Systems

Understand timing-critical embedded applications

Hardware Abstraction

Work with HALs and device drivers

Project Roadmap

Phase 1: Basic Servo Control ✅

  • Set up Embassy project structure
  • Configure PWM outputs for servo control
  • Basic servo positioning and movement

Phase 2: Sensor Integration 🔄

  • Add potentiometer input for manual control
  • Implement feedback sensors on servos
  • Basic PID control for position accuracy

Phase 3: Web Interface 📋

  • HTTP server on Pico W
  • Web-based control interface
  • Real-time telemetry and monitoring

Phase 4: Advanced Features 📋

  • Inverse kinematics for precise positioning
  • Motion planning and path optimization
  • OTA firmware updates

Code Structure

robot-arm/
├── src/
│ ├── main.rs # Embassy executor and task setup
│ ├── servo.rs # Servo motor control abstraction
│ ├── kinematics.rs # Robot arm mathematics
│ └── web.rs # HTTP server (future)
├── memory.x # Linker script for Pico
├── rust-toolchain.toml # Specific Rust version
└── .woodpecker.yaml # CI/CD pipeline

Key Learnings

Embassy Framework Patterns

#[embassy_executor::main]
async fn main(spawner: Spawner) {
// Initialize peripherals
let p = embassy_rp::init(Default::default());
// Spawn async tasks
spawner.spawn(servo_control_task(p.PWM_CH0)).unwrap();
spawner.spawn(sensor_reading_task(p.ADC)).unwrap();
}

PWM Servo Control

// Configure PWM for servo (50Hz, 1-2ms pulse)
let mut config = PwmConfig::default();
config.top = 25000; // 50Hz
config.compare_a = 1500; // 1.5ms (neutral position)
// Set servo position (0-180 degrees)
fn set_servo_angle(pwm: &mut Pwm, angle: f32) {
let duty = (angle / 180.0 * 1000.0 + 1000.0) as u16;
pwm.set_duty(duty);
}

Challenges & Solutions

Memory Constraints

  • Problem: Limited RAM on Pico (264KB)
  • Solution: Careful memory management, avoid heap allocations in hot paths

Real-time Requirements

  • Problem: Servo control needs precise timing
  • Solution: Embassy’s async runtime with hardware timers

Debugging Embedded Code

  • Problem: Limited debugging capabilities
  • Solution: probe-rs debugger, serial logging, LED indicators

Resources & References

Documentation

Learning Materials

Contributing

This is primarily a learning project, but contributions are welcome:

  • Hardware expertise - Better servo control algorithms
  • Rust patterns - Idiomatic embedded Rust code
  • Documentation - Tutorials and guides for others learning

View on Codeberg | Hardware Setup Guide