Skip to the content
PCBKitNew board
2 layers48.8 × 106 mm10hp generic, the printed circuit board in 3D

10hp generic

riban-bw/modular1

Riban modular is an open source and (where practical) open hardware virtual modular synthesiser with physical control panels that fit the Eurorack physical format. See the wiki for documentation.

Size
48.8 × 106 mm
Copper layers
2
Thickness
1.6 mm
Parts
89
Nets
59
Pads
328
Tracks, vias
936, 25
Pours
2
Routed
Yes
KiCad
KiCad 8.99 (file 20240225)
Created
30 Apr 2025
Updated
19 May 2025

Overview

10hp generic is an open-source printed circuit board by riban-bw, from the riban-bw/modular repository on GitHub. It is a 2-layer board of 48.8 × 106 mm with 89 parts on 59 nets, routed with 936 tracks and 25 vias.

It is built around the TJA1051T/3/1, AMS1117-3.3 and WS2812B. Its parts include 41 capacitors, 16 diodes, 16 switches, 3 ICs and 3 connectors. It belongs with the STM32 boards of this library.

Main components

3

README

README.md

riban modular

Overview

Riban modular is an open source and (where practical) open hardware virtual modular synthesiser with physical control panels that fit the Eurorack physical format. See the wiki for documentation.

There are hardware panels that represent each virtual module. The panels are plugged together via a daisy-chain ribbon cable which provides power and a CAN bus for inter-communication. Modules have rotary controls, switches, LEDs, etc. that mimic and control the virtual modules. A Raspberry Pi 5 forms the core, providing the audio processing and interfacing with the hardware panels. Panels are detected automatically when connected, creating a corresponding virtual module within the virtual modular system.

The system consists of a Brain and panels. The Brain consists of a Raspberry Pi 5, STM32F103 microcontroller, CAN connector, audio interface and associated connectors, buttons, pots, etc. Panels consist of STM32F103 microcontroller, CAN connector and buttons, pots, etc.

Each panel is based on a STM32F103C8 microcontroller with a common firmware that supports various quantities and types of controls and indicators. Each panel has a type number that identifies what type of virtual module it represents.

Connect each module to a ribbon cable connector then power up the system. The core will communicate via CAN to detect which panels are installed, assign each panel an id then add a correspoding virtual module to its model.

Usage

Hardware panels are required to interface with the firmware. See the wiki for documentation.

Building

There are two core elements to riban modular: Hardware panels (including the firmware that runs on them) and the core. Panel firmware is written in C++ for the STMicroelectronics STM32 range of ARM based microcontrollers. The core is written in C++ for the Raspberry Pi ARM based SBC. VSCode IDE is used by the developer with plugins including platformio, which provides the build platform for the STM32 firmware. VSCode is run on a development PC, connected via ssh to the target (Raspberry Pi) platform.

Core

The core code runs on a Raspberry Pi (4 or later), running DietPi operating system. CMake is used as the build tool. We use some modules from Bogaudio so have a dependancy on their source code with a small patch to exclude the GUI code. To compile the code:

  • Install dependencies, e.g. sudo apt install build-essentials libjack-jackd2-dev git cmake nlohmann-json3-dev
  • Clone this repository, e.g. git clone --recursive https://github.com/riban-bw/modular.git
  • Change to the directory, e.g. cd modular/firmware/rmcore
  • Create a build directory, e.g. mkdir build
  • Change to the build directory, e.g. cd build
  • Create build files, e.g. cmake ..
  • Build executable, e.g. make

An executable file called rmcore is creaed in the build directory. This may be run with optional command line options, e.g. rmcore -h to show help / usage.

Panels

Each panel has a platformio configuration. These build instructions are for platformio within vscode IDE. (You could just use platformio directly.) I have written up a guide to using platformio within vscode over ssh to a Raspberry Pi to develop STM32 code. Follow that guide to get a working build environment. There are sepearate platformio projects for each panel, defined by a platformio.ini file in the panel's firmware directory.

  • Within vscode, click on the platformio icon in the left toolbar.
  • Click on "Open Folder" and open the panel directory.
  • If this is the first time, platformio will download and install the STM32 toolkit which may take several minutes.
  • Click on the tick icon in the bottom toolbar to build the project. First time build may take longer as it builds all the dependant libraries.

To switch panels, use vscode file menu, open folder... Each time a new panel project is opened for the first time, platformio takes some time to configure. (Even on subsequent switches, platformio can take some time to open a project.)

Be aware that rmcore is within the firmware directory but is not a panel firmware and should be built as described in the above section.

CAN Protocol

