Community project

Automatic Waste Sorting Machine

Arduino
Photo of Automatic Waste Sorting Machine
Generated with AI

Jas

Published October 31, 2026

This automatic waste sorting machine uses computer vision and sensors to identify and route different types of waste into separate bins. Built around an Arduino Uno, the system combines a rotating tube mechanism, servo-controlled gate, HuskyLens AI camera for material classification, and multiple sensors including an inductive metal detector, IR break-beam pair, and ultrasonic distance sensor to detect, identify, and sort incoming items.

The guide provides a complete wiring diagram, parts list, and step-by-step assembly instructions for constructing the mechanical sorting tube, positioning the collection bins, and integrating all electrical components. Included is the full Arduino firmware with state machine logic for controlling the sorting workflow, plus calibration procedures and camera training steps to get the system operational with your chosen waste categories.

Wiring diagram

Loading diagram…

Gather all the parts

QtyComponent
1

HC-SR04

HC-SR04 ultrasonic distance sensor module with separate 40 kHz transmitter and receiver transducers, measuring 2 to 400 cm. A 10 us pulse on TRIG starts a measurement and ECHO stays high for the echo's round-trip time. This HC-SR04+ board runs from 3.3 V or 5 V.

1

MG996R Servo Motor

High-torque digital metal gear RC servo motor by TowerPro. Operating voltage 4.8V-7.2V (nominal 5V-6V external supply). Standard RC servo control: 50 Hz signal with roughly 500-2500 us pulse width for 0-180 degree rotation. Three-wire interface: Brown = GND, Red = VCC, Orange = signal. Stall current can reach about 2.5A at 6V, so use a dedicated external servo supply and common ground with the controller. Add bulk capacitance across the servo rail when driving one or more servos. Torque: 9.4 kg.cm (4.8V) / 11 kg.cm (6V).

1

MG996R Servo Motor

High-torque digital metal gear RC servo motor by TowerPro. Operating voltage 4.8V-7.2V (nominal 5V-6V external supply). Standard RC servo control: 50 Hz signal with roughly 500-2500 us pulse width for 0-180 degree rotation. Three-wire interface: Brown = GND, Red = VCC, Orange = signal. Stall current can reach about 2.5A at 6V, so use a dedicated external servo supply and common ground with the controller. Add bulk capacitance across the servo rail when driving one or more servos. Torque: 9.4 kg.cm (4.8V) / 11 kg.cm (6V).

1

LCD 16x2 I2C

16x2 character LCD display with I2C backpack

1

Push Button

Momentary push button switch

1

PC817 Optocoupler

Single-channel optocoupler (opto-isolator) in a 4-pin DIP package. Galvanically isolates a low-voltage logic side from a separate circuit by coupling an internal infrared LED to a phototransistor across an insulating gap (isolation voltage ~5 kV). Used to read a higher-voltage signal safely, switch between circuits with different grounds, or shield a microcontroller from a noisy or mains-referenced domain. The input LED needs a series current-limiting resistor (~1 kOhm from a 5 V signal, ~220-330 Ohm from 3.3 V) sized for ~5-20 mA forward current; the output transistor is typically wired open-collector with a pull-up to the MCU side.

1

DFRobot SEN0503 IR break-beam pair

Emitter and receiver kit; both red leads to VCC, both black leads to GND; white receiver lead is NPN OUT. Opaque targets required.

1

DFRobot SEN0503 IR break-beam pair

Emitter and receiver kit; both red leads to VCC, both black leads to GND; white receiver lead is NPN OUT. Opaque targets required.

1

DFRobot HuskyLens SEN0305 K210

I2C mode: T=SDA, R=SCL. Train object classification IDs 1 bottle, 2 can, 3 paper, 4 reject.

1

LJ12A3-4-Z/BX NPN NO inductive sensor

6–36V NPN normally open ONLY; use regulated 12V. Aluminum sensing range shorter than steel rating: test every permitted can.

1

Regulated enclosed 5V 8A DC supply

Certified enclosed supply, no exposed mains; heavy wire distribution, never via breadboard.

1

12V Barrel-Jack Adapter

12 V / 2 A wall adapter with a 5.5 mm / 2.1 mm barrel jack. Used to power motor drivers, LED strips, or boards that need a higher rail.

1

Regulated enclosed 5V 2A DC supply

Dedicated camera supply; do not connect its positive to Uno 5V or USB.

