Community project
Automated Roti Pressing and Cooking
Generated with AIThis guide builds an automated roti press that handles dough feeding, pressing, cooking, and ejection with precise temperature control. The system uses an ESP32 microcontroller to orchestrate multiple 24 V motors, monitor press position and dough presence, and maintain the heated press plate at the correct cooking temperature using a thermocouple sensor and solid-state relay.
Builders will receive a complete wiring diagram, parts list with sourcing guidance, safety-critical firmware with state machine control, and step-by-step assembly instructions covering food-contact fabrication, thermal protection integration, mains enclosure construction, and safe commissioning procedures before production use.
Wiring diagram
Interactive · read-only
Pan and zoom to explore the wiring. Remix the project to edit it in your own workspace.
Parts list
Bill of materials| Component | Qty | Notes |
|---|---|---|
| MAX31855 Thermocouple AmplifierMAX31855 | 1 | Cold-junction compensated K-type thermocouple-to-digital converter with SPI interface. Reads thermocouple temperatures up to +1350°C and performs on-chip cold-junction compensation. 3.3V compatible on the Adafruit breakout (includes onboard 3.3V regulator and level shifting). 14-bit thermocouple resolution (~0.25°C). Read-only SPI (SCK, CS, SO); no MOSI needed. |
| Grounded K-type thermocouple probe0–300 °C | 1 | Food-appliance-rated K-type probe mounted in a drilled blind hole near the lower cooking surface; never contacts dough. |
| 20 cm heated non-stick press plate assembly230 VAC, 1200 W total | 1 | Fabricated upper and lower 200 mm food-contact cooking plates, each with 230 VAC heater. Specify PFOA-free food-contact non-stick coating, 1200 W total, 230 VAC, and a bonded protective-earth stud. |
| Zero-cross AC solid-state relay25 A minimum, zero-cross | 1 | Genuine DIN/heatsink-mounted 3–32 VDC-input, 24–280 VAC-output zero-cross SSR, rated at least 25 A; sized with an aluminium heatsink. Drives the heater only. |
| 24 V DC press linear actuator with limit switches24 V, force set by fabricator | 1 | Fabricator-selected 24 V DC linear actuator and guided linkage that provides controlled closing force; includes normally-closed end-limit switches mechanically set for open and 2 mm finished roti thickness. |
| 24 V dough-ball feeder gear motor24 V DC geared motor | 1 | Low-speed 24 V DC geared motor that indexes one pre-portioned dough ball from a covered hopper into the open press; use food-safe removable hopper and chute. |
| 24 V cooked-roti ejector gear motor24 V DC geared motor | 1 | Low-speed 24 V DC geared motor operating a food-safe silicone-edged pusher to move a cooked roti to the collection tray after the press has opened. |
| 24 V brushed-DC motor driver24 V H-bridge | 1 | Opto-isolated, 3.3 V logic-compatible H-bridge motor driver for the press actuator; choose a genuine driver with continuous-current rating above measured actuator stall current. |
| 24 V brushed-DC motor driver24 V H-bridge | 1 | 3.3 V logic-compatible H-bridge driver for the dough feeder motor. |
| 24 V brushed-DC motor driver24 V H-bridge | 1 | 3.3 V logic-compatible H-bridge driver for the cooked-roti ejector motor. |
| 2-pole mains safety contactor and thermal safety chain230 VAC, ≥16 A, 2-pole | 1 | DIN-mounted 2-pole contactor whose coil is fed through a manual-reset 300 °C thermal cutoff and normally-closed emergency-stop contact; it removes live and neutral from the heater circuit. Fabricator/electrician must size it for the heater current. |
| Enclosed isolated 24 V DC power supply24 V, 10 A minimum | 1 | Certified enclosed 230 VAC to 24 VDC supply for all motors; select ≥10 A after actuator and motor stall-current measurement. Protective earth case where required. |
| Isolated 5 V DC power supply5 V, 1 A minimum | 1 | Certified isolated 230 VAC to 5 VDC supply for the ESP32 via its 5 V/VIN pin; 1 A minimum. |
| Start button and guarded safety-input module24 V field / 3.3 V logic | 1 | 24 V industrial input module with opto-isolated 3.3 V outputs: start pushbutton, door/guard switch, dough-present sensor, and normally-closed emergency-stop feedback. Its separate hard-wired safety-chain contact is in series with the contactor coil; the E-stop also directly breaks that coil circuit. |
| Fused 230 V IEC inlet with protective earth230 VAC, fused | 1 | Qualified appliance inlet with appropriately rated fuse, double-pole switch, strain relief, and protective-earth conductor. Fabricator must use Indian 230 VAC rated parts. |
| MCP23017 isolated digital-input expanderI2C address 0x20 | 1 | MCP23017 3.3 V I2C GPIO expander receiving opto-isolated start, guard, dough, E-stop feedback, and press limit outputs. Use its internal input pull-ups or verified external pull-ups. |
| 3.3 V opto-isolated SSR input driver3.3 V logic / SSR input | 1 | DIN-mounted 3.3 V logic optocoupler/transistor output module that switches the SSR DC input. Verify it sources/sinks the chosen SSR input current; the ESP32 only drives this module input. |
| Dual-channel 3.3 V opto-isolated motor-command interface2-channel, 3.3 V logic | 1 | Two-channel industrial opto-isolated interface. Accepts ESP32 3.3 V PWM/DIR inputs and provides compatible isolated command outputs for the 24 V press motor driver; no 24 V signal reaches ESP32 GPIO. |
| Dual-channel 3.3 V opto-isolated motor-command interface2-channel, 3.3 V logic | 1 | Two-channel industrial opto-isolated interface for the feeder motor driver; no 24 V signal reaches ESP32 GPIO. |
| Dual-channel 3.3 V opto-isolated motor-command interface2-channel, 3.3 V logic | 1 | Two-channel industrial opto-isolated interface for the ejector motor driver; no 24 V signal reaches ESP32 GPIO. |
| Fused 24 V DC distribution terminal block24 V fused DIN terminal block | 1 | Finger-safe DIN terminal/fuse block distributing the isolated 24 V supply to the three motor drivers and safety-input module. Fit branch fuses based on measured loads. |
Assembly
6 stepsFabricate the food-contact press and hopper
Have the qualified fabricator make two flat, parallel 200 mm cooking faces with a certified PFOA-free food-contact non-stick coating. Use a guided upper plate so it cannot tilt, set a fixed mechanical closing stop for about 2 mm roti thickness, and provide a removable covered food-safe hopper/chute that releases only one pre-portioned dough ball at a time. Use a food-safe silicone-edged ejector and removable collection tray.
- Tip: Target dough balls of roughly 35–45 g; final diameter, thickness, and cooking time must be tuned with the actual flour hydration.
- Tip: Make every food-contact part removable for washing; keep motors, grease, bearings, and wiring outside the food zone.
- Tip: Do not use loose flour dust as the anti-stick method inside the machine; specify the coating and a repeatable low-stick dough recipe instead.
- ⚠ Do not use damaged, scratched, unknown, or unverified non-stick coating.
- ⚠ The guide frame must prevent finger access to the closing gap; use a guard/interlock designed by the fabricator.
Fit heaters, sensing, and independent thermal protection
Mount the plate heaters as specified by the fabricator. Install the K-type probe in a blind hole close to the lower cooking surface, using thermal compound compatible with its temperature rating; it must not enter the food area. Fit a manual-reset 300 °C thermal cutoff directly on the hottest credible plate/heater location, in series with the contactor coil.
- Tip: Use a second independent temperature measurement during commissioning to calibrate the 225 °C firmware setpoint to actual plate temperature.
- Tip: Route thermocouple wire away from mains and motor wires; use a proper thermocouple extension connector where needed.
- ⚠ The thermal cutoff and emergency stop must be hard-wired; they are not firmware-controlled.
- ⚠ A qualified appliance electrician must choose the cutoff temperature and placement after measuring worst-case heater temperatures.
Build the earthed mains enclosure
A qualified appliance electrician must mount the fused IEC inlet, 2-pole safety contactor, SSR on its required heatsink, and both enclosed isolated power supplies in a metal, earthed, finger-safe enclosure. Bond protective earth continuously from the inlet to the metal chassis and both heated plates. Keep 230 VAC wiring physically segregated from the 24 V and 3.3 V control wiring.
- Tip: For 1200 W at 230 VAC, heater current is about 5.2 A; electrician must select approved wire, fuse, terminals, contactor and enclosure ratings with margin.
- Tip: Mount the SSR on a correctly sized aluminium heatsink and provide ventilation; verify its case temperature during a sustained heating run.
- Tip: Use strain relief at the mains inlet and cover all live terminals.
- ⚠ 230 VAC can kill or start a fire. Do not build, test, or service the mains section while energized unless you are qualified to do so.
- ⚠ Never rely on the SSR as the sole means of removing mains power: the 2-pole contactor and thermal/E-stop safety chain are mandatory.
Install 24 V motion hardware and guarded inputs
Wire the 24 V supply to the three motor drivers and isolated safety-input module. Connect each motor to its dedicated driver. Fit normally-closed open and close limit switches mechanically on the press motion, then route their isolated outputs to input-expander pins GPA4 and GPA5. Install the guard, start button, dough-present sensor, and emergency stop through the isolated input module; its separate normally-closed safety contact must be in series with the contactor coil.
- Tip: Measure each motor's real stall current and replace the provisional 24 V supply/driver ratings if needed before regular use.
- Tip: Verify physically that pressing E-stop removes contactor coil power and heater supply even with the ESP32 unplugged.
- Tip: Set the dough sensor so it detects the ball seated in the feed pocket, not dough higher in the hopper.
- ⚠ Keep the mechanism de-energized while setting limit switches.
- ⚠ The press must stop mechanically at the calibrated thickness even if a limit switch fails.
Connect the low-voltage controller
Power the ESP32 from the isolated 5 V supply. Wire MAX31855 to ESP32 GPIO 18 (SCK), GPIO 19 (SO), and GPIO 23 (CS). Wire the MCP23017 expander to GPIO 21 (SDA) and GPIO 22 (SCL). Connect motor commands: press PWM/DIR to GPIO 26/27, feeder PWM/DIR to GPIO 32/33, ejector PWM/DIR to GPIO 13/14. GPIO 25 drives only the opto-isolated SSR-input driver.
- Tip: Check the selected motor-driver modules accept 3.3 V PWM/DIR signals before installation.
- Tip: Use ferrules, labelled terminal blocks, and separate cable ducts for mains, motor, and sensor wiring.
- Tip: Do a low-voltage-only test first: unplug the heater mains feed and confirm directions and every sensor/limit state.
- ⚠ Do not connect 24 V or 5 V directly to ESP32 GPIO pins.
- ⚠ Do not power the ESP32 from a motor-driver logic pin.
Commission safely before making food
With an electrician present, verify protective-earth continuity, insulation, fuse operation, E-stop contactor dropout, guard fault behavior, thermal-cutoff dropout, limit-switch behavior, and SSR heatsink temperature. Then use the Deploy button in Schematik to load the controller. Make dry runs without dough, followed by supervised test batches, tuning feeder duration and cook duration until a 20 cm roti cooks evenly and ejects cleanly.
- Tip: Start with the provided 225 °C / 28 s settings; adjust in small increments after measuring actual plate temperature and evaluating real rotis.
- Tip: Keep a physical fire extinguisher appropriate for electrical equipment nearby during commissioning.
- Tip: Clean the plates only when cool, using non-abrasive tools approved for the coating.
- ⚠ Never bypass the guard, E-stop, thermal cutoff, contactor, or earth bond for testing.
- ⚠ Stop immediately if temperature overshoots, the plate sticks, the press stalls, or an SSR/terminal becomes unusually hot.
Pin assignments
Board wiring reference| Pin | Connection | Type |
|---|---|---|
| 3V3 | thermocouple_interface VCC | power |
| GND | thermocouple_interface GND | ground |
| GPIO 18 | thermocouple_interface SCK | spi |
| GPIO 19 | thermocouple_interface SO | spi |
| EXT | thermocouple_interface T+ → Grounded K-type thermocouple probe K+ | analog |
| EXT | thermocouple_interface T- → Grounded K-type thermocouple probe K- | analog |
| GND | heater_ssr IN- | ground |
| EXT | heater_ssr AC_OUT_L → 20 cm heated non-stick press plate assembly HEATER_L | power |
| EXT | heated_press HEATER_N → 2-pole mains safety contactor and thermal safety chain SAFE_OUT_N | power |
| EXT | heated_press PE → Fused 230 V IEC inlet with protective earth PE | ground |
| EXT | press_driver M+ → 24 V DC press linear actuator with limit switches M+ | power |
| EXT | press_driver M- → 24 V DC press linear actuator with limit switches M- | power |
| EXT | feeder_driver M+ → 24 V dough-ball feeder gear motor M+ | power |
| EXT | feeder_driver M- → 24 V dough-ball feeder gear motor M- | power |
| EXT | ejector_driver M+ → 24 V cooked-roti ejector gear motor M+ | power |
| EXT | ejector_driver M- → 24 V cooked-roti ejector gear motor M- | power |
| EXT | mains_inlet L → 2-pole mains safety contactor and thermal safety chain MAINS_IN_L | power |
| EXT | mains_inlet N → 2-pole mains safety contactor and thermal safety chain MAINS_IN_N | power |
| EXT | mains_safety_contactor SAFE_OUT_L → Zero-cross AC solid-state relay AC_IN_L | power |
| EXT | mains_safety_contactor COIL_N → protected mains neutral | power |
| 5V | psu_5v V+ | power |
| GND | psu_5v V- | ground |
| 3V3 | input_expander VCC | power |
| GND | input_expander GND | ground |
| GPIO 21 | input_expander SDA | i2c |
| GPIO 22 | input_expander SCL | i2c |
| EXT | safety_inputs START_OUT → MCP23017 isolated digital-input expander GPA0 | digital |
| EXT | safety_inputs GUARD_OK_OUT → MCP23017 isolated digital-input expander GPA1 | digital |
| EXT | safety_inputs DOUGH_OUT → MCP23017 isolated digital-input expander GPA2 | digital |
| EXT | safety_inputs ESTOP_OK_OUT → MCP23017 isolated digital-input expander GPA3 | digital |
| EXT | press_actuator OPEN_LIMIT → MCP23017 isolated digital-input expander GPA4 | digital |
| EXT | press_actuator CLOSE_LIMIT → MCP23017 isolated digital-input expander GPA5 | digital |
| EXT | mains_safety_contactor COIL_L → Start button and guarded safety-input module SAFETY_CHAIN | power |
| GPIO 23 | thermocouple_interface CS | spi |
| 3V3 | heater_ssr_driver VCC | power |
| GND | heater_ssr_driver GND | ground |
| GPIO 25 | heater_ssr_driver IN | digital |
| EXT | heater_ssr_driver OUT+ → Zero-cross AC solid-state relay IN+ | power |
| EXT | heater_ssr_driver OUT- → Zero-cross AC solid-state relay IN- | ground |
| EXT | psu_24v AC_L → Fused 230 V IEC inlet with protective earth L | power |
| EXT | psu_24v AC_N → Fused 230 V IEC inlet with protective earth N | power |
| EXT | psu_5v AC_L → Fused 230 V IEC inlet with protective earth L | power |
| EXT | psu_5v AC_N → Fused 230 V IEC inlet with protective earth N | power |
| 3V3 | press_logic_isolator VCC | power |
| GND | press_logic_isolator GND | ground |
| GPIO 26 | press_logic_isolator IN1 | digital |
| GPIO 27 | press_logic_isolator IN2 | digital |
| EXT | press_logic_isolator OUT1 → 24 V brushed-DC motor driver PWM | digital |
| EXT | press_logic_isolator OUT2 → 24 V brushed-DC motor driver DIR | digital |
| 3V3 | feeder_logic_isolator VCC | power |
| GND | feeder_logic_isolator GND | ground |
| GPIO 32 | feeder_logic_isolator IN1 | digital |
| GPIO 33 | feeder_logic_isolator IN2 | digital |
| EXT | feeder_logic_isolator OUT1 → 24 V brushed-DC motor driver PWM | digital |
| EXT | feeder_logic_isolator OUT2 → 24 V brushed-DC motor driver DIR | digital |
| 3V3 | ejector_logic_isolator VCC | power |
| GND | ejector_logic_isolator GND | ground |
| GPIO 13 | ejector_logic_isolator IN1 | digital |
| GPIO 14 | ejector_logic_isolator IN2 | digital |
| EXT | ejector_logic_isolator OUT1 → 24 V brushed-DC motor driver PWM | digital |
| EXT | ejector_logic_isolator OUT2 → 24 V brushed-DC motor driver DIR | digital |
| EXT | psu_24v V+ → Fused 24 V DC distribution terminal block IN+ | power |
| EXT | psu_24v V- → Fused 24 V DC distribution terminal block IN- | ground |
| EXT | press_driver VM+ → Fused 24 V DC distribution terminal block OUT1+ | power |
| EXT | press_driver VM- → Fused 24 V DC distribution terminal block OUT1- | ground |
| EXT | feeder_driver VM+ → Fused 24 V DC distribution terminal block OUT2+ | power |
| EXT | feeder_driver VM- → Fused 24 V DC distribution terminal block OUT2- | ground |
| EXT | ejector_driver VM+ → Fused 24 V DC distribution terminal block OUT3+ | power |
| EXT | ejector_driver VM- → Fused 24 V DC distribution terminal block OUT3- | ground |
| EXT | safety_inputs V24 → Fused 24 V DC distribution terminal block OUT4+ | power |
| EXT | safety_inputs GND → Fused 24 V DC distribution terminal block OUT4- | ground |
Firmware
ESP32#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_MAX31855.h>
#include <Adafruit_MCP23X17.h>
// ESP32 wiring. PWM/DIR outputs pass through opto-isolated interfaces before the motor drivers.
enum class State : uint8_t { WARMING, IDLE, FEEDING, CLOSING, COOKING, OPENING, EJECTING, FAULT };
// Forward declarations
bool inputHealthy(uint8_t pin);
bool guardOk();
bool eStopOk();
bool pressIsOpen();
bool pressIsClosed();
bool doughPresent();
void driveMotor(int pwmPin, int dirPin, bool forward, bool enabled);
void stopAllMotors();
void setHeater(bool enabled);
void enterState(State next);
void enterFault();
void controlHeater(float temperatureC);
bool startPressed();
constexpr int THERMO_SCK = 18;
constexpr int THERMO_CS = 23;
constexpr int THERMO_SO = 19;
constexpr int HEATER_ENABLE_PIN = 25;
constexpr int PRESS_PWM_PIN = 26;
constexpr int PRESS_DIR_PIN = 27;
constexpr int FEED_PWM_PIN = 32;
constexpr int FEED_DIR_PIN = 33;
constexpr int EJECT_PWM_PIN = 13;
constexpr int EJECT_DIR_PIN = 14;
constexpr int I2C_SDA_PIN = 21;
constexpr int I2C_SCL_PIN = 22;
// MCP23017 pins are active LOW because the isolated field-input outputs pull down.
constexpr uint8_t START_INPUT = 0;
constexpr uint8_t GUARD_OK_INPUT = 1;
constexpr uint8_t DOUGH_PRESENT_INPUT = 2;
constexpr uint8_t ESTOP_OK_INPUT = 3;
constexpr uint8_t PRESS_OPEN_INPUT = 4;
constexpr uint8_t PRESS_CLOSED_INPUT = 5;
constexpr float SETPOINT_C = 225.0F;
constexpr float HEATER_HYSTERESIS_C = 5.0F;
constexpr float MAX_SAFE_TEMP_C = 280.0F;
constexpr unsigned long WARMUP_TIMEOUT_MS = 8UL * 60UL * 1000UL;
constexpr unsigned long FEED_TIME_MS = 1300UL; // Fabricator tunes for exactly one 35-45 g ball.
constexpr unsigned long PRESS_TIMEOUT_MS = 7000UL;
constexpr unsigned long COOK_TIME_MS = 28000UL; // Tune with flour hydration and target browning.
constexpr unsigned long EJECT_TIME_MS = 2200UL;
constexpr unsigned long START_DEBOUNCE_MS = 80UL;
Adafruit_MAX31855 thermocouple(THERMO_SCK, THERMO_CS, THERMO_SO);
Adafruit_MCP23X17 inputs;
State state = State::WARMING;
unsigned long stateStartedAt = 0;
unsigned long lastStartEdgeAt = 0;
bool heaterOn = false;
bool inputHealthy(uint8_t pin) {
return inputs.digitalRead(pin) == LOW;
}
bool guardOk() { return inputHealthy(GUARD_OK_INPUT); }
bool eStopOk() { return inputHealthy(ESTOP_OK_INPUT); }
bool pressIsOpen() { return inputHealthy(PRESS_OPEN_INPUT); }
bool pressIsClosed() { return inputHealthy(PRESS_CLOSED_INPUT); }
bool doughPresent() { return inputHealthy(DOUGH_PRESENT_INPUT); }
void driveMotor(int pwmPin, int dirPin, bool forward, bool enabled) {
digitalWrite(dirPin, forward ? HIGH : LOW);
digitalWrite(pwmPin, enabled ? HIGH : LOW);
}
void stopAllMotors() {
digitalWrite(PRESS_PWM_PIN, LOW);
digitalWrite(FEED_PWM_PIN, LOW);
digitalWrite(EJECT_PWM_PIN, LOW);
}
void setHeater(bool enabled) {
heaterOn = enabled;
digitalWrite(HEATER_ENABLE_PIN, enabled ? HIGH : LOW);
}
void enterState(State next) {
stopAllMotors();
state = next;
stateStartedAt = millis();
}
void enterFault() {
setHeater(false);
stopAllMotors();
state = State::FAULT;
stateStartedAt = millis();
}
void controlHeater(float temperatureC) {
if (isnan(temperatureC) || temperatureC > MAX_SAFE_TEMP_C || !eStopOk()) {
enterFault();
return;
}
if (temperatureC <= SETPOINT_C - HEATER_HYSTERESIS_C) {
setHeater(true);
} else if (temperatureC >= SETPOINT_C + HEATER_HYSTERESIS_C) {
setHeater(false);
}
}
bool startPressed() {
if (!inputHealthy(START_INPUT)) return false;
const unsigned long now = millis();
if (now - lastStartEdgeAt < START_DEBOUNCE_MS) return false;
lastStartEdgeAt = now;
return true;
}
void setup() {
pinMode(HEATER_ENABLE_PIN, OUTPUT);
pinMode(PRESS_PWM_PIN, OUTPUT);
pinMode(PRESS_DIR_PIN, OUTPUT);
pinMode(FEED_PWM_PIN, OUTPUT);
pinMode(FEED_DIR_PIN, OUTPUT);
pinMode(EJECT_PWM_PIN, OUTPUT);
pinMode(EJECT_DIR_PIN, OUTPUT);
setHeater(false);
stopAllMotors();
Serial.begin(115200);
Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
if (!inputs.begin_I2C(0x20)) {
enterFault();
return;
}
for (uint8_t pin = START_INPUT; pin <= PRESS_CLOSED_INPUT; ++pin) {
inputs.pinMode(pin, INPUT_PULLUP);
}
enterState(State::WARMING);
}
void loop() {
const float temperatureC = thermocouple.readCelsius();
controlHeater(temperatureC);
if (state == State::FAULT) {
setHeater(false);
stopAllMotors();
delay(25);
return;
}
// A guard opening or E-stop feedback loss aborts motion immediately.
if (!guardOk() || !eStopOk()) {
enterFault();
delay(25);
return;
}
const unsigned long elapsed = millis() - stateStartedAt;
switch (state) {
case State::WARMING:
if (elapsed > WARMUP_TIMEOUT_MS) enterFault();
else if (temperatureC >= SETPOINT_C - HEATER_HYSTERESIS_C && pressIsOpen()) enterState(State::IDLE);
break;
case State::IDLE:
if (!pressIsOpen()) {
driveMotor(PRESS_PWM_PIN, PRESS_DIR_PIN, false, true); // retract to open
if (elapsed > PRESS_TIMEOUT_MS) enterFault();
} else if (startPressed() && doughPresent() && temperatureC >= SETPOINT_C - HEATER_HYSTERESIS_C) {
enterState(State::FEEDING);
}
break;
case State::FEEDING:
driveMotor(FEED_PWM_PIN, FEED_DIR_PIN, true, true);
if (elapsed >= FEED_TIME_MS) enterState(State::CLOSING);
break;
case State::CLOSING:
if (pressIsClosed()) enterState(State::COOKING);
else if (elapsed > PRESS_TIMEOUT_MS) enterFault();
else driveMotor(PRESS_PWM_PIN, PRESS_DIR_PIN, true, true);
break;
case State::COOKING:
// Plates remain mechanically closed at the calibrated 2 mm stop.
if (!pressIsClosed()) enterFault();
else if (elapsed >= COOK_TIME_MS) enterState(State::OPENING);
break;
case State::OPENING:
if (pressIsOpen()) enterState(State::EJECTING);
else if (elapsed > PRESS_TIMEOUT_MS) enterFault();
else driveMotor(PRESS_PWM_PIN, PRESS_DIR_PIN, false, true);
break;
case State::EJECTING:
driveMotor(EJECT_PWM_PIN, EJECT_DIR_PIN, true, true);
if (elapsed >= EJECT_TIME_MS) enterState(State::IDLE);
break;
case State::FAULT:
break;
}
delay(20);
}“Deploy to device” opens this project in Schematik, where you can flash it to your board over USB.
Remix this project
Make it yours in one click
Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.