Inspiration
Embedded development is one of the few remaining disciplines where debugging still happens after compilation. You write code, upload it to a microcontroller, and only then discover that a pin was wrong, your I2C address was invalid, you overflowed RAM, or the ESP32 silently rebooted because a strapping pin was misconfigured.
This workflow is slow, unclear, and often frustrating—especially for beginners and even more so for production firmware engineers.
I wanted to fix that.
My inspiration for Sentinel came from a simple question:
“Why doesn’t embedded development have real-time diagnostics, the same way modern languages have type checking?”
Every other domain has intelligent tooling. Hardware developers still rely on trial and error. Sentinel makes embedded development feel modern. It moves error detection from after compilation to as you type.
What it does
Sentinel is a hardware-aware VS Code extension that prevents embedded system bugs before they happen.
It uses a custom Language Server Protocol (LSP) to perform:
Real-time memory analysis (±3% accuracy)
- RAM + Flash estimation before compilation
- Global variable + stack analysis
- Dynamic allocation tracking
- Framework overhead calibration (Serial/Wire/SPI/WiFi/BLE)
Pin conflict detection
- Tracks all pin assignments across files
- Detects overlapping usage: digital/PWM/analog/UART/SPI/I2C
- ESP32 strapping pin warnings
- Boot-mode interference alerts
Protocol validation
- I2C address checking (0x08–0x77)
- Conflict detection for shared buses
- SPI clock compatibility
- UART baud validation
- Pull-up resistor reminders
- 200+ I2C device address autocompletion
Hardware-aware IntelliSense
- Device register suggestions
- Board-specific pin hints
- Parameter hints based on hardware constraints
Visualization tools
- Pin usage map (color-coded)
- Live RAM bar in the status bar
- Post-build Flash/RAM charts
How I built it
Sentinel consists of two major components:
1. The VS Code Extension (Frontend)
- Built with TypeScript
- Uses Webviews for the sidebar panel
- Provides UI for:
- Memory bars
- Pin assignment maps
- Build/Flash actions
- Global variable breakdown
- Memory bars
- Integrates with
arduino-clito compile and upload firmware
2. The Embedded Language Server Protocol (Backend)
A custom LSP built in Node.js that performs:
Static code analysis
- Parses
.inoand.cppinto an AST - Walks declarations, functions, and library calls
- Tracks global variables, stack usage, and dynamic allocation
Hardware model
Maintains state for:
- Pin assignments
- I2C/SPI/UART configuration
- ESP32 strapping rules
- Arduino memory limits
Validation engine
- Runs 50+ hardware-specific rules
- Validates code incrementally (<100ms), re-checking only changed nodes
Calibration pipeline
To estimate memory accurately, Sentinel:
- Collected 100+ Arduino sketches
- Compiled them with
arduino-cli - Parsed
.mapfiles - Matched real memory usage to static estimates
- Tuned the model until accuracy hit ±3%
Challenges I ran into
1. Memory estimation is extremely hard
Static analysis can't know runtime stack size perfectly. Achieving ±3% required:
- Multi-pass analysis
- Calibrating for framework overhead
- Reverse engineering compiler behavior
- Handling recursion, mutual calls, and unused globals
2. Parsing embedded code reliably
Arduino code mixes:
- Preprocessor macros
- Header includes
- C++ classes
.inoautowiring rules
I had to build a custom parser layer on top of a standard TypeScript-based AST engine.
3. ESP32 strapping pin rules are messy
Espressif’s documentation is inconsistent. I had to test behaviours manually:
- GPIO0/GPIO2/GPIO12/GPIO15 during boot
- WiFi stack placement on Core 0
- PSRAM-induced memory fragmentation
4. Real-time performance
LSP diagnostics must run under 100ms or VS Code becomes sluggish.
I rewrote several algorithms using:
- Incremental parsing
- AST diffing
- Cached symbol tables
- Memoized hardware state
5. Building something this large in a hackathon timeline
This is more of a dev tool startup than a typical weekend script. Balancing scope vs quality was tough.
Accomplishments that I'm proud of
- Built a custom Language Server Protocol from scratch
- Achieved ±3% RAM/Flash accuracy
- Wrote a 50-rule hardware validation engine
- Created real-time pin conflict detection
- Designed a full-featured VS Code sidebar UI
- Added Arduino + ESP32 support
- Implemented hardware-aware IntelliSense
- Delivered a tool that genuinely improves embedded development
Sentinel works, it’s fast, and it solves a real problem.
What I learned
- How to build a full LSP system and integrate it with a VS Code extension
- Deep insights into Arduino’s memory model, ESP32 boot rules, and microcontroller constraints
- How compilers allocate global variables and stack frames
- How to design UI/UX for developer tools
- How to optimize static analysis to run in <100ms
- How to build something that feels like a real product, not just a hack
What's next for Sentinel
Near-Term
- Full ESP32 memory analysis (IRAM/DRAM/PSRAM breakdown)
- ESP32 pin map visualization
- Support for Arduino Mega, Nano, ESP8266, STM32, Raspberry Pi Pico
- Power consumption estimator
- Serial plotter + oscilloscope integration
- Multi-board project workflows
Long-Term
- A universal embedded developer platform
- Cloud-based hardware simulation
- Real-time emulator for AVR + ESP32
- AI-assisted firmware auto-fixing
- Marketplace for new board definitions
Sentinel has the potential to become the modern toolchain for embedded systems, similar to how VS Code transformed web development.
Built With
- arduino
- esp32
- javascript
- lsp
- node.js
- typescript
- vscode-api
Log in or sign up for Devpost to join the conversation.