Introduction: How to Make a Tactile Feedback Compass Belt

Have you ever wondered how migratory birds manage to have such an amazing sense of direction despite being so generally clueless? They can sense the Earth's magnetic field with what is basically a compass built into their body. Wouldn't it be cool to feel what that's like?

The following instructions are loosely based off of a research paper by the (German) OFFIS Institute of Technology, or Oldenburger Forschungs und Entwicklungsinstitut für Informatik-Werkzeuge und Systeme, if you sprechen sie Deutsch. It can be found here:

http://pielot.org/wp-content/uploads/2011/05/Pielot2011-TactileCompass.pdf

Further thanks go to a couple of guides on how to make simple vibration motor and digital compass circuits, respectively. If my explanations aren't doing it for you, these probably will for their corresponding aspects of the project:

http://learningaboutelectronics.com/Articles/Vibration-motor-circuit.php
http://www.funnyrobotics.com/2011/03/arduino-with-hmc6352-digital-compass.html

Step 1: Materials

So with the citations out of the way, let's get started. First, you'll need a bunch of materials. A lot of these are available easily from Sparkfun, but in many cases more cheaply from Jameco or Digikey or something. Total cost is around $150, largely due to the Arduino or similar, compass chip, motors, and appropriate belt. For this project you will need:

1x:        Arduino or homemade ATMega microprocessor board. I recommend an Arduino because it's difficult to fit voltage regulators, a resonator, etc into a small package by yourself. You'll need a serial interface too, although a USB cable works fine for an Arduino. I used an Arduino Uno with an ATMega 328p. (~$30)

1x:        Honeywell HMC6352 compass chip. (~$35)

1x:        Belt. Preferably canvas or fabric, of the boating variety. Leather is really no good for this, and the loop buckles won't get in the way of the circuit elements like a traditional pin-and-hole buckle might. (~$20)

8x:        Vibration motors; I used sparkfun's #8449, they do well @~3V (~$5 ea.)

8x:        1N4001 diode (cheap)

8x:        0.1uF capacitor (cheap)

8x:        2N2222 Transistor (any NPN will probably work.) (cheap)

8x:        1K resistors (1/4W will be fine, microprocessors output low current.) (cheap)

8x:        33-75ish ohm resistors (33 minimum, I used 47 because I had them lying around.) (cheap)

Some:  9V batteries/clips

