# ikea-led-obegraensad: turning an IKEA wall lamp into a programmable canvas

> An ESP32 firmware project that replaces the controller inside the IKEA OBEGRANSAD LED wall lamp, adds a web GUI, OTA updates, a plugin system and a DDP endpoint for pushing frames from Python. It is a hardware mod, and the README says to use it at your own risk.

**ph1p/ikea-led-obegraensad** — ESP32/Arduino hack for the ikea OBEGRÄNSAD led wall lamp

- Repository: https://github.com/ph1p/ikea-led-obegraensad
- Stars: 882 · Forks: 188
- Language: C++
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/ph1p-ikea-led-obegraensad

## Four identical plates of 64 LEDs, and a controller that has to go

The mod starts with what is inside the lamp and what has to change there. Opening the housing is the first hurdle, and it is not a screw job: IKEA uses rivets instead of regular screws, so the instructions describe inserting a screwdriver between the rivets and the back panel and prying it open carefully with a second object, with drilling out the rivets offered as a cleaner but permanent alternative.

Inside there are four identical plates with 64 LEDs each, arranged in four fields. The instructions focus on the lowest plate, because that is the one you interface with. It has six connectors along its bottom edge, which are the connection points for your board, and the original microcontroller sits at the top of that plate and must be removed.

Removing that controller is the irreversible step, and it is what makes the project a hack rather than a configuration change. Once it is gone, the panel is under your control and the lamp can be driven by anything that speaks the panel protocol. The lamp's own switch is repurposed at the same time, with the original button wiring offered as an alternative to adding an external one.

The README carries an explicit disclaimer that the code and instructions should be used at your own risk, since improper use may damage the device. That warning is not boilerplate here. The panel expects a specific clock, latch and data timing, and driving it wrongly can damage hardware.

## Pin selection lives in include/constants.h, not in the firmware logic

The wiring is described by a table that maps the panel's four signals onto board specific pins, and the table is long because the project supports several boards. For a plain ESP32 dev board the mapping runs GND to GND, VCC to 5V, EN (PIN_ENABLE) to GPIO26, IN (PIN_DATA) to GPIO27, CLK (PIN_CLOCK) to GPIO14 and CLA (PIN_LATCH) to GPIO12, with one end of the button to GPIO16 and the other to GND.

Other boards shift those assignments. The table covers an ESP32-C3, a TTGO LoRa32, a NodeMCUv2, a Wemos D1 mini, a Lolin D32 Pro and a Xiao ESP32S3, and each column renumbers the same four signals. Notably the power rail is not always 5V: the NodeMCUv2 column uses VIN, the Lolin D32 Pro column uses USB, and the Xiao ESP32S3 column uses VUSB.

The project states that the pins must be configured in include/constants.h according to your board, which is the point to notice. The constants file is where the abstraction ends and the hardware begins, and it is the first file to read after you pick a board. The include/ directory sits at the top level of the repository next to src/, lib/ and platformio.ini, so the separation between configuration and logic is visible in the layout.

The board list also carries a limitation. The software is designed for ESP32 dev boards but can work with other Arduino boards, with the caveat that WiFi, OTA and the web server features have to be removed for non-ESP boards. The ESP8266 path has its own constraint: per-pixel brightness only works when storage and global brightness are disabled.

## Twenty-six plugins, and a button to cycle through them

The lamp's behaviour after the mod is driven by plugins, and the list is the clearest statement of the project's scope. The available plugins are Draw, Game of Life, Breakout, Snake, Stars, Lines, Circle, Clock, Big Clock, Weather, Rain, Animation, Firework, DDP, Pong Clock, BigPong, Auto Walker, Bouncing Ball, Face, Falling Sand, Flappy Bird, Space Invaders, Spotlight, Tetris and Tron.

Reading that list tells you what the hardware is actually for. Most of these are animations that would sit on a desk, and several of them are games, which only works because a 64 pixel matrix is a legible display. Two entries are more structural. Animation comes with an animation creator in the web interface, so you can build content rather than only view it. DDP is a protocol entry rather than a visual one, and it is the hook for external control.

The plugin switching mechanism is deliberately physical. The feature list says you switch plugin by pressing the button, and there is a separate scheduler that switches plugins after a given number of seconds, plus scheduled brightness for a time frame. So the lamp can run unattended on a daily schedule without anyone touching it.

Development is documented in the same order as the rest of the project. Plugin development has two steps, creating the plugin files and then registering the plugin in main.cpp, which tells you the model is compile time registration rather than a runtime loader. The README also covers Arduino/C++ development, frontend development and code quality, and the repository holds a .clang-format file, a .pre-commit-config.yaml and a CODE_OF_CONDUCT.md.

## A web GUI, a WiFi setup step and OTA updates over the air

Once the firmware is running, the lamp is controlled over the network rather than by reflashing. The feature list names WiFi Control, a Web GUI and OTA Update, and the quick start section tells you to control the lamp using the built-in web GUI and to find the device IP address either from the serial monitor output or from the router admin panel.

The README's table of contents shows how much of the network side is specified in detail. There is a WiFi Configuration section with subsections for resetting WiFi and for DNS servers, and an OTA Updates section with a Configuration subsection, two upload methods described as a manual upload through the web interface and an automated upload through PlatformIO, and a Visual Feedback subsection that presumably covers what the lamp shows during an update. Those headings are the documented surface; the text behind them is beyond what the project description shows.

The HTTP API reference is broken into named groups that map onto what you would want to automate: device information, plugin control, display control with set brightness, scheduled brightness and get display data, message display with a display and remove pair, a plugin scheduler with set, start, stop and clear, and storage management with a clear storage call.

