March 17, 2025
Description
Buddy Jr.
I created Buddy Jr as a troubleshooting step with a larger Robot arm project I'm working on called Buddy (Buddy is the name of one of the robot arms Tony Stark uses in the movie Ironman). I wanted something that is really quick to print so I can test out different methods of moving the arm. The larger robot arm, Buddy, takes around 8 - 10 hours to print each individual part (with an arm piece being around 4 parts each), and Buddy arm takes around 40 minutes to print.
Design goals
When designing Buddy Jr, I wanted to create a robot arm that was:
Design
I used Fusion 360 to design Buddy Jr. The simple design consists of 4 servos, a base, a shoulder, an elbow, and a camera holder. The servos are controlled by a PCA9685 servo driver board, which is connected to a Raspberry Pi 5 (though any Pi with header pins will do).
v1 Base
Either use the v1 or updated v2 Base.
Updated v2 Base
Pivot
Either use the Pivot or the Shoulder.
Arm
Assembly
The assembly of Buddy Jr is straightforward. The servos are screwed into the base, shoulder, and elbow, and the camera holder is attached to the elbow. The servos are then connected to the PCA9685 board, which is connected to the Raspberry Pi.
Bill of Materials
| Item | Description | Quantity | Price | Total |
| Servos | SG90 servos | 4 | $2.50 | $10.00 |
| Servo Driver | PCA9685 | 1 | $14.00 | $14.00 |
| Camera | Raspberry Pi Camera Module | 1 | $25.00 | $25.00 |
| Raspberry Pi | Raspberry Pi 5 | 1 | $80.00 | $80.00 |
Note: You can use *any* Raspberry Pi with header pins, and any Raspberry Pi camera module compatible *with that model* of Raspberry Pi.
Python code
The latest version of the Python code for Buddy Jr can be found on https://www.github.com/kevinmcaleer/buddy_jr. The code uses the adafruit-circuitpython-servokit library to control the servos.
For now I'm not using the camera in the Python code, but I plan to add this in the future.
You can watch the output of the camera using the rpicam-hello -t 0 command in the terminal.
This code outlines a basic framework for a robotic arm controlled by a Raspberry Pi, utilizing the Adafruit CircuitPython ServoKit library. It's designed to move parts of the arm (base, shoulder, elbow, and a camera) to specific angles smoothly over a period and calculate positions using inverse kinematics. Here's a breakdown of how it works:
Setup and Initialization
- The Arm class initializes the servo controller with 16 channels, assuming you're using a PCA9685 PWM servo driver, which is common for such projects. This setup supports controlling up to 16 individual servo motors.
- Four servos are defined for different parts of the arm, each assigned to a specific channel. Initial angles are set to 90 degrees, aiming to start the servos in a neutral position.
Calibration
- The calibrate async method moves all servos (base, shoulder, elbow, camera) to a middle position (90 degrees). This method serves as a starting reference point to ensure all parts are aligned before any further operations.
Moving the Servos
- The move_to method is designed to move a servo on a specified channel to a target angle smoothly over a given duration. It does so by calculating the steps needed based on the duration and gradually moving the servo to the target angle using these steps.
- This method incorporates several checks, including ensuring the target angle is within a valid range (0 to 180 degrees) and the channel is within the expected range (0 to 15). If the target angle is outside the valid range, it defaults to 0 degrees as a safety measure.
Calculating Position with Inverse Kinematics
- The calculate_position method applies inverse kinematics principles to calculate the necessary angles for the shoulder, elbow, and camera to reach a target point (x, y). This method is crucial for determining how the arm should move to position the end effector (in this case, a camera) at a specific location in space.
- It calculates the distance to the target point and then uses the law of cosines to find the angles for the shoulder and elbow. The camera angle is adjusted to maintain a specific orientation, presumed to keep the camera facing forward by compensating for the movement of the other two joints.
Implementation Details and Considerations
- The Adafruit CircuitPython ServoKit library is utilized to simplify interfacing with the PCA9685 module, providing an easy way to control multiple servos.
- Asynchronous programming (asyncio) is used to allow the arm movements to be non-blocking, enabling the possibility of running other tasks concurrently or managing multiple arms simultaneously.
- This code includes mechanisms to deal with potential issues, such as invalid angles or servo channels, by setting safe defaults or skipping adjustments that would exceed the servo's capabilities.
Using on Raspberry Pi 5
- To run this on a Raspberry Pi 5, ensure that the CircuitPython libraries are installed and that the I2C interface is enabled on the Pi. This can usually be done through the raspi-config tool or the Raspberry Pi Configuration tool in the desktop interface.
- Make sure to connect the PCA9685 module correctly to the Pi's I2C pins (SCL, SDA, VCC, and GND) and to supply adequate power to the servos, especially if they require more current than the Pi can provide directly.
Powering the arm
I used a Pimoroni Yukon https://shop.pimoroni.com/collections/yukon with the [Bench Power supply module - https://shop.pimoroni.com/products/bench-power-module-for-yukon?variant=41186888122451 to provide power to the servos via the PCA9685 board. I *could* have used the Yukon to control the servos too, but I wanted to run the project from the Raspberry Pi as the camera is attached to the arm.
License:
BSD License
7