Skip to main content
Version: FILS English

Matrix LED Adaptive Headlight System

A simplified replica of modern adaptive headlight systems found in vehicles, using a matrix of LEDs, real-time sensor input, and Rust-powered control logic running on a Raspberry Pi Pico 2W.

info

Author: Eduard-Andrei Balaceanu
GitHub Project Link:: https://github.com/UPB-PMRust-Students/project-eduard1506

Description

This project showcases the knowledge acquired throughout the semester by designing a functional hardware system that runs software written entirely in Rust. The system replicates a simplified version of the adaptive headlight functionality found in modern vehicles, using a matrix of LEDs controlled by a Raspberry Pi Pico 2W microcontroller.

The setup includes multiple white LEDs arranged in a grid, which dynamically turn on/off or dim based on real-time sensor input. The system uses light sensors to detect the presence and direction of oncoming lights, and a distance sensor to identify nearby objects. It also features adaptive cornering simulation using a joystick input.

The goal is to demonstrate real-time hardware control, sensor input interpretation, and modular embedded design using the Rust programming language.

Motivation

One of my biggest passions is cars—and everything they represent. I've always loved the feeling of a late-night drive, but to truly enjoy it, you need a powerful and intelligent lighting system. Matrix LED headlights represent the pinnacle of automotive lighting technology, adapting dynamically to changing road conditions, light sources, and traffic.

I’ve been fascinated by how this system works, how it improves both safety and comfort, and why it isn’t more widely adopted across all types of vehicles. Through this project, I wanted to explore the core principles behind adaptive lighting and bring a simplified version to life using accessible components and Rust-based control logic.

Architecture

The system architecture consists of the following functional layers:

  1. Sensor Layer

    • Three ambient light sensors (TEMT6000) detect the direction and intensity of incoming light sources.
    • One ultrasonic sensor (HC-SR04) measures the distance to nearby objects.
  2. Control Layer

    • A Raspberry Pi Pico 2W reads input data from all sensors.
    • A custom control algorithm written in Rust determines which LEDs should be turned on, off, or dimmed.
  3. Output Layer

    • A matrix of white LEDs is powered and controlled via IRLZ44N MOSFETs.
    • The system dims or disables individual LEDs based on sensor input to avoid blinding oncoming traffic while preserving road visibility.

Each component is connected using breadboards and jumper wires, with careful power and grounding design to ensure stability. The entire system operates without external Wi-Fi or cloud dependency, functioning in a fully local, embedded environment.

Diagram

alt text

Weekly Log

Week 8 – May 4th

Over the past few weeks, I’ve been gathering all the necessary components for the project. After pitching my idea to the professor and getting the green light, I decided to attempt building a simplified version of the Matrix LED adaptive headlight system used in modern vehicles.

This week marked the official start of the documentation process. I’ve already experimented with wiring the Pico 2W, tested the debugger, and ran a few simple LED blink tests in Rust to confirm everything’s working. Most of the hardware is now in place — the MOSFETs, LEDs, sensors, and breadboards — though I’m still waiting on the OLED screen and joystick module.

I also started working on the architecture diagram using diagrams.net. I’m aiming to create something clean and professional, so the structure makes sense both visually and logically. Once that’s done, I’ll export it and integrate it into the site. Documentation is coming together nicely so far.

Week 9 – May 11

Building the physical matrix was the main focus this week. I wired the 6×3 LED grid on the breadboards and connected the column MOSFET gates to the Pico’s GPIO 7 through 12. The row anode lines were wired to GPIO 13 through 15, each protected by a 330Ω resistor to limit current. After checking the wiring multiple times, I was able to confirm that I could control each LED individually and that the matrix multiplexing logic worked as planned.

Week 10 – May 18

Sensor integration was the big challenge for this week. I connected two TEMT6000 light sensors, one on each side of the matrix, to serve as left/right ambient detectors. Both sensors were connected to Pico ADC pins (GP16 and GP17), and I wrote the initial Rust code to read and process their analog output. I also integrated the HC-SR04 ultrasonic distance sensor, adding a simple voltage divider on the ECHO pin to safely handle the 5V signal. There were some early issues with sensor noise and ADC instability, but after a few tweaks to the software and power supply setup, the sensor readings became reliable.

Week 11 – May 25

This week was all about refining the software. I finished the main matrix control algorithm in Rust, implementing column-based multiplexing and software PWM for smooth row dimming. After some trial and error, I managed to significantly reduce LED flicker by increasing the PWM steps and optimizing the timing of the multiplex loop. I also improved the sensor code by reading the ultrasonic sensor less frequently (to avoid blocking LED refresh) and adding a smoothing function to the global brightness value, which eliminated any visible jitter in the LEDs. By the end of the week, the system reliably adapted the LED matrix in real time based on both ambient light and object distance, running smoothly and consistently.

