Drop the drip - hidden tormentor!

< BACK to Arduino main page
Click HERE to open in a new tab full-screen if not already.

If you have never heard of a hidden tormentor then this might be a good time to explain it. You know sometimes when you have a device (like a digital watch with an hourly chime) that makes a little beep now and then - but it's just long enough for you to hear and not be able to locate it? It'll drive you nuts looking for it. That's the idea behind the hidden tormentor.

It is usually a simple one transistor beeping gadget that sounds out a capacitor discharging every once in a while. But with the ATTINY 85 we can add a little more personality without losing the form-factor of something small enough to easily hide.

The drip - simple two component project...
   
The project takes just a few minutes to assemble on any small breadboard. Getting it packaged for later deployment may take a little longer. The capacitor shown is to keep the MCU from resetting. You can lose that later on. Basically it is just two things 1) the ATTINY 85 and 2) the active piezo.

It's important to note that the active piezo is one that already has driver circuitry in it. So applying a little voltage will sound a tone all by itself. You can of course adapt the project using a normal piezo speaker if you like (a code change). Click on the pictured piezos below for an Amazon link to the ones I used.

So what's the DRIP PART ABOUT? Well, I coded it to sporadically make a sound - brief. And slightly different in length and delay afterward. I also added a condition that will perodically cause it to repeat the same tonal expression several times in a row. That's to cause the observer to notice there can be a pattern, although very seldom; adding to the frustration.
Note - using analogWrite you can achieve a cricket sound...

The ATTINY Core and Arduino UNO as programmer...

To get started you are going to need a way to program the ATTINY. There are USB stand alone programmers available online that can handle the task just fine. But if you are here, you likely have an Arduino UNO or similar MCU developer board already. There's no sense in getting an additional programmer if you have one. So first you need the ATTINY core. You can get that HERE. Download the zip file and copy the main folder to your HARDWARE folder under your Arduino Compiler installation. E.g. "C:\Program Files (x86)\Arduino\hardware\"
~ Setting up an UNO to program the ATTINY - You will need a library for that...

Once you have the libraries installed you can download my code HERE, or just copy and paste it from below...

Now when you run the Arduino Compiler you will notice the ATTINY boards have been added to your list under boards manager. Select the Attiny 85. Next check your COM port and make sure you are set correctly. Then under the Tools menu goto the bottom and set Programmer: to "Arduino as ISP" [NOT ArduinoISP]. You should now be ready to send the code to the ATTINY and test it out.

Oh yeah - and you need to wire up the ATTINY to your UNO too. Click on the picture next to the code below for a schematic to follow.

//------------------------------------------------------------------------
// -- code section //
// drip the drop hidden tormentor code. Copyright (c) 2018
// Public domain. Atomkey Laboratories. 
// for use with an active piezo buzzer - the kind that already has
// the driver circuit built in and makes a tone on its own when given
// a DC power source. 
// Intended setup is for the ATTINY 85 for a small form factor.

#define PIEZO 0
#define DRIP_TIME 7
#define DRIP_REPEAT 3
#define DROP_SIZE 255
#define DROP_STOP 8
#define JUST_WAIT 100
#define OFF 0
#define ON 255

#define MAX_WAIT 5
#define MAX_REPEAT 3
#define DRIP_CHANGE 3

typedef enum {as_digital, as_analog} faucet;

int drip, drop, dropSize, i; // some vars and a counter
faucet dripping;

// function prototype 
void dripTheDrop(faucet flowrate, int on_off); // sound function

// the setup function ------------------------------------------------
void setup() 
{
  // set the ATTINY 85 pinout to the active piezo buzzer
  pinMode(PIEZO, OUTPUT);
  drip = 0, drop = 0; // not necessary to init, but good code to see
  i = 0, dripping = as_digital; // here too...
}

// the loop function -------------------------------------------------
void loop() // start dripping some drops...
 {
    
   if(!random(MAX_WAIT)) // outer loop triggers "now and then" drip
    { // if this is the case, then we are going to drip a drop from
      // the faucet, so let's decide what kind. Digital or analog?
      
       if(random(DRIP_CHANGE)) // chance to make something other 
                               // than a tone
        {
          dripping = as_analog; // going to make a cricket sound
          dropSize = random((DROP_SIZE - (DROP_SIZE / 2) / 2)) + 10;
          // this sound will be a lower pitch the smaller the value
        }
       else 
        {
          dripping = as_digital; // going to make a tonal sound
          dropSize = DROP_SIZE;  // highest pitch
        }
        
       drip = random(DRIP_TIME) + 1;  // how long to make the drip last
       dripTheDrop(dripping, dropSize);  // make the sound
       delay(drip);
       
       if(!random(MAX_REPEAT)) // inner "repeat the drip" loop
        {
          // repeat drip exactly to show there can be design and not
          // just randomness - designed to perodically make the observer
          // ponder the source differently

          drop = DROP_STOP; (random(DROP_STOP) + 1); // delay after drip
      
          i = DRIP_REPEAT; // a random number of repetitions coutner
        
          while(--i)       // repeat the former drip this [i] many times
           {
             dripTheDrop(dripping, OFF);
             delay(drop);
             dripTheDrop(dripping, dropSize);
             delay(drip);
           }
        }
    }
  
  digitalWrite(PIEZO, OFF); // clean up and set to go again.
  delay(DROP_STOP);
  delay(JUST_WAIT); // add to force a longer delay between chances
}

// function to make our sounds
void dripTheDrop(faucet flowrate, int on_off)
{
  if(on_off)      // are we turning the drip on?
   switch(flowrate)
    {
      case as_digital: digitalWrite(PIEZO, on_off);  break;
      case as_analog:  analogWrite(PIEZO, on_off);   break; 
    }
   else digitalWrite(PIEZO, LOW); // turn drip off
}
// ------------- end of code --


Click to see full size with pinouts labeled. +Opens in a new tab.

Whoa