Communication between the Brain and panels uses CAN two wire serial bus. CAN uses differential balanced cabling to provide robust, high speed communication over long distance. Detection of panels uses CAN extended frame format (to allow fewer frames during detection) whilst normal operation uses standad frame format (to allow shorter frames for realtime data). Each panel starts by advertising its 96-bit hardware UID (STM32 serial number). The Brain module detects new panels and negotiates a panel id (1..63) for each. CAN uses a lowest-id-wins mechanism for bus arbitration which allows the Brain to negotiate each panel partaking in the detection process. The panel with the lowest UUID is assigned the next available panel id which then leaves the detection process and joins the pool of configured panels. The Brain iterates over all panels currently advertising their participation in the detection process.

Subsequent communication between the Brain and each panel is via CAN messages initiated by panels for sensor changes (switches, knobs, etc.) or the Brain for indications (LEDs, etc.). The message type is encoded in the CAN ID. Each panel uses CAN filters to only listen for messages from the Brain. Similarly the Brain listens for messages from panels. All CAN traffic occurs between STM32F103 based devices.

CAN Message Protocol

CAN message id is 11-bit (std) or 29-bit (ext) word.

Standard CAN format (11-bit id) is used for runtime realtime messages.

Extended CAN format (29-bit id) is used for configuration and firmware update.

CAN runtime realtime messages

Brain to panel (B→P) CAN ID: bit [0] = 0, bits [1:7] = panel id (1..63), bits [8:11] = opcode.

Panel to Brain (B←P) CAN ID: bits [0:7] = 0, bits [8:11] = opcode.

Brain to rmcore splits messages into whole bytes, i.e. CAN ID[1], opcode[1], data[8].

rmcore can send messages to the Brain by setting first byte to 0xFF or to a panel by setting first byte to panel (CAN) id.

CAN payload may have varying length (0..8 bytes) depending on message type.

Brain always listens for panel messages and may request values with appropriate commands. This is asynchronous.

Host (RPi) communicates with Brain via serial port, mostly using same CAN protocol, i.e. the Brain passes through the CAN messages. An exception is for panel detection which the Brain handles locally and passes a single message to the host after detecting each panel.

B↔PIDOpCodePayloadPurpose
B→PLED0x01Index [0:7] Mode [0:7] RGB1 [0:23] RGB2 [0:23]Set LED type and mode. RGB colours are both optional
B←PADC0x02PanelId [0:7] Index [0:7] Value [0:15]ADC value
B←PSW0x03PanelId [0:7] Index[0:7] EventType [0:7]See below for event types
B←PENC0x04PanelId [0:7] Index [0:7] Value [0:7]Encoder value +/-
B←PPNL_DUMP0xF1PanelId [0:7]Request panel to send its parameter values
B←PALIVE0x0ESent periodically if no other data sent to support watchdog
B→PRESET0x0FRequest panel to reset to detection mode
B←HNUM_PNL0x01Request quantity of detected panels
B←HPNL_INFO0x01Request type of all panels
B→HPNL_INFO0x01PanelId [0:5] Type [0:31] UUID [0:95] Ver [0:31]Panel type (sent when new panel detected or PNL_INFO requested)
B→HPNL_REMOVED0x02PanelId [0:5] UUID [0:95]
B←HPNL_RUN0x03Request all panels go to run mode
LED Modes
ValueMode
0x00Off
0x01Colour 1 on
0x02Colour 2 on
0x03Flash colour 1 / colour 2
0x04Fast flash colour 1 / colour 2
0x05Pulse colour 1 / colour 2
0x06Fast pulse colour 1 / colour 2
Switch States
ValueState
0x00Release
0x01Press
0x02Bold
0x03Long
Panel Detection

Panels advertise themselves with a CAN message which the Brain detects and starts a negotation. Detection messages use extended CAN ID which is 29-bits long (compared with standard frames used for realtime messages which are 11-bits). Each panel advertises itself by encoding its 96-bit UUID in the CAN ID of 4 consecutive messages. Each message is acknowledged by the Brain, indicating which panel UUID are accepted. Only panels that match that segment of the UUID continue with the negotiation. Eventually only one panel remains and is assigned a panel ID. Finally the panel indicates it has accepted the panel, sending its type and version. This allows the Brain to build a table of panel UUID, panel ID and panel type so that the core can create the appropriate virtual modules. It also allows the Brain to know whether a panel is running old firmware, allowing firmware update. The table is used to ensure that existing panels that restart, e.g. after a firmware update get the same panel ID.