A Few:  Needles & thread (for sewing circuit elements onto the belt once they're properly soldered.)

Lots:     ~22ga wire, electrical tape, solder.

Optional but recommended: A case/enclosure for your Arduino or microprocessor assembly.

Optional: An on/off switch so that you don't have to unplug the battery to turn it off.

Note that while I used 8 motors, you can use however many you like; just replace 8 with your number in these instructions, and use 360 / X instead of 45 degree increments in the final code.

Step 2: Build a Motor Assembly

Before starting to work with the actual belt, you'll probably want to make a prototype using breadboards. The motor assemblies are pretty simple, but you'll need 8 of them. Each assembly will connect to one of your microprocessor's digital IO pins, plus a common 5V vcc and ground. You'll want the assemblies in parallel.

For one assembly, tl;dr refer to the picture. More lengthily, simply connect your desired digital pin to a 1K resistor, and connect that to the B pin of your chosen transistor. The E pin goes to ground, and the C pin is just a bit more complicated. You'll want it connected to three circuit elements connected in parallel; a diode, a 0.1uF capacitor, and a motor. The motor doesn't have polarity, and the capacitor is small enough that you don't have to worry about it. Make sure that the diode's cathode (the side with the stripe) is facing away from the transistor's C pin. That's important, because the diode is there to prevent your motor from drawing too much current and frying the microprocessor. If you do fry your microprocessor, no big deal. Don't spring for a whole new board, just get another ATMega 168/328 for 5 or 6 bucks and pop it in; sparkfun sells ones with optiboot pre-loaded so you won't even need a real serial interfacing board. Finally, connect your small-ohm (33-75ish) resistor to the diode's cathode (and the motor/capacitor by extension), and hook that up to the 5V out. See the picture for details. Refer to your chosen transistor's data sheet to determine which pin is which.

That's it! Run a simple test to make sure that everything is hooked up correctly. Note that the motors I recommended have tiny leads, so if you want to plug them into a breadboard you'll really want to solder a short slip of 22ga wire to each one to ensure that they make consistent contact.

Motor test code (for Arduino or microprocessor board w/ Arduino optiboot):

const int motorPin = <your pin #>;

void setup()
{
  pinMode(motorPin, OUTPUT);
}

void loop()
{
  // Turn on for 2 seconds, then off for 1 second.
  digitalWrite(motorPin, HIGH);
  delay(2000);
  digitalWrite(motorPin, LOW);
  delay(1000);
}

Step 3: Build More Motor Assemblies

This step is pretty short in writing, but it'll take a bit of time and patience. Now you need to build 7 more motor assemblies and hook them all up for a total of 8 digital IO pins. Your voltage and ground wires should be shared among the assemblies; just use the +/- columns if you have a breadboard to make it easier on yourself. Once you're done, it should look something like the picture, except with 8 motors instead of 4. I used two breadboards with 4 on each. I only took a picture of one though, sorry. Each yellow wire should go to its own digital pin on the Arduino, the red/white to 5V/Ground.

I'm pretty sure you could get away with using just one diode/capacitor if you hooked it up right, but this makes the wiring easier and they're really cheap anyways. Don't forget to test all of the motors. Since they're in parallel, one failure won't cause the whole thing to stop working, which makes troubleshooting very easy. Plug them all in, and just add 7 more pins to the sample code from the previous step. For each one you need to define it, set the mode to output, and tell it to turn on and off:

// I used pins 2-9, you may have different ones.
const int motorPin = 2;
const int motorPin2 = 3;
const int motorPin3 = 4;
const int motorPin4 = 5;
const int motorPin5 = 6;
const int motorPin6 = 7;
const int motorPin7 = 8;
const int motorPin8 = 9;

void setup()
{
  pinMode(motorPin, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
  pinMode(motorPin5, OUTPUT);
  pinMode(motorPin6, OUTPUT);
  pinMode(motorPin7, OUTPUT);
  pinMode(motorPin8, OUTPUT);
}

void loop()
{
  // Turn each pin on for 2 seconds, then off for 1.
  digitalWrite(motorPin, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, HIGH);
  digitalWrite(motorPin5, HIGH);
  digitalWrite(motorPin6, HIGH);
  digitalWrite(motorPin7, HIGH);
  digitalWrite(motorPin8, HIGH);
  delay(2000);
  digitalWrite(motorPin, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin5, LOW);
  digitalWrite(motorPin6, LOW);
  digitalWrite(motorPin7, LOW);
  digitalWrite(motorPin8, LOW);
  delay(1000);
}

Step 4: Hook Up the Compass

These compass chips are tiny, so soldering the pins can be intimidating. I went through some trial and error here and a burnt finger, but on the upside I can say that if I didn't fry the chip with my somewhat clumsy soldering, there's not much chance that you will. So, look at the first picture. This is a good way to solder the leads on. Just stick a wire in the hole, twist it into a little loop, and apply a dab of solder. Works great.

At first, I tried to stick headers on (see image 2). I would have gone with male-to-female, but male-to-male were all I had lying around. Anyways, it did not work well. The solder would not bind the headers to the board. Probably the solder I had just didn't like the headers I had, but sticking the wires in and soldering them worked so well that I don't recommend trying to go with headers.

Your compass will have 4 pins; GND, VCC, SDA, SDL. They're labeled, but for reference to my pictures: white-red-yellow-white = GND-VCC-SDA-SDL. Hook the GND pin up to ground, and the VCC pin to a 3.3V out. This is where having the arduino is nice; you get both 3.3 and 5V regulators onboard, and it can easily run off of a 9V battery (5-20V range, 7-12V recommended), which we'll get to in a bit. Anyways, hook the SDA pin up to analog pin A4 (20), and the SDL up to pin A5 (21). Note that these chips lose about 2 degrees of accuracy for every 1 degree of tilt and work unreliably beyond 10-15 degrees of tilt, so you'll want to keep it flat. Load the code at the end of this step onto your microprocessor and open the serial interface while it's plugged in (ctrl+shift+M in the Arduino interface) to check the output.

In the interest of helping you not repeat my mistakes, I can offer some troubleshooting advice: if, when testing your chip, you get a stream of 0.0 degrees, check your voltage and ground pins' connections. If you don't get any output at all, check your SLA and SLD pins. Anyways, here's the code to test your compass: (see the intro for citation, the digital compass page also has a great image showing better than I could where to connect the logic pins if you're still confused.)

#include <Wire.h>

void setup()
{
  Serial.begin(9600);
  Wire.begin();
}

void loop()
{
  Wire.beginTransmission(0x21);
  Wire.write("A");
  delay(100);
  Wire.requestFrom(0x21, 2);
  byte MSB = Wire.read();
  byte LSB = Wire.read();
  Wire.endTransmission();
  float degs = ((MSB << 8) + LSB) / 10;
  Serial.print(degs);
  Serial.println(" degrees.");
  delay(100);
}

Step 5: Finish the Prototype

Great! Now you have a heading, and 8 motors ready to buzz at your bidding. They should all be plugged into the Arduino, too. Here's the code I used to combine the two. Note that I kept the serial interface so that I would be able to troubleshoot it. You'll want to offset each motor's activation regions by a certain number of degrees based on the compass' heading in relation to its place on the belt once you have everything together, and it's good to be able to see just how many degrees you want to offset by. That part should wait until you have the belt put together, though.

#include <Wire.h>

// I used pins 2-9, ymmv
const int NPin = 2;
const int NEPin = 3;
const int EPin = 4;
const int SEPin = 5;
const int SPin = 6;
const int SWPin = 7;
const int WPin = 8;
const int NWPin = 9;

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  pinMode(NPin, OUTPUT);
  pinMode(NEPin, OUTPUT);
  pinMode(EPin, OUTPUT);
  pinMode(SEPin, OUTPUT);
  pinMode(SPin, OUTPUT);
  pinMode(SWPin, OUTPUT);
  pinMode(WPin, OUTPUT);
  pinMode(NWPin, OUTPUT);
}

