2011-09-16

Compass Belt

So, I made my own compass belt, like many others. I was inspired by the Wired article published a couple of years ago.



The core parts are a HMC6352 compass module connected to a 3.3V Arduino Pro Mini. A ULN2803 with eight Darlington drivers supply power to the vibrators positioned at even intervals around the belt. Everything is powered by a 9V battery.



I found some sample code to read the bearing from the compass, and then added the vibrator control myself.


#include <Wire.h>

int compassAddress = 0x42 >> 1; // From datasheet compass address is 0x42
// shift the address 1 bit right, the Wire library only needs the 7
// most significant bits for the address
int reading = 0;

int bearing = 0;
int offset = 10;

void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial communication at 9600bps
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);

pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
}

void loop()
{
// step 1: instruct sensor to read echoes
Wire.beginTransmission(compassAddress); // transmit to device
// the address specified in the datasheet is 66 (0x42)
// but i2c adressing uses the high 7 bits so it's 33
Wire.send('A'); // command sensor to measure angle
Wire.endTransmission(); // stop transmitting

// step 2: wait for readings to happen
delay(10); // datasheet suggests at least 6000 microseconds

// step 3: request reading from sensor
Wire.requestFrom(compassAddress, 2); // request 2 bytes from slave device #33

// step 4: receive reading from sensor
if (2 <= Wire.available()) // if two bytes were received
{
reading = Wire.receive(); // receive high byte (overwrites previous reading)
reading = reading << 8; // shift high byte to be high 8 bits
reading += Wire.receive(); // receive low byte as lower 8 bits
reading /= 10;
Serial.println(reading); // print the reading
}

// Activate vibrators
offset = -offset;
bearing = reading + 180 + offset;
if (bearing > 359) bearing -= 360;
if (bearing < 0) bearing += 360;

digitalWrite(9, bearing >= 0 && bearing < 45 ? HIGH : LOW);
digitalWrite(8, bearing >= 45 && bearing < 90 ? HIGH : LOW);
digitalWrite(7, bearing >= 90 && bearing < 135 ? HIGH : LOW);
digitalWrite(6, bearing >= 135 && bearing < 180 ? HIGH : LOW);
digitalWrite(5, bearing >= 180 && bearing < 225 ? HIGH : LOW);
digitalWrite(4, bearing >= 225 && bearing < 270 ? HIGH : LOW);
digitalWrite(3, bearing >= 270 && bearing < 315 ? HIGH : LOW);
digitalWrite(2, bearing >= 315 && bearing < 360 ? HIGH : LOW);

delay(10);

digitalWrite(9, LOW);
digitalWrite(8, LOW);
digitalWrite(7, LOW);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
digitalWrite(4, LOW);
digitalWrite(3, LOW);
digitalWrite(2, LOW);
}


The vibrators are glued on velcro, to be easily adjustable for various waist sizes. The cables are nicely embedded in velcro as well.

One of my friends advised me not to go on the subway with this thing, unless I wanted to get arrested. May you live in interesting times.

No comments: