Close

Entry 2: Leave Well Enough Alone... Not.

A project log for The Wash-Is-Done-inator

I'm tired of wasting time between when the washing machine finishes, and when I notice it's done. Time to build a gadget!

Jorj BauerJorj Bauer 01/30/2018 at 02:090 Comments

A simple buzz was a good start for notification, but it's not enough. I mean, obviously, if I'm going to have to listen to this thing going off then I don't want it to annoy the bejeebers outta me. So yeah, I can make it do a square wave PWM tone. But that's not where it's going to wind up.

Which brings us to tone(). We ditch the ATTiny for the moment, because it's easier to do this on an Uno...

#define SPEAKER 2

loop() {
  tone(SPEAKER, 440);
  delay(1000);
  noTone(SPEAKER);
  delay(1000);
}  

A lovely 440Hz square wave, just as I always wanted it. And, of course, that's not enough. It goes something like this:

uint16_t notes[] = { NOTE_F5, NOTE_D5, NOTE_A4, NOTE_D5, NOTE_F5, NOTE_D5, NOTE_A4, NOTE_D5, NOTE_F5, NOTE_C5, NOTE_A4, NOTE_C5, NOTE_F5, NOTE_C5, NOTE_A4, NOTE_C5 };

uint16_t notePos = 0;

loop() {
  uint16_t currentNote = notes[notePos];
  tone(SPEAKER, currentNote);

  notePos++;
  notePos %= sizeof(notes);

  delay(200);
}

which, of course, becomes

typedef struct _note {
  uint16_t frequency;
  uint32_t duration;
} note_t;

#define EIGHTH 1
#define QUARTER 2
#define DOTTEDQUARTER 3
#define HALF 4
#define DOTTEDHALF (QUARTER*3)
#define WHOLE (QUARTER*4)

note_t treble[NUMTREBLE] = {
  // First bar
  { NOTE_F5, EIGHTH },
  { NOTE_D5, EIGHTH },
  { NOTE_A4, EIGHTH },
  { NOTE_D5, EIGHTH },
  { NOTE_F5, EIGHTH },
  { NOTE_D5, EIGHTH },
  { NOTE_A4, EIGHTH },
  { NOTE_D5, EIGHTH },

  // Second bar
  { NOTE_F5, EIGHTH },
  { NOTE_C5, EIGHTH },
  { NOTE_A4, EIGHTH },
  { NOTE_C5, EIGHTH },
  { NOTE_F5, EIGHTH },
  { NOTE_C5, EIGHTH },
  { NOTE_A4, EIGHTH },
  { NOTE_C5, EIGHTH },
};

uint32_t songClock = 0;
int8_t nextTrebleTime = 0;
uint32_t treblePos = 0;
int8_t nextTrebleTime = 0;

#define BASETIME 120

loop()
{
  if (millis() >= songClock) {
    songClock = millis() + BASETIME;
    if (--nextTrebleTime <= 0) {
      tone(SPEAKER, treble[treblePos].frequency);
      nextTrebleTime = treble[treblePos].duration;
      treblePos++;
      treblePos %= sizeof(treble);
    }
  }
}

And it's at this point that one realizes that, although it's fairly easy to transcribe the Gravity Falls melody, that's not what I want.

What I want is a polyphonic sound engine playing, at minimum, a melody and harmony.

So quickly, we switch to the old and obsolete Tone third-party driver -- which lets me add a second voice on a second pin, throw a couple resistors in, and drive one speaker with the combined waveforms from both. And just as quickly, it becomes clear that's also not sufficient. No, I want the real deal. If you take a gander at https://github.com/dzlonline/the_synth , you'll find a polyphonic waveform generator for Arduino. Nice. So now the code suddenly blossoms in to

setup()
{ // ...
  edgar.begin(DIFF);
  edgar.setupVoice(0,SINE,60,ENVELOPE0,80,64);
  edgar.setupVoice(1,SINE,62,ENVELOPE0,100,64);
  edgar.setupVoice(3,NOISE,60,ENVELOPE2,60,64);
  // ...
}


void toneMaint()
{
  if (millis() >= songClock) {
    songClock = millis() + BASETIME; // time for the next eighth note to strike
    songTick++;

    if (--nextBassTime <= 0) {
      if (bass[bassPos].frequency != REST) {
        edgar.mTrigger(0, bass[bassPos].frequency + 22);
      }
      nextBassTime = bass[bassPos].duration;
      bassPos++;
      bassPos %= NUMBASS;
    }

    if (--nextTrebleTime <= 0) {
      if (treble[treblePos].frequency != REST) {
        edgar.mTrigger(1, treble[treblePos].frequency + 22);
      }
      nextTrebleTime = treble[treblePos].duration;
      treblePos++;
      treblePos %= NUMTREBLE;
    }

  }
}

The Synth has four voices; this sets up 0 and 1 as short and long duration (0 used for the bass line, and 1 for the treble). Voice 3 is a nice bass-y snare, which I'm starting to code up now; and I hope to configure voice 2 as a kick drum just as soon as I figure out how to make a square wave sound kick-y using this synth driver.

None of this, of course, has anything to really do with alerting us about laundry. It's all a temporary distraction, because the real notification system is still in the mail! Maybe this weekend...

Discussions