Category Archives: Notes

Behold the Debouncinator!

When you throw a switch or press a button, you expect that device to transition definitively and atomically from one state to the other. The switch is either open or it is closed, the button either is pressed or it is not. But in the course of those transitions, the metal contacts of the underlying switch can gain and lose connectivity many times. This is referred to as “bouncing”.

I grabbed some quick measurements with a USB scope (an MSO-19). This is a toggle switch:
switch

This is a tiny little clicky button:
button

If you are polling one of these switches with a microcontroller, you may wind up with short bursts of fluctuating measurements at each open and close. The fix for this is to “debounce” the switch by waiting for it to settle down before you decide that it has actually changed state.

#define DEBOUNCE_TIME 50 //milliseconds
unsigned long switchClosedTime = 0;
int state = HIGH;

void loop() {
  if (digitalRead(PIN) == LOW) {
    if (state == HIGH) {
      if (switchClosedTime == 0) {
        switchClosedTime = millis();
      } else if (millis() - switchClosedTime > DEBOUNCE_TIME) {
        state = LOW;
      }
    }
  } else {
    state = HIGH;
    switchClosedTime = 0;
  }
  if (state == LOW) {
    // The switch is flipped!  Do a thing!
  }
}

This is a basic debounce pattern. If the switch has been in the trigger state for a long time, then decide that it is done changing state. If you see it in the opposite state, then forget it, and start the measurement over when you next see it in the transition state.

I found myself implementing this same pattern in project after project, and eventually I wrote a little Arduino library for it (I used it in the NeoPixel Control Panel project). The Debouncinator makes it simple and convenient to debounce all of your inputs.

#include <Debouncinator.h>

Debouncinator db;

void setup() {
  // pin, initial state, trigger state
  db.init(5, HIGH, LOW);

  // same as 5, HIGH and LOW are the defaults
  db.init(6);

  // this pin triggers when it goes HIGH
  db.init(7, LOW, HIGH);
}

void loop() {
  if (db.read(5)) {
    // pin 5 has been debounced and is LOW
  }
  if (db.read(7)) {
    // pin 7 has been debounced and is HIGH
  }
  db.read(6);
  if (db.fired(6)) {
    // this will be true once for every time the pin
    // debounces to the trigger state
  }
}

You can find the Debouncinator on github: https://github.com/erickhammersmark/Debouncinator

What’s this?

This was a fun one.

I like to repair stuff. Fixing a thing is good for the planet. Not only do you continue to take advantage of all of the energy that went into obtaining the materials and crafting the thing, but you also save it from being buried in a hole in the ground. It can save you a bit of money, too.

Yesterday, I decided to repair my son’s headphones. He had been propping them up so that they pressed into the headphone jack of his computer at angle, because if they sat at the wrong angle, they didn’t work. I figured the connector was bad, I surely had an 1/8″ stereo headphone jack laying around, and it should be an easy repair. In order to hear the problem for myself, I plugged his headphones into a device and started to watch Nightmare Before Christmas. Sure enough, I couldn’t hear Jack Skellington singing “What’s This?” at all.

But wait. I could hear the orchestra, and I could hear them in both ears. I turned it up. I listened carefully. There was no trace of Skeleton Jack, but the instrumentals were clear, if muted. Pressing on the connector at the proper angle brought Jack’s vocals in perfectly. If the headphones didn’t work, I would expect there to be no sound at all, either in one ear or both ears. But what defect would cause just the vocals to disappear?

The answer turns out to be that the stereo audio of the movie I was testing with was encoded for Dolby Pro Logic surround. Before there were 7.1 channels of pure digital audio piped along our HDMI cables, there was Dolby Pro Logic. A stereo audio signal encoded for DPL has some material out of phase between the two channels. When you add the two signals together, the out of phase signal cancels out, and you get just what should be in the surround channel. When you subtract the signals, you get just what should be in the center channel. 4 channels of surround sound out of 2 channels of audio. Pretty neat.

What was happening in the headphones is that the two audio channels were shorting together, cancelling out what should be in the center channel and leaving me with just what should be in the surround channel. I clipped off the end of the cable, spent a few minutes learning which color meant which conductor of the headphone plug, and soldered on a new connector. All better!

2015-12-26-21.09.01