void loop()
{
  Wire.beginTransmission(0x21);
  Wire.write("A");
  delay(100);
  Wire.requestFrom(0x21, 2);
  byte MSB = Wire.read();
  byte LSB = Wire.read();
  Wire.endTransmission();
  float degs = ((MSB << 8) + LSB) / 10;
  Serial.print(degs);
  Serial.println(" degrees.");
  // Special case with north pin to deal with crossing 0 degrees.
  if ((degs >= 337.5 && degs <= 360) || (degs >= 0.0 && degs < 22.5))
  {
    digitalWrite(NPin, HIGH);
  }
  else
  {
    digitalWrite(NPin, LOW);
  }
  // Check all other directions using a 45-degree range.
  if (degs >= 22.5 && degs < 67.5)
  {
    digitalWrite(NEPin, HIGH);
  }
  else
  {
    digitalWrite(NEPin, LOW);
  }
  if (degs >= 67.5 && degs < 112.5)
  {
    digitalWrite(EPin, HIGH);
  }
  else
  {
    digitalWrite(EPin, LOW);
  }
  if (degs >= 112.5 && degs < 157.5)
  {
    digitalWrite(SEPin, HIGH);
  }
  else
  {
    digitalWrite(SEPin, LOW);
  }
  if (degs >= 157.5 && degs < 202.5)
  {
    digitalWrite(SPin, HIGH);
  }
  else
  {
    digitalWrite(SPin, LOW);
  }
  if (degs >= 202.5 && degs < 247.5)
  {
    digitalWrite(SWPin, HIGH);
  }
  else
  {
    digitalWrite(SWPin, LOW);
  }
  if (degs >= 247.5 && degs < 292.5)
  {
    digitalWrite(WPin, HIGH);
  }
  else
  {
    digitalWrite(WPin, LOW);
  }
  if (degs >= 292.5 && degs < 337.5)
  {
    digitalWrite(NWPin, HIGH);
  }
  else
  {
    digitalWrite(NWPin, LOW);
  }
  delay(100);
}

Upload that or similar, and you should get one motor buzzing at a time, depending on the compass' heading. Congrats! That's the whole thing. Now the problem is, how do you get it into a belt?

Step 6: How to Get It Into a Belt

First, measure your waist; don't be shy, it's important. Cinch the belt comfortably but firmly, and measure how long it is from buckle to the point where it cinches. Divide that by 8, and that's how much space you'll have for each motor assembly. For example, I got 30” in total, so 3.75” for each motor. Mark out the amount of space each motor assembly can take up on the inside of the belt to make sure that you get it right; refer to the lower half of the second picture for an example of marking the belt. I also outlined a couple of semicircles to signify where I wanted each transistor to lie, since they make a decent center for each assembly's position.

