Skip to the content
PCBKitNew board
2 layers92.4 × 33.8 mmUIbuttons, the printed circuit board in 3D

Reverse engineering of a truck steering-wheel cruise/retarder switch panel (SKNY_FXP1 V1.1): schematic, netlist, resistor ladder decode, Arduino + Python toolchain

Size
92.4 × 33.8 mm
Copper layers
2
Thickness
1.6 mm
Parts
63
Nets
28
Pads
118
Tracks, vias
277, 20
Pours
1
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
11 Aug 2026
Updated
5 Sep 2026

Overview

UIbuttons is an open-source printed circuit board by ThatguyCplus, from the ThatguyCplus/truck-switch-reverse-eng repository on GitHub, published under the MIT licence. It is a 2-layer board of 92.4 × 33.8 mm with 63 parts on 28 nets, routed with 277 tracks and 20 vias.

Its parts include 26 resistors, 10 diodes and 1 connector.

README

README.md

Truck Steering-Wheel Switch Panel — Reverse Engineering

image

Complete reverse engineering of a truck steering-wheel cruise/retarder switch panel: schematic, netlist, resistor values, connector pinout, and an Arduino + Python toolchain that reads all twelve buttons.

The board identifies itself on the silkscreen as SKNY_FXP1 V1.1 / 20220615 / G295197. It is sold as a replacement cruise-control switch module for Scania L/P/G/R/S-series tractors (OEM reference 2545507).

Independent research. Not affiliated with, authorised by, or endorsed by Scania or any vehicle manufacturer. Manufacturer and part numbers appear solely to identify which part was studied. Everything here was derived by measuring a unit purchased on the open market — no manufacturer documentation, firmware, or software was used or reproduced. The panel is entirely passive: resistors, LEDs, and switch contacts, with no firmware, encryption, or access control of any kind.

Component side


What it is

A 12-button steering-wheel panel with white LED backlighting, connected to the truck by a single 6-pin cable. Twelve buttons on three wires is achieved with three analog resistor ladders — a very common automotive pattern, because it gets the wire count down and gives open/short fault detection for free.

Buttons12 (in five physical zones)
Backlight10× white LED, individually ballasted
ConnectorMolex DuraClik, 6-pin (560020-0620 footprint)
Signal wires3 analog ladder lines
Active componentsnone — fully passive

Connector pinout (J1)

PinFunctionNotes
1Backlight +~5 V dimmable illumination rail
2Ladder Acruise speed rocker (two-stage)
3Ladder Bcruise resume/cancel + follow distance
4Ladder Cdownhill/retarder
5Ground
6Backlight −LED cathode common

How button detection works

Each signal line is an identical series ladder — 62 → 100 → 150 → 390 Ω — with a 2 kΩ pulldown to ground. Every button shorts its own tap to ground, so each button presents a distinct resistance at the connector pin.

text
J1 pin ──62Ω──┬──100Ω──┬──150Ω──┬──390Ω──┬
              │        │        │        │
             SW1      SW2      SW3      SW4          2kΩ pulldown
              │        │        │        │            to GND
             GND      GND      GND      GND

The 2 kΩ pulldown is what makes the scheme fault-tolerant: an unplugged connector or a broken wire reads open-circuit, and a shorted harness reads ~0 Ω. Both are distinguishable from every legitimate button state.

Decode table

Resistance seen at the pin, and the resulting 10-bit ADC value with a 1 kΩ pull-up to 5 V (the wiring used by the tools in this repo):

TapLadder∥ 2 kΩADCLine A (pin 2)Line B (pin 3)Line C (pin 4)
162 Ω60 Ω58Cruise − BIGCruise CANCELDownhill CANCEL
2162 Ω150 Ω133Cruise − SMALLFollow dist +Downhill −
3312 Ω270 Ω217Cruise + BIGCruise RESUMEDownhill RESUME
4702 Ω520 Ω350Cruise + SMALLFollow dist −Downhill +
—idle2 kΩ682———
—open∞1023faultfaultfault

Physical layout

Five zones, left to right, twelve contacts total:

ZoneButtonsLine
Cruise resume / cancel2B (taps 3, 1)
Cruise speed rocker4 — two-stage: light press = small step, firm = big stepA (all four)
Follow distance2B (taps 2, 4)
Downhill rocker2C (taps 2, 4)
Retarder resume / cancel2C (taps 3, 1)

The cruise rocker is the only two-stage control, which is why one whole ladder is spent on a single rocker.


Simultaneous presses

Within a line the taps are a series chain, so grounding one tap shorts out every tap beyond it. Holding two buttons on the same line produces a reading that is bit-for-bit identical to holding the nearer-to-connector one alone — there is no signal to recover.

Rule: the reported button is the lowest-index one held; everything past it is invisible.

Enumerating all 2¹² combinations (tools/enumerate_combos.py → docs/button_combinations.csv):

