Hack Notes CVA 090326

From Noisebridge
Revision as of 11:04, 10 April 2009 by Elgreengeeto (talk | contribs) (→‎The Code)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Compass Vibro-Anklet Hack Notes 2009.03.26

Today's Tasks

  • While we're waiting on more bits and pieces, today we're just going to try and add two more pager motors and then experiement with the different display patterns that having two more motors allows us.
  • The LCD display is super useful for debugging. As it is now, there are only two open pins left, neither of which will do PWM out. So to keep the LCD on for now, we'll attach motors to those pins and just settle with only being able to set them full on or off.
    • This has inspired us to order some of these.
    • Looking on digikey also prompted some quick research on alternative economical 3-axis compass chips since the HMC5843 that we all wanted is back ordered until May sometime. We couldn't find anything good, and then diverted into discussing ways, using just software or a tilt-meter and software, to discount the outlier values we expect to be produced by compass mis-readings at the high part of a users stride - thereby allowing use of a 2-axis chip on the ankle without diaflkj....... runonsentencesyaaay.

Anklethack-10.jpg

Task: Get 4 motors rigged

  • 4 circuits put on one crowded breadboard.
  • Set the two remaining binary pins as output, using digitalWrite(pin_num, HIGH/LOW)
  • Ummm our pulses are broken. ??? we aren't doing the digitalWrite right somehow?
  • OK, pins 0 and 1, which we were trying to use with digitalWrite(pin_num, HIGH/LOW) have some kind of crazy constraints on them and we're freaking tired of debugging this business. Solution: bye-bye LCD!

Anklethack-11.jpg

The Code

  • Rewrite the code to activate motors directionally rather than the previous pulsing scheme. We'll start by dividing the circle into eight zones, four of which cause only one motor to vibrate, and the other four defined by an overlap which causes two motors to vibrate. If it's possible to detect that two adjacent ones are on rather than just one on, this could give us a resolution of 8 using just four pager motors:
Motor Range (in degrees, 0=North)
motor 1 -77.5 < angle < 77.5
motor 2 22.5 < angle < 177.5
motor 3 112.5 < angle < -112.5
motor 4 -177.5 > angle > -22.5
  • OK, we got that working, but let's try without overlapping:
Motor # Range (in degrees, 0=North)
motor 1 -77.5 < angle < 77.5
motor 2 45 < angle < 135
motor 3 135 < angle < -135
motor 4 -135 > angle > -45
  • Results: 2 out of 2 expert testers agree, overlapping is feelable, but delivers a kind of fuzzy transition between directions that, rather than delivering a higher resolution, is confusing and less intuitive than the sharp transition felt when it is programmed without the overlap.
/*
Some Hitachi HM55B Compass reading code copied from: kiilo kiilo@kiilo.org
License:  http://creativecommons.org/licenses/by-nc-sa/2.5/ch/
*/

#include <math.h> //


//// VARS
byte VIB1_pin = 9;
byte VIB2_pin = 10;
byte VIB3_pin = 3;
byte VIB4_pin = 5;
byte CLK_pin = 6;
byte EN_pin = 4;
byte DIO_pin = 11;

int X_Data = 0;
int Y_Data = 0;
int angle;

int status;
unsigned long serialTimer = millis();

//// FUNCTIONS

void ShiftOut(int Value, int BitsCount) {
  for(int i = BitsCount; i >= 0; i--) {
    digitalWrite(CLK_pin, LOW);
    if ((Value & 1 << i) == ( 1 << i)) {
      digitalWrite(DIO_pin, HIGH);
      //Serial.print("1");
    }
    else {
      digitalWrite(DIO_pin, LOW);
      //Serial.print("0");
    }
    digitalWrite(CLK_pin, HIGH);
    delayMicroseconds(1);
  }
}

