Built-in project · Arduino Uno R3

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.

Touchless soap dispenser · Arduino Uno R3live0.000 s 0.00x
Click to open it in the editor
The circuit itself, running here on the simulator. Press what can be pressed; click anything else to open it in the editor.

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// 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.

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.