Touchless soap dispenser on an Arduino Uno
An FC-51 infrared obstacle sensor and a pump on a transistor: hold a hand under the spout and it pumps one dose, then waits for the hand to go away. The whole build, an Arduino Uno and 5 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
BeginnerRuns in your browser. Free, and no account needed.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Touchless soap dispenser: an FC-51 infrared obstacle sensor under the spout,
// and a small pump on a transistor.
//
// pin 2 the FC-51's OUT (low when a hand is in range)
// pin 9 through 1 k into the transistor's base; the pump hangs off 5 V
// into the collector, with a diode across it, band to 5 V
// 5V/GND the FC-51's VCC and GND
//
// The FC-51 shines infrared forward and watches for it to come back. A hand
// a few centimeters under the spout sends plenty back and OUT goes low; with
// the trimmer in the middle a white card trips it at about 13 cm. Skin is
// somewhere between white and black, so the spout's sensor is set to see a
// hand only when it is right underneath.
//
// # One dose per hand
//
// A dispenser that pumps for as long as a hand is there empties the bottle.
// So the sketch pumps one dose, then waits until OUT has been high for half a
// second (the hand has gone) before it will pump again.
const int SENSOR = 2;
const int PUMP = 9;
const unsigned long DOSE_MS = 700;
const unsigned long AWAY_MS = 500;
int doses = 0;
void setup() {
Serial.begin(115200);
Serial.println("Mokxi Arduino Uno: touchless soap dispenser");
pinMode(SENSOR, INPUT);
pinMode(PUMP, OUTPUT);
digitalWrite(PUMP, LOW);
}
bool handThere() {
return digitalRead(SENSOR) == LOW;
}
void loop() {
if (!handThere()) {
delay(20);
return;
}
doses++;
Serial.print("hand: dose ");
Serial.println(doses);
digitalWrite(PUMP, HIGH);
delay(DOSE_MS);
digitalWrite(PUMP, LOW);
// Wait for the hand to leave, and stay gone for AWAY_MS.
unsigned long clear = millis();
while (millis() - clear < AWAY_MS) {
if (handThere()) clear = millis();
delay(10);
}
Serial.println("ready");
}
Parts list
7 parts, plus the jumper wires. Every one is in the editor's parts bin.
- 1 × Arduino Uno R3
- 1 × Full-size breadboard
- 1 × Obstacle sensor, FC-51
- 1 × Transistor (NPN or PNP)
- 1 × Resistor, 1k Ω
- 1 × Diode
- 1 × DC motor
How it is wired
6 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.
- Arduino Uno R3 pin 9; Resistor, 1k Ω pin 1
- Arduino Uno R3 pin 2; Obstacle sensor, FC-51 pin OUT
- Arduino Uno R3 pin 5V; Obstacle sensor, FC-51 pin VCC; Diode pin C; DC motor pin 1
- Ground: Arduino Uno R3 pin GND; Obstacle sensor, FC-51 pin GND; Transistor (NPN or PNP) pin E
- Transistor (NPN or PNP) pin C; Diode pin A; DC motor pin 2
- Transistor (NPN or PNP) pin B; Resistor, 1k Ω pin 2
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.