Skip to the content
PCBKitNew board
4 layers50 × 60 mmCanarynode, the printed circuit board in 3D

Custom CAN sensor node: STM32G474 + IMU + environmental, USB-C, 4-layer PCB

Size
50 × 60 mm
Copper layers
4
Thickness
1.6 mm
Parts
65
Nets
83
Pads
260
Tracks, vias
474, 47
Pours
4
Routed
Yes
KiCad
KiCad 9.0 (file 20241229)
Created
21 May 2026
Updated
27 Oct 2026

Overview

Canarynode is an open-source printed circuit board by aboller1212, from the aboller1212/canarynode repository on GitHub. It is a 4-layer board of 50 × 60 mm with 65 parts on 83 nets, routed with 474 tracks and 47 vias.

It is built around the TCAN334GD, BME280 and BMI270, with the TPS62160DGK, USBLC6-2P6 and ESDZL5-1F4 among its other parts. Its parts include 22 capacitors, 18 resistors, 6 ICs, 6 diodes and 6 connectors. It belongs with the sensors and measurement and home automation and IoT boards and the STM32 boards of this library.

Main components

7

README

README.md

CANaryNode

A CAN FD sensor node built around an STM32G474. It reads an IMU and an environmental sensor and puts the data on a CAN bus. The firmware is bare-metal — no HAL, no RTOS, no generated code, just CMSIS headers and the reference manual. I'm building it this way because I want to understand what every peripheral is actually doing at the register level, not call somebody's library function and hope.

I designed the board as well, so the schematic and layout live in this repo alongside the firmware.

Hardware

The custom board is a 4-layer PCB with:

  • STM32G474RCT6 (Cortex-M4F, 256K flash)
  • BMI270 IMU on SPI
  • BME280 temperature/pressure/humidity sensor on I2C (SDO tied to ground, so address 0x76)
  • TI TCAN CAN FD transceiver
  • USB-C
  • Four LEDs, a button, and headers for SWD and UART

Most of the driver work was done on a Nucleo-G474RE first, bringing up one peripheral at a time, so that porting to the real board would mostly be remapping pins. The custom board is here now and boots.

A couple of things differ between the two: the Nucleo has a G474RET6 (512K flash) and routes CAN to FDCAN1 on PA11/PA12, while my board uses an RCT6 (256K) and puts CAN on PB5/PB6, which is FDCAN2. That's an instance swap, not just a pin change, so it needs its own message RAM offset. My board uses PA11/PA12 for USB instead.

Pin map on the custom board:

FunctionPins
LEDsPB0, PB1, PB2, PC4
I2C1 (BME280)PA15 SCL, PB7 SDA
SPI1 (BMI270)PA4 CS, PA5 SCK, PA6 MISO, PA7 MOSI
FDCAN2PB5 RX, PB6 TX
USBPA11, PA12
SWDPA13, PA14, NRST on PG10
USART2PA2, PA3
BOOT0 jumperPB8
IMU interruptPB10

Layout

  • firmware/ — the STM32 firmware, where most of the work is
  • hardware/ — schematic and board files
  • docs/ — datasheets and my bring-up notes
  • tools/ — scripts

Building

CMake + Ninja with the arm-none-eabi GCC toolchain.

text
cd firmware
cmake -B build -G Ninja
cmake --build build

Produces build/canary_firmware (ELF) and a .bin next to it.

Flashing

Two ways, depending on the board.

The custom board can be programmed over USB with no debugger at all. The STM32 has a bootloader burned into ROM — jumper BOOT0 high, plug in USB-C, and it enumerates as a DFU device:

text
STM32_Programmer_CLI -c port=USB1 -w build/canary_firmware.bin 0x08000000

Pull the jumper and power cycle to run the firmware instead. That's handy for quick iteration, but DFU only programs — for actual debugging I use OpenOCD as a GDB server with arm-none-eabi-gdb over SWD.

On the Nucleo I use an external ST-Link V2 on SWD (SWDIO to PA13, SWCLK to PA14, plus GND and 3V3). The onboard ST-Link V3E doesn't work reliably from an Apple Silicon Mac, so its USB stays unplugged and the target gets power from the V2.

Status

Working and verified on the custom board:

  • It powers up, enumerates over USB, and takes a verified flash write.
  • LED blink driven by a TIM6 timer interrupt. Small thing on its own, but it's the first proof that my startup code, vector table, linker script and clock setup are all correct on this silicon.
  • I2C master and the BME280 driver, remapped to PA15/PB7. The sensor answers with the right chip ID.

Verified earlier on the Nucleo, not yet ported over:

  • The full BME280 read path — calibration read and reassembly plus Bosch's fixed-point compensation math. It streams real temperature, pressure and humidity, and the humidity climbs when you breathe on it.
  • FDCAN at 500 kbit/s in internal loopback. A frame goes out, loops through the peripheral's message RAM, and comes back byte for byte.

In progress:

  • BMI270 over SPI. The driver is written, including the 8 KB configuration blob the sensor needs uploaded before it will do anything, but the chip isn't answering yet — the chip ID read comes back wrong. The wiring checks out against the schematic, so it's something in the SPI setup or the read timing. Waiting on a 1.27mm SWD adapter so I can put a debugger on it instead of guessing.