B⬌PIDIDPayloadPurpose
B←PDETECT_10x1F<UUID[0:23]>Notify Brain that panel is added to bus but not initialised
B→PDETECT_10x1F000000UUID[0:23]Brain acknowledges lowest UUID panels
B←PDETECT_20x1E<UUID[24:47]>Panel requests detect stage 2
B→PDETECT_20x1E000000UUID[24:47]Brain acknowledges lowest UUID panels
B←PDETECT_30x1D<UUID[48:71]>Panel requests detect stage 3
B→PDETECT_30x1D000000UUID[48:71]Brain acknowledges lowest UUID panels
B←PDETECT_40x1C<UUID[71:95]>Panel requests detect stage 4
B→PDETECT_40x1C000000UUID[72:95] PanelID[0:7]Brain acknowledges UUID of only remaining panel
B←PACK_ID0x1B0000Type [0:31] Version [0:31]Panel acknowledges ID and informs Brain of its version & type
Broadcast messages and firmware update

The CAN ID 0x000 is used to broadcast messages to all panels. This is the highest priority CAN ID (lowest value wins all bus conflict negotiation) and is used for low latency messaging (e.g. synchronisation) and firmware update. The first byte of a broadcast payload data is the opcode for a command. All broadcast messages use standard (11-bit) CAN format.

Broadcast messages

DirIDIDPayloadPurpose
B→PBROADCAST0x00000000OPCODE[0:7]Broadcast from Brain payload contains opcode (see below)
B→PBROADCAST0x000000000x01 UUID[0:23]Start detection - all panels should join detection without software reset
B→PBROADCAST0x000000000x02 PanelType [0:23] Ver [0:31]Start firmware update
B→PBROADCAST0x000000000x03 Checksum [0:31]End firmware update
B→PFIRMWARE0x01000000Firmware Block [0:63]Firmware update data block
B→PBROADCAST0x000000000xFFFull reset - all panels should perform software reset

Firmware is started with the broadcast message (CAN ID=0x000) with opcode 0x02. The panel type and firmware version are sent in this message. Any panel of this type with an older firmware will join the firmware update. Subsequent firmware update messages use the CAN ID 0x400 (msb set) with 8 bytes of firmware data. Panels configure a CAN filter to listen to this address during firmware update only. Upon completion of firmware update the Brain sends broadcast message with opcode 0x03 and a 32-bit checksum of the firmware data. The Brain ends its firmware update. Panels validate the checksum then apply the new firmware, restart and advertise as new panels.

Watchdog

Each panel periodically sends an ALIVE message if no other message has been sent in the previous 1.5s. If the Brain has not received any message from a panel for longer than 2s it assumes the panel has been removed from the bus and removes its entry from the panel table. This triggers removal of the corresponding virtual module.

Configuration

Configuration is stored in config.json which is loaded before command line parameters are parsed, so command line parameters take precedent.

Global settings are defined in the "global" object.

text
{
    "global": { # Global settings
        "polyphony": 1 # Quantity of concurrent voices (1..16)
    }
}

Each panel is defined in "panel" object.

text
{
    "panels" : { # Object of panel types
        "1": { # Object of panel configuration indexed by panel type id
            "module": "vco", # Name of the module type this panel controls
            "buttons": [ # List of buttons, indexed by physical button number
                [0, # Button function (input, poly input, output, poly output, param)
                0], # Index of the parameter or input/output
                # .. more button configs
            ],
            "leds": [ # List of LEDs, indexed by physical LED number
                [0, # LED function  (input, poly input, output, poly output, param)
                0], # Index of parameter or input/output
                # ... more LEDs
            ],
            "adcs": [ # List of parameters, indexed by physical ADC number
                0, # Parameter index
                # ... more ADCs
            ]
            "encs": { # List of parameters, indexed by physical PEC11 encoder number
                0, # Parameter index
                # ... more encoders
            }
        }, # ... More panel types
    }
}

panel_types.h defines mapping of panel types to module types and defines the STM32F103 pins used for sensors (controls) on each panel.

License

riban modular is free and open source software, avaialble for distibution, use and modification by all. It has three open source licences, each applied to different parts of the code. Each source code file (including headers) contain a copyright notice describing which license applies to that part of the code. If a file is missing this banner, LGPL v3 is applied.

LGPL V3

LGPL v3 is used for the core software and some plugins. This protects the core application whilst allowing non-open source plugins to be hosted by exercising dynamic linking with runtime loading (plugin exception). The text of the LGPL v3 license is distributed with the source code within the file called, lgpl-3.0.txt and may also be obtained from https://www.gnu.org/licenses/lgpl-3.0.en.html.

GPL V3

To support plugins derived from GPL licensed code, some plugins have been licenced using GPL v3. These plugins continue to be fully copy-left protected whilst also able to be loaded into the core application using dynamic linking with runtime loading (plugin exception). The text of the GPL v3 license is distributed with the source code within the file called, gpl-3.0.txt and may also be obtained from https://www.gnu.org/licenses/gpl-3.0.en.html.

MIT

