Embedded Programming Cover

4. EMBEDDED PROGRAMMING

[ MISSION: Communicating with the soul of the machine. ]

What is Embedded Programming?

It is the art of writing code specifically for hardware that isn't a "traditional" computer. It's about efficiency, real-time response, and controlling every single electron moving through the pins to make a device come to life.

[ THE CONTROLLER: RASPBERRY PI PICO 2 ]

For this mission, I chose the Pico 2. I love the workflow using VS Code with the Pico extension—it makes the process much more professional and streamlined.

Pico 2 Pinout

> FIG 01: PINOUT_DIAGRAM

PIN TYPEFUNCTION
PowerVBUS (5V), 3V3, GND
GPIOGeneral purpose Input/Output (3.3V)
ADCAnalog to Digital Converter (12-bit)
PWMPulse Width Modulation (Motor/LED control)
SPECIFICATIONDETAILS
MicrocontrollerRP2350 (Dual Core ARM Cortex-M33)
Clock Speed150 MHz
Memory (SRAM)520 KB Internal
Flash Memory4 MB Off-chip (via QSPI)
LanguagesC/C++, MicroPython, Rust
Communication2x UART, 2x SPI, 2x I2C
Features8x PIO State Machines

SELECT EXECUTION ENVIRONMENT.

[ MISSION: WOKWI SIMULATION ]

STEP 01

Wiring the UI

Connecting the SSD1306 OLED display via I2C and the Joystick to the ADC pins.

Wokwi Setup
STEP 02

Logic Flow

Defining the physics of the speed simulation: acceleration, coasting, and braking.

Wokwi Code
STEP 03

Logic Flow

Defining the physics of the speed simulation: acceleration, coasting, and braking.

Wokwi Code
STEP 04

Logic Flow

Defining the physics of the speed simulation: acceleration, coasting, and braking.

Wokwi Code
STEP 05

Logic Flow (🔗)

Defining the physics of the speed simulation: acceleration, coasting, and braking.

> RUN_SIMULATION_ON_WOKWI
Wokwi Code

[ CLICK IMAGE TO OPEN PROJECT ]

STEP 06

Logic Flow

Defining the physics of the speed simulation: acceleration, coasting, and braking.

Wokwi Code
STEP 07

Logic Flow

Defining the physics of the speed simulation: acceleration, coasting, and braking.

Wokwi Code
STEP 08

Logic Flow

Defining the physics of the speed simulation: acceleration, coasting, and braking.

> RECORDING_ACTIVE
LIVE_FEED CAM_08
STEP 09

Logic Flow

Defining the physics of the speed simulation: acceleration, coasting, and braking.

Wokwi Code
STEP 1
from machine import Pin, ADC, I2C
import time
import ssd1306

# ---------- Pin Declarations ----------
joy_y = ADC(26)
brake = Pin(15, Pin.IN, Pin.PULL_UP)
brake_led = Pin(16, Pin.OUT)

i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=400_000)
oled = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C)

MAX_KMH = 30.0
DT_MS = 50
ACCEL_KMH_PER_S = 14.0
COAST_KMH_PER_S = 6.0
BRAKE_KMH_PER_S = 30.0
DEADZONE = 0.08
SMOOTH = 0.15

speed = 0.0
y_filt = 0.5

def clamp(x, a, b):
    return a if x < a else (b if x > b else x)

while True:
    dt = DT_MS / 1000.0
    y = joy_y.read_u16() / 65535.0
    y_filt = (1.0 - SMOOTH) * y_filt + SMOOTH * y
    cmd = (y_filt - 0.5) * 2.0
    if abs(cmd) < DEADZONE: cmd = 0.0
    braking = (brake.value() == 0)
    brake_led.value(1 if braking else 0)
    if braking:
        speed -= BRAKE_KMH_PER_S * dt
    else:
        if cmd > 0: speed += (cmd * ACCEL_KMH_PER_S) * dt
        else: speed -= COAST_KMH_PER_S * dt
    speed = clamp(speed, 0.0, MAX_KMH)
    oled.fill(0)
    oled.text("JOY SPD", 0, 0)
    oled.text(f"{int(speed + 0.5)} km/h", 0, 20)
    oled.text(f"cmd:{cmd:+.2f}", 0, 48)
    if braking: oled.text("BRK", 100, 0)
    oled.show()
    time.sleep_ms(DT_MS)
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
from micropython import const
import framebuf

