Digital compass

Hi all,
I have to say thanks so much for all the help everyone, I've learned so much in these last couple months from everyone's help and I just gotta say this is a great forum! I still am a novice though!

I'm building a digital compass armband that will give you a little vibration pulse when you're aligned with North. Thought it would be a cool first project.

First of all, this thing is vibrating for the specified 250ms every 7.5 seconds no matter what, and for the life of me I can't figure out why. Timer0 should reset every 7.5 seconds, which it does, but it shouldn't be pulsing.

Most frustratingly, is this:

  //if bearing is within boundaries and trip = 0
  if ((avg >= -40) && (avg <= 20) && (trip == 0)) {
    buzz = 1;       // turn on vibrator
    trip = 1;       // do not allow chunk of code to run again until reset
    timer0 = -40; } // reset timer

I want this section of code to only run only once until "trip" is reset. I'm looking at the serial.print of trip, and it never turns to 1, it stays at 0. Why is this happening?

A further question, does every new line of serial.print represent 1 processor cycle? Or is the processor running much quicker than this?

Thanks!

/*
An Arduino code example for interfacing with the HMC5883

by: Jordan McConnell
 SparkFun Electronics
 created on: 6/30/11
 license: OSHW 1.0, http://freedomdefined.org/OSHW

Analog input 4 I2C SDA
Analog input 5 I2C SCL
*/

  const int PAD = 13; //assigns pin to pad

  const int LED = 10; //LED assigned to pin 10
  

#include <Wire.h> //I2C Arduino Library
#include <elapsedMillis.h> // Timer library
elapsedMillis timer0; //correlate timers with elapsedMillis
elapsedMillis timer1;
#define interval250 250 //Create delays in mS
#define interval7500 7500
#define address 0x1E //0011110b, I2C 7bit address of HMC5883


void setup() {
  //Initialize Serial and I2C communications
  Serial.begin(9600);
  Wire.begin();
  
  //Put the HMC5883 IC into the correct operating mode
  Wire.beginTransmission(address); //open communication with HMC5883
  Wire.write(0x02); //select mode register
  Wire.write(0x00); //continuous measurement mode
  Wire.endTransmission();
  
  pinMode(PAD, OUTPUT); //assigns PAD as an output
  pinMode(LED, OUTPUT); //assigns LED as an output
  
}

void loop() {
  
  int x,y,z; //triple axis data
  int avg; //average of axis data
  int buzz; //sets vibrator to buzz
  int trip; //allows calculations 
  
  //Tell the HMC5883 where to begin reading data
  Wire.beginTransmission(address);
  Wire.write(0x03); //select register 3, X MSB register
  Wire.endTransmission();
  
 
 //Read data from each axis, 2 registers per axis
  Wire.requestFrom(address, 6);
  if(6<=Wire.available()){
    x = Wire.read()<<8; //X msb
    x |= Wire.read(); //X lsb
    z = Wire.read()<<8; //Z msb
    z |= Wire.read(); //Z lsb
    y = Wire.read()<<8; //Y msb
    y |= Wire.read(); //Y lsb
  }
  
  //Create average values of Y and Z axis
  avg=y+z/2;
  
  //Print out values of each axis
  Serial.print("x: ");
  Serial.print(x);
  Serial.print("  y: ");
  Serial.print(y);
  Serial.print("  z: ");
  Serial.print(z);
  Serial.print(" avg:   ");
  Serial.print(avg);
  Serial.print("  timer0:  ");
  Serial.print(timer0);
  Serial.print("  buzz  ");
  Serial.print(buzz);
  Serial.print("  trip  ");
  Serial.println(trip);

  
  //if bearing is within boundaries and trip = 0
  if ((avg >= -40) && (avg <= 20) && (trip == 0)) {
    buzz = 1;       // turn on vibrator
    trip = 1;       // do not allow chunk of code to run again until reset
    timer0 = -40; } // reset timer
    
  //let first chunk of code run if bearing out of boundaries  
  if ((avg <= -42) || (avg >= 22)) {
    trip = 0; }
    
  if (buzz == 1) {
    digitalWrite (PAD, HIGH); }
    
  if (timer0 > interval250) {
     buzz = 0;
    digitalWrite(PAD, LOW); }
    
  if (timer0 > interval7500) {
    timer0 = -40;
    trip = 0; }

  }

I don't know anything about the ElapsedMillis library but I suspect the problem is that you never update the value in timer0.

I just use millis() directly as illustrated in several things at a time.

A further question, does every new line of serial.print represent 1 processor cycle? Or is the processor running much quicker than this?

This is a confusing question - I'm not sure what you had in mind.
The Arduino runs at 16MHz - which is much much faster. But it takes a large number of processor cycles to Serial.print() even a single character.

I think your IF statements could be tidied up and simplified like this

  if ((avg <= -42) || (avg >= 22)) {
    trip = 0; 
  }
  else {
    if (trip == 0) {
       buzz = 1;       // turn on vibrator
       trip = 1;       // do not allow chunk of code to run again until reset
       imer0 = -40; 
    }
  }

The advantage of simplification is that it is easier to be sure it is doing what you want.

...R

Part of your problem is that 'trip' and 'buzz' and both "automatic" variables that get created fresh each time loop() runs. If you want a local variable to persist you should declare it as 'static int'. An alternative is to make it a global variable by moving it outside the functions.