Eric Schneider
Published © CERN-OHL

Musical Soap Dispenser

Play your favorite tune for 20 seconds while you wash your hands.

IntermediateFull instructions provided3 hours1,833
Musical Soap Dispenser

Things used in this project

Hardware components

ATmega328
Microchip ATmega328
×1
16 MHz Crystal
16 MHz Crystal
×1
Multilayer Ceramic Capacitor, 20 pF
Multilayer Ceramic Capacitor, 20 pF
×2
5V Power Supply
×1
DFPlayer Mini
×1
Resistor 1k ohm
Resistor 1k ohm
×1
Speaker: 0.25W, 8 ohms
Speaker: 0.25W, 8 ohms
×1
Umbra Automatic Soap Dispenser
×1
Micro SD Card
×1

Software apps and online services

Patchr
Patchr
I used the PCB design editor to design the final PCBs used in this project.
Audacity
I used this free, open source, audio editing software to create the 20 second clips.

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free
Bantam Tools Desktop PCB Milling Machine
Bantam Tools Desktop PCB Milling Machine
Wire Stripper, STRIPAX
Wire Stripper, STRIPAX
Wire Cutter / Stripper, 5.25 " Overall Length
Wire Cutter / Stripper, 5.25 " Overall Length

Story

Read more

Schematics

Musical Soap Dispenser Control Board

Musical Soap Dispenser MP3 Board

Code

Musical Soap Dispenser

Arduino
//Musical Soap Dispenser//
//Hardware by: Eric Schneider, 2020
//Adapted from Nick Koumaris' Arduino MP3 Player Tutorial//
/////////// http://educ8s.tv/arduino-mp3-player/ //////////


#include "SoftwareSerial.h"
SoftwareSerial mySerial (10,11); //Digital pins on ATmega328p
# define Start_Byte 0x7E
# define Version_Byte 0xFF
# define Command_Length 0x06
# define End_Byte 0xEF
# define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info]

# define ACTIVATED HIGH

int buttonNext = 2; //Automatic Soap Dispenser Data Pin <--> ATmega328p
int buttonPause = 3; //DFPlayer Busy Pin <--> ATmega328p
boolean isPlaying = false;

void setup () {

  pinMode(buttonPause, INPUT);
  digitalWrite(buttonPause, LOW);
  pinMode(buttonNext, INPUT);
  digitalWrite(buttonNext, LOW);

  mySerial.begin (9600);
  delay(1000);
  isPlaying = true;
}

void loop () {
  if (digitalRead(buttonNext) == HIGH)
  {
    if (isPlaying)
    {
      playNext();
    }
    else if (digitalRead(buttonPause) == HIGH)
    {
      if (isPlaying)
      {
        pause();
        isPlaying = false;
        //delay(10000);
      } else
      {
        isPlaying = true;
        play();
      }
    }
  }
}

void playFirst()
{
  execute_CMD(0x3F, 0, 0);
  delay(500);
  setVolume(30);
  delay(500);
  execute_CMD(0x11, 0, 1);
  delay(500);
}

void pause()
{
  execute_CMD(0x0E, 0, 0);
  delay(500);
}

void play()
{
  execute_CMD(0x0D, 0, 1);
  delay(500);
}

void playNext()
{
  execute_CMD(0x01, 0, 1);
  delay(500);
}

void setVolume(int volume)
{
  execute_CMD(0x06, 0, volume); // Set the volume (0x00~0x30)
  delay(2000);
}

void execute_CMD(byte CMD, byte Par1, byte Par2)
// Excecute the command and parameters
{
  // Calculate the checksum (2 bytes)
  word checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);
  // Build the command line
  byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge,
                            Par1, Par2, highByte(checksum), lowByte(checksum), End_Byte
                          };
  //Send the command line to the module
  for (byte k = 0; k < 10; k++)
  {
    mySerial.write( Command_line[k]);
  }
}

Credits

Eric Schneider

Eric Schneider

6 projects • 24 followers
Maker + Artist
Thanks to Nick Koumaris and Umbra.

Comments