Hardware Design

The core of the system is built around a Raspberry Pi Pico 2W, which interfaces with a 6×3 matrix of white LEDs. These LEDs are arranged in 6 columns and 3 rows and are controlled through IRLZ44N N-channel MOSFETs. Each column has a dedicated MOSFET that connects the cathodes of the LEDs in that column to ground, while the rows are powered individually using GPIO pins through 330Ω resistors. This allows matrix-style multiplexing, which significantly reduces the number of GPIOs required to control multiple LEDs individually.

The full assembly is split across two breadboards:

One holds the Pico microcontroller, all necessary resistors, and distributes row power rails

The second contains all MOSFETs, the LEDs, and the column control wiring

In addition to the LED control, the hardware integrates multiple sensors:

Two TEMT6000 light sensors, used to detect ambient brightness from both sides

One HC-SR04 ultrasonic distance sensor, used to measure object proximity

(Planned) A joystick for manual steering simulation

All sensors are powered by the Pico and are connected to its GPIOs as shown below.

Pico GPIO PinFunctionConnected To
GP17TRIG signal for ultrasonic sensorHC-SR04 pin 3 (TRIG)
GP16ECHO signal input (via voltage divider)HC-SR04 pin 4 (ECHO)
GP7MOSFET Gate for Column 1Gate of MOSFET 1 (via 220Ω resistor)
GP8MOSFET Gate for Column 2Gate of MOSFET 2 (via 220Ω resistor)
GP9MOSFET Gate for Column 3Gate of MOSFET 3 (via 220Ω resistor)
GP10MOSFET Gate for Column 4Gate of MOSFET 4 (via 220Ω resistor)
GP11MOSFET Gate for Column 5Gate of MOSFET 5 (via 220Ω resistor)
GP12MOSFET Gate for Column 6Gate of MOSFET 6 (via 220Ω resistor)
GP13LED Matrix Row 1 (Anode supply)Row 1 LEDs via 330Ω resistor
GP14LED Matrix Row 2Row 2 LEDs via 330Ω resistor
GP15LED Matrix Row 3Row 3 LEDs via 330Ω resistor
GP26Light Sensor 1 (left side)Analog OUT (V pin) of TEMT6000 #1
GP17Light Sensor 2 (right side)Analog OUT (V pin) of TEMT6000 #2

Sensor Wiring TEMT6000 Ambient Light Sensors (x2) The project uses two TEMT6000 ambient light sensors, placed on opposite sides of the breadboard to detect directional brightness — simulating oncoming traffic from the left or right. These sensors output an analog voltage that varies with light intensity, allowing the Pico to react accordingly.

Each sensor has three pins: S (Supply): Connected directly to the Pico’s 3.3V output pin G (Ground): Connected to the common GND rail shared across the circuit V (Analog output): Connected to an ADC-capable GPIO on the Pico

HC-SR04 Ultrasonic Distance Sensor The HC-SR04 module is used to detect obstacles in front of the LED array, simulating real-time responsiveness to nearby objects or vehicles. It has four pins: VCC: Connected to 5V (VSYS) from the Pico GND: Connected to the common ground rail TRIG: Connected to GP2, configured as an output ECHO: Connected to GP3, configured as an input, with a voltage divider

The ECHO pin outputs 5V, which is unsafe for direct connection to the Pico’s 3.3V GPIOs. To protect the microcontroller, a simple resistive voltage divider is used: A 10kΩ resistor connects ECHO to GP3 A 22kΩ resistor connects the midpoint between ECHO and GP3 to GND This reduces the 5V ECHO pulse to ~3.3V, making it safe for the RP2040 input.

📸 Photos of the Build

The following images show the current stage of hardware assembly, including breadboard layout, wiring details, and sensor positioning.

alt text alt text

KiCad Schematic

Full Setup

Bill of Materials

DeviceUsagePrice
Raspberry Pi Pico WThe microcontroller35 RON
BreadboardThe main breadboard10 RON
Light Sensors (x2)Measure ambient light2 x 9.99 RON
Ultrasonic SensorDetect object distance6.49 RON
MOSFETs (IRLZ44N x6)Drive high-power LEDs6 x 4.99 RON
LED AssortmentVisual output (matrix lighting)26.99 RON

Software

LibraryDescriptionUsage
heaplessData structure libraryUsed for String vectors
embassy_rpEmbassy HAL for the Raspberry Pi RP2040Used to program the Pico
embassy_syncSync primitives and async data supportCommunicating through tasks
embedded-halHardware abstraction traitsCommon interface for embedded peripherals
defmt, defmt-rttLightweight logging + RTT interfaceDebugging via the probe
cortex-mARM Cortex-M microcontroller supportLow-level control
cortex-m-rtRuntime supportStartup and interrupts
panic-haltPanic behaviorSafe stop on crash