GEO-DUDe Electronics¶
The GEO-DUDe servicer subscale model runs on a 12V system. A Raspberry Pi controls all 10 servos and a MACE reaction wheel via a PCA9685 PWM driver board over I2C. The entire system sits inside the rotating satellite body, powered by 120V AC mains passed through a slip ring.
Controller¶
| Main controller | Raspberry Pi 4 Model B (4 GB RAM) |
| Hostname | geodude |
| OS | Debian 13 (Trixie) / Raspberry Pi OS, kernel 6.12, aarch64 |
| IP | 192.168.4.166 (WiFi via groundstation hotspot) |
| PWM driver | PCA9685 16-channel I2C PWM board |
| Camera | RPi Camera Module 3 (IMX708, CSI) |
| Comms to ESP32 | WiFi |
| Comms to base station | WiFi (SSID: groundstation) |
SSH Access¶
| User | zeul |
| Auth | SSH key from groundstation (/home/zeul/.ssh/id_ed25519) |
Services¶
| Service | Port | Description |
|---|---|---|
sensor-server.service |
5000 | Sensor polling, PCA9685 control, camera stream |
attitude-controller.service |
5001 | PID attitude control loop |
The PCA9685 drives all 10 servo signal lines and the ESC PWM signal over I2C (2 Pi pins). The IMU and magnetic encoder also share the I2C bus (different addresses). Limit switches connect directly to Pi GPIO (10 needed, one per joint across both arms).
I2C address: 0x40. Initialized at 50Hz. Servo range: 500-2500us (center 1500us). ESC range: 1000-2000us.
Pi Connections¶
| Pi Pin | Goes To | Protocol | Notes |
|---|---|---|---|
| I2C SDA (GPIO 2) | PCA9685 | I2C | All 10 servo PWM signals |
| I2C SCL (GPIO 3) | PCA9685 | I2C | Shared bus |
| GPIO 4 | Arm 1 Base limit switch | Digital input | Internal pull-up |
| GPIO 5 | Arm 1 Shoulder limit switch | Digital input | Internal pull-up |
| GPIO 6 | Arm 1 Elbow limit switch | Digital input | Internal pull-up |
| GPIO 17 | Arm 1 Wrist Rotate limit switch | Digital input | Internal pull-up |
| GPIO 27 | Arm 1 Wrist Pan limit switch | Digital input | Internal pull-up |
| GPIO 22 | Arm 2 Base limit switch | Digital input | Internal pull-up |
| GPIO 23 | Arm 2 Shoulder limit switch | Digital input | Internal pull-up |
| GPIO 24 | Arm 2 Elbow limit switch | Digital input | Internal pull-up |
| GPIO 25 | Arm 2 Wrist Rotate limit switch | Digital input | Internal pull-up |
| GPIO 26 | Arm 2 Wrist Pan limit switch | Digital input | Internal pull-up |
| CSI connector | Pi Camera | Ribbon cable | Fixed mount near Pi |
| I2C SDA (GPIO 2) | ICM20948 IMU | I2C | MACE attitude sensing (addr 0x69) |
| I2C SDA (GPIO 2) | AS5600 Encoder | I2C | MACE wheel speed sensing (addr 0x36) |
| WiFi | ESP32 | Wireless | Coordinated operation |
| WiFi | Base station Pi | Wireless | Ground control commands |
No GPIO is used for power switching -- the toggle switch is manual.
Robotic Arms¶
Two independent identical 5-DOF servo-driven arms for approach and capture via the defunct satellite's kick-engine nozzle. All dumb PWM servos, no smart servos. Each arm has 5 joints with 1 servo per joint.
Servo Specifications¶
| Joint | Servo | Torque | Qty (per arm) | Voltage | Stall Current (each) | Source |
|---|---|---|---|---|---|---|
| Base | HOOYIJ 150kg | 150 kg-cm | 1 | 12V | 8.0A | Datasheet |
| Shoulder | ANNIMOS 150kg | 150 kg-cm | 1 | 12V | 8.0A | |
| Elbow | ANNIMOS 80kg | 80 kg-cm | 1 | 7.4V | 5.0A | Specs |
| Wrist (rotate) | Wishiot RDS3218 | 20 kg-cm | 1 | 5V | 1.6A | 270 deg, with U-bracket |
| Wrist (pan) | Wishiot RDS3218 | 20 kg-cm | 1 | 5V | 1.6A | 270 deg, with U-bracket |
Total: 10 dumb PWM servos (5 per arm), all driven by PCA9685 I2C PWM driver.
PCA9685 Channel Assignments¶
Arm 1 (PCA9685 Ch 0-4)¶
| Channel | Joint | Servo | Voltage |
|---|---|---|---|
| Ch 0 | Base | HOOYIJ 150kg | 12V |
| Ch 1 | Shoulder | ANNIMOS 150kg | 12V |
| Ch 2 | Elbow | ANNIMOS 80kg | 7.4V |
| Ch 3 | Wrist Rotate | RDS3218 | 5V |
| Ch 4 | Wrist Pan | RDS3218 | 5V |
Arm 2 (PCA9685 Ch 5-9)¶
| Channel | Joint | Servo | Voltage |
|---|---|---|---|
| Ch 5 | Base | HOOYIJ 150kg | 12V |
| Ch 6 | Shoulder | ANNIMOS 150kg | 12V |
| Ch 7 | Elbow | ANNIMOS 80kg | 7.4V |
| Ch 8 | Wrist Rotate | RDS3218 | 5V |
| Ch 9 | Wrist Pan | RDS3218 | 5V |
Ch 14: ESC for MACE reaction wheel (unchanged).
Limit Switches (Pi GPIO)¶
10 limit switches total, one per joint (5 per arm). Connected directly to Pi GPIO with internal pull-up resistors. Signal wiring is 22 AWG + GND.
| GPIO | Limit Switch |
|---|---|
| GPIO 4 | Arm 1 Base |
| GPIO 5 | Arm 1 Shoulder |
| GPIO 6 | Arm 1 Elbow |
| GPIO 17 | Arm 1 Wrist Rotate |
| GPIO 27 | Arm 1 Wrist Pan |
| GPIO 22 | Arm 2 Base |
| GPIO 23 | Arm 2 Shoulder |
| GPIO 24 | Arm 2 Elbow |
| GPIO 25 | Arm 2 Wrist Rotate |
| GPIO 26 | Arm 2 Wrist Pan |
MACE (Reaction Wheel)¶
Momentum Attitude Control Electronics - a single-axis reaction wheel for attitude demonstration.
| Component | Model | Voltage | Current | Interface | I2C Addr |
|---|---|---|---|---|---|
| Motor | Uangel X2807 1700KV BLDC | 12V (via ESC) | ~1-3A realistic | PWM via ESC | - |
| ESC | ~~Drfeify 40A~~ → Bidirectional 40A 2-6S (Amazon.ca) | 7.4-25.2V (2-6S) | 40A cont / 50A burst | PWM (PCA9685 pin 12 / ch 11) | - |
| IMU | ICM20948 | 3.3V | ~mA | I2C | 0x69 |
| Magnetic encoder | AS5600 | 3.3V | ~mA | I2C | 0x36 |
Power: ESC powered from 12V bus through the toggle switch (no separate fuse needed -- ESC has built-in overcurrent protection, and the motor draws only ~1-3A as a reaction wheel).
Control: PCA9685 pin 12 (channel 11) sends PWM to ESC. Bidirectional ESC — center-stick protocol: 1500us = stopped, 1500-1900us = forward, 1100-1500us = reverse. No arming sequence needed (plug and play, no calibration). Small deadband around 1500us (~±50-75us) handled in software. 5V/3A BEC output (unused). Max wheel RPM limited to 600 in software.
Attitude Control: Closed-loop PID controller (attitude-controller.service, port 5001) integrates gz gyro for body angle and commands the reaction wheel to hold a setpoint. 100Hz control loop with rate-limited output (40.5%/s max). Gyro bias calibrated on enable. Bidirectional ESC provides full proportional torque in both directions — PID has symmetric authority, no longer relies on friction for reverse torque.
ESC upgrade (ordered 2026-03-30)
Replaced uni-directional Drfeify 40A with bidirectional 40A ESC. The old ESC could only apply torque in one direction (forward throttle 1000-2000us), relying on friction for the reverse direction. The new ESC provides proportional forward and reverse torque from a single PWM signal centered at 1500us. No brake mode needed — active reverse torque is more controllable and effective than passive phase-shorting brake at all RPMs. Software changes required: remap PID output and manual control from 1000-2000us to center-stick 1500us ± 500us.
RPM Limiting: Software-limited to 600 RPM. Saturation triggers coast with hysteresis (resumes at 420 RPM / 70%). RPM computed server-side with 10-sample rolling average (~330ms window at 30Hz). Overshoot observed to ~1000 RPM at initial 50-sample window — reduced to 10 samples for faster response.
Sensors: IMU (ICM20948 at 0x69, ±2g accel / ±250°/s gyro) and encoder (AS5600 at 0x36) share the I2C bus with PCA9685 (0x40). Sensor loop runs at 30Hz (100Hz caused I2C lock contention with motor writes).
Camera: RPi Camera Module 3 (IMX708, CSI) — 640x480 MJPEG @ 10fps, streamed via sensor server.
Power Supply¶
| Voltage | 12V |
| Power | 600W (50A max) |
| Input | 120V AC mains via slip ring |
| Location | Inside rotating GEO-DUDe body |
| Output terminals | Screw terminals to Wago distribution blocks |
| Link | Amazon.ca |
Power Distribution (Wago Blocks)¶
All DC power distribution uses Wago lever connectors (from Mach). Each voltage rail gets its own Wago block. The PCA9685 only carries signal wires - servo power is wired directly from the correct voltage rail.
12V PSU output (2x 16 AWG parallel trunk)
|
+-- Main Fuse (30A) --> 12V Bus (Wago)
| |
| +-- Fuse (3A) --> Buck conv 2 (5V) --> 5V Pi Wago
| | (ALWAYS ON - taps off BEFORE toggle switch)
| | +--> Raspberry Pi (20 AWG)
| | \--> PCA9685 VCC (22 AWG)
| |
| \-- 40A TOGGLE SWITCH (manual, panel mount)
| |
| +-- Arm 1 Fuse Board (perfboard)
| | +-- 12V --> Base servo (8A slow-blow fuse)
| | +-- 12V --> Shoulder servo (8A slow-blow fuse)
| | +-- 7.4V --> Elbow servo (5A slow-blow fuse)
| | +-- 5V --> Wrist Rotate (3A slow-blow fuse)
| | \-- 5V --> Wrist Pan (3A slow-blow fuse)
| +-- Arm 2 Fuse Board (perfboard)
| | +-- 12V --> Base servo (8A slow-blow fuse)
| | +-- 12V --> Shoulder servo (8A slow-blow fuse)
| | +-- 7.4V --> Elbow servo (5A slow-blow fuse)
| | +-- 5V --> Wrist Rotate (3A slow-blow fuse)
| | \-- 5V --> Wrist Pan (3A slow-blow fuse)
| +-- Buck conv 1 (7.4V) --> feeds fuse boards
| +-- Buck conv 3 (5V) --> feeds fuse boards
| +-- ESC (40A) --> MACE reaction wheel motor
| \-- 12V fan (1A fuse)
|
\-- GND Bus (2x 16 AWG parallel) --> Everything (star ground via Wago bus)
Fuse board: Single perfboard fuse board for both arms (merged from two separate boards). Receives three voltage inputs (12V direct, 7.4V from buck conv 1, 5V from buck conv 3) and routes the correct voltage through the correct fuse to each of the 10 servos across both arms. GND is shared across all fuses on the board.
Power-on sequence: Pi and PCA9685 are always powered via buck 2 (before toggle switch, always on). When the operator is ready, they flip the panel-mount toggle switch to energize all fuse boards and the ESC. PCA9685 outputs are off until Pi sends I2C commands, so servos stay still even after the toggle switch is flipped on. ESC requires arming sequence (1000us PWM for ~2s) before accepting throttle.
Base and shoulder servos run directly off 12V - no buck converter needed. They're rated 10-12.6V and the PSU outputs 12V.
Grounding: Star topology. Every component gets its own GND wire back to the GND Wago bus - no daisy-chaining. This prevents high-current servo ground return from raising the Pi/PCA9685 ground reference. The GND bus may need 2-3 ganged Wago blocks to fit all the wires (17+ connections).
Buck Converters¶
3 of 4 20A 300W buck converters are needed. 1 spare.
| Buck # | Output V | Feeds | Max Current | Location | Status |
|---|---|---|---|---|---|
| 1 | 7.4V | 2x elbow servos (one per arm) | 10A stall | After toggle switch (fuse block 8A circuit) | OK |
| 2 | 5V | Raspberry Pi + PCA9685 | ~2.6A | Before toggle switch (always on) | OK |
| 3 | 5V | 4x RDS3218 wrist (two per arm) | ~6.4A stall | After toggle switch (fuse block 8A circuit) | OK |
| 4 | - | Spare | - | - |
Buck converter specs: Input 6-40V, Output 1.25-36V adjustable (potentiometer), 20A max / 15A continuous, 300W, screw terminals, short circuit protection.
Fuses¶
Fuses from Mach. Sized at 125-150% of expected max draw.
| Fuse | Branch | Max Draw | Rating | Wire Gauge | Notes |
|---|---|---|---|---|---|
| AC inline | Mains hot line before slip ring | ~5A at 120V | 6A slow-blow | Mains cable | Protects AC path |
| Main DC | 12V bus after PSU | ~30A worst case | 30A | 2x 16 AWG parallel | |
| Base servo (x2) | One per arm, on fuse board | 8A stall each | 8A each (per-servo) | 16 AWG | Glass tube slow-blow |
| Shoulder servo (x2) | One per arm, on fuse board | 8A stall each | 8A each (per-servo) | 16 AWG | Glass tube slow-blow |
| Elbow servo (x2) | One per arm, on fuse board | 5A stall each | 5A each (per-servo) | 18 AWG | Glass tube slow-blow |
| Wrist rotate (x2) | One per arm, on fuse board | 1.6A stall each | 3A each (per-servo) | 18 AWG | Glass tube slow-blow |
| Wrist pan (x2) | One per arm, on fuse board | 1.6A stall each | 3A each (per-servo) | 18 AWG | Glass tube slow-blow |
| Buck 1 input | Elbow servos | ~6.2A at 12V in | 8A | 18 AWG | Fuse block circuit |
| Buck 2 input | Pi + PCA9685 only | ~1.1A at 12V in | 3A | 18 AWG | Before toggle switch (always on) |
| Buck 3 input | Wrist servos | ~2.7A at 12V in | 8A | 18 AWG | Fuse block circuit |
| Fan line | 12V fan | 0.15A | 1A | 22 AWG | Fuse block circuit |
Slip Ring (AC Mains Passthrough)¶
A 3-wire 15A slip ring passes 120V AC mains from the gantry through the rotation point (thrust bearing) into the GEO-DUDe body. The servicer rotates continuously (360+) on the thrust bearing on the linear rails.
| Model | 3-wire, 15A per wire, 150 RPM |
| Carries | 120V AC mains (live, neutral, ground) |
| Location | Between gantry/rail base (stationary) and rotating GEO-DUDe body |
AC Wiring Path¶
Wall outlet
--> IEC C16 panel socket on gantry (crimp spade terminals, 6.3mm insulated)
--> 6A slow-blow inline fuse
--> Wire to slip ring input (stationary side, solder or crimp butt connectors)
--> Slip ring output (rotating side)
--> 12V 600W PSU AC input screw terminals (inside GEO-DUDe)
AC mains safety
- Slip ring rated 15A per wire at 120V - sufficient for 600W PSU (~5A at 120V)
- All AC connections must use proper crimp spade terminals on the IEC C16
- Ground wire MUST pass through the slip ring
- AC wiring physically separated from DC wiring inside GEO-DUDe
- Inline fuse on AC hot line before slip ring (6A slow-blow)
- Emergency shutdown: pull the mains plug
Limit Switches¶
Momentary limit switches - 10 needed (one per joint per arm: base, shoulder, elbow, wrist rotate, wrist pan, for each of the two arms). Connected directly to Pi GPIO with internal pull-up resistors. 24 switches in stock (2 packs of 12), 14 spares.
Cooling¶
| Fan | 12V 80mm fan |
| Powered from | 12V bus via fuse (1A) |
Dropped Components¶
These items from the original BOM are no longer needed for GEO-DUDe electronics:
| Item | Reason |
|---|---|
| ~~Waveshare smart servo driver board~~ | All servos are dumb PWM, using PCA9685 instead |
| ~~Feetech STS3215 smart servos~~ | Replaced with Wishiot RDS3218 20kg PWM servos for wrist |
| ~~PCF8575 I2C GPIO expander~~ | Only 10 limit switches, Pi GPIO handles it directly |
| ~~Buck converter 4~~ | Only 3 needed (7.4V elbow, 5V Pi, 5V servo), 1 spare |
| ~~120A 12V relay (irhapsody)~~ | Replaced by manual toggle switch |
| ~~2N2222 NPN transistor~~ | Was for relay coil driver, no longer needed |
| ~~1N4007 flyback diode~~ | Was for relay back-EMF protection, no longer needed |
| ~~1k ohm resistor~~ | Was for transistor base limiter, no longer needed |
| ~~Miuzei MG90S x4~~ | End-effector design deferred |
Components To Add to BOM¶
| Item | Purpose | Status |
|---|---|---|
| ~~PCA9685 16-ch PWM driver~~ | ~~Drive all 10 servo signal lines via I2C~~ | Added (row 5, $19.99) |
| ~~GPIO screw terminal breakout HAT~~ | ~~Clean wiring for Pi GPIO connections~~ | Added (row 24, $12.99) |
Diagrams¶
See the System Diagrams page for full power and signal architecture diagrams (D2 rendered SVGs).
Design Notes and Concerns¶
Servo Factory Wire Gauge¶
The HOOYIJ and ANNIMOS 150kg servos ship with thin pre-attached leads (~18-20 AWG) despite their 8A stall current rating. This is acceptable because:
- Factory leads are short (typically 15-30cm)
- Voltage drop over short runs is minimal
- The fuse protects the branch, not the individual servo lead
- Do NOT extend these leads with thin wire. If longer runs are needed, splice with 16 AWG and use proper crimp butt connectors with heat shrink.
Heat Dissipation¶
The GEO-DUDe body is a semi-enclosed rotating structure containing:
- 600W PSU (generates heat even at partial load)
- Up to 10 servos (heat from those near the body)
- 3x buck converters
Currently only 1x 80mm 12V fan for cooling. Considerations:
- The body is not fully sealed - 3D printed PLA structure will have gaps and openings for the arms
- Rotation itself creates some airflow through openings
- Most servos are on the arms (outside the body), not inside
- Buck converters and PSU are the main internal heat sources
- Monitor temperatures during initial testing. If thermals are a problem, add a second fan or cut ventilation slots in the body panels.
WiFi Reliability¶
The Pi communicates with the ESP32 via WiFi. The rotating GEO-DUDe body may attenuate the signal if it has significant metal structure.
- PLA body is RF-transparent, so if the structure is mostly 3D printed, WiFi should be fine
- Metal fasteners, the PSU housing, and the thrust bearing are localized shielding
- The Pi's onboard WiFi antenna is omnidirectional
- If signal is weak: mount a small external antenna or use a USB WiFi adapter positioned near a PLA panel opening
- Test WiFi RSSI during rotation before relying on it for real-time control
Cable Management (Rotating Body)¶
All wires inside the GEO-DUDe body experience forces during rotation. At low RPM (subscale test speeds), centrifugal forces are small, but wires still need to be secured:
- Zip-tie all wire bundles to the internal frame/structure
- Strain relief at every connection point (screw terminals, Wago blocks, servo connectors)
- Use cable clips or adhesive tie mounts on the 3D printed structure
- Route wires along structural members, not floating freely
- The arm cable bundles (signal + power to all 10 servos across both arms) exit the body through openings - use a grommet or cable gland at each exit to prevent chafing
- Keep slack to a minimum, but leave enough for each arm's range of motion
Software Current Limiting¶
No hardware current sensing is implemented. Software-side protections to implement on the Pi:
- Stall detection: If a servo command doesn't result in expected motion (via limit switches or timing), cut PWM to that channel via PCA9685
- Startup sequence: Enable servos one joint at a time (base first, then shoulder, etc.) rather than all at once, to avoid inrush current spikes
- Timeout: If any servo is commanded to a position for more than a few seconds without reaching it, assume stall and disable
- Temperature monitoring: Consider adding a cheap I2C temperature sensor (like DS18B20) near the PSU and buck converters to trigger fan speed increase or servo shutdown if overheating