int ShiftIn(int BitsCount) {
  int ShiftIn_result;
    ShiftIn_result = 0;
    pinMode(DIO_pin, INPUT);
    for(int i = BitsCount; i >= 0; i--) {
      digitalWrite(CLK_pin, HIGH);
      delayMicroseconds(1);
      if (digitalRead(DIO_pin) == HIGH) {
        ShiftIn_result = (ShiftIn_result << 1) + 1; 
      }
      else {
        ShiftIn_result = (ShiftIn_result << 1) + 0;
      }
      digitalWrite(CLK_pin, LOW);
      delayMicroseconds(1);
    }
  //Serial.print(":");

// below is difficult to understand:
// if bit 11 is Set the value is negative
// the representation of negative values you
// have to add B11111000 in the upper Byte of
// the integer.
// see: http://en.wikipedia.org/wiki/Two%27s_complement
  if ((ShiftIn_result & 1 << 11) == 1 << 11) {
    ShiftIn_result = (B11111000 << 8) | ShiftIn_result; 
  }


  return ShiftIn_result;
}

void HM55B_Reset() {
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  ShiftOut(B0000, 3);
  digitalWrite(EN_pin, HIGH);
}

void HM55B_StartMeasurementCommand() {
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  ShiftOut(B1000, 3);
  digitalWrite(EN_pin, HIGH);
}

int HM55B_ReadCommand() {
  int result = 0;
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  ShiftOut(B1100, 3);
  result = ShiftIn(3);
  return result;
}


void setup() {
  Serial.begin(115200);
  pinMode(EN_pin, OUTPUT);
  pinMode(CLK_pin, OUTPUT);
  pinMode(DIO_pin, INPUT);

  pinMode(VIB1_pin, OUTPUT);
  pinMode(VIB2_pin, OUTPUT);
  pinMode(VIB3_pin, OUTPUT);
  pinMode(VIB4_pin, OUTPUT);

  HM55B_Reset();
}

void loop() {
 if ((millis() - serialTimer) > 50 ) {

  //read compass and print data to serial out
  HM55B_StartMeasurementCommand(); // necessary!!
  delay(40); // the data is 40ms later ready
  status = HM55B_ReadCommand();
  Serial.print(status); // read data and print Status
  Serial.print(" ");
  X_Data = ShiftIn(11); // Field strength in X
  Y_Data = ShiftIn(11); // and Y direction
  Serial.print(X_Data); // print X strength
  Serial.print(" ");
  Serial.print(Y_Data); // print Y strength
  Serial.print(" ");
  digitalWrite(EN_pin, HIGH); // ok deselect chip
  angle = 180 * (atan2(-1 * Y_Data , X_Data) / M_PI); // angle is atan( -y/x) !!!
  Serial.print(angle); // print angle
  Serial.println(" ");

  analogWrite(VIB1_pin, 0);
  analogWrite(VIB2_pin, 0);
  analogWrite(VIB3_pin, 0);
  analogWrite(VIB4_pin, 0);

/*
  //with overlap 
  if ((angle > -77.5) and (angle < 77.5)) {
    analogWrite(VIB1_pin, 215);
  }

  if ((angle > 22.5) and (angle < 157.5)) {
    analogWrite(VIB2_pin, 215);
  }

  if (((angle > 112.5) and (angle < 180)) or ((angle < -112.5) and (angle > -180))){
    analogWrite(VIB3_pin, 215);
  }

  if ((angle > -157.5) and (angle < -22.5)) {
    analogWrite(VIB4_pin, 215);
  }    
*/

  //without overlap 
  if ((angle > -45) and (angle < 45)) {
    analogWrite(VIB1_pin, 215);
  }

  if ((angle > -135) and (angle < -45)) {
    analogWrite(VIB2_pin, 215);
  }

  if (((angle > 135) and (angle < 180)) or ((angle < -135) and (angle > -180))){
    analogWrite(VIB3_pin, 215);
  }

  if ((angle > 45) and (angle < 135)) {
    analogWrite(VIB4_pin, 215);
  }    
 }
}

Anklethack-12.jpg