1

5V active piezo buzzer, <=20mA

Self oscillating; switched with NPN transistor.

1

PN2222A NPN transistor

Check purchased manufacturer lead order; wire by B C E, not assumed package orientation.

1

2.2k ohm 0.25W resistor

2.2k ohm 0.25W resistor

1

10k ohm resistor

10k ohm resistor

1

1k ohm resistor

1k ohm resistor

1

10k ohm resistor

10k ohm resistor

1

Electrolytic Capacitor

2200uF 10V

Radial aluminium electrolytic capacitor bought by value and voltage rating, such as 10 µF, 100 µF or 1000 µF 10 V. It is polarised: the + lead goes to the higher voltage and the - lead, marked by the stripe on the sleeve, to the lower voltage or ground. It is mostly used for bulk filtering across a power rail, with a voltage rating comfortably above the rail.

Assemble it in 11 steps

1. Build a light rotating tube

Use exactly two standard positional MG996R servos, not continuous-rotation versions. Mount a lightweight holding tube on a bearing-supported turntable. Servo 1 turns only the tube through a linkage. Fit a hinged bottom gate operated by Servo 2, with a mechanical closed stop. Bearings and frame, not servo shafts, must carry the tube and item weight. Use dry, empty single items only.

  • Guard all rotating and gate pinch points. Disconnect all supplies before touching a jam. This is a supervised tabletop prototype, not an unattended public machine.

2. Position the three fixed bins

Fix the blue bottle bin at 45 degrees, red can bin at 90 degrees, and green paper bin at 135 degrees relative to the tube servo linkage. Home is initially 90 degrees. Use fixed funnel mouths wide enough to catch the rotating tube outlet. Keep the gate closed during every rotation. Allow flexible wiring with strain relief and enough slack for 45–135 degrees.

  • Keep the identification sensors fixed at the home station. The exit beam moves with the outlet just below the gate, so it covers every selected bin path. Fixed bins and funnels never rotate.

3. Distribute servo and camera power

Use an enclosed regulated 5V 8A supply for both servos, and a separate enclosed 5V 2A supply for HuskyLens. Connect servo red wires directly to the servo supply positive using screw-terminal distribution and suitable heavy wire; connect brown/black grounds to its negative. Join this negative and camera supply negative to Uno GND in a star connection. Place the 2200uF 10V capacitor across the servo rail, positive to +5V and marked negative stripe to GND. Tube signal goes to D9 and gate signal to D10. Power Uno through USB.

  • Never power either servo from Uno 5V or through a breadboard. Do not join either external 5V positive to Uno 5V or USB. Do not expose or wire mains terminals. Capacitor reversal can cause rupture. Switch off servo power during firmware updates and keep the tube empty at startup.

4. Connect the insertion and exit beams

Use two SEN0503 break-beam kits. For each kit, both red leads go to Uno 5V and both black leads to GND. Entry receiver white OUT goes to D2; exit receiver white OUT to D4. Uno internal pull-ups hold inputs high; blocked beam is low. Align entry beam across the tube mouth and exit beam immediately below the gate, away from the gate's own path. Check both clear and blocked levels before use.

  • These beams are specified for opaque objects. Present a bottle label or opaque cap across the beam and restrict bottle sizes/orientations accordingly. Clear plastic can pass undetected: test every allowed bottle. Unconfirmed passages earn zero points.

5. Connect distance and start control

HC-SR04 VCC to 5V and GND to GND; TRIG to D7 sends the ranging pulse, ECHO to D6 receives it. Mount above the tube at home, with the empty gate more than 18cm below and the object surface 2–18cm away. Button SIGNAL to D5 and GND to GND, across the switch contacts that close when pressed. Use a breadboard for low-current connections only.

  • Change the distance threshold in src/main.cpp for your tube. The firmware requires three close readings or entry beam blockage. Insert only after the screen says Insert Trash; one press starts one cycle.

6. Isolate the 12V metal detector

