The Community Water Allocation Simulator
Press the pushbutton to test connected Wi-Fi/sensor logic.
- ESP32 NodeMCU Development Board
- LED indicator (green)
- 220 ohm resistor
- Tactile pushbutton switch
- Jumper wires (male-male)
🔧 Build Your Water Allocation FSM
enum DispenserState {
IDLE,
AUTHENTICATED,
DISPENSING,
QUOTA_DEPLETED,
EMERGENCY
};
DispenserState currentState = IDLE;
float dailyQuota = 20.0; // 20 Liters per household
float dispensedToday = 0.0;
const int SOLENOID_PIN = 23;
const int FLOW_PULSE_PIN = 18;
void setSolenoid(bool state) {
digitalWrite(SOLENOID_PIN, state ? HIGH : LOW);
}
void setup() {
pinMode(SOLENOID_PIN, OUTPUT);
pinMode(FLOW_PULSE_PIN, INPUT_PULLUP);
Serial.begin(115200);
Serial.println("Smart Water Dispenser FSM Active.");
}
void loop() {
switch (currentState) {
case IDLE:
setSolenoid(false);
// Awaiting RFID user card authentication...
break;
case AUTHENTICATED:
Serial.println("Token Verified. Solenoid Energizing.");
currentState = DISPENSING;
break;
case DISPENSING:
setSolenoid(true);
dispensedToday += 0.5; // Simulate flow sensor pulse increment
Serial.print("Dispensing: "); Serial.print(dispensedToday);
Serial.println(" / 20.0 Liters");
if (dispensedToday >= dailyQuota) {
currentState = QUOTA_DEPLETED;
}
break;
case QUOTA_DEPLETED:
setSolenoid(false);
Serial.println("Daily Quota Met! Tap Locked until tomorrow.");
currentState = IDLE;
break;
case EMERGENCY:
setSolenoid(false);
Serial.println("EMERGENCY SHUTOFF ACTIVATED!");
break;
}
delay(1000);
}
A deterministic Finite State Machine (FSM) guarantees safe, verifiable actuator states under all operating conditions.
⚗️ Test your model
| Test Condition / Action | Expected Result |
|---|---|
| RFID Token Swiped | Transitions from IDLE to AUTHENTICATED to DISPENSING; Solenoid opens |
| Water Flowing (0 to 20L) | Accumulates volume accurately via flow meter pulses |
| Quota Exceeded (20.0L reached) | State forces QUOTA_DEPLETED; Solenoid closes immediately; tap locks |
| Emergency Button Pressed | Forces EMERGENCY state; valve locks shut regardless of token balance |
Connect an RFID RC522 card reader that tracks distinct household account IDs and independent quota balances!
📖 Our Story & Concepts
In semi-arid communities, solar water kiosks are shared lifeline resources. If a valve sticks open or someone hacks the dispenser to siphon 2,000 liters, the aquifer runs dry and neighbors go without drinking water.
Mission-critical embedded firmware is engineered around a Finite State Machine (FSM). An FSM mathematically guarantees that a system can only exist in one valid state at any instant, with strictly controlled transitions. This eliminates race conditions, rogue actuator commands, and resource depletion.
</> Full Annotated Code Walkthrough
// Complete Deterministic Water Dispenser State Engine
#include
enum State { ST_IDLE, ST_AUTH, ST_DISPENSE, ST_LOCKED, ST_EMERGENCY };
State st = ST_IDLE;
float quota = 20.0;
float dispensed = 0.0;
const int VALVE_PIN = 23;
const int ESTOP_PIN = 0;
void setup() {
pinMode(VALVE_PIN, OUTPUT);
pinMode(ESTOP_PIN, INPUT_PULLUP);
Serial.begin(115200);
}
void loop() {
// Global Emergency Override
if (digitalRead(ESTOP_PIN) == LOW) {
st = ST_EMERGENCY;
}
switch (st) {
case ST_IDLE:
digitalWrite(VALVE_PIN, LOW);
Serial.println("[STATE: IDLE] Waiting for card swipe...");
delay(1500);
st = ST_AUTH; // Simulate user card tap
break;
case ST_AUTH:
Serial.println("[STATE: AUTH] Household #104 Verified. Remaining: 20L");
dispensed = 0.0;
st = ST_DISPENSE;
break;
case ST_DISPENSE:
digitalWrite(VALVE_PIN, HIGH);
dispensed += 2.0; // Simulate 2L water draw
Serial.printf("[STATE: DISPENSING] Flow: %.1f / %.1f Liters
", dispensed, quota);
if (dispensed >= quota) {
st = ST_LOCKED;
}
delay(800);
break;
case ST_LOCKED:
digitalWrite(VALVE_PIN, LOW);
Serial.println("[STATE: LOCKED] Daily quota exhausted! Valve shut.");
delay(2000);
st = ST_IDLE;
break;
case ST_EMERGENCY:
digitalWrite(VALVE_PIN, LOW);
Serial.println("[CRITICAL EMERGENCY] Hardware interlock trip! Manual reboot required.");
while(1) { delay(1000); }
}
}
A deterministic Finite State Machine (FSM) guarantees safe, verifiable actuator states under all operating conditions.
▷ Expected Results & Troubleshooting
| Test Condition / Action | Expected Result |
|---|---|
| RFID Token Swiped | Transitions from IDLE to AUTHENTICATED to DISPENSING; Solenoid opens |
| Water Flowing (0 to 20L) | Accumulates volume accurately via flow meter pulses |
| Quota Exceeded (20.0L reached) | State forces QUOTA_DEPLETED; Solenoid closes immediately; tap locks |
| Emergency Button Pressed | Forces EMERGENCY state; valve locks shut regardless of token balance |
⚑ Extension Challenges & Blueprints
- Level 1: Attach a flow pulse interrupt handler on GPIO 18 to measure actual water milliliters.
- Level 2: Display live volume and household credit balance on a 16x2 I2C LCD screen.
- Level 3: Sync household usage transactions to an encrypted cloud billing endpoint via MQTT.