Not working yet:

  • CAN on a real bus. The MCU side checks out — I can read the FDCAN registers mid-transmit and see clean frames going out with no errors — but the transceiver breakout I was using never drives the bus. CANH and CANL sit at 0.3 V when they should idle around 2.3 V, so the transceiver isn't operating at all. Either the part is dead or its slew rate resistor is limiting it well below 500 kbit/s.

What's left

Port the remaining peripherals to the custom board, get the BMI270 talking, write a UART driver so I can print values instead of stepping through a debugger, pack sensor readings into CAN frames, and get those frames onto a real bus where my laptop can decode them.

Parts

65
QtyValueFootprintReferences
14100nCapacitor_SMD:C_0402_1005MetricC4, C7, C8, C9, C10, C11, C13, C14, C16, C17, C18, C19, C20, C22
50RResistor_SMD:R_0402_1005MetricR4, R5, R6, R12, R13
41uCapacitor_SMD:C_0603_1608MetricC3, C5, C6, C21
4330RResistor_SMD:R_0402_1005MetricR15, R16, R17, R18
4LEDLED_SMD:LED_0603_1608MetricD3, D4, D5, D6
3, ,
210uCapacitor_SMD:C_0603_1608MetricC1, C15
24.7kResistor_SMD:R_0402_1005MetricR10, R11
25.1kResistor_SMD:R_0402_1005MetricR8, R9
2Conn_01x02Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_VerticalJ1, J4
2SW_PushButton_Switch_SMD:SW_SPST_PTS645Sx43SMTR92SW1, SW2
1100kResistor_SMD:R_0402_1005MetricR3
110kResistor_SMD:R_0402_1005MetricR7
1120RResistor_SMD:R_0603_1608MetricR14
1180kResistor_SMD:R_0402_1005MetricR2
122uCapacitor_SMD:C_0603_1608MetricC2
13.3uCoilcraft_Local:IND_XFL3012_COCL1
14.7uCapacitor_SMD:C_0603_1608MetricC12
1562kResistor_SMD:R_0402_1005MetricR1
1BME280Package_LGA:Bosch_LGA-8_2.5x2.5mm_P0.65mm_ClockwisePinNumberingU5
1BMI270BMI270:BMI270_BOSU4
1Conn_01x04Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_VerticalJ6
1Conn_02x05_Odd_EvenConnector_PinHeader_1.27mm:PinHeader_2x05_P1.27mm_Vertical_SMDJ5
1ESDZL5-1F4Diode_SMD:D_0201_0603MetricD1
1PESD2CANFD27V-TRPESD2CANFD27V-TR:SOT23_PESD2_NEXD2
1STM32G474RETxPackage_QFP:LQFP-64_10x10mm_P0.5mmU2
1Screw_Terminal_01x03BMI270:PhoenixMC_1x03_P3.5_DB2EVC.kicad_modJ3
1TCAN334GPackage_SO:SOIC-8_3.9x4.9mm_P1.27mmU6
1TPS62160DGKPackage_SO:MSOP-8_3x3mm_P0.65mmU1
1USBLC6-2P6Package_TO_SOT_SMD:SOT-666U3
1USB_C_Receptacle_USB2.0_16PConnector_USB:USB_C_Receptacle_HRO_TYPE-C-31-M-12J2

The 64 most common of 65 parts.

Questions

How big is the Canarynode PCB?

It measures 50 × 60 mm and has 4 copper layers, 1.6 mm thick.

What parts does the Canarynode use?

65 parts, built around the TCAN334GD, BME280, BMI270 and TPS62160DGK. 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 Canarynode KiCad files?

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

Can I use the Canarynode design in my own project?

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

Similar boards

  • 2 layers140.5 × 106 mmPcbgalapagos, the printed circuit board in 3D

    Pcbgalapagos

    catuta0/HAB-payload

    Carrier PCB for a high-altitude balloon payload. An ESP32 DevKitC V4 (WROOM-32) plugs into the board together with breakout modules for GPS (NEO-8M, I2C or UART header, fit only one), INA260 power monitor, BME280…

    62 parts
  • 4 layers90 × 70 mmPsu-01, the printed circuit board in 3D

    Psu-01

    alxhub/arc

    Addy's Railroad Company

    97 parts
  • 4 layers49.5 × 56.8 mmBLE CAN module, the printed circuit board in 3D

    BLE CAN module

    shivamtiwari020505/Automotive-BLE-CAN-Module

    KiCad hardware design for an automotive BLE-to-CAN module

    110 parts
  • 4 layers140 × 80 mm24V High Side Driver, the printed circuit board in 3D

    24V High Side Driver

    tracelabs-pcb/can-do12

    4-Layer IC-Gate-Driver for industrial application - Kicad, TPS274160, CANBUS

    147 parts
  • 2 layers88 × 115 mmBadge, the printed circuit board in 3D

    Badge

    endsummercamp/badge

    Per l'anno 2024 anche l'End Summer Camp si vuole dotare di un badge interattivo e programmabile, in linea con gli eventi simili internazionali.

    131 parts1CERN-OHL-P-2.0
  • 2 layers87.5 × 70 mm010 Implementation, the printed circuit board in 3D

    010 Implementation

    NewTec-GmbH/esp32-can-iot

    A ESP32 based interface between CAN-bus and IoT environments.

    70 parts51BSD-3-Clause