text
total combinations      : 4096
fully observable        : 125
at least one masked     : 3971
distinct ADC signatures : 125   (5 states ^ 3 lines)

The three ladders are independent, so up to 3 buttons — one per line — register simultaneously. That is the hard ceiling of the design, not a software limit.


Backlight

Ten white LEDs sit in parallel between pin 1 and pin 6, each with its own ballast resistor. The values are deliberately unequal — that is brightness balancing, so legends behind heavier diffusers get more current and the panel looks even.

LEDBallastValueLEDBallastValue
LED1R16330 ΩLED6R21680 Ω
LED2R17680 ΩLED7R22470 Ω
LED3R18360 ΩLED8R23390 Ω
LED4R19300 ΩLED9R24680 Ω
LED5R20620 ΩLED10R25330 Ω

R26 (3.9 kΩ) bridges the rail with no LED — a bleeder that keeps the dimmer's off-state leakage from ghost-lighting the panel.

The LEDs are a 5 mA white part (2.9 V forward drop typical). Working backwards from the ballast values, the illumination rail is ~5 V, not 24 V — at 12 V the 330 Ω legs would pull 27 mA and at 24 V over 60 mA, well beyond the die rating. Total panel draw is about 47 mA including R26. The truck regulates and PWM-dims this rail before it reaches the wheel.


Full resistor list

RefCodeValueRoleRefCodeValueRole
R1391390 Ωladder A tap 4R142022 kΩpulldown B
R2151150 Ωladder A tap 3R152022 kΩpulldown C
R31000100 Ωladder A tap 2R16331330 ΩLED1
R462062 Ωladder A tap 1R17681680 ΩLED2
R5391390 Ωladder B tap 4R18361360 ΩLED3
R6151150 Ωladder B tap 3R19301300 ΩLED4
R71000100 Ωladder B tap 2R20621620 ΩLED5
R862062 Ωladder B tap 1R21681680 ΩLED6
R9391390 Ωladder C tap 4R22471470 ΩLED7
R10151150 Ωladder C tap 3R23391390 ΩLED8
R111000100 Ωladder C tap 2R24681680 ΩLED9
R1262062 Ωladder C tap 1R25331330 ΩLED10
R132022 kΩpulldown AR263923.9 kΩrail bleeder

Note that many chips are mounted rotated 180°, so their codes read upside-down in photographs — 189 on the board is a 681. Several values were only settled by rotating the image until neighbouring silkscreen read the right way up.

Test points

Every ladder node is brought out to a test pad, which makes fault-finding easy:

NodeLine ALine BLine C
tap 1TP1, TP2TP8TP13
tap 2TP3, TP6TP9TP12
tap 3TP5TP7TP14
tap 4TP4TP10TP11

Using it with an Arduino

Six wires and three resistors:

J1 pinArduino
15 V
2A0, plus 1 kΩ from A0 to 5 V
3A1, plus 1 kΩ from A1 to 5 V
4A2, plus 1 kΩ from A2 to 5 V
5GND
6GND, or a low-side MOSFET on D9 for PWM dimming

Do not use the internal pull-ups. At ~35 kΩ they would squash every button below 0.1 V and make the four taps indistinguishable. The external 1 kΩ spreads the five states across the ADC range with 75–330 counts between them — far more margin than the ADC's noise floor.

Worst-case current is 4.7 mA per line, and the source impedance the ADC sees never exceeds ~1 kΩ, comfortably inside the ATmega328P's 10 kΩ recommendation.

Flash firmware/panel_reader/panel_reader.ino. It streams raw averaged ADC counts as a,b,c at ~60 Hz and deliberately does not decode on-device, so thresholds can be retuned on the host without reflashing.


Tools

bash
pip install pyserial
python tools/panel_gui.py      # live monitor
python tools/panel_diag.py     # ladder fault finder

On Windows, tools/install_shortcuts.ps1 creates desktop shortcuts, or use the .bat launchers (which check for pyserial first).

Panel monitor — lights up a drawing of the real panel as buttons are pressed. Buttons that are held but electrically masked are labelled as such rather than silently ignored.

Monitor

Ladder diagnostics — works in the resistance domain rather than raw ADC, converting each reading back to ohms so a fault maps onto a physical node. It fits two competing models (a stuck switch on a healthy 2 kΩ line, versus a leak dragging the pulldown down) and reports which one the data actually supports.

Diagnostics

https://github.com/user-attachments/assets/56d19fef-1fe3-4a56-b6b1-583ad4992691


Repository layout

text
hardware/    KiCad 10 project — schematic, PCB, exported netlist
photos/      board photographs, plus PDFs with the traces drawn over
firmware/    Arduino sketch
tools/       Python monitor, diagnostics, combination enumerator
docs/        full combination table, screenshots

