MechBase PLC
PLC-style logic editor for industrial automation and Lego Technic projects. Web-based interface with Studio 5000 fidelity, targeting ESP32 firmware.
Overview
| Field |
Value |
| Path |
/home/vincent/projects/mechbase-plc/ |
| Port |
5003 |
| Stack |
Flask, TailwindCSS, React, C++ |
| Target |
ESP32 firmware |
| Business |
Build fee + monthly retainer for local shops |
| Status |
Active — Reactive subscriptions + structuredClone |
Architecture
┌─────────────────────────────────────────────────────────┐
│ ESP32 Firmware (C++) │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Ladder Interpreter │ │
│ │ │ │
│ │ For each scan: │ │
│ │ 1. Read digital inputs (GPIO) │ │
│ │ 2. Evaluate networks rung-by-rung │ │
│ │ a. Input branches (OR) │ │
│ │ b. Output branches (OTE/OTL/OTU/Timers) │ │
│ │ 3. Update timers (TON/TOF/TP) │ │
│ │ 4. Write physical outputs (GPIO) │ │
│ └───────────────────────────────────────────────────┘ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Web UI (served from ESP32) │ │
│ │ — Visual ladder editor │ │
│ │ — I/O monitoring │ │
│ │ — Program download │ │
│ └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
Ladder Logic Instructions
| Symbol |
Name |
Description |
--\| \|--- |
NO |
Normally Open — passes when TRUE |
--\|/\|--- |
NC |
Normally Closed — passes when FALSE |
--\|P\|--- |
Rising Edge |
Single-scan TRUE→FALSE transition |
--\|N\|--- |
Falling Edge |
Single-scan FALSE→TRUE transition |
T0.DN |
Timer Done |
Timer has reached preset |
T0.TT |
Timer Timing |
Timer is currently running |
T0.EN |
Timer Enable |
Timer rung has power flow |
Outputs
| Symbol |
Name |
Description |
--( )-- |
OTE |
Output Energize — follows input power |
--(L)-- |
OTL |
Output Latch — SET, stays ON once set |
--(U)-- |
OTU |
Output Unlatch — RESET, clears latched output |
--(TON)-- |
TON |
Timer On-Delay |
--(TOF)-- |
TOF |
Timer Off-Delay |
--(TP)-- |
TP |
Timer Pulse |
Timer Status Bits
| Bit |
Meaning |
| EN |
Enable — controlling rung has power flow |
| TT |
Timing — timer is currently counting |
| DN |
Done — timer has reached preset |
GPIO Map (ESP32)
| Pin |
Function |
| GPIO 27 |
Digital Input 0 |
| GPIO 26 |
Digital Input 1 |
| GPIO 33 |
Digital Input 2 |
| GPIO 35 |
Digital Input 3 |
| GPIO 34 |
Digital Input 4 |
| GPIO 25 |
Digital Output 0 |
| GPIO 32 |
Digital Output 1 |
| GPIO 4 |
Digital Output 2 |
| GPIO 15 |
Digital Output 3 |
Key Files
| Path |
Purpose |
src/ladder_interpreter.h |
C++ header — all types, enums, structs |
src/ladder_interpreter.cpp |
C++ implementation — evaluation, I/O, timers |
tests/ladder_test.py |
Python test harness (runs on Pi for testing) |
templates/motor_control.json |
Motor interlock template |
Testing
cd ~/projects/mechbase-plc
python3 tests/ladder_test.py
10 tests covering: NO/NC, OTE, OTL/OTU, parallel branching, series contacts, TON/TOF/TP with all status bits, start/stop latching, motor interlock.