Use ONLY the NPN normally-open LJ12A3-4-Z/BX version. Brown goes to enclosed 12V adapter positive, blue to adapter negative. Wire 12V positive through the 2.2k ohm 0.25W resistor to PC817 pin 1 Anode. PC817 pin 2 Cathode connects to sensor black output. On the Uno side, PC817 pin 3 Emitter goes to Uno GND, pin 4 Collector to D3, and a 10k resistor from Collector to Uno 5V. Read PC817 pin numbers from the notch/dot and its datasheet. Keep the isolated 12V negative separate from Uno ground. Metal detection produces LOW on D3.

  • Place the sensor beside a nonmetallic guide that holds the side of every accepted can very close to the sensing face. The nominal 4mm rating is for steel; aluminum range is much shorter. Test all accepted cans and adjust the guide; no metal signal means a visually identified can is rejected. Keep screws, gate hardware and servo metal away from the sensing face. Inductive sensing detects metals, not uniquely aluminum; visual class and a restricted set of cans are also required.
  • Never connect black, brown, or any 12V wire directly to the Uno. Do not substitute a PNP sensor. This optocoupler circuit is specifically for a 12V supply, not 24V.

7. Connect screen and camera

LCD VCC to Uno 5V, GND to GND, SDA to A4 (data), SCL to A5 (clock). LCD address is initially 0x27; adjust its contrast knob. HuskyLens + goes to the dedicated camera 5V supply, - to common GND, T to A4 (SDA) and R to A5 (SCL). The circuit diagram labels those two camera signals SDA and SCL; the actual camera case labels them T and R. Both devices share the I2C wires; HuskyLens address is 0x32. Select I2C in the camera General Settings.

  • If your PCF8574 backpack uses 0x3F rather than 0x27, change the LCD constructor address. Mount the camera fixed at the home identification station, with its view centered on the closed tube, not through reflective plastic walls.

8. Train the identification camera

On HuskyLens select Object Classification and enable Learn Multiple. Start with no old learned objects. Learn IDs in this exact order: 1 plastic bottle, 2 aluminum can, 3 crumpled paper, 4 reject/background. For each ID hold the learning button and show the permitted objects from different angles and distances inside the actual tube. Press learning again during the continue countdown to add the next ID. Include the empty tube and likely invalid objects in the reject class. Keep lighting, background, tube geometry and object sizes consistent.

  • Code requires 12 consecutive matching readings, rejects missing/multiple/unsupported IDs and metal/vision disagreement, and times out after six seconds. A can needs both visual ID2 and inductive confirmation. Verify many separate test samples, including unknowns, before enabling sorting. If it confuses bottle and paper, improve training and constrain permitted items; do not simply force a class.
  • This camera reports class IDs without a calibrated confidence score. Twelve consistent readings are a stability test, not proof of material or reliable rejection of arbitrary unseen waste. Use only a validated limited set of bottles, aluminum cans and paper. Do not use this prototype to promise universal classification or fraud-proof points.

9. Connect the processing buzzer

Use a self-oscillating 5V active piezo buzzer drawing at most 20mA. Its positive goes to Uno 5V and negative to PN2222A Collector. Emitter goes to GND. D8 goes through 1k ohm to Base; fit 10k ohm between Base and GND. Check the purchased transistor's B/C/E pin order. The transistor avoids loading D8 with the buzzer current.

  • Buzzer stays off while waiting for insertion, on during detection, identification, rotation, release and normal return, then off on success or fault. This specifies a piezo buzzer, not an inductive magnetic sounder.

10. Calibrate without trash first

With linkages disconnected, power the controller to establish servo positions, then switch all power off before fitting horns. Align CLOSED=0 and OPEN=90 so the gate clears without forcing an endpoint; change constants if necessary. Set HOME and bin angles to your mechanism. ROTATE_MS=2000 and GATE_MS=900 are initial movement plus settling delays. Test empty movements and lengthen delays for the actual load.

  • Hobby servos provide no external arrival or gate-closed feedback. The code waits calibrated times; it cannot detect a stalled servo or verify bin alignment. Restrict loads, use a closed gate stop and inspect alignment. Do not operate if a servo stalls, hums at an endpoint or the gate cannot close. Guards and supervision remain necessary.

11. Test scoring and fault recovery