To encourage third party plugin developement, there is a plugin template released under MIT license. This permits the use of the template as the basis of new plugins with the option for the author to release the derived work under any other license. We encourage use of LGPL for plugins where an open source license is required or preferred.

Guidance and advice for plugin creators

If you are creating plugins to run within riban modular, you may use the template.h and template.cpp files as the boiler plate code. These files are published under the MIT license, specifically to allow and encourage developers to create new plugins without restricitve licensing constraints. You may create a new plugin and use the riban modular cmake based build system to create the shared library. You may release this under a license that best suits your use case. You must attribute riban ltd as the author of the original template code, as described in the template source code.

Parts

89
QtyValueFootprintReferences
30100nFCapacitor_SMD:C_0402_1005MetricC1, C2, C10, C11, C12, C13, C14, C15, C16, C17, C18, C19, C20, C21, C22, C24 +14
16SW_Pushriban:SW_PUSH_6mm_H4.3mmSW1, SW2, SW3, SW4, SW5, SW6, SW7, SW8, SW9, SW10, SW11, SW12, SW13, SW14, SW15, SW16
16WS2812Briban:LED_XL-1615RGBC-WS2812BD1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, D16
810Kriban:Potentiometer_9mm_VerticalRV1, RV2, RV3, RV4, RV5, RV6, RV7, RV8
2100nFCapacitor_SMD:C_0603_1608MetricC23, C37
210uFCapacitor_SMD:C_0805_2012MetricC32, C34
222pFCapacitor_SMD:C_0603_1608MetricC38, C39
24.7uFCapacitor_SMD:C_0805_2012MetricC27, C29
1100pFCapacitor_SMD:C_0402_1005MetricC41
110KResistor_SMD:R_0402_1005MetricR1
110nFCapacitor_SMD:C_0402_1005MetricC30
11uFCapacitor_SMD:C_0402_1005MetricC31
18MHzriban:HC-49SY1
1AMS1117-3.3Package_TO_SOT_SMD:SOT-223U2
1CAN_PWRConnector_IDC:IDC-Header_2x03_P2.54mm_VerticalJ1
1I2CConnector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_VerticalJ3
1STM32F103C8TxPackage_QFP:LQFP-48_7x7mm_P0.5mmU3
1SWDConnector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_VerticalJ2
1TJA1051T-3Package_SO:SOIC-8_3.9x4.9mm_P1.27mmU1

Questions

How big is the 10hp generic PCB?

It measures 48.8 × 106 mm and has 2 copper layers, 1.6 mm thick.

What parts does the 10hp generic use?

89 parts, built around the TJA1051T/3/1, AMS1117-3.3 and WS2812B. 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 10hp generic KiCad files?

From the riban-bw/modular repository on GitHub, at the commit this page was made from: the board is panels/pcb/10hp_generic/10hp_generic.kicad_pcb and its schematic panels/pcb/10hp_generic/10hp_generic.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the 10hp generic design in my own project?

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

Similar boards

  • 4 layers95 × 24 mmBoardyMcBoardFace, the printed circuit board in 3D

    BoardyMcBoardFace

    akhilveeraghanta/the-bots-mainboard

    The main board for the the bots SSL robocup team

    115 parts1
  • 4 layers50 × 50 mmKleverLogger, the printed circuit board in 3D

    KleverLogger

    charclo/KleverLogger

    Logger for Klever Speedpedelec

    75 parts
  • 2 layers91 × 55 mmPcb Name Card R4, the printed circuit board in 3D

    Pcb Name Card R4

    tokai-student-rocket-project/Pcb-Name-Card-R4

    Renesas RA4M1 (Arduino UNO R4) を搭載した名刺サイズの自作マイコン基板。USB Type-C・CAN通信 (TJA1051T/3)・NeoPixel・各種I/Oヘッダーを備えた実用的なPCB名刺のKiCad設計データです。

    49 parts
  • 4 layers99.5 × 69 mmPump controller reva, the printed circuit board in 3D

    Pump controller reva

    UWARG/pump-controller-hardware

    Hardware for Competition 2026 Water Pump Controller on Project Valkyrie

    244 parts
  • 4 layers135 × 82.5 mmProteus, the printed circuit board in 3D

    Proteus

    mck1117/proteus

    protean: able to do many different things; versatile.

    1,052 parts50
  • 2 layers120 × 90 mmBobbycontroller, the printed circuit board in 3D

    Bobbycontroller

    bobbycar-graz/Bobbycar-FOC-hardware

    Our own dual BLDC Motorcontroller

    328 parts23
  • 2 layers156 × 66 mmDash 6.8, the printed circuit board in 3D

    Dash 6.8

    romioRN/Dash6.8-hardware

    wifi name "service", password 12345678, connect to 192.167.4.1

    152 parts11Apache-2.0