After a long trip to CA, I am finally back at working on fun stuff. First up is an app for the Misfit Flash that lights up the lowest LED on the board. Source is here, but it is a bit hapazard and documentation is somewhat scarce. So if you are going to build it make sure you have a few minutes.
This technique assumes that the board is not accelerating at much more than 1g in any direction- in other words, gravity has to be the dominant force. It would not work very well if you were in a car speeding up, but it would work ok you were in a car with a constant velocity.
To determine which way is down, I read the accelerometer and look at the X and Y components. The Z does not have very much information for me, because tilting the board to the same angle in any direction will give you pretty much the same Z value. The Z value would be good for something like a bubble level, but it is not useful here. Another way to think about it is that a gravity vector straight down is being decomposed into ijk vectors that are fixed to the reference frame of the board. We want to know in the ij plane which way is most “in line” with the gravity vector. The X and Y axes of the accelerometer are collinear with the i and j unit vectors in this case.
The X and Y components form a vector that points in some direction on the face of the board (orange vector above). Each LED lies along an imaginary circle with a radius of 64 units, although I show it as a unit circle above. Each of these direction vectors is dotted with the XY vector, which gives a “score” of how much the XY vector is pointing in the direction of the LED. The vector with the largest score has its LED illuminated.
Other Approaches and improvements:
There are simpler ways to do this with non-integer math and conditionals, but floating point math is apparently “expensive” on a M0. The easy way to do it with floats would be to make a table of inverse tangents, and find the ratio between the X and Y components. Then it would be simple to just look up which range you were within- for example the 2 o’clock LED here is between .25 and .66. There would have to be special provisions if X were ever 0 to avoid a division by 0 error, but that would be pretty simple.
An easier optimization would be to get “hints” from the sign of the XY vector, if optimizing for speed. right now, each 12 dot product operations and 12 conditionals are evaluated each time. This could probably be cut down to 4 dot products and 6 conditionals if by looking at the quadrant of to do the dot products in first, depending on the value of the XY vector. Given that the processor is only doing one thing, it does not seem like it is useful to implement.