Skip to the content
PCBKitNew board
4 layers78 × 70 mmRadome dish controller, the printed circuit board in 3D

Radome dish controller

ay2718/RadomeMotorController1

The Radome CAN protocol is very simple. Send azimuth commands to address 0x1 and elevation commands to address 0x2. Azimuth and elevation reply back from addresses 0x101 and 0x102 respectively.

Size
78 × 70 mm
Copper layers
4
Thickness
1.6 mm
Parts
89
Nets
101
Pads
365
Tracks, vias
541, 444
Pours
16
Routed
Yes
KiCad
KiCad 7 (file 20221018)
Created
22 Oct 2023
Updated
2 Sep 2025

Overview

Radome dish controller is an open-source printed circuit board by ay2718, from the ay2718/RadomeMotorController repository on GitHub. It is a 4-layer board of 78 × 70 mm with 89 parts on 101 nets, routed with 541 tracks and 444 vias.

It is built around the STM32G431CBU3, SN75176AD and LF2190NTR, with the AS5047D, MAX3051EKA and SIR426DP among its other parts. Its parts include 33 capacitors, 15 resistors, 14 ICs, 9 connectors and 6 transistors. It belongs with the STM32 boards of this library.

Main components

7

README

README.md

Radome motor controller

CAN protocol

The Radome CAN protocol is very simple. Send azimuth commands to address 0x1 and elevation commands to address 0x2. Azimuth and elevation reply back from addresses 0x101 and 0x102 respectively. Any packet sent to address 0x0 will trigger both azimuth and elevation to reply back with their current status without initiating a motor movement, sending commands will also trigger a reply back.

Even if you feed the CAN total garbage the dish will not exceed safe positions (for elevation), speeds, or acceleration.

The controllers must be updated at least every 100 ms or faster. Othewise they will safely bring the dish to a halt.

The command structure is as follows:

text
Transmit:
// 2^24 is 360 degrees, position is unsigned
tx byte 0 = position bits 23:16
tx byte 1 = position bits 15:8
tx byte 2 = position bits 7:0

// LSB is 1 arcsecond/s = 1/1200 dps, signed
tx byte 3 = velocity bits 15:8
tx byte 4 = velocity bits 7:0

Receive:
// 2^24 is 360 degrees, position is unsigned
rx byte 0 = position bits 23:16
rx byte 1 = position bits 15:8
rx byte 2 = position bits 7:0

// LSB is 1 arcsecond/s = 1/1200 dps, signed
rx byte 3 = velocity bits 15:8
rx byte 4 = velocity bits 7:0

// LSB is 1 mA, signed
rx byte 5 = current bits 15:8
rx byte 6 = current bits 7:0

// LSB is 0.5V, unsigned
rx byte 7 = bus voltage bits 7:0

I recommend casting position as a uint32_t such that 232 is equivalent to 360 degrees. This makes position math very nice since overflow lines up with one rotation.

We feed the dish position and velocity because the velocity information in order to generate very smooth trajectories. If you want to command a position and you don't care much about timing, it's fine to send a position command with zero velocity. If you're tracking a satellite moving a couple degrees per second across the sky on X band, the velocity really helps (empirically we were able to maintain 0.05 degrees of tracking error up to 10 dps or so)

Firmware overview

If you decide to build the firmware, this is an STM32CubeIDE project. You may need to enable floating point support for printf. Define or underine azimuth or elevation in Core/Inc/main.h to set azimuth or elevation. Encoder offsets are hardcoded in.

CAN Bootloader usage

az_bootloader.bin and el_bootloader.bin should already be loaded onto their respective motor drives. The bootloader takes up 2 flash pages on each drive (4 kB)

flash_motor.py is used to upload firmware over CAN bus. The baud rate is 125000 (same as for operating the drives).

