Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed MPU6050_template ledControl2 USBDevice
Revision 13:e9fe7586ab0c, committed 2020-11-30
- Comitter:
- mposter
- Date:
- Mon Nov 30 16:39:57 2020 +0000
- Parent:
- 12:8422738bdd21
- Commit message:
- final
Changed in this revision
--- a/MPU6050_template.lib Sun Nov 29 03:38:43 2020 +0000 +++ b/MPU6050_template.lib Mon Nov 30 16:39:57 2020 +0000 @@ -1,1 +1,1 @@ -https://os.mbed.com/users/mposter/code/MPU6050_template/#0751a6497c6a +https://os.mbed.com/users/mposter/code/MPU6050_template/#f91e6ad66cf8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBDevice.lib Mon Nov 30 16:39:57 2020 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/USBDevice/#53949e6131f6
--- a/main.cpp Sun Nov 29 03:38:43 2020 +0000
+++ b/main.cpp Mon Nov 30 16:39:57 2020 +0000
@@ -56,7 +56,17 @@
#include "mbed.h"
#include "MPU6050.h"
#include "ledControl.h"
+#include "USBMouse.h"
+#include <deque> // std::queue
+#include <math.h>
+
+#define QUEUE_LENGTH 5
+#define SCREEN_DISTANCE 0.5
+#define RESOLUTION 100
+#define ACCEL_RESOLUTION 500
+#define SCROLLUP_LENGTH 5
+#define SCROLLDOWN_LENGTH 5
//! Variable debug
#define DEBUG
/* */
@@ -65,7 +75,7 @@
//I2C i2c(p9,p10); // setup i2c (SDA,SCL)
//! Instance pc de classe Serial
-Serial pc(USBTX,USBRX); // default baud rate: 9600
+//Serial pc(USBTX,USBRX); // default baud rate: 9600
//! Instance mpu6050 de classe MPU6050
MPU6050 mpu6050; // class: MPU6050, object: mpu6050
//! instance toggler1 de classe Ticker
@@ -76,6 +86,9 @@
Ticker toggler1;
Ticker filter;
+//USBMouse objcet
+USBMouse mouse;
+
void toggle_led1();
void toggle_led2();
void compFilter();
@@ -83,49 +96,402 @@
float pitchAngle = 0;
float rollAngle = 0;
+//My funcs
+void calibrateGyro();
+void calibrateAccel();
+float sampleQueue(deque<float> q,float bias);
+void clearDeques();
+void updateDeques();
+int16_t processGX();
+int16_t processGZ();
+void processGyro();
+int16_t processAX();
+int16_t processAZ();
+void processAccel();
+void processMovement();
+void checkClicks();
+//end my funcs
+
+//Create queue to insert gyroReadings into
+deque<float> gyroReadingsx;
+deque<float> gyroReadingsz;
+
+//Create queue to insert accelReadings into
+deque<float> accelReadingsx;
+deque<float> accelReadingsz;
+
+//Predefined gyro bias. Subtract these from queue averages to get movement weight
+float gyroBiasx = 0;
+float gyroBiasz = 0;
+
+//Predefined accel bias. Subtract these from queue averages to get movement weight
+float accelBiasx = 0;
+float accelBiasz = 0;
+
+//Clicking pins
+DigitalIn leftClick(p16);
+DigitalIn rightClick(p15);
+
+//Scroll pins
+DigitalIn upScroll(p18);
+DigitalIn downScroll(p19);
+
+//Pause pin
+DigitalIn pause(p20);
+
int main()
{
- pc.baud(9600); // baud rate: 9600
+ //Imported
+ ////pc.baud(9600); // baud rate: 9600
mpu6050.whoAmI(); // Communication test: WHO_AM_I register reading
wait(1);
mpu6050.calibrate(accelBias,gyroBias); // Calibrate MPU6050 and load biases into bias registers
- pc.printf("Calibration is completed. \r\n");
+ ////////pc.printf("Calibration is completed. \r\n");
wait(0.5);
mpu6050.init(); // Initialize the sensor
wait(1);
- pc.printf("MPU6050 is initialized for operation.. \r\n\r\n");
+ ////////pc.printf("MPU6050 is initialized for operation.. \r\n\r\n");
wait_ms(500);
+ //End imported
+
+ //Perform our own sampling calibration
+ for(int i = 0; i < QUEUE_LENGTH; i++){
+ filter.attach(&compFilter, 0.005);
+ updateDeques();
+ }
+ calibrateGyro();
+ calibrateAccel();
+
+ ////////pc.printf("Bias x: %.3f | Bias z: %.3f\r\n",gyroBiasx,gyroBiasz);
+
+ //wait(2.5);
while(1)
{
-
- /* Uncomment below if you want to see accel and gyro data */
+
+
- pc.printf(" _____________________________________________________________ \r\n");
- pc.printf("| Accelerometer(g) | ax=%.3f | ay=%.3f | az=%.3f \r\n",ax,ay,az);
- pc.printf("| Gyroscope(deg/s) | gx=%.3f | gy=%.3f | gz=%.3f \r\n",gx,gy,gz);
- pc.printf("|_____________________________________________________________ \r\n\r\n");
-//
- wait(2.5);
-
- //filter.attach(&compFilter, 0.005); // Call the complementaryFilter func. every 5 ms (200 Hz sampling period)
+ //////////pc.printf(" _____________________________________________________________ \r\n");
+ //////////pc.printf("| Accelerometer(g) | ax=%.3f | ay=%.3f | az=%.3f \r\n",ax,ay,az);
+ printf("| Gyroscope(deg/s) | gx=%.3f | gy=%.3f | gz=%.3f \r\n",gx,gy,gz);
+ //////////pc.printf("|_____________________________________________________________ \r\n\r\n");
+//
+ //X AXIS GYRO
+ //////pc.printf("x axis (gyro): ");
+ //for(int i = 0; i < QUEUE_LENGTH; i++){
+ //////////pc.printf("%.3f ",gyroReadingsx[i]);
+ //}
+ //////pc.printf("\r\n");
- #ifdef DEBUG
- pc.printf(" [Debug On] \r\n");
- mpu6050.complementaryFilter(&pitchAngle, &rollAngle);
- #endif
- pc.printf(" _______________\r\n");
- pc.printf("| Pitch: %.3f \r\n",pitchAngle);
- pc.printf("| Roll: %.3f \r\n",rollAngle);
- pc.printf("|_______________\r\n\r\n");
+ //Z AXIS GYRO
+ //////pc.printf("z axis (gyro): ");
+ //for(int i = 0; i < QUEUE_LENGTH; i++){
+ //////////pc.printf("%.3f ",gyroReadingsz[i]);
+ //}
+ //////pc.printf("\r\n");
+ //wait(2.5);
+
+
+ filter.attach(&compFilter, 0.005); // Call the complementaryFilter func. every 5 ms (200 Hz sampling period)
- wait(1);
-
+ //#ifdef DEBUG
+ //////////pc.printf(" [Debug On] \r\n");
+ //mpu6050.complementaryFilter(&pitchAngle, &rollAngle);
+ //#endif
+ //////////pc.printf(" _______________\r\n");
+ //////////pc.printf("| Pitch: %.3f \r\n",pitchAngle);
+ //////////pc.printf("| Roll: %.3f \r\n",rollAngle);
+ //////////pc.printf("|_______________\r\n\r\n");
+
+ //wait(1);
+ updateDeques();
+ processMovement();
+ checkClicks();
+
+ //wait(2.5);
}
}
+//Function to check and process button clicks for left and right mouse buttons
+void checkClicks(){
+
+ //Imported
+ static bool preRightClick = false;
+
+ if (leftClick)
+ {
+ mouse.press(MOUSE_LEFT);
+ }
+ else
+ {
+ mouse.release(MOUSE_LEFT);
+ }
+
+ // Right Mouse Click ___ Falling Edge Detection
+ if (rightClick && !preRightClick)
+ {
+ preRightClick = true;
+ }
+ else if (!rightClick && preRightClick)
+ { preRightClick = false;
+ mouse.click(MOUSE_RIGHT);
+ }
+ //End imported
+
+ //Listen for scroll up button
+ if(upScroll){
+ for(int i = 0; i < SCROLLUP_LENGTH; i++){
+ mouse.scroll(-1);
+ }
+ mouse.release(MOUSE_MIDDLE);
+ }
+
+ //Listen for scroll down button
+ if(downScroll){
+ for(int i = 0; i < SCROLLDOWN_LENGTH; i++){
+ mouse.scroll(1);
+ }
+ mouse.release(MOUSE_MIDDLE);
+ }
+
+ //Loop while pause button is pressed
+ while(pause);
+}
+
+//Only care about x and z axis
+ // -z -> Right side of screen; +z -> Left side of screen
+ // -x - > Bottom of screen; +x -> Top of screen
+
+int16_t processGX(){
+
+ //Obtain sample from deque
+ float sample = sampleQueue(gyroReadingsx,gyroBiasx);
+
+ //Convert to radians
+ float sampleRadians = sample*PI/180.0;
+
+ float deltaX = SCREEN_DISTANCE*RESOLUTION*tan(sampleRadians);
+
+ int16_t sending = 0 + deltaX;
+
+ printf("x axis MOVING: %.3f, sending: %i\r\n",deltaX,sending);
+
+ //Do tangent calculation to obtain opposite length
+ //x = L*tan(theta)
+ //mouse.move(0,sending*-1);
+
+ return -1*sending;
+}
+
+int16_t processGZ(){
+
+ //Obtain sample from deque
+ float sample = sampleQueue(gyroReadingsz,gyroBiasz);
+
+ //////////////pc.printf("sample y: %.3f \r\n", sample);
+
+ //Convert to radians
+ float sampleRadians = sample*PI/180.0;
+
+ //////pc.printf("sample (Radians) y: %.3f \r\n", sampleRadians);
+
+ float deltaZ = SCREEN_DISTANCE*RESOLUTION*tan(sampleRadians);
+
+ //Apply multipliers to enable mouse acceleration
+ if(deltaZ > 0){
+ deltaZ*=1.75;
+ }else{
+ deltaZ*=1.5;
+ }
+
+ //////pc.printf("without cast: %.3f",SCREEN_DISTANCE*RESOLUTION*tan(sampleRadians));
+
+ int16_t sending = 0 + deltaZ;
+
+ printf("z axis MOVING: %.3f, sending: %i\r\n",deltaZ,sending);
+
+ //Do tangent calculation to obtain opposite length
+ //x = L*tan(theta)
+ //mouse.move(sending*-1,0);
+ return -1*sending;
+}
+
+int16_t processAX(){
+
+ //Obtain sample from deque
+ float sample = sampleQueue(accelReadingsx,accelBiasx);
+
+ int16_t sending = 0 + sample*ACCEL_RESOLUTION;
+
+ printf("ax axis MOVING: %.3f, sending: %i\r\n",sample,sending);
+
+ //Do tangent calculation to obtain opposite length
+ ////x = L*tan(theta)
+ //mouse.move(0,sending*-1);
+ return -1*sending;
+}
+
+int16_t processAZ(){
+
+ //Obtain sample from deque
+ float sample = sampleQueue(accelReadingsz,accelBiasz);
+
+ //////////////pc.printf("sample y: %.3f \r\n", sample);
+
+ //////pc.printf("without cast: %.3f",SCREEN_DISTANCE*RESOLUTION*tan(sampleRadians));
+
+ int16_t sending = 0 + sample*ACCEL_RESOLUTION;
+
+ printf("az axis MOVING: %.3f, sending: %i\r\n",sample,sending);
+
+ //Do tangent calculation to obtain opposite length
+ //x = L*tan(theta)
+ //mouse.move(sending*-1,0);
+ return -1*sending;
+}
+
+void processGyro(){
+ int16_t y = processGX();
+ int16_t x = processGZ();
+ mouse.move(x,y);
+}
+
+void processAccel(){
+ int16_t y = processAX();
+ int16_t x = processAZ();
+ mouse.move(x,y);
+}
+
+void processMovement(){
+ processGyro();
+ //processAccel();
+}
+
+void updateDeques(){
+
+ //Update gyro deques
+ gyroReadingsx.pop_back();
+ gyroReadingsz.pop_back();
+ gyroReadingsx.push_front(gx);
+ gyroReadingsz.push_front(gz);
+
+ //Update accel deques
+ accelReadingsx.pop_back();
+ accelReadingsz.pop_back();
+ accelReadingsx.push_front(ax);
+ accelReadingsz.push_front(az);
+}
+
+void clearDeques(){
+
+ //Check for bad queue size
+ if(gyroReadingsx.size() < QUEUE_LENGTH || gyroReadingsz.size() < QUEUE_LENGTH || accelReadingsx.size() < QUEUE_LENGTH || accelReadingsz.size() < QUEUE_LENGTH){
+ while(1) printf("Bad queue size. Hanging...\n");
+ }
+
+ //Clear gyro deques
+ for(int i = 0; i < QUEUE_LENGTH; i++){
+ gyroReadingsx.pop_back();
+ gyroReadingsz.pop_back();
+ }
+
+ //Clear accel deques
+ for(int i = 0; i < QUEUE_LENGTH; i++){
+ accelReadingsx.pop_back();
+ accelReadingsz.pop_back();
+ }
+}
+
+void calibrateGyro(){
+ //Only care about x and z axis
+ // -z -> Right side of screen; +z -> Left side of screen
+ // -x - > Bottom of screen; +x -> Top of screen
+
+ float xSum = 0;
+ float zSum = 0;
+
+ //Iterate for QUEUE_LENGTH samples from gyroscope
+ for(int i = 0; i < QUEUE_LENGTH; i++){
+
+ float xReading = gx;
+ float zReading = gz;
+
+ printf("CALIB GX,GZ: %.3f %.3f \r\n", gx,gz);
+
+ //Apply filter to incoming readings
+ filter.attach(&compFilter, 0.005);
+
+ //push gyro x and z readings onto deque
+ gyroReadingsx.push_front(xReading);
+ gyroReadingsz.push_front(zReading);
+
+ //add samples to sum totals
+ xSum += xReading;
+ zSum += zReading;
+
+ }
+
+ //Set sampled bias for each gyro axis
+ gyroBiasx = xSum/QUEUE_LENGTH;
+ gyroBiasz = zSum/QUEUE_LENGTH;
+
+}
+
+void calibrateAccel(){
+ //Only care about x and z axis
+ // -z -> Right side of screen; +z -> Left side of screen
+ // -x - > Bottom of screen; +x -> Top of screen
+
+ float xSum = 0;
+ float zSum = 0;
+
+ //Iterate for QUEUE_LENGTH samples from gyroscope
+ for(int i = 0; i < QUEUE_LENGTH; i++){
+
+ float xReading = ax;
+ float zReading = az;
+
+ printf("CALIB AX,AZ: %.3f %.3f \r\n", ax,az);
+
+ //Apply filter to incoming readings
+ filter.attach(&compFilter, 0.005);
+
+ //push gyro x and z readings onto deque
+ accelReadingsx.push_front(xReading);
+ accelReadingsz.push_front(zReading);
+
+ //add samples to sum totals
+ xSum += xReading;
+ zSum += zReading;
+
+ }
+
+ //Set sampled bias for each gyro axis
+ accelBiasx = xSum/QUEUE_LENGTH;
+ accelBiasz = zSum/QUEUE_LENGTH;
+
+}
+
+//Calculate average of samples in a deque
+float calculateAverage(deque<float> q){
+ float sum = 0;
+ for(int i = 0; i < q.size(); i++){
+ sum+=q[i];
+ }
+ return sum/q.size();
+}
+
+//Subtract the bias from the average of samples in a deque to offset idle values
+float sampleQueue(deque<float> q,float bias){
+
+ //Alternatively, may want to calculate the average and subtract next incoming reading by avg
+ return calculateAverage(q) - bias;
+}
+
+//Imported
void toggle_led1() {ledToggle(1);}
void toggle_led2() {ledToggle(2);}
/* This function is created to avoid address error that caused from Ticker.attach func */
void compFilter() {mpu6050.complementaryFilter(&pitchAngle, &rollAngle);}
+//End imported
\ No newline at end of file