Use Accelerometer and Joystick to mimic a mouse. This is for a class project. It is done for educational purpose. It is not practical to real world use.

Dependencies:   C12832_lcd MMA7660 USBDevice mbed

Committer:
thlu
Date:
Sat Mar 15 09:32:43 2014 +0000
Revision:
0:22bdcdc386df
Child:
1:03d0f8a4a2d7
Got calibration working using x,y, and z-axes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
thlu 0:22bdcdc386df 1 #include "accelestick.h"
thlu 0:22bdcdc386df 2
thlu 0:22bdcdc386df 3 inline void reset_tm_joystick_dc()
thlu 0:22bdcdc386df 4 {
thlu 0:22bdcdc386df 5 tm_joystick_running = 0;
thlu 0:22bdcdc386df 6 tm_joystick_dc.stop();
thlu 0:22bdcdc386df 7 tm_joystick_dc.reset();
thlu 0:22bdcdc386df 8 }
thlu 0:22bdcdc386df 9
thlu 0:22bdcdc386df 10 // This function checks for joystick button presses which emulate a mouse's
thlu 0:22bdcdc386df 11 // left button, right button, middle button, double click, and scroll
thlu 0:22bdcdc386df 12 // features. Double click requires a timer
thlu 0:22bdcdc386df 13 void get_joystick_input()
thlu 0:22bdcdc386df 14 {
thlu 0:22bdcdc386df 15 static uint8_t prev_js = 0;
thlu 0:22bdcdc386df 16 static bool debug_sel_en = 0;
thlu 0:22bdcdc386df 17 static int mouse_scroll = 0;
thlu 0:22bdcdc386df 18
thlu 0:22bdcdc386df 19 mouse_info.button = 0;
thlu 0:22bdcdc386df 20 mouse_info.scroll = 0;
thlu 0:22bdcdc386df 21 mouse_info.dc = 0;
thlu 0:22bdcdc386df 22
thlu 0:22bdcdc386df 23 if (debug_on && debug_sel_en && (joyb != JS_NONE)) {
thlu 0:22bdcdc386df 24 debug_sel_en = 0;
thlu 0:22bdcdc386df 25 debug_sel = joyb;
thlu 0:22bdcdc386df 26 }
thlu 0:22bdcdc386df 27
thlu 0:22bdcdc386df 28 if (debug_on && (debug_sel == JS_NONE) && (joyb == JS_NONE)) {
thlu 0:22bdcdc386df 29 debug_sel_en = 1;
thlu 0:22bdcdc386df 30 }
thlu 0:22bdcdc386df 31
thlu 0:22bdcdc386df 32 switch(joyb) { // 1 = down, 2 = left, 4 = center, 8 = up, 16 = right
thlu 0:22bdcdc386df 33 case JS_LEFT:
thlu 0:22bdcdc386df 34 // 1 click = left button, 2 clicks = double click
thlu 0:22bdcdc386df 35 if ((prev_js != JS_LEFT) && (tm_joystick_running == JS_LEFT)) { // double click
thlu 0:22bdcdc386df 36 mouse_info.dc = 1;
thlu 0:22bdcdc386df 37 reset_tm_joystick_dc();
thlu 0:22bdcdc386df 38 } else if (!tm_joystick_running) {
thlu 0:22bdcdc386df 39 tm_joystick_running = JS_LEFT;
thlu 0:22bdcdc386df 40 tm_joystick_dc.start();
thlu 0:22bdcdc386df 41 }
thlu 0:22bdcdc386df 42 mouse_info.button = MOUSE_LEFT;
thlu 0:22bdcdc386df 43 break;
thlu 0:22bdcdc386df 44 case JS_CENTER: // center
thlu 0:22bdcdc386df 45 if ((prev_js != JS_CENTER) && (tm_joystick_running == JS_CENTER)) { // double click
thlu 0:22bdcdc386df 46 calib_on = 1;
thlu 0:22bdcdc386df 47 reset_tm_joystick_dc();
thlu 0:22bdcdc386df 48 } else if (!tm_joystick_running) {
thlu 0:22bdcdc386df 49 tm_joystick_running = JS_CENTER;
thlu 0:22bdcdc386df 50 tm_joystick_dc.start();
thlu 0:22bdcdc386df 51
thlu 0:22bdcdc386df 52 }
thlu 0:22bdcdc386df 53 mouse_info.button = MOUSE_MIDDLE;
thlu 0:22bdcdc386df 54 break;
thlu 0:22bdcdc386df 55 case JS_RIGHT:
thlu 0:22bdcdc386df 56 if ((prev_js != JS_RIGHT) && (tm_joystick_running == JS_RIGHT)) {
thlu 0:22bdcdc386df 57 debug_on = !debug_on;
thlu 0:22bdcdc386df 58 reset_tm_joystick_dc();
thlu 0:22bdcdc386df 59 lcd.cls();
thlu 0:22bdcdc386df 60 lcd.locate(0,0);
thlu 0:22bdcdc386df 61 if (debug_on) {
thlu 0:22bdcdc386df 62 lcd.printf("Debug print is ON\n");
thlu 0:22bdcdc386df 63 debug_sel = JS_NONE;
thlu 0:22bdcdc386df 64 debug_sel_en = 0;
thlu 0:22bdcdc386df 65 }
thlu 0:22bdcdc386df 66 } else if (!tm_joystick_running) {
thlu 0:22bdcdc386df 67 tm_joystick_running = JS_RIGHT;
thlu 0:22bdcdc386df 68 tm_joystick_dc.start();
thlu 0:22bdcdc386df 69 }
thlu 0:22bdcdc386df 70 mouse_info.button = MOUSE_RIGHT;
thlu 0:22bdcdc386df 71 break;
thlu 0:22bdcdc386df 72 case JS_DOWN: // down
thlu 0:22bdcdc386df 73 if (prev_js == JS_DOWN) {
thlu 0:22bdcdc386df 74 mouse_scroll++;
thlu 0:22bdcdc386df 75 } else {
thlu 0:22bdcdc386df 76 mouse_scroll = 1; // >0 means down
thlu 0:22bdcdc386df 77 }
thlu 0:22bdcdc386df 78 debug.printf("down scroll = %0d\r\n", mouse_info.scroll);
thlu 0:22bdcdc386df 79 reset_tm_joystick_dc();
thlu 0:22bdcdc386df 80 mouse_info.scroll = mouse_scroll;
thlu 0:22bdcdc386df 81
thlu 0:22bdcdc386df 82 break;
thlu 0:22bdcdc386df 83 case JS_UP: // up
thlu 0:22bdcdc386df 84 if (prev_js == JS_UP) {
thlu 0:22bdcdc386df 85 mouse_scroll--;
thlu 0:22bdcdc386df 86 } else {
thlu 0:22bdcdc386df 87 mouse_scroll = -1;
thlu 0:22bdcdc386df 88 }
thlu 0:22bdcdc386df 89 debug.printf("up scroll = %0d\r\n", mouse_info.scroll);
thlu 0:22bdcdc386df 90 reset_tm_joystick_dc();
thlu 0:22bdcdc386df 91 mouse_info.scroll = mouse_scroll;
thlu 0:22bdcdc386df 92 break;
thlu 0:22bdcdc386df 93 }
thlu 0:22bdcdc386df 94
thlu 0:22bdcdc386df 95
thlu 0:22bdcdc386df 96 if (tm_joystick_dc.read_ms() > 1000) { // timeout for double-click detection
thlu 0:22bdcdc386df 97 reset_tm_joystick_dc();
thlu 0:22bdcdc386df 98 }
thlu 0:22bdcdc386df 99
thlu 0:22bdcdc386df 100 prev_js = joyb;
thlu 0:22bdcdc386df 101 }
thlu 0:22bdcdc386df 102
thlu 0:22bdcdc386df 103
thlu 0:22bdcdc386df 104 void sample_mma() // Accelerometer value ranges from -1.5 to 1.5
thlu 0:22bdcdc386df 105 {
thlu 0:22bdcdc386df 106 mma_g.x = mma.x();
thlu 0:22bdcdc386df 107 mma_g.y = mma.y();
thlu 0:22bdcdc386df 108 mma_g.z = mma.z();
thlu 0:22bdcdc386df 109 G_int_t current;
thlu 0:22bdcdc386df 110
thlu 0:22bdcdc386df 111 if (mma_g.x > peaks.max_x) {
thlu 0:22bdcdc386df 112 peaks.max_x = mma_g.x;
thlu 0:22bdcdc386df 113 } else if (mma_g.x < peaks.min_x) {
thlu 0:22bdcdc386df 114 peaks.min_x = mma_g.x;
thlu 0:22bdcdc386df 115 }
thlu 0:22bdcdc386df 116 if (mma_g.y > peaks.max_y) {
thlu 0:22bdcdc386df 117 peaks.max_y = mma_g.y;
thlu 0:22bdcdc386df 118 } else if (mma_g.y < peaks.min_y) {
thlu 0:22bdcdc386df 119 peaks.min_y = mma_g.y;
thlu 0:22bdcdc386df 120 }
thlu 0:22bdcdc386df 121 if (mma_g.z > peaks.max_z) {
thlu 0:22bdcdc386df 122 peaks.max_z = mma_g.z;
thlu 0:22bdcdc386df 123 } else if (mma_g.z < peaks.min_z) {
thlu 0:22bdcdc386df 124 peaks.min_z = mma_g.z;
thlu 0:22bdcdc386df 125 }
thlu 0:22bdcdc386df 126
thlu 0:22bdcdc386df 127 current = conv_g2int(mma_g);
thlu 0:22bdcdc386df 128 if (calib_on) {
thlu 0:22bdcdc386df 129 calib_mma(current);
thlu 0:22bdcdc386df 130 }
thlu 0:22bdcdc386df 131 mouse_info.x = current.x - offset.x;
thlu 0:22bdcdc386df 132 mouse_info.y = current.y - offset.y;
thlu 0:22bdcdc386df 133 mouse_info.z = current.z - offset.z;
thlu 0:22bdcdc386df 134 detect_mma_rest();
thlu 0:22bdcdc386df 135 }
thlu 0:22bdcdc386df 136
thlu 0:22bdcdc386df 137 void drive_mouse()
thlu 0:22bdcdc386df 138 {
thlu 0:22bdcdc386df 139 // x-direction is reversed on PC screen
thlu 0:22bdcdc386df 140 mouse.move(-mouse_info.x, mouse_info.y);
thlu 0:22bdcdc386df 141 mouse.press(mouse_info.button);
thlu 0:22bdcdc386df 142 mouse.scroll(mouse_info.scroll);
thlu 0:22bdcdc386df 143 if (mouse_info.dc) {
thlu 0:22bdcdc386df 144 mouse.doubleClick();
thlu 0:22bdcdc386df 145 }
thlu 0:22bdcdc386df 146 }
thlu 0:22bdcdc386df 147
thlu 0:22bdcdc386df 148 // Used for debugging
thlu 0:22bdcdc386df 149 void print_debug_msg()
thlu 0:22bdcdc386df 150 {
thlu 0:22bdcdc386df 151 if (debug_on) {
thlu 0:22bdcdc386df 152 switch (debug_sel) {
thlu 0:22bdcdc386df 153 case JS_LEFT:
thlu 0:22bdcdc386df 154 debug.printf("Mx = %1.2f, mx = %1.2f ", peaks.max_x, peaks.min_x);
thlu 0:22bdcdc386df 155 debug.printf("My = %1.2f, my = %1.2f ", peaks.max_y, peaks.min_y);
thlu 0:22bdcdc386df 156 debug.printf("Mz = %1.2f, mz = %1.2f\r\n", peaks.max_z, peaks.min_z);
thlu 0:22bdcdc386df 157 break;
thlu 0:22bdcdc386df 158 case JS_CENTER:
thlu 0:22bdcdc386df 159 debug.printf("x=%1.2f y=%1.2f z=%1.2f\r\n", mma_g.x, mma_g.y, mma_g.z);
thlu 0:22bdcdc386df 160 debug.printf("x=%0d, y=%0d, z=%0d, button=%0d, scroll=%0d, dc=%0d\r\n\n",
thlu 0:22bdcdc386df 161 mouse_info.x, mouse_info.y, mouse_info.z, mouse_info.button,
thlu 0:22bdcdc386df 162 mouse_info.scroll, mouse_info.dc);
thlu 0:22bdcdc386df 163 break;
thlu 0:22bdcdc386df 164 case JS_RIGHT:
thlu 0:22bdcdc386df 165 debug.printf("offset.x=%0d, y=%0d, z=%0d\r\n", offset.x, offset.y, offset.z);
thlu 0:22bdcdc386df 166 break;
thlu 0:22bdcdc386df 167 }
thlu 0:22bdcdc386df 168 }
thlu 0:22bdcdc386df 169 }
thlu 0:22bdcdc386df 170
thlu 0:22bdcdc386df 171 // calibrate the accelerometer for leveling
thlu 0:22bdcdc386df 172 void calib_mma(const G_int_t current)
thlu 0:22bdcdc386df 173 {
thlu 0:22bdcdc386df 174 static uint8_t ctr = 0;
thlu 0:22bdcdc386df 175 static G_int_t prev[CALIB_SMPLS]; // average array
thlu 0:22bdcdc386df 176
thlu 0:22bdcdc386df 177 int temp;
thlu 0:22bdcdc386df 178
thlu 0:22bdcdc386df 179 if (ctr == 0) {
thlu 0:22bdcdc386df 180 lcd.cls();
thlu 0:22bdcdc386df 181 lcd.locate(0,0);
thlu 0:22bdcdc386df 182 lcd.printf("Calibrating mma");
thlu 0:22bdcdc386df 183 wait(3);
thlu 0:22bdcdc386df 184 } else {
thlu 0:22bdcdc386df 185 lcd.printf(".");
thlu 0:22bdcdc386df 186 }
thlu 0:22bdcdc386df 187 prev[ctr++] = current;
thlu 0:22bdcdc386df 188
thlu 0:22bdcdc386df 189 if (ctr == CALIB_SMPLS) {
thlu 0:22bdcdc386df 190 temp = 0;
thlu 0:22bdcdc386df 191 for (uint8_t i=0; i<CALIB_SMPLS; i++) {
thlu 0:22bdcdc386df 192 debug.printf("CALIB[%0d]: x=%0d, y=%0d, z=%0d\r\n", i, prev[i].x, prev[i].y, prev[i].z);
thlu 0:22bdcdc386df 193 temp += prev[i].x;
thlu 0:22bdcdc386df 194 }
thlu 0:22bdcdc386df 195 offset.x = temp/CALIB_SMPLS; // average
thlu 0:22bdcdc386df 196
thlu 0:22bdcdc386df 197 temp = 0;
thlu 0:22bdcdc386df 198 for (uint8_t i=0; i<CALIB_SMPLS; i++) {
thlu 0:22bdcdc386df 199 temp += prev[i].y;
thlu 0:22bdcdc386df 200 }
thlu 0:22bdcdc386df 201 offset.y = temp/CALIB_SMPLS;
thlu 0:22bdcdc386df 202
thlu 0:22bdcdc386df 203 temp = 0;
thlu 0:22bdcdc386df 204 for (uint8_t i=0; i<CALIB_SMPLS; i++) {
thlu 0:22bdcdc386df 205 temp += prev[i].z;
thlu 0:22bdcdc386df 206 }
thlu 0:22bdcdc386df 207 offset.z = temp/CALIB_SMPLS;
thlu 0:22bdcdc386df 208
thlu 0:22bdcdc386df 209 ctr = 0;
thlu 0:22bdcdc386df 210 calib_on = 0; // calibration done
thlu 0:22bdcdc386df 211 lcd.cls();
thlu 0:22bdcdc386df 212 lcd.locate(0,0);
thlu 0:22bdcdc386df 213 lcd.printf("Calibration Completed!\n");
thlu 0:22bdcdc386df 214 wait(1);
thlu 0:22bdcdc386df 215 }
thlu 0:22bdcdc386df 216 }
thlu 0:22bdcdc386df 217
thlu 0:22bdcdc386df 218 void detect_mma_rest ()
thlu 0:22bdcdc386df 219 {
thlu 0:22bdcdc386df 220 if ((abs(mouse_info.z) <= 0.06*SCALE_Z) &&
thlu 0:22bdcdc386df 221 (abs(mouse_info.x) <= 0.10*SCALE_X) &&
thlu 0:22bdcdc386df 222 (abs(mouse_info.y) <= 0.10*SCALE_Y)) {
thlu 0:22bdcdc386df 223 mouse_info.x = 0;
thlu 0:22bdcdc386df 224 mouse_info.y = 0;
thlu 0:22bdcdc386df 225 }
thlu 0:22bdcdc386df 226 }
thlu 0:22bdcdc386df 227
thlu 0:22bdcdc386df 228 // convert mma signed g float value into signed int value
thlu 0:22bdcdc386df 229 G_int_t conv_g2int (G_float_t mma_g)
thlu 0:22bdcdc386df 230 {
thlu 0:22bdcdc386df 231 G_int_t temp;
thlu 0:22bdcdc386df 232
thlu 0:22bdcdc386df 233 temp.x = (mma_g.x * SCALE_X);
thlu 0:22bdcdc386df 234 temp.y = (mma_g.y * SCALE_Y);
thlu 0:22bdcdc386df 235 temp.z = (mma_g.z * SCALE_Z);
thlu 0:22bdcdc386df 236 return temp;
thlu 0:22bdcdc386df 237 }
thlu 0:22bdcdc386df 238
thlu 0:22bdcdc386df 239 //
thlu 0:22bdcdc386df 240 void flash_led_alive()
thlu 0:22bdcdc386df 241 {
thlu 0:22bdcdc386df 242 static bool led_state = 0;
thlu 0:22bdcdc386df 243 led_alive = led_state;
thlu 0:22bdcdc386df 244 led_state = !led_state;
thlu 0:22bdcdc386df 245
thlu 0:22bdcdc386df 246 }
thlu 0:22bdcdc386df 247
thlu 0:22bdcdc386df 248 int8_t init_accelestick()
thlu 0:22bdcdc386df 249 {
thlu 0:22bdcdc386df 250 lcd.cls();
thlu 0:22bdcdc386df 251 reset_tm_joystick_dc();
thlu 0:22bdcdc386df 252
thlu 0:22bdcdc386df 253 offset.x = 0;
thlu 0:22bdcdc386df 254 offset.y = 0;
thlu 0:22bdcdc386df 255 offset.z = 1.0*SCALE_Z;
thlu 0:22bdcdc386df 256
thlu 0:22bdcdc386df 257 peaks.max_x=ACCEL_MIN, peaks.max_y=ACCEL_MIN, peaks.max_z=ACCEL_MIN;
thlu 0:22bdcdc386df 258 peaks.min_x=ACCEL_MAX, peaks.min_y=ACCEL_MAX, peaks.min_z=ACCEL_MAX;
thlu 0:22bdcdc386df 259
thlu 0:22bdcdc386df 260 if (!mma.testConnection()) {
thlu 0:22bdcdc386df 261 lcd.printf("Error in MMA init\n");
thlu 0:22bdcdc386df 262 return -1;
thlu 0:22bdcdc386df 263 }
thlu 0:22bdcdc386df 264 tk_led_alive.attach(&flash_led_alive, 1.0);
thlu 0:22bdcdc386df 265 tk_print_debug.attach(&print_debug_msg, 1.0);
thlu 0:22bdcdc386df 266 return 0;
thlu 0:22bdcdc386df 267
thlu 0:22bdcdc386df 268 }
thlu 0:22bdcdc386df 269
thlu 0:22bdcdc386df 270 int8_t run_accelestick()
thlu 0:22bdcdc386df 271 {
thlu 0:22bdcdc386df 272 int8_t status;
thlu 0:22bdcdc386df 273
thlu 0:22bdcdc386df 274 status = init_accelestick();
thlu 0:22bdcdc386df 275
thlu 0:22bdcdc386df 276 if (status != 0) {
thlu 0:22bdcdc386df 277 return -1;
thlu 0:22bdcdc386df 278 }
thlu 0:22bdcdc386df 279
thlu 0:22bdcdc386df 280 while(1) {
thlu 0:22bdcdc386df 281 get_joystick_input();
thlu 0:22bdcdc386df 282 sample_mma();
thlu 0:22bdcdc386df 283 drive_mouse();
thlu 0:22bdcdc386df 284 }
thlu 0:22bdcdc386df 285
thlu 0:22bdcdc386df 286 }
thlu 0:22bdcdc386df 287
thlu 0:22bdcdc386df 288 int main()
thlu 0:22bdcdc386df 289 {
thlu 0:22bdcdc386df 290 run_accelestick();
thlu 0:22bdcdc386df 291 }