Example usage: ./flash_motor.py --id 0x01 -f radome_azimuth.bin. The --idflag selects which drive to write toe (0x01 is azimuth, 0x02 is elevation) and the-for--filename` flag selects the binfile to upload.

If a motor drive is unresponsive to being flashed, try running ./flash_motor.py ..., leave it running, and cycle power to the motor drives. This is useful if there's a problem with the firmware--flash_motor.py sends out pings to each motor's address every 100ms and the drives wait for pings in bootloader mode for 500ms before starting up.

Parts

89
QtyValueFootprintReferences
15100nFCapacitor_SMD:C_0603_1608MetricC113, C114, C201, C202, C203, C204, C205, C206, C304, C305, C306, C308, C309, C312, C313
610uFCapacitor_SMD:C_2220_5650MetricC102, C103, C105, C106, C108, C109
61uFCapacitor_SMD:C_0603_1608MetricC301, C302, C303, C307, C310, C311
63Resistor_SMD:R_0603_1608MetricR301, R302, R303, R304, R305, R306
6SIR426DPPackage_SO:PowerPAK_SO-8_SingleQ301, Q302, Q303, Q304, Q305, Q306
5Solder PadConnector_Wire:SolderWirePad_1x01_SMD_5x10mmJ101, J102, J103, J104, J105
410uFCapacitor_SMD:C_1206_3216MetricC107, C110, C111, C112
31N4148WDiode_SMD:D_SOD-123D301, D302, D303
32mResistor_SMD:R_Shunt_Vishay_WSK2512_6332Metric_T2.21mmR307, R308, R309
3INA181-A2Package_TO_SOT_SMD:SOT-23-6U304, U305, U306
3LF2190NPackage_SO:SOIC-8_3.9x4.9mm_P1.27mmU301, U302, U303
21kResistor_SMD:R_0603_1608MetricR310, R311
2220uFCapacitor_THT:CP_Radial_D12.5mm_P5.00mmC101, C104
2Molex Micro-Fit+ayeiser_misc:MOLEX_2165711002J107, J108
2SN75176ADPackage_SO:SOIC-8_3.9x4.9mm_P1.27mmU102, U103
11Resistor_SMD:R_2512_6332MetricR101
1100kResistor_SMD:R_0603_1608MetricR204
110kResistor_SMD:R_0603_1608MetricR313
110nFCapacitor_SMD:C_0603_1608MetricANACAP201
116MHzCrystal:Resonator_SMD_Murata_CSTxExxV-3Pin_3.0x1.1mmY201
12.2uHInductor_SMD:L_Vishay_IHLP-5050L101
1200kResistor_SMD:R_0603_1608MetricR312
1600ohm@100MHzInductor_SMD:L_0603_1608MetricFB201
1AS5047DPackage_SO:TSSOP-14_4.4x5mm_P0.65mmU101
1AZ1117-3.3Package_TO_SOT_SMD:SOT-223-3_TabPin2U104
1AZ1117-5.0Package_TO_SOT_SMD:SOT-223-3_TabPin2U105
1Conn_02x07_Odd_EvenConnector_PinHeader_1.27mm:PinHeader_2x07_P1.27mm_Vertical_SMDJ201
1K78UXXayeiser_misc:K78UXX-RightAngleU106
1MAX3051Package_SO:SO-8_3.9x4.9mm_P1.27mmU202
1Molex Micro-Fit+ayeiser_misc:MOLEX_2068320602J106
1NetTie_2NetTie:NetTie-2_SMD_Pad2.0mmNT101
1STM32G431CBU3Package_DFN_QFN:QFN-48-1EP_7x7mm_P0.5mm_EP5.3x5.3mmU201

The 85 most common of 89 parts.

Questions

How big is the Radome dish controller PCB?

It measures 78 × 70 mm and has 4 copper layers, 1.6 mm thick.

What parts does the Radome dish controller use?

89 parts, built around the STM32G431CBU3, SN75176AD, LF2190NTR and AS5047D. 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.

Where can I download the Radome dish controller KiCad files?

From the ay2718/RadomeMotorController repository on GitHub, at the commit this page was made from: the board is kicad/radome_dish_controller.kicad_pcb and its schematic kicad/drive.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Radome dish controller design in my own project?

Its repository states no licence, so its author keeps all rights: ask ay2718 before reusing the design.

Similar boards

  • 2 layers115.8 × 60.5 mmMainBoard V4, the printed circuit board in 3D

    MainBoard V4

    Rione/ssl-Circuit

    90 parts1
  • 2 layers40 × 24 mmBLDC driver, the printed circuit board in 3D

    BLDC driver

    walmis/BLDC-Servo

    FOC Motor Controller for 57BLF0x NEMA brushless motor

    107 parts43
  • 4 layers100 × 100 mmMWGEN G1, the printed circuit board in 3D

    MWGEN G1

    MR-DOS/MWGEN-G1

    12.5 MHz - 6400 MHz (LMX2572) or even up to 20 GHz (LMX2595) generator board with int./ext. reference.

    373 parts18GPL-3.0
  • 4 layers65.5 × 74.8 mmEng Thesis, the printed circuit board in 3D

    Eng Thesis

    Roxasch97/Eng_Thesis

    Engineering thesis HW repo

    118 parts2
  • 2 layers40 × 51 mmAllie reader, the printed circuit board in 3D

    Allie reader

    b4ck5p4c3/allie

    (WIP) Aliro, EMV, and UID reader for ACS

    37 parts1
  • 4 layers80 × 50 mmMianCtrl H7, the printed circuit board in 3D

    MianCtrl H7

    Aiyin4Da-2/Main_Ctrl_H7

    STM32H723VGT6 MainCtrlBoard Author: Aiyin4DaGLD · Hardware: v1.2 · Updated: 2026-08-21

    153 partsMIT