Try one validated item per button press. Check that the tube turns with gate closed, waits two seconds, then opens. Exit confirmation requires a fresh blocked beam followed by 150ms clear. Only after closing the gate and returning home are exactly two points added, once. Total points are held in RAM and reset to zero when Uno restarts. Confirm the screen returns to Click to Begin and requires a new press.

  • For any fault, switch off all supplies, remove the item and clear the path without putting fingers into a powered mechanism. Restore power empty; the score resets. For a non-jammed sensor or unknown-item fault, manually clear with power off, then restart. A released-and-pressed button can also acknowledge a cleared fault; the controller closes the gate before returning home. Never clear a jam while powered.
  • An exit beam confirms chute passage, not material identity or arrival inside the bin. Points are not a secure financial reward system. An unknown item stays behind the closed gate at home and earns nothing. After a release timeout the tube deliberately stays over its bin with gate open to avoid pinching a jam; buzzer turns off, zero points are added, and there is no automatic retry.

Review all connections

1. Connections between "sonar" and "Arduino"

FunctionsonarArduino
powerVCC5V
groundGNDGND
digitalTRIGGPIO 7
digitalECHOGPIO 6

2. Connections between "lcd" and "Arduino"

FunctionlcdArduino
powerVCC5V
groundGNDGND
i2cSDAGPIO 18
i2cSCLGPIO 19

3. Connections between "entry" and "Arduino"

FunctionentryArduino
powerVCC5V
groundGNDGND
digitalOUTGPIO 2

4. Connections between "exit" and "Arduino"

FunctionexitArduino
powerVCC5V
groundGNDGND
digitalOUTGPIO 4

5. Connections between "start" and "Arduino"

FunctionstartArduino
digitalSIGNALGPIO 5
groundGNDGND

6. Connections between "tube" and "Arduino"

FunctiontubeArduino
pwmSIGGPIO 9
powerVCC5V
groundGNDGND

7. Connections between "gate" and "Arduino"

FunctiongateArduino
pwmSIGGPIO 10
powerVCC5V
groundGNDGND

8. Connections between "servo_supply" and "Arduino"

Functionservo_supplyArduino
power+5V5V
groundGNDGND

9. Connections between "bulk" and "Arduino"

FunctionbulkArduino
power+5V
ground-GND

10. Connections between "camera_supply" and "Arduino"

Functioncamera_supplyArduino
power+5V5V
groundGNDGND

11. Connections between "vision" and "Arduino"

FunctionvisionArduino
power+5V
ground-GND
i2cSDAGPIO 18
i2cSCLGPIO 19

12. Connections between "sensor_supply" and "Arduino"

Functionsensor_supplyArduino
power+12V12V
powerGND0V

13. Connections between "metal" and "Arduino"

FunctionmetalArduino
powerBrown12V
powerBlue0V

14. Connections between "opto_r" and "Arduino"

Functionopto_rArduino
power112V
digital2 → PC817 Optocoupler AnodeEXT

15. Connections between "opto" and "Arduino"

FunctionoptoArduino
groundCathode → LJ12A3-4-Z/BX NPN NO inductive sensor BlackEXT
groundEmitterGND
digitalCollectorGPIO 3

16. Connections between "pullup" and "Arduino"

FunctionpullupArduino
power15V
digital2 → PC817 Optocoupler CollectorEXT

17. Connections between "buzzer" and "Arduino"

FunctionbuzzerArduino
power+5V
ground- → PN2222A NPN transistor CEXT

18. Connections between "driver" and "Arduino"

FunctiondriverArduino
groundEGND

19. Connections between "base_r" and "Arduino"

Functionbase_rArduino
digital1GPIO 8
digital2 → PN2222A NPN transistor BEXT

20. Connections between "base_pd" and "Arduino"

Functionbase_pdArduino
digital1 → PN2222A NPN transistor BEXT
ground2GND

Deploy the firmware

#include <Arduino.h>
#include <Wire.h>
#include <Servo.h>
#include <LiquidCrystal_I2C.h>
#include <HUSKYLENS.h>
#include <limits.h>
// Calibrate with empty mechanisms first. Standard positional servos only.
constexpr uint8_t ENTRY=2, METAL=3, EXIT=4, BUTTON=5, ECHO=6, TRIG=7,
 BUZZER=8, TUBE=9, GATE=10;
constexpr int HOME=90, CLOSED=0, OPEN=90;
const int BIN_ANGLE[4]={HOME,45,90,135};
constexpr unsigned long ROTATE_MS=2000, GATE_MS=900, EXIT_TIMEOUT=7000;
Servo tube, gate;
LiquidCrystal_I2C lcd(0x27,16,2);
HUSKYLENS camera;
enum State {BOOT,IDLE,INSERT,DETECTED,IDENTIFY,LABEL,ROTATE,BASELINE,
 RELEASE,CLOSE_GATE,RETURN_HOME,SUCCESS,TOTAL,FAULT};
