AI and I Suck

ESP32 Vacuum Sealer Controller

Replacing a failed vacuum sealer control board with closed-loop pressure control and WiFi parameter adjustment.

Overview

When the control board failed on a commercial vacuum sealer, the distributor was unable to provide a replacement board, leaving the choice between replacing the entire unit or building a new controller from scratch. Building from scratch won. The result is an ESP32-based system with a pressure sensor for closed-loop vacuum control, a state machine for precise cycle management, an OLED display for at-a-glance status, and a WiFi web interface for parameter adjustment from a phone — no app required.

The original board had no pressure sensor — it relied purely on timed sequences with no feedback. The new controller monitors actual chamber pressure and moves through each stage of the sealing cycle only when the correct conditions are met, producing more consistent and reliable seals.

How the Machine Works

Understanding the original machine's pneumatics was the most interesting part of this project. The vacuum sealer uses a clever differential pressure mechanism for the sealing bar clamp that requires no motor or dedicated actuator.

The sealing chamber contains a rubber bladder connected to the chamber via a solenoid valve (Valve 1). When the chamber is pumped down, the bladder evacuates along with everything else, so no clamping force is generated — the sealing bar stays up and the bag mouth is free to evacuate fully. When Valve 1 is de-energized, atmospheric air rushes into the bladder through the normally-closed valve. The pressure differential between the atmospheric-pressure bladder and the evacuated chamber pushes the sealing bar down firmly onto the bag, clamping it in place for the heat seal.

A second solenoid (Valve 2) vents the chamber back to atmosphere at the end of the cycle. As the chamber pressure returns to atmospheric, the differential disappears and the sealing bar lifts automatically.

Both solenoids are 120VAC normally-closed type, meaning they require power to open. This means the safe default state (power off) has both valves closed — the chamber stays sealed and the bladder stays connected to the chamber. The relay contacts switch the mains voltage directly to the solenoid coils.

Cycle Sequence

The controller implements a state machine with the following sequence:

Step

State

Action

1

EVACUATING

Valve 1 energizes (seals chamber), pump starts, pressure monitored until target vacuum reached. Fault if pump timeout exceeded.

2

DWELL

Pump holds vacuum for dwell time. Allows offgassing to settle before sealing.

3

CLAMPING

Valve 1 de-energizes. Atmospheric air enters bladder, differential pressure clamps sealing bar onto bag. Short settle delay.

4

SEALING

Heater bar energizes for seal time. Bag sealed under full vacuum.

5

COOLING

Heater off. Bar stays clamped, weld solidifies under pressure.

6

VENTING

Pump off. Valve 2 energizes for vent time, releasing chamber vacuum. Bar lifts as pressure equalizes. Bag collapses tightly around contents.

7

IDLE

Cycle complete. Ready for next bag.

Hardware

The controller is built around an ESP32-DEVKITV1 module. The choice of ESP32 gives built-in WiFi for the web interface, two hardware I2C buses, and plenty of GPIO for all the outputs required.

Parts List

Component

Description

ESP32-DEVKITV1

Main controller, WiFi, runs firmware

Adafruit MPRLS