Fortunately, it's actually not too difficult to get your motor assembly into a small linear space. The circuit is pretty much linear anyways; from left to right, VCC → low-ohm resistor → diode/capacitor/motor in parallel → transistor, with the ground line below, and then transistor → 1K resistor → digital pin. Clip the resistor and diode legs to shorten things up. Look at the first picture for an example of a miniaturized assembly (albeit upside-down). Note that it is sewn and taped on and already connected to the other 7 assemblies, which will be described below. Do not sew or tape on your assemblies until a common ground and voltage line connects them all.

Note: make sure that you affix the motor assemblies to the INSIDE of the belt.
Miniaturize all 8 assemblies with gobs of solder, then just run a common VCC wire along the middle and a common ground along the bottom. Be sure to coat any exposed wires that overlap or get too close to each other with electrical tape to prevent short circuits. Your signal wires can run along the top, and they'll all terminate at the microprocessor. Remember that your assemblies are in parallel, so one broken connection won't break the whole thing; troubleshooting failure should be easy. See the third picture for what 8 connected miniaturized assemblies look like fully laid out.

Once you have all 8 assemblies soldered into one long string of circuitry, sew the wires onto/into the belt, and use electrical tape to seal it up against the elements. Once you have it working, you can clip the signal wires to size and coat the whole thing in electrical tape.

Now you may have noticed already, but you can just run the whole thing off a 9V battery once the code is uploaded. Just plug the battery clip's + wire into the VCC pin, and the – wire into ground. I've been running it for a few days off of one battery without issue, so I'd say it gets pretty good battery life out of a standard 9V.

As for the compass, use electrical tape to securely fix it along the top of your microprocessor housing to ensure that it remains reasonably flat; see the fourth picture. Note however, that I wound up tweaking the design a bit from what is displayed in the fourth picture. I don't know whether the board produced excessive interference, or the aluminum housing dampened the compass' detection of the earth's magnetic field, but my compass only reported between roughly 110 and 240 degrees when the chip was affixed underneath the housing. I fixed it by putting the chip on top of the housing instead. The actual chip (the black square on the board) should be face up, and not pressed against the case.

Once you have the whole thing assembled, cut the wires to size so that they can lie flat against the belt without much extra length. If they fit well while the belt is laying flat, they'll fit well when it's around your waist, as long as you don't have an elastic belt. Finally, put the belt on and plug your board into a computer with a serial interface. Look at another compass or use google maps to see which direction is north, and calibrate the degree ranges in your code to match the motor's locations on your belt to the compass's heading. To do that, face due North and look at the serial readout. Offset your degree ranges by that amount in the code so that the front motor buzzes when you face within 22.5 degrees in either direction of that heading. If you make sure that the buckle is in the same place every time you wear the belt, your calibration should remain accurate.

That should be about it. Pop a battery in and see what it feels like. Try walking around somewhere you've never been! You should stay relatively upright, though; the compass loses accuracy quickly as it rotates away from being flat.

Step 7: Tips

And that's it! Having worn the one I made around for several days, I have a few tips for using it if you're interested.

1. Avoid excessive water. It SHOULD be able to survive getting wet as long as you make sure that it is powered off until it completely dries, and the electrical tape should protect it from the worst of the elements. Still, I'd avoid wearing it in a downpour.

2. Write 'COMPASS' in large, legible letters on the front of the microprocessor assembly. People get nervous when they see an unexplained box with wires coming out of it. Along similar lines, don't wear this to the airport. The TSA are not famous for being understanding of electronics hobbyists. I don't like that such steps are necessary, and hopefully the stigma will diminish once wearable electronics become more popular, but don't be dumb about it.

3. The wires can move when you do, and rubbing things against the belt may cause the circuit elements' positions to shift. If a motor assembly cuts out, it should be easy to diagnose; just look at the offending assembly. If every motor past a certain point cuts out, your power or ground line got cut between the last working motor and the first non-functioning one. If the wrong motor is going off, check your code and/or compass connections. I'm planning on printing out a bunch of thin clips to go around the belt and provide more protection, but it's pretty robust as is.

Arduino Contest

Participated in the
Arduino Contest

Great Outdoors Contest

Participated in the
Great Outdoors Contest