State state=BOOT;
unsigned long since=0,lastButton=0,lastSample=0,clearSince=0,blockSince=0;
bool rawButton=HIGH, stableButton=HIGH, armed=false, seenExit=false;
uint8_t kind=0,candidate=0,votes=0,nearVotes=0;
uint32_t points=0;
char oldLines[2][17]={{0},{0}};
void line(uint8_t row,const char *text) {
 char padded[17]; memset(padded,' ',16); padded[16]=0;
 for(uint8_t i=0;i<16 && text[i];i++) padded[i]=text[i];
 if(strcmp(oldLines[row],padded)!=0){lcd.setCursor(0,row);lcd.print(padded);strcpy(oldLines[row],padded);}
}
void show(const __FlashStringHelper *a,const __FlashStringHelper *b) {
 char text[17]; strncpy_P(text,(PGM_P)a,16);text[16]=0;line(0,text);
 strncpy_P(text,(PGM_P)b,16);text[16]=0;line(1,text);
}
void enter(State s){state=s;since=millis();}
void standby(){
 digitalWrite(BUZZER,LOW);show(F("Click to Begin"),F(""));
 char text[17];snprintf(text,sizeof text,"Points: %lu",(unsigned long)points);line(1,text);
 armed=false;enter(IDLE);
}
void fault(const __FlashStringHelper *message){
 // Keep tube stationary. Never sweep a possibly jammed item across bins.
 digitalWrite(BUZZER,LOW);show(message,F("Clear; press btn"));armed=false;enter(FAULT);
}
bool pressed(){
 bool r=digitalRead(BUTTON);unsigned long now=millis();
 if(r!=rawButton){rawButton=r;lastButton=now;}
 bool event=false;
 if(now-lastButton>=35 && stableButton!=r){stableButton=r;if(!r && armed){event=true;armed=false;}}
 if(stableButton==HIGH && (state==IDLE || state==FAULT))armed=true;
 return event;
}
bool beam(uint8_t pin){return digitalRead(pin)==LOW;}
unsigned int distanceCm(){
 digitalWrite(TRIG,LOW);delayMicroseconds(2);digitalWrite(TRIG,HIGH);
 delayMicroseconds(10);digitalWrite(TRIG,LOW);
 unsigned long us=pulseIn(ECHO,HIGH,12000UL);return us?us/58:0;
}
bool setupCamera(){return camera.begin(Wire) && camera.writeAlgorithm(ALGORITHM_OBJECT_CLASSIFICATION);}
void setup(){
 pinMode(ENTRY,INPUT_PULLUP);pinMode(EXIT,INPUT_PULLUP);pinMode(METAL,INPUT_PULLUP);
 pinMode(BUTTON,INPUT_PULLUP);pinMode(BUZZER,OUTPUT);digitalWrite(BUZZER,LOW);
 pinMode(TRIG,OUTPUT);pinMode(ECHO,INPUT);digitalWrite(TRIG,LOW);
 Wire.begin();Wire.setClock(100000);
 #if defined(WIRE_HAS_TIMEOUT)
 Wire.setWireTimeout(25000,true);
 #endif
 lcd.init();lcd.backlight();show(F("Starting..."),F("Gate closing"));
 gate.write(CLOSED);gate.attach(GATE);gate.write(CLOSED);
 // Close gate before enabling tube movement.
 enter(BOOT);
}
void loop(){
 bool click=pressed();unsigned long now=millis(), elapsed=now-since;
 switch(state){
 case BOOT:
  if(elapsed>=GATE_MS){tube.write(HOME);tube.attach(TUBE);tube.write(HOME);enter(RETURN_HOME);}break;
 case IDLE:
  if(click){
   if(beam(ENTRY)||beam(EXIT)||beam(METAL)){fault(F("Clear sensors"));break;}
   if(!setupCamera()){fault(F("Camera Error"));break;}
   if(points>UINT32_MAX-2){fault(F("Score Full"));break;}
   show(F("Insert Trash"),F("Ready to Sort"));nearVotes=0;lastSample=0;enter(INSERT);
  }break;
 case INSERT:
  if(beam(ENTRY)){digitalWrite(BUZZER,HIGH);show(F("Trash Detected"),F("On Processing"));enter(DETECTED);}
  else if(now-lastSample>=100){lastSample=now;unsigned int cm=distanceCm();
   // Empty tube must measure >18 cm. Calibrate this threshold for your tube.
   nearVotes=(cm>=2 && cm<=18)?nearVotes+1:0;
   if(nearVotes>=3){digitalWrite(BUZZER,HIGH);show(F("Trash Detected"),F("On Processing"));enter(DETECTED);}
  }
  if(state==INSERT && elapsed>60000){fault(F("Insert Timeout"));}break;
 case DETECTED:
  if(elapsed>=800){votes=0;candidate=0;lastSample=0;enter(IDENTIFY);}break;
 case IDENTIFY:
  if(now-lastSample>=150){lastSample=now;uint8_t id=0,count=0;
   if(!camera.request()){fault(F("Camera Error"));break;}
   while(camera.available()){HUSKYLENSResult r=camera.read();if(r.command==COMMAND_RETURN_BLOCK){count++;id=r.ID;}}
   bool metal=beam(METAL);
   // Can requires both visual can class AND metal. Conflicting evidence rejects.
   bool valid=count==1 && id>=1 && id<=3 && ((id==2 && metal)||(id!=2 && !metal));
   if(!valid){candidate=0;votes=0;}
   else if(candidate==id){if(votes<12)votes++;}else{candidate=id;votes=1;}
   if(votes>=12){kind=candidate;show(F("Trash Identified"),kind==1?F("Plastic Bottle"):kind==2?F("Aluminum Can"):F("Crumpled Paper"));enter(LABEL);}
  }
  if(state==IDENTIFY && elapsed>=6000)fault(F("Unknown Trash"));break;
 case LABEL:
  if(elapsed>=1500){if(beam(EXIT)){fault(F("Exit Blocked"));break;}
   gate.write(CLOSED);tube.write(BIN_ANGLE[kind]);show(F("Sorting Trash"),F("Please Wait..."));enter(ROTATE);}
  break;
 case ROTATE:
  if(elapsed>=ROTATE_MS){clearSince=0;enter(BASELINE);}break;
 case BASELINE:
  if(beam(EXIT)){clearSince=0;if(elapsed>=2000)fault(F("Exit Blocked"));}
  else{if(!clearSince)clearSince=now;if(now-clearSince>=300){
   seenExit=false;blockSince=0;clearSince=0;gate.write(OPEN);enter(RELEASE);}}
  break;
 case RELEASE:
  // Require fresh beam obstruction followed by 150ms continuously clear.
  if(beam(EXIT)){
   clearSince=0;if(!blockSince)blockSince=now;
   if(now-blockSince>=5)seenExit=true;
  }else{blockSince=0;if(seenExit){if(!clearSince)clearSince=now;
   if(now-clearSince>=150 && elapsed>=GATE_MS){gate.write(CLOSED);enter(CLOSE_GATE);}}}
  if(state==RELEASE && elapsed>=EXIT_TIMEOUT){
   // Leave gate open and tube over selected bin; closing could pinch trapped trash.
   fault(F("Exit Jam/Timeout"));
  }break;
 case CLOSE_GATE:
  if(elapsed>=GATE_MS){tube.write(HOME);enter(RETURN_HOME);}break;
 case RETURN_HOME:
  if(elapsed>=ROTATE_MS){digitalWrite(BUZZER,LOW);
   if(kind){points+=2;show(kind==1?F("Bottle Sorted!"):kind==2?F("Can Sorted!"):F("Paper Sorted!"),F("+2 Points"));enter(SUCCESS);}
   else standby();}
  break;
 case SUCCESS:
  if(elapsed>=1800){show(F("Sorting Success"),F(""));char text[17];
   if(points<=999999UL)snprintf(text,sizeof text,"Total: %lu Points",(unsigned long)points);
   else snprintf(text,sizeof text,"Total:%lu",(unsigned long)points);
   line(1,text);enter(TOTAL);}break;
 case TOTAL:if(elapsed>=2200){kind=0;standby();}break;
 case FAULT:
  // A new release-and-press after manual clearing is mandatory. No automatic retry.
  if(click && !beam(ENTRY) && !beam(EXIT) && !beam(METAL)){
   kind=0;gate.write(CLOSED);enter(CLOSE_GATE);show(F("Resetting..."),F("Stand Clear"));
  }break;
 }
}

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.

Open in Schematik