Hack Notes CVA 090411
Jump to navigation
Jump to search
(Skory's) Hacknotes 090411
Hella Progress[edit | edit source]
- Remade the pager motor array on a ribbon cable without plastic crimps and added two more pager motors.
- It's plenty comfortable now, but I don't like the spacing of the motors. Nothing is ever perfect! I might add a ninth motor (although I've already trimmed the ribbon cable and doing that would definitly be non-trivial!) or possibly resort to resoldering a couple current ones in different positions.
- Built (well, really my dad did most of the work because he's the one with a bandsaw) a plastic casing for the electronics. It definitely adds bulk, but it still fits in the external elastic pocket and there's no way I could wear this thing without protecting all that hard work.
- Borrowed a socket for the battery connector from the Sparkfun charger (it has three sockets I only need one to charge a battery...)
- Added timing to the code so motors don't just stay on forever if you aren't moving around. Currently it just counts iterations through the main loop, which I timed at about 22 cycles per second. I have it set to stay on any one motor for no more than about 10 seconds, and to buzz once a minute if you haven't moved. As long as you keep moving more than once every ten seconds it won't shut off. I might mess around later with having the buzz duration diminish with time if you continue to not move. Here's the code (sorry Eric it was too messy to leave your compass functions in there):
/* Skory & Eric * Compass Vibro-Anklet * We Rule, April 11, 2009 */ /* Some code from: * 2009-03-24, pager motor test, lamont lucas Some Hitachi HM55B Compass reading code copied from: kiilo kiilo@kiilo.org License: http://creativecommons.org/licenses/by-nc-sa/2.5/ch/ */ // define the pins used to run the shift registers int enable_low = 10; //enable outputs, low = on int serial_in = 12; int ser_clear_low = 9; //pulse low to zero out the shift buffer int RCK = 7; //RCK, push the serial buffer to the outputs int SRCK = 8; // #include <math.h> //// define pins used to operate the digital compass (HM55B) byte CLK_pin = 11; byte EN_pin = 5; byte DIO_pin = 4; int X_Data = 0; int Y_Data = 0; int angle; unsigned long counter = 0; int prev_motor = 1; int curr_motor = 1; int status; unsigned long serialTimer = millis(); int MotorStrength = 230; // 255 = full power void setup() { pinMode(enable_low, OUTPUT); // set shift register pins as outputs pinMode(serial_in, OUTPUT); pinMode(ser_clear_low, OUTPUT); pinMode(RCK, OUTPUT); pinMode(SRCK, OUTPUT); // use some serial for debugging Serial.begin(115200); Serial.println("Setting up board"); // make sure we start out all off digitalWrite(enable_low, HIGH); // this should wipe out the serial buffer on the shift register digitalWrite(ser_clear_low, LOW); delay(100); //delay in ms // the TPIC6b595 clocks work on a rising edge, so make sure they're low to start. digitalWrite(RCK, LOW); digitalWrite(SRCK, LOW); digitalWrite(ser_clear_low, HIGH); //we are now clear to write into the serial buffer Serial.println("Board is setup"); // setup for HM55B compass chip pinMode(EN_pin, OUTPUT); pinMode(CLK_pin, OUTPUT); pinMode(DIO_pin, INPUT); HM55B_Reset(); } void loop() { // make the compass get a reading HM55B_StartMeasurementCommand(); // necessary!! delay(40); // the data is ready 40ms later 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 X_Data = X_Data * -1; // In current rig, chip Y_Data = Y_Data * -1; // is upside-down; compensate 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) !!! if (angle < 0) angle = (360 + angle); //offset neg angles Serial.print(angle); // print angle Serial.println(" "); //Turn on the appropriate motor while keeping track of time curr_motor = CalcMotor(8, angle); if (curr_motor != prev_motor) { //if we changed angle enough TurnOnMotor(curr_motor); //turn on the new motor counter = 0; //reset counter } else { if (counter < 250) { //otherwise only keep TurnOnMotor(curr_motor); //same motor on for } else { //less than 250 cycles TurnOnMotor(0); //(it's ~22 cycles / second) } counter++; //increment counter if (counter > 1320){ counter = 0; //reset counter after ~1 min. } } prev_motor = curr_motor; Serial.println(counter); /* //Debug wacky motor wiring disorder count++; TurnOnMotor(count); Serial.print(count); // print angle Serial.println(" "); delay(2000); if (count >= 8) { count = 0; delay(2000); }*/ } //// FUNCTIONS void TurnOnMotor(int which){ // accept which from 1 to 8 // send message to shift register as appropiate digitalWrite(enable_low, HIGH); delayMicroseconds(100); //slow and steady Serial.print("Motor "); Serial.println(which); // print angle switch(which){ case 1: shiftOut(serial_in, SRCK, LSBFIRST, B00000100); break; case 2: shiftOut(serial_in, SRCK, LSBFIRST, B00000001); break; case 3: shiftOut(serial_in, SRCK, LSBFIRST, B00001000); break; case 4: shiftOut(serial_in, SRCK, LSBFIRST, B00000010); break; case 5: shiftOut(serial_in, SRCK, LSBFIRST, B00010000); break; case 6: shiftOut(serial_in, SRCK, LSBFIRST, B00100000); break; case 7: // not used in current armature shiftOut(serial_in, SRCK, LSBFIRST, B01000000); break; case 8: // not used in current armature shiftOut(serial_in, SRCK, LSBFIRST, B10000000); break; case 9: shiftOut(serial_in, SRCK, LSBFIRST, B11111111); break; case 10: shiftOut(serial_in, SRCK, LSBFIRST, B11110000); break; case 11: shiftOut(serial_in, SRCK, LSBFIRST, B00001111); break; default: // turn them all off shiftOut(serial_in, SRCK, LSBFIRST, B00000000); } //in all cases, pulse RCK to pop that into the outputs delayMicroseconds(100); digitalWrite(RCK, HIGH); delayMicroseconds(100); digitalWrite(RCK, LOW); analogWrite(enable_low, 255-MotorStrength); } int CalcAngle(int howMany, int which) { // function which calculates the "switch to next motor" angle // given how many motors there are in a circle and which position you want // assume which is 1-indexed (i.e. first position is 1, not zero) // assume circle is 0-360, we can always offset later... return (360/howMany*(which-0.5)); } int CalcMotor(int howMany, int angle) { // function to calculate which motor to turn on, given // how many motors there are and what the current angle is // assumes motor 1 = angle 0 // assumes angle is from 0-360 int i; for (i = 1; i<howMany;i++) { if ( (angle >= CalcAngle(howMany, i)) & (angle <= CalcAngle(howMany, i+1)) ) return i+1; } // if we're still here, it's the last case, the loop over case, which // is actually motor 1 by assumption return 1; } //HM55B 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; }
- I still really need to order all that stuff that we need to order already but haven't yet...