The .kicad_pcb is large (~31 MB) because it embeds the board photographs that were used as tracing underlays while the copper was being followed.

Method

  1. Photograph both sides at high resolution under even lighting.
  2. Draw over every visible trace in an image editor, working from the two PDFs in photos/ — one per side, with the component-side image mirrored so pad positions line up between the two.
  3. Transcribe to a KiCad schematic, then export the netlist and check it against the photos.
  4. Read every resistor code, rotating crops so upside-down parts read correctly.
  5. Verify electrically: measure each ladder node and confirm the predicted resistance.

The netlist was the useful cross-check throughout — the three ladders coming out identical (62/100/150/390 + 2 kΩ) was strong evidence the trace-following was right, and it caught two transcription errors that the photographs alone had not.

License

Code and documentation: MIT.

The measured electrical characteristics are facts about a physical object and are not claimed as anyone's intellectual property. Photographs are original work by the repository author.

Parts

63
QtyValueFootprintReferences
14TestPointTestPoint:TestPoint_Pad_D1.5mmTP1, TP2, TP3, TP4, TP5, TP6, TP7, TP8, TP9, TP10, TP11, TP12, TP13, TP14
12Push_ButtonPCM_SparkFun-Switch:Push_SMD_6x3.5mm+Downhill1, BigCruise-1, BigCruise+1, CancelCruiseControl1, CancelDownhillControl1, DecreaseFollowDistance1, DownHill-1, IncreaseFollowDistance1, ResumeCruiseControl1, ResumeDownHillControl1, SmallCruise-1, SmallCruise+1
10LED_1206_WhitePCM_LED_SMD_AKL:LED_1206_3216MetricLED1, LED2, LED3, LED4, LED5, LED6, LED7, LED8, LED9, LED10
4391PCM_Resistor_SMD_AKL:R_0805_2012MetricR1, R5, R9, R23
31000PCM_Resistor_SMD_AKL:R_0805_2012MetricR3, R7, R11
3151PCM_Resistor_SMD_AKL:R_0805_2012MetricR2, R6, R10
3202PCM_Resistor_SMD_AKL:R_0805_2012MetricR13, R14, R15
3620PCM_Resistor_SMD_AKL:R_0805_2012MetricR4, R8, R12
3681PCM_Resistor_SMD_AKL:R_0805_2012MetricR17, R21, R24
2331PCM_Resistor_SMD_AKL:R_0805_2012MetricR16, R25
1301PCM_Resistor_SMD_AKL:R_0805_2012MetricR19
1361PCM_Resistor_SMD_AKL:R_0805_2012MetricR18
1392PCM_Resistor_SMD_AKL:R_0805_2012MetricR26
1471PCM_Resistor_SMD_AKL:R_0805_2012MetricR22
15600200620molex:CONN_SD-560020-001_06_MOLJ1
1621PCM_Resistor_SMD_AKL:R_0805_2012MetricR20

Questions

How big is the UIbuttons PCB?

It measures 92.4 × 33.8 mm and has 2 copper layers, 1.6 mm thick.

What parts does the UIbuttons use?

63 parts. 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 UIbuttons KiCad files?

From the ThatguyCplus/truck-switch-reverse-eng repository on GitHub, at the commit this page was made from: the board is hardware/UIbuttons.kicad_pcb and its schematic hardware/UIbuttons.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the UIbuttons design in my own project?

Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).

Similar boards

  • 2 layers143.3 × 116.6 mmLeft, the printed circuit board in 3D

    Left

    hackclub/OnBoard

    💡 Join 1,000 teenagers and make your first PCB with a $100 grant!

    63 parts915
  • 2 layers107 × 54 mmInterface board 1, the printed circuit board in 3D

    Interface board 1

    Green-bms/SmartBMS

    Open source Smart Battery Management System

    63 parts756
  • 2 layers81.9 × 39.8 mmCAUTION LIGHTS PANEL, the printed circuit board in 3D

    CAUTION LIGHTS PANEL

    jrsteensen/OpenHornet

    OpenHornet 1:1 F/A-18C Simulator Repository

    63 parts431
  • 2 layers76.3 × 122.8 mmDiscipad pcb, the printed circuit board in 3D

    Discipad pcb

    coseyfannitutti/discipad

    17-key numpad assembled with only through hole components, including usb type-c

    63 parts221GPL-3.0
  • 2 layers53 × 47 mmServo control, the printed circuit board in 3D

    Servo control

    eddyem/stm32samples

    Code samples and ready projects based on bare-metal STM32

    63 parts208
  • 2 layers98 × 38 mmBldc control ver2, the printed circuit board in 3D

    Bldc control ver2

    pekkaroi/bldc-drive

    Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller

    63 parts199GPL-2.0
  • 2 layers60 × 75 mmMakennbot, the printed circuit board in 3D

    Makennbot

    idlehandsdev/makennbot

    A neural network bot for Make

    63 parts175