
STM32 Drone
bassammorsy/stm32-flight-controller
Custom 4-layer STM32F405RGTx quadcopter flight controller PCB designed in KiCad. Betaflight compatible, 4S–6S LiPo input, SMT assembled by JLCPCB.

Autonomous can-collecting robot for the MIT MASLAB 2026 competition. Features dual-camera vision, YOLOv11 segmentation, path planning with Theta, and a distributed architecture with Pi-side execution and computer-side…
Raven is an open-source printed circuit board by jguo22, from the jguo22/MDS repository on GitHub. It is a 4-layer board of 63.2 × 54.2 mm with 198 parts on 170 nets, routed with 1,543 tracks and 409 vias.
It is built around the QMC5883L, TPS548B28RWWR and 74HC595, with the ICM-42688-P, AO3400A and DMP2002UPS among its other parts. Its parts include 67 capacitors, 64 resistors, 25 connectors, 17 diodes and 10 ICs. It belongs with the STM32 boards of this library.
https://maslab.mit.edu/2026/wiki/team02
Autonomous can-collecting robot for the MIT MASLAB 2026 competition. Features dual-camera vision, YOLOv11 segmentation, path planning with Theta*, and a distributed architecture with Pi-side execution and computer-side control.
┌─────────────────────────────────────────────────────────────────────┐
│ Computer │
│ ┌─────────────────┐ ┌──────────────────┐ ┌────────────────┐ │
│ │ ComputerReceiver│◄───│ RobotHandler │◄───│ Vision (YOLO) │ │
│ │ (video in, │ │ State Machine │ │ Segmentation │ │
│ │ commands out) │ │ + Theta* Path │ │ + Pixel-to-3D │ │
│ └────────┬────────┘ └──────────────────┘ └────────────────┘ │
│ │ │
│ │ TCP (video: 5000, commands: 5001) │
│ ▼ │
│ ┌─────────────────┐ │
│ │RemoteRobotCmd │ ◄── IRobotCommander interface │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│
│ Network
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Raspberry Pi │
│ ┌─────────────────┐ ┌──────────────────┐ ┌────────────────┐ │
│ │ PiStreamer │───►│ DirectRobotCmd │───►│ Nav + Raven │ │
│ │ (video out, │ │ (local execution)│ │ Motor Control │ │
│ │ commands in) │ └──────────────────┘ └────────────────┘ │
│ └─────────────────┘ │# Install dependencies
pip install -e .
# Run computer receiver (waits for Pi connection)
python main_comp.py# Install dependencies
pip install -e .
# Run Pi streamer (auto-reconnects to computer)
python main_pi.py --camera-top /dev/videoblacktop --camera-bottom /dev/videoblackbotMDS/
├── main_comp.py # Computer entry point (receiver + vision + state machine)
├── main_pi.py # Pi entry point (streamer + command execution)
│
├── IRobotCommander.py # Abstract interface for robot commands
├── RemoteRobotCommander.py # Network implementation (computer side)
├── DirectRobotCommander.py # Direct execution (Pi side)
│
├── RobotHandler.py # Full state machine with zone/can tracking
├── RobotHandler_Simple.py # Simplified state machine for basic collection
│
├── thetaStar.py # Theta* path planning with obstacle avoidance
├── nav.py # Navigation controller (IMU + odometry)
├── navHelpers.py # Movement command generators
│
├── raven.py # Raven motor controller driver
├── RavenWrapper.py # High-level Raven interface (gripper, elevator)
├── IMUWrapper.py # BNO08x IMU wrapper
├── distanceSensorWrapper.py # Distance sensor for can approach
│
├── config.py # Robot configuration constants
├── colors.py # YOLO class names and color constants
├── getPickedCanColor.py # Detect color of can in gripper
│Custom YOLOv11n model trained on 8 classes:
Boundary (0), Golden Can (1), Golden Zone (2)Green Can (3), Green Zone (4), Red Can (5), Red Zone (6), Robot (7)from vision.segment import segmentImage
from vision.can_utils import getCans
from vision.zone_utils import getZones
result = segmentImage(image) # Run YOLO segmentation
cans, can_classes = getCans(result, image, is_top=True) # Get can positions (mm)
zones, zone_classes = getZones(result, image, is_top=True) # Get zone quads (mm)Transforms pixel coordinates to ground plane (mm) using camera calibration:
from vision.pixelTo3D import transform_uv_to_xy
# pixel (u, v) -> world (x, y) in mm
x, y = transform_uv_to_xy(pixel_x, pixel_y, is_top=True)SE2-based world/relative coordinate conversion:
from spatialmath import SE2
from vision.relativeCoordinates import world_to_relative, relative_to_world
robot_pose = SE2(robot_x, robot_y, robot_heading)
local_x, local_y = world_to_relative(world_point, robot_pose)
world_x, world_y = relative_to_world(local_point, robot_pose)Detect which color can is currently in the gripper:
from getPickedCanColor import getPickedUpCanColor
color = getPickedUpCanColor(result, image) # Returns 'Green Can', 'Red Can', etc.All robot commands go through IRobotCommander, with two implementations:
| Method | Description |
|---|---|
override_movement(args) | Raw motor commands [left, right, ticks, ...] |
override_waypoints(args) | Navigate through waypoints [x1, y1, x2, y2, ...] |
override_relative_xy(x, y) | Move relative to robot (mm) |
override_world_xy(x, y) | Navigate to world coordinates (mm) |
pickup_can() | Close gripper + raise elevator |
set_down_can() | Lower elevator + open gripper |
open_gripper() | Open gripper only |
lower_elevator() | Lower elevator only |
approach_can_with_ds() | Approach can using distance sensor |
backup() | Back up short distance |
stack(temp, stack, count) | Stack can at position |
waitFinishedMoving() | Block until movement complete |
Complex state machine with:
Basic can collection:
SearchForCan -> MoveToCan -> ApproachingCan -> GrabCan -> MoveToZone -> DoneConfiguration:
MAX_STACK: Number of cans to collect before going to zonetarget_zone: Which zone to deliver to (GREEN_ZONE, RED_ZONE, GOLDEN_ZONE)target_can_color: Which color cans to collectCustom serial motor controller (460800 baud):
TCP-based with custom framing:
Message types defined in connection/message_types.py:
OVERRIDE_MOVEMENTS = 2 # [left, right, ticks, ...]
OVERRIDE_WAYPOINTS = 3 # [x1, y1, x2, y2, ...]
PICKUP_CAN = 4 # No args
RELEASE_CAN = 5 # No args
APPROACH_CAN_DS = 9 # No args
OPEN_GRIPPER = 15 # No args
LOWER_ELEVATOR = 16 # No args
# ... and moreKey constants in config.py:
FRAME_WIDTH = 640
FRAME_HEIGHT = 480
FPS = 30
CAN_DIAMETER = 76.2 # mm
ROBOT_DIAMETER = 300 # mm
CLAW_OFFSET = 150 # mm from robot center
APPROACH_OFFSET = 200 # mm approach distance# Test segmentation on image
python vision/segment.py
# Test can detection
python getPickedCanColor.pycd vision/train
python train.pyimages/ with cooldownStreamer classprofiles/See pyproject.toml:
| Qty | Value | Footprint | References |
|---|---|---|---|
| 31 | 7k5 | Resistor_SMD:R_0402_1005Metric | R25, R26, R28, R29, R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, R40, R41 +15 |
| 28 | 1k | Resistor_SMD:R_0402_1005Metric | R1, R2, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23 +12 |
| 20 | 100n | Capacitor_SMD:C_0402_1005Metric | C2, C4, C10, C14, C16, C18, C19, C21, C24, C26, C30, C31, C34, C35, C36, C39 +4 |
| 15 | 22u | Capacitor_SMD:C_0805_2012Metric | C13, C50, C51, C52, C53, C54, C57, C58, C59, C60, C61, C62, C63, C64, C65 |
| 7 | 2u2 | Capacitor_SMD:C_0402_1005Metric | C3, C6, C9, C15, C20, C25, C67 |
| 7 | GLED | LED_SMD:LED_0603_1608Metric | D1, D3, D6, D9, D12, D14, D27 |
| 6 | 1u | Capacitor_SMD:C_0402_1005Metric | C37, C38, C46, C47, C48, C49 |
| 5 | 22n | Capacitor_SMD:C_0402_1005Metric | C5, C17, C22, C27, C69 |
| 5 | Conn_01x02_Pin | Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical | J4, J6, J7, J8, J9 |
| 5 | Conn_01x04_Pin | Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical | J14, J15, J16, J17, J18 |
| 5 | DRV8874PWPR | Package_SO:HTSSOP-16-1EP_4.4x5mm_P0.65mm_EP3.4x5mm_Mask2.46x2.31mm | U1, U4, U5, U6, U30 |
| 5 | RLED | LED_SMD:LED_0603_1608Metric | D4, D7, D10, D13, D28 |
| 5 | Screw_Terminal_01x02 | TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal | J20, J26, J27, J28, J29 |
| 5 | WLED | LED_SMD:LED_0603_1608Metric | D2, D5, D8, D11, D26 |
| 4 | 47u | Capacitor_SMD:C_1206_3216Metric | C40, C41, C42, C43 |
| 4 | Conn_01x03_Pin | Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical | J21, J22, J23, J24 |
| 4 | MountingHole_Pad | MountingHole:MountingHole_2.5mm_Pad | H1, H2, H3, H4 |
| 2 | 12p | Capacitor_SMD:C_0402_1005Metric | C32, C33 |
| 2 | 220n | Capacitor_SMD:C_0402_1005Metric | C11, C44 |
| 2 | 56k | Resistor_SMD:R_0402_1005Metric | R53, R57 |
| 2 | Conn_01x04_MountingPin | Connector_JST:JST_SH_SM04B-SRSS-TB_1x04-1MP_P1.00mm_Horizontal | J2, J5 |
| 2 | LOGO | LOGO | G1, G2 |
| 2 | SW_Push | Footprints:TS-1088 | SW1, SW2 |
| 1 | 100k | Resistor_SMD:R_0402_1005Metric | R58 |
| 1 | 100n | Capacitor_SMD:C_0603_1608Metric | C23 |
| 1 | 100u | Capacitor_SMD:C_Elec_8x6.2 | C1 |
| 1 | 10u | Capacitor_SMD:C_0603_1608Metric | C28 |
| 1 | 10u | Capacitor_SMD:C_0402_1005Metric | C55 |
| 1 | 16MHz | Crystal:Crystal_SMD_3225-4Pin_3.2x2.5mm | Y1 |
| 1 | 1u | Footprints:L_0660A | L1 |
| 1 | 2u2 | Capacitor_SMD:C_0805_2012Metric | C45 |
| 1 | 33k | Resistor_SMD:R_0402_1005Metric | R24 |
| 1 | 47k | Resistor_SMD:R_0402_1005Metric | R56 |
| 1 | 4u7 | Capacitor_SMD:C_0603_1608Metric | C12 |
| 1 | 74HC595 | Package_SO:SOIC-16_3.9x9.9mm_P1.27mm | U8 |
| 1 | AO3400A | Package_TO_SOT_SMD:SOT-23 | Q1 |
| 1 | Conn_01x02_Pin | Connector_JST:JST_PH_B2B-PH-K_1x02_P2.00mm_Vertical | J11 |
| 1 | Conn_01x02_Pin | Connector_AMASS:AMASS_XT30UPB-M_1x02_P5.0mm_Vertical | J3 |
| 1 | Conn_02x20_Odd_Even | Connector_PinSocket_2.54mm:PinSocket_2x20_P2.54mm_Vertical | J1 |
| 1 | Conn_ARM_SWD_TagConnect_TC2030-NL | Connector:Tag-Connect_TC2030-IDC-NL_2x03_P1.27mm_Vertical | J10 |
| 1 | DMP2002UPS | Footprints:DMP2002UPS | Q3 |
| 1 | FerriteBead | Inductor_SMD:L_0805_2012Metric | FB1 |
| 1 | Fuse | Fuse:Fuse_1206_3216Metric | F1 |
| 1 | ICM-42688-P | Package_LGA:LGA-14_3x2.5mm_P0.5mm_LayoutBorder3x4y | U2 |
| 1 | NetTie_2 | NetTie:NetTie-2_SMD_Pad0.5mm | NT1 |
| 1 | QMC5883L | Package_LGA:LGA-16_3x3mm_P0.5mm | U3 |
| 1 | STM32G431CBUx | Package_DFN_QFN:QFN-48-1EP_7x7mm_P0.5mm_EP5.6x5.6mm | U7 |
| 1 | TPS548B28RWWR | Footprints:TPS548B28RWWR | U9 |
It measures 63.2 × 54.2 mm and has 4 copper layers, 1.61 mm thick.
198 parts, built around the QMC5883L, TPS548B28RWWR, 74HC595 and ICM-42688-P. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the jguo22/MDS repository on GitHub, at the commit this page was made from: the board is raven/pcb/raven.kicad_pcb and its schematic raven/pcb/encoder.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask jguo22 before reusing the design.

bassammorsy/stm32-flight-controller
Custom 4-layer STM32F405RGTx quadcopter flight controller PCB designed in KiCad. Betaflight compatible, 4S–6S LiPo input, SMT assembled by JLCPCB.

oiver12/VariometerV2
Paragliding variometer: custom KiCad PCBs, ESP32 firmware, sensor fusion, e-ink UI, and desktop flight replay.






sbarisic/MagMouse
Open source hall-effect based mouse - no mechanical contacts - no failure points