LEDs & gravity

I thought it would be a nice touch if the LEDs in the Selleck Striker behaved more like the metal ringer in an old school mechanical hi-striker. So rather than rising up the scale in a linear way, what if it looked like the LED “ringer” was being pulled down by gravity (and friction, and air resistance) like the real thing?

time_distanceSo I figured an ascending object will decelerate in the same way a falling object will accelerate, since they’re both subjected to the same force (gravity). I found some formulas for acceleration due to gravity, particularly :

d=gt2

where d = distance, g = the gravitational constant, and t = time. I would calculate the trip from top to bottom as if the ringer was falling, then use that data in reverse.

The LEDs turn on in sequence, with a delay value in between to determine how long each one stays on (and how fast the “ringer” appears to move). So in order to determine that value I need to solve for t in the equation above. So:

t=sqrtt_g

I know that on Earth the gravitational constant — or g — is 9.8 m/s² (meters per second per second). I know the distance d between each LED is 1.37″, or .035m. So the time tx to get from the very top LED to the next one is:

tx

So the first .035m step down from the top will take 59ms. In order to find tz for the second step, I need to find ty for the total distance from the top to the second step (.035m x 2 = .07m), then subtract tx for the first step:

distance

So:

equations

I need to do this for each of the 51 steps (50 LEDs plus the very top, the winner!). Actually, I’m not calculating this at all. I’ll let the Arduino do all the calculations, and save the delay value for each step in an array that it can quickly access when it needs to. Here’s how I did it in the Arduino script:

  float gravity_constant = 9.8;                         // the constant of gravity, or G
                                                        // we can adjust this to tweak the effect

  int gravity[50] = {};                                  // set up the gravity array

  for (int i = 1; i <= 51; i++) {                        // this will loop 51 times
    float distance_x = i * .035;                         // calculate the total distance from the top to the LED in question
    float distance_y = (i - 1) * .035;                   // same distance, minus one step 
    float time_x = sqrt(distance_x / gravity_constant);  // the time it takes for an object to fall distance_x meters
    float time_y = sqrt(distance_y / gravity_constant);  // the time it takes for an object to fall distance_y meters
    float time = time_x - time_y;                        // the time it takes for an object to fall to our LED from the one before it, in seconds
    int time_ms = time * 1000;                           // convert to milliseconds
    gravity[i] = time_ms;                                // add this value to the gravity array
  }

The gravity array will look something like [59, 26, 16, 14, 13, 12, 11, 10, 9, etc…….], dropping rapidly at first and then slower until it levels off at 4ms or so. If we then light the LEDs in sequence, applying these delay values to each step:

  int level = 48;             // this is the level the person hit to
                              // * entered manually for testing purposes,
                              // in the final product this will be determined by 
                              // the force of the hammer strike  

  for (int i = level; i > 0; i--) {
    digitalWrite(ledPins[level - i], HIGH);
    delay (gravity[i]);
    digitalWrite(ledPins[level - i], LOW);
  }

then we get something like this:

Note: the blinking at the beginning is the Arduino booting up, and the blinking at the end was added later to highlight the level of the hit.

2 Responses to “LEDs & gravity”

  1. Matt Turner writes:

    It should be d = 1/2 g t^2

  2. Smoker_Dave writes:

    Those floating point operations are not ideal.

    You would be best using a spreadsheet to calculate the values and store them in array. It will speed things up nicely.