Absolute pressure sensor, 0-170 kPa, I2C (Adafruit #3965)

SSD1306 OLED

0.96" 128x64 I2C display for status readout

4-Channel Relay Module

5V opto-isolated, active LOW, switches 120VAC solenoids and SSR triggers

2x SSR-25DA

Solid state relays for pump motor and heater bar (mains switching)

HLK-10M12

Hi-Link 120VAC to 12V DC supply for solenoid coils

Buck converter

12V to 5V for ESP32 and logic

2x Momentary buttons

START and STOP, panel mount

Pin Assignments

GPIO

Function

GPIO19

Relay 1 — pump SSR trigger (active LOW)

GPIO26

Relay 2 — heater SSR trigger (active LOW)

GPIO27

Relay 3 — Valve 1 bladder/vent solenoid (active LOW)

GPIO18

Relay 4 — Valve 2 chamber release solenoid (active LOW)

GPIO21

SDA — MPRLS pressure sensor + OLED display (shared I2C bus)

GPIO22

SCL — MPRLS pressure sensor + OLED display (shared I2C bus)

GPIO4

START button (active LOW, internal pullup)

GPIO5

STOP button (active LOW, internal pullup)

Firmware

The firmware is written in Arduino C++ and implements a non-blocking state machine. All timing and pressure parameters are stored in ESP32 NVS (non-volatile storage) flash and survive power cycles.

WiFi Web Interface

The ESP32 connects to the home WiFi network and announces itself via mDNS as vacuumsealer.local. On a phone or computer, simply browse to http://vacuumsealer.local to access the settings page. If the home network is unavailable, the controller falls back to broadcasting its own WiFi hotspot (SSID: VacuumSealer).

The web page updates the current state and chamber pressure every two seconds, and displays a fault message if the pump timeout is exceeded. Settings can only be changed when the machine is idle.

Adjustable Parameters

Parameter

Default

Description

Target Vacuum (kPa)

3.0

Chamber pressure at which to end evacuation. Lower = deeper vacuum.

Pump Timeout (s)

60.0

Fault alarm if target vacuum not reached in this time. Catches lid not seated or leaks.

Dwell Time (s)

3.0

Hold at vacuum before clamping. Allows offgassing to settle.

Clamp Settle (s)

0.0

Delay after bladder inflates before heater fires.

Seal Time (s)

2.0

Heater bar on time.

Cool Time (s)

3.0

Hold after heater off. Weld solidifies under clamp pressure.

Vent Time (s)

10.0

Valve 2 open time to release chamber vacuum at end of cycle.

Safety Features

STOP button — pressing STOP at any point in the cycle immediately turns off the pump and heater, opens Valve 1, then energizes Valve 2 for the configured vent time to safely release the chamber vacuum before returning to IDLE. The chamber is always safe to open before the display returns to IDLE.

Pump timeout fault — if the target vacuum is not reached within the configured timeout, the machine faults, vents the chamber, and displays the fault reason on the OLED and web page. Press STOP to reset.

Boot safety — all relay output pins are set HIGH (relays off) immediately on boot before any other code runs, preventing false triggering during startup.

Libraries Used

Library

Author / Source

Adafruit SSD1306

Adafruit — Arduino Library Manager

Adafruit GFX

Adafruit — Arduino Library Manager

Adafruit MPRLS

Adafruit — Arduino Library Manager

Adafruit BusIO

Adafruit — Arduino Library Manager

AsyncTCP

mathieucarbou — github.com/mathieucarbou/AsyncTCP (install via ZIP — required for ESP32 core 3.x)

ESPAsyncWebServer

mathieucarbou — github.com/mathieucarbou/ESPAsyncWebServer (install via ZIP — required for ESP32 core 3.x)

Lessons Learned

M5Stack ecosystem

The project originally targeted the M5Stack AtomS3 Lite with the M5Stack 4-Relay Unit — a clean Grove-connector-based system that would require minimal wiring. The AtomS3 Lite worked well but the 4-Relay Unit arrived DOA; the STM32 on the relay board failed to respond to I2C and the M5Stack EasyLoader firmware flash also failed. The project was redesigned around a standard ESP32-DEVKITV1 and a generic optoisolated 4-relay module.

ESP32 library compatibility

The M5Stack AtomS3 Lite path exposed several library compatibility issues specific to that ecosystem. The standard ESPAsyncWebServer and AsyncTCP libraries (lacamera/dvarrel forks) fail to compile with the current ESP32 core due to mbedtls API changes. The mathieucarbou forks of both libraries are maintained for the current core and must be installed manually via ZIP from GitHub rather than through the Arduino Library Manager. These issues were another factor in favour of switching to the standard ESP32-DEVKITV1, which had none of these compatibility problems.

Similarly, FastLED conflicts with the M5AtomS3 library due to namespace changes in newer FastLED versions — an issue specific to the M5Stack library ecosystem and not present on the standard ESP32-DEVKITV1.

Boot-sensitive GPIO pins

The ESP32-DEVKITV1 has several GPIO pins that have defined states at boot (GPIO0, GPIO2, GPIO12, GPIO14, GPIO15, GPIO25, GPIO26). Connecting active-LOW relay inputs to these pins caused relays to trigger on every power-up. GPIO19, GPIO26, GPIO27, and GPIO18 were selected as clean output pins with no boot-state concerns.

Know your solenoids

The original solenoids were sealed units with no visible markings for voltage or normally-open/normally-closed configuration. They were initially assumed to be 12V DC — a reasonable guess for appliance solenoids — which drove the selection of a 12V power supply. Had the solenoids actually been 12V, the 12V supply would have powered both the solenoids and the ESP32 logic (via a buck converter). Testing revealed they are in fact 120VAC normally-closed type, so the 12V supply ended up unnecessary. A simple 5V supply would have been sufficient for the ESP32 and relay module. In hindsight, always measure before ordering power supplies. Getting the solenoid logic correct required understanding the full pneumatic sequence of the machine, which took several iterations of testing to map correctly.

Results

The controller reliably achieves 3.0 kPa absolute (97% vacuum) with a 30-second pump-down time. Seal quality with a 2.0 second seal time and 3.0 second cool time is excellent and consistent. The closed-loop pressure control means every bag is sealed at the same vacuum level regardless of ambient conditions or bag size, which was not possible with the original timed-only board.

Total cycle time from pressing START to IDLE is approximately 50 seconds: 30s pump-down + 3s dwell + 2s seal + 3s cool + 10s vent. This is comparable to the original machine.

The ability to adjust all parameters from a phone browser without reflashing the firmware is the most practically useful improvement over the original design. Seal time, dwell time, and target vacuum can all be tuned for different bag materials and contents without any tools.

Source Code

The full source code is available on GitHub at: https://github.com/GregNuspel/vacuum-sealer-controller

Before flashing, update the WiFi credentials at the top of the sketch:

const char* HOME_SSID = "YOUR_WIFI_NAME";

const char* HOME_PASSWORD = "YOUR_WIFI_PASSWORD";