Hack Notes CVA 090326
Jump to navigation
Jump to search
Compass Vibro-Anklet Hack Notes 2009.03.26
Today's Tasks[edit | edit source]
- 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.
Task: Get 4 motors rigged[edit | edit source]
- 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!
The Code[edit | edit source]
- 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); } } }