TinyBubble is a bubble level using the accelerometer and edge LED shields.
/*
* TinyBubble - Bubble Level
*
* Uses Accelerometer and 16 or 21-LED TinyShields
*
* Version 140515
*/
#include <Wire.h>
#include <math.h>
#define SENSITIVITY 15
#define CALIBRATION 0.0
#define BMA250_I2CADDR 0x18
#define BMA250_BW 0x08 // 7.81Hz
int N_LEDs;
void setup()
{
Wire.begin();
// Setup the filter bandwidth
Wire.beginTransmission(BMA250_I2CADDR);
Wire.write(0x10);
Wire.write(BMA250_BW);
Wire.endTransmission();
// Distinguish between 16 and 21 LED boards by detecting LED #21
pinMode(4, INPUT);
pinMode(9, OUTPUT);
bool led_21 = ((digitalWrite(9, HIGH), digitalRead(4)) &&
(digitalWrite(9, LOW), !digitalRead(4)));
pinMode(9, INPUT);
N_LEDs = led_21 ? 21 : 16;
}
void loop()
{
static int led;
static int clock4; // 4-bit clock
clock4 = (clock4 + 1) & 15; // range: [0, 15]
// Read X and Y
Wire.beginTransmission(BMA250_I2CADDR);
Wire.write(0x02);
Wire.endTransmission();
Wire.requestFrom(BMA250_I2CADDR, 4);
int x_lsb = Wire.read();
int x_msb = Wire.read();
int y_lsb = Wire.read();
int y_msb = Wire.read();
int X = ((x_msb << 8) | x_lsb) >> 6;
int Y = ((y_msb << 8) | y_lsb) >> 6;
if (((long) X*X + (long) Y*Y) < SENSITIVITY) {
// Spin if board is level within sensitivity
if (++led > N_LEDs)
led = 1;
}
else {
// Compute angle
float angle = atan2(-X, -Y) * (10.5 / M_PI); // range: [-10.5, 10.5]
float ramp = (clock4 - 7.5) * (1.0 / 18.75); // range: [-0.4, 0.4]
led = angle + ramp + 19.5 + CALIBRATION; // range: [8, 29]
if (led > 21)
led -= 21;
}
LED_on(led);
}
void LED_on(int n)
{
static uint8_t high_pin[21] = {5, 6, 5, 7, 6, 7, 6, 8, 5, 8, 8, 7, 9, 7, 9, 8, 5, 9, 6, 9, 9};
static uint8_t low_pin [21] = {6, 5, 7, 5, 7, 6, 8, 6, 8, 5, 7, 8, 7, 9, 8, 9, 9, 5, 9, 6, 4};
for (int i = 4; i <= 9; i++)
pinMode(i, INPUT);
if (n >= 1 && n <= N_LEDs) {
digitalWrite(high_pin[n - 1], HIGH);
digitalWrite(low_pin [n - 1], LOW);
pinMode(high_pin[n - 1], OUTPUT);
pinMode(low_pin [n - 1], OUTPUT);
}
}