This is the part that turns the project from a novelty into a component in a house. The Home Assistant integration section names two routes, a HACS integration marked as recommended and an HTTP API integration for people who would rather point their own automation at the endpoints directly.

## DDP pushes frames from Python, and the Python side is a small Poetry project

DDP, the Display Data Protocol, is the one plugin that takes its input from somewhere else. The README has a dedicated section for it, and the repository holds a ddp.py file at the top level along with blobs.py and upload.py. The documented subsections are a Python project setup with Poetry, a quick start, using ddp.py and the protocol specification itself.

The Python side is a small, readable project. The pyproject.toml names it ikea-led-obegraensad at version 0.1.0, requires Python 3.12 or newer, and pulls in three dependencies: requests with a floor of 2.32.5, requests-toolbelt with a floor of 1.0.0 and tqdm with a floor of 4.70.1. The build backend is poetry-core and the package mode is off, so this is an application project rather than a library anyone installs.

The frontend is a separate concern with its own container definition. The docker-compose.yaml builds the frontend with a node alpine image, mounting the repository at /home/node/app with the frontend as the working directory, and running a shell command that installs libc6-compat, enables corepack, prepares pnpm at latest, installs from the frozen lockfile and runs the build.

```yaml
services:
  node:
    image: "node:alpine"
    volumes:
      - ./:/home/node/app
    working_dir: /home/node/app/frontend
    stdin_open: true
    tty: true
    command: >
      sh -c "
      apk add --no-cache --no-progress libc6-compat &&
      corepack enable &&
      corepack prepare pnpm@latest --activate &&
      pnpm install --frozen-lockfile && pnpm run build"
```

That definition is the frontend development loop in full, and it is worth reading as a signal: the web interface is a modern TypeScript and Vite style build, while the firmware underneath is an Arduino project with a PlatformIO configuration and a partitions-4MB.csv file.

## Recent commits, MIT terms, and a troubleshooting section that admits failure modes

The maintenance picture is good. The repository is not archived and the last push was on 2026-10-19, so the project is being worked on. The release history is short but real: v1.0.1 and v1.0.0 both on 2025-12-22, preceded by a first automatic release v0.0.1 on 2025-12-19. The licence is MIT, so the firmware and the tooling can be reused in commercial hardware without copyleft obligations, though the disclaimer about damaging the device is the project's own warning rather than a licence term.

The troubleshooting section names two failure modes that anyone doing this mod will care about. One is a flickering panel. The other is a microcontroller stuck in a boot loop, flickering panel and black panel, which the heading groups together as a single symptom. A boot loop on an ESP32 is usually a power or brownout problem, and on a lamp with a 5V rail and a matrix of 64 LEDs per plate the supply is the first thing to suspect.

There is also an upstream support question worth flagging. The panel is driven by a specific protocol with an enable line, a clock, a latch and a data line, and the original controller also appears to handle the button. The troubleshooting headings suggest the project has seen real failures here rather than theoretical ones, which is a reasonable signal for a hardware project of this size.

The one thing the project does not offer is a closed form bill of materials. The pin table names boards, and the repository layout names the firmware and tooling directories, but there is no listed list of parts, so an assembler has to derive the requirements from the panel and the wiring table.

## Conclusion

This project fits a maker who owns the IKEA OBEGRANSAD lamp, is comfortable soldering the panel connectors, and wants a programmable LED matrix on their own network rather than a packaged gadget. It does not fit anyone hoping to add a feature over the air to a lamp they have not opened, because the original microcontroller has to be removed and the board wired to the panel connectors by hand. Before you start, confirm you can open the housing without destroying it, since IKEA uses rivets rather than screws, set the pins in include/constants.h for the board you chose, and note that the ESP8266 path loses per-pixel brightness.

## FAQ

### How do I open the IKEA OBEGRANSAD lamp?

The lamp uses rivets instead of regular screws. The instructions are to insert a screwdriver between the rivets and the back panel and carefully pry it open with a second object, or to drill the rivets out, which is cleaner but permanent.

### Which boards does ikea-led-obegraensad support?

The software targets ESP32 dev boards and can work with other Arduino boards with WiFi, OTA and web server features removed. The pin table covers an ESP32, an ESP32-C3, a TTGO LoRa32, a NodeMCUv2, a Wemos D1 mini, a Lolin D32 Pro and a Xiao ESP32S3, and the pins must be set in include/constants.h.

### Can I control the lamp from my own code?

Yes. The project ships a DDP plugin, the Display Data Protocol, and a Python side with a ddp.py script, a Poetry setup and a protocol specification section. The HTTP API also offers plugin control, display control, brightness control and a scheduler.

### Does the mod need the original IKEA controller removed?

Yes. Inside the lamp there are four identical plates with 64 LEDs each, and the instructions focus on the lowest plate, where the original microcontroller sits at the top and must be removed. The six connectors along the bottom edge are where your board connects.

## Sources

- [Issues](https://github.com/ph1p/ikea-led-obegraensad/issues)
- [License: MIT](https://github.com/ph1p/ikea-led-obegraensad/blob/main/LICENSE)
- [ph1p/ikea-led-obegraensad on GitHub](https://github.com/ph1p/ikea-led-obegraensad)
- [README](https://github.com/ph1p/ikea-led-obegraensad/blob/main/README.md)
- [Releases](https://github.com/ph1p/ikea-led-obegraensad/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ph1p-ikea-led-obegraensad
