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
accelestick.cpp
- Committer:
- thlu
- Date:
- 2014-03-15
- Revision:
- 0:22bdcdc386df
- Child:
- 1:03d0f8a4a2d7
File content as of revision 0:22bdcdc386df:
#include "accelestick.h" inline void reset_tm_joystick_dc() { tm_joystick_running = 0; tm_joystick_dc.stop(); tm_joystick_dc.reset(); } // This function checks for joystick button presses which emulate a mouse's // left button, right button, middle button, double click, and scroll // features. Double click requires a timer void get_joystick_input() { static uint8_t prev_js = 0; static bool debug_sel_en = 0; static int mouse_scroll = 0; mouse_info.button = 0; mouse_info.scroll = 0; mouse_info.dc = 0; if (debug_on && debug_sel_en && (joyb != JS_NONE)) { debug_sel_en = 0; debug_sel = joyb; } if (debug_on && (debug_sel == JS_NONE) && (joyb == JS_NONE)) { debug_sel_en = 1; } switch(joyb) { // 1 = down, 2 = left, 4 = center, 8 = up, 16 = right case JS_LEFT: // 1 click = left button, 2 clicks = double click if ((prev_js != JS_LEFT) && (tm_joystick_running == JS_LEFT)) { // double click mouse_info.dc = 1; reset_tm_joystick_dc(); } else if (!tm_joystick_running) { tm_joystick_running = JS_LEFT; tm_joystick_dc.start(); } mouse_info.button = MOUSE_LEFT; break; case JS_CENTER: // center if ((prev_js != JS_CENTER) && (tm_joystick_running == JS_CENTER)) { // double click calib_on = 1; reset_tm_joystick_dc(); } else if (!tm_joystick_running) { tm_joystick_running = JS_CENTER; tm_joystick_dc.start(); } mouse_info.button = MOUSE_MIDDLE; break; case JS_RIGHT: if ((prev_js != JS_RIGHT) && (tm_joystick_running == JS_RIGHT)) { debug_on = !debug_on; reset_tm_joystick_dc(); lcd.cls(); lcd.locate(0,0); if (debug_on) { lcd.printf("Debug print is ON\n"); debug_sel = JS_NONE; debug_sel_en = 0; } } else if (!tm_joystick_running) { tm_joystick_running = JS_RIGHT; tm_joystick_dc.start(); } mouse_info.button = MOUSE_RIGHT; break; case JS_DOWN: // down if (prev_js == JS_DOWN) { mouse_scroll++; } else { mouse_scroll = 1; // >0 means down } debug.printf("down scroll = %0d\r\n", mouse_info.scroll); reset_tm_joystick_dc(); mouse_info.scroll = mouse_scroll; break; case JS_UP: // up if (prev_js == JS_UP) { mouse_scroll--; } else { mouse_scroll = -1; } debug.printf("up scroll = %0d\r\n", mouse_info.scroll); reset_tm_joystick_dc(); mouse_info.scroll = mouse_scroll; break; } if (tm_joystick_dc.read_ms() > 1000) { // timeout for double-click detection reset_tm_joystick_dc(); } prev_js = joyb; } void sample_mma() // Accelerometer value ranges from -1.5 to 1.5 { mma_g.x = mma.x(); mma_g.y = mma.y(); mma_g.z = mma.z(); G_int_t current; if (mma_g.x > peaks.max_x) { peaks.max_x = mma_g.x; } else if (mma_g.x < peaks.min_x) { peaks.min_x = mma_g.x; } if (mma_g.y > peaks.max_y) { peaks.max_y = mma_g.y; } else if (mma_g.y < peaks.min_y) { peaks.min_y = mma_g.y; } if (mma_g.z > peaks.max_z) { peaks.max_z = mma_g.z; } else if (mma_g.z < peaks.min_z) { peaks.min_z = mma_g.z; } current = conv_g2int(mma_g); if (calib_on) { calib_mma(current); } mouse_info.x = current.x - offset.x; mouse_info.y = current.y - offset.y; mouse_info.z = current.z - offset.z; detect_mma_rest(); } void drive_mouse() { // x-direction is reversed on PC screen mouse.move(-mouse_info.x, mouse_info.y); mouse.press(mouse_info.button); mouse.scroll(mouse_info.scroll); if (mouse_info.dc) { mouse.doubleClick(); } } // Used for debugging void print_debug_msg() { if (debug_on) { switch (debug_sel) { case JS_LEFT: debug.printf("Mx = %1.2f, mx = %1.2f ", peaks.max_x, peaks.min_x); debug.printf("My = %1.2f, my = %1.2f ", peaks.max_y, peaks.min_y); debug.printf("Mz = %1.2f, mz = %1.2f\r\n", peaks.max_z, peaks.min_z); break; case JS_CENTER: debug.printf("x=%1.2f y=%1.2f z=%1.2f\r\n", mma_g.x, mma_g.y, mma_g.z); debug.printf("x=%0d, y=%0d, z=%0d, button=%0d, scroll=%0d, dc=%0d\r\n\n", mouse_info.x, mouse_info.y, mouse_info.z, mouse_info.button, mouse_info.scroll, mouse_info.dc); break; case JS_RIGHT: debug.printf("offset.x=%0d, y=%0d, z=%0d\r\n", offset.x, offset.y, offset.z); break; } } } // calibrate the accelerometer for leveling void calib_mma(const G_int_t current) { static uint8_t ctr = 0; static G_int_t prev[CALIB_SMPLS]; // average array int temp; if (ctr == 0) { lcd.cls(); lcd.locate(0,0); lcd.printf("Calibrating mma"); wait(3); } else { lcd.printf("."); } prev[ctr++] = current; if (ctr == CALIB_SMPLS) { temp = 0; for (uint8_t i=0; i<CALIB_SMPLS; i++) { debug.printf("CALIB[%0d]: x=%0d, y=%0d, z=%0d\r\n", i, prev[i].x, prev[i].y, prev[i].z); temp += prev[i].x; } offset.x = temp/CALIB_SMPLS; // average temp = 0; for (uint8_t i=0; i<CALIB_SMPLS; i++) { temp += prev[i].y; } offset.y = temp/CALIB_SMPLS; temp = 0; for (uint8_t i=0; i<CALIB_SMPLS; i++) { temp += prev[i].z; } offset.z = temp/CALIB_SMPLS; ctr = 0; calib_on = 0; // calibration done lcd.cls(); lcd.locate(0,0); lcd.printf("Calibration Completed!\n"); wait(1); } } void detect_mma_rest () { if ((abs(mouse_info.z) <= 0.06*SCALE_Z) && (abs(mouse_info.x) <= 0.10*SCALE_X) && (abs(mouse_info.y) <= 0.10*SCALE_Y)) { mouse_info.x = 0; mouse_info.y = 0; } } // convert mma signed g float value into signed int value G_int_t conv_g2int (G_float_t mma_g) { G_int_t temp; temp.x = (mma_g.x * SCALE_X); temp.y = (mma_g.y * SCALE_Y); temp.z = (mma_g.z * SCALE_Z); return temp; } // void flash_led_alive() { static bool led_state = 0; led_alive = led_state; led_state = !led_state; } int8_t init_accelestick() { lcd.cls(); reset_tm_joystick_dc(); offset.x = 0; offset.y = 0; offset.z = 1.0*SCALE_Z; peaks.max_x=ACCEL_MIN, peaks.max_y=ACCEL_MIN, peaks.max_z=ACCEL_MIN; peaks.min_x=ACCEL_MAX, peaks.min_y=ACCEL_MAX, peaks.min_z=ACCEL_MAX; if (!mma.testConnection()) { lcd.printf("Error in MMA init\n"); return -1; } tk_led_alive.attach(&flash_led_alive, 1.0); tk_print_debug.attach(&print_debug_msg, 1.0); return 0; } int8_t run_accelestick() { int8_t status; status = init_accelestick(); if (status != 0) { return -1; } while(1) { get_joystick_input(); sample_mma(); drive_mouse(); } } int main() { run_accelestick(); }