# register definitions
SET_CONTRAST        = const(0x81)
SET_ENTIRE_ON       = const(0xA4)
SET_NORM_INV        = const(0xA6)
SET_DISP            = const(0xAE)
SET_MEM_ADDR        = const(0x20)
SET_COL_ADDR        = const(0x21)
SET_PAGE_ADDR       = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_SEG_REMAP       = const(0xA0)
SET_MUX_RATIO       = const(0xA8)
SET_COM_OUT_DIR     = const(0xC0)
SET_DISP_OFFSET     = const(0xD3)
SET_COM_PIN_CFG     = const(0xDA)
SET_DISP_CLK_DIV    = const(0xD5)
SET_PRECHARGE       = const(0xD9)
SET_VCOM_DESEL      = const(0xDB)
SET_CHARGE_PUMP     = const(0x8D)

class SSD1306(framebuf.FrameBuffer):
    def __init__(self, width, height, external_vcc):
        self.width = width
        self.height = height
        self.external_vcc = external_vcc
        self.pages = self.height // 8
        self.buffer = bytearray(self.pages * self.width)
        super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
        self.init_display()

    def init_display(self):
        for cmd in (
            SET_DISP | 0x00,               # off
            SET_MEM_ADDR, 0x00,            # horizontal addressing
            SET_DISP_START_LINE | 0x00,
            SET_SEG_REMAP | 0x01,          # rotate
            SET_MUX_RATIO, self.height - 1,
            SET_COM_OUT_DIR | 0x08,        # rotate
            SET_DISP_OFFSET, 0x00,
            SET_COM_PIN_CFG, 0x12 if self.height == 64 else 0x02,
            SET_DISP_CLK_DIV, 0x80,
            SET_PRECHARGE, 0x22 if self.external_vcc else 0xF1,
            SET_VCOM_DESEL, 0x30,
            SET_CONTRAST, 0xFF,
            SET_ENTIRE_ON,
            SET_NORM_INV,
            SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,
            SET_DISP | 0x01                # on
        ):
            self.write_cmd(cmd)
        self.fill(0)
        self.show()

    def poweroff(self):
        self.write_cmd(SET_DISP | 0x00)

    def poweron(self):
        self.write_cmd(SET_DISP | 0x01)

    def contrast(self, contrast):
        self.write_cmd(SET_CONTRAST)
        self.write_cmd(contrast)

    def invert(self, invert):
        self.write_cmd(SET_NORM_INV | (invert & 1))

    def show(self):
        self.write_cmd(SET_COL_ADDR)
        self.write_cmd(0)
        self.write_cmd(self.width - 1)
        self.write_cmd(SET_PAGE_ADDR)
        self.write_cmd(0)
        self.write_cmd(self.pages - 1)
        self.write_data(self.buffer)

    def write_cmd(self, cmd):
        raise NotImplementedError

    def write_data(self, buf):
        raise NotImplementedError

class SSD1306_I2C(SSD1306):
    def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
        self.i2c = i2c
        self.addr = addr
        self.temp = bytearray(2)
        super().__init__(width, height, external_vcc)

    def write_cmd(self, cmd):
        self.temp[0] = 0x80
        self.temp[1] = cmd
        self.i2c.writeto(self.addr, self.temp)

    def write_data(self, buf):
        # 0x40 = data stream
        self.i2c.writeto(self.addr, b"\x40" + buf)

[ SYSTEM LOG: AI COLLABORATION ]

LOG_01

"Optimized technical tables and elastic UI components for enhanced readability."

> STATUS: CODE_RELIABILITY_OPTIMIZED