Renamed to program to Doom_Controller.

Dependencies:   DebounceIn USBDevice mbed

Fork of BNO055_reader by Ben, Simon, Inez IDD

Revision:
1:38cd433ff221
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main_old.txt	Sun Sep 20 00:58:37 2015 +0000
@@ -0,0 +1,488 @@
+#include "mbed.h"
+#include "USBMouseKeyboard.h"
+#include "DebounceIn.h"
+
+//LEDs to indicate clibration status
+DigitalOut redLED(LED_RED);
+DigitalOut greenLED(LED_GREEN);
+
+//pushbuttons inputs
+DebounceIn trigger(D3);
+DebounceIn move(D4);
+DebounceIn door(D5);
+DebounceIn centerBut(D12);
+
+// Motor output
+DigitalOut vibrate(D2);
+Timeout vibrateTimeout;
+ 
+//USBMouseKeyboard
+//do we need absolute or relative mouse?
+USBMouseKeyboard key_mouse(ABS_MOUSE);
+HID_REPORT kbHIDReport;;
+
+Serial pc(USBTX,USBRX);
+I2C i2c(D7, D6);
+
+const int bno055_addr = 0x28 << 1;
+
+const int BNO055_ID_ADDR                                          = 0x00;
+const int BNO055_EULER_H_LSB_ADDR                                 = 0x1A;
+const int BNO055_GRAVITY_DATA_X_LSB_ADDR                          = 0x2E;
+const int BNO055_TEMP_ADDR                                        = 0x34;
+const int BNO055_OPR_MODE_ADDR                                    = 0x3D;
+const int BNO055_CALIB_STAT_ADDR                                  = 0x35;
+const int BNO055_SYS_STAT_ADDR                                    = 0x39;
+const int BNO055_SYS_ERR_ADDR                                     = 0x3A;
+const int BNO055_AXIS_MAP_CONFIG_ADDR                             = 0x41;
+const int BNO055_SYS_TRIGGER_ADDR                                 = 0x3F;
+const int BNO055_ACC_DATA_X_ADDR                                  = 0x08;
+
+typedef struct CalibStatus_t
+{
+    int mag;
+    int acc;
+    int gyr;
+    int sys;
+} CalibStatus;
+
+typedef struct Euler_t
+{
+    float heading;
+    float pitch;
+    float roll;
+} Euler;
+
+// The "zero" offset positions
+short int headingOffset;
+short int pitchOffset;
+short int rollOffset;
+
+
+/**
+ * Function to write to a single 8-bit register
+ */
+void writeReg(int regAddr, char value)
+{
+    char wbuf[2];
+    wbuf[0] = regAddr;
+    wbuf[1] = value;
+    i2c.write(bno055_addr, wbuf, 2, false);  
+}
+
+/**
+ * Function to read from a single 8-bit register
+ */
+char readReg(int regAddr)
+{
+    char rwbuf = regAddr;
+    i2c.write(bno055_addr, &rwbuf, 1, false);
+    i2c.read(bno055_addr, &rwbuf, 1, false);
+    return rwbuf;
+}
+
+/**
+ * Returns the calibration status of each component
+ */
+CalibStatus readCalibrationStatus()
+{
+    CalibStatus status;
+    int regVal = readReg(BNO055_CALIB_STAT_ADDR);
+        
+    status.mag = regVal & 0x03;
+    status.acc = (regVal >> 2) & 0x03;
+    status.gyr = (regVal >> 4) & 0x03;
+    status.sys = (regVal >> 6) & 0x03;
+    
+    return status;
+}
+
+
+/**
+ * Returns true if all the devices are calibrated
+ */
+bool calibrated()
+{
+    CalibStatus status = readCalibrationStatus();
+    
+    if(status.mag == 3 && status.acc == 3 && status.gyr == 3)
+        return true;
+    else
+        return false;
+}
+  
+ 
+/**
+ * Checks that there are no errors on the accelerometer
+ */
+bool bno055Healthy()
+{
+    int sys_error = readReg(BNO055_SYS_ERR_ADDR);
+    wait(0.001);
+    int sys_stat = readReg(BNO055_SYS_STAT_ADDR);
+    wait(0.001);
+    
+    if(sys_error == 0 && sys_stat == 5)
+        return true;
+    else {
+        //pc.printf("SYS_ERR: %d SYS_STAT: %d\r\n", sys_error, sys_stat);
+        return false;
+    }
+}
+    
+
+/**
+ * Configure and initialize the BNO055
+ */
+bool initBNO055()
+{
+    unsigned char regVal;
+    i2c.frequency(400000);
+    bool startupPass = true;
+    
+    // Do some basic power-up tests
+    regVal = readReg(BNO055_ID_ADDR);
+    if(regVal == 0xA0)
+        pc.printf("BNO055 successfully detected!\r\n");
+    else {
+        pc.printf("ERROR: no BNO055 detected\r\n");
+        startupPass = false;
+    }
+        
+    regVal = readReg(BNO055_TEMP_ADDR);
+    pc.printf("Chip temperature is: %d C\r\n", regVal);
+    
+    if(regVal == 0)
+        startupPass = false;
+ 
+    // Change mode to CONFIG
+    writeReg(BNO055_OPR_MODE_ADDR, 0x00);
+    wait(0.2);
+    
+    regVal = readReg(BNO055_OPR_MODE_ADDR);
+    pc.printf("Change to mode: %d\r\n", regVal);
+    wait(0.1);
+    
+    // Remap axes
+    writeReg(BNO055_AXIS_MAP_CONFIG_ADDR, 0x06);    // b00_00_01_10
+    wait(0.1);    
+
+    // Set to external crystal
+    writeReg(BNO055_SYS_TRIGGER_ADDR, 0x80);
+    wait(0.2);    
+
+    // Change mode to NDOF
+    writeReg(BNO055_OPR_MODE_ADDR, 0x0C);
+    wait(0.2);
+ 
+    regVal = readReg(BNO055_OPR_MODE_ADDR);
+    pc.printf("Change to mode: %d\r\n", regVal);
+    wait(0.1);
+    
+    return startupPass;
+}
+
+/**
+ * Sets the current accelerometer position as the zero position.
+ */
+void setZeroPosition()
+{
+    char buf[16];
+    
+    // Read the current euler angles and set them as the zero position
+    buf[0] = BNO055_EULER_H_LSB_ADDR;
+    i2c.write(bno055_addr, buf, 1, false);
+    i2c.read(bno055_addr, buf, 6, false);
+        
+    headingOffset = buf[0] + (buf[1] << 8);
+    rollOffset = buf[2] + (buf[3] << 8);
+    pitchOffset = buf[4] + (buf[5] << 8);
+}
+
+
+/**
+ * Sets the current accelerometer position as the zero position.
+ */
+void setZeroHeading()
+{
+    char buf[16];
+    
+    // Read the current euler angles and set them as the zero position
+    buf[0] = BNO055_EULER_H_LSB_ADDR;
+    i2c.write(bno055_addr, buf, 1, false);
+    i2c.read(bno055_addr, buf, 6, false);
+        
+    headingOffset = buf[0] + (buf[1] << 8);
+}
+
+
+/**
+ * Reads the Euler angles, zeroed out
+ */
+Euler getEulerAngles()
+{
+    char buf[16];
+    Euler e;
+    
+    // Read in the Euler angles
+    buf[0] = BNO055_EULER_H_LSB_ADDR;
+    i2c.write(bno055_addr, buf, 1, false);
+    i2c.read(bno055_addr, buf, 6, false);
+    
+    short int euler_head = buf[0] + (buf[1] << 8);
+    short int euler_roll = buf[2] + (buf[3] << 8);
+    short int euler_pitch = buf[4] + (buf[5] << 8);
+    
+    e.heading = ((int)euler_head - (int)headingOffset) / 16.0;
+    e.roll = ((int)euler_roll - (int)rollOffset) / 16.0;
+    e.pitch = ((int)euler_pitch - (int)pitchOffset) / 16.0;
+    
+    if(e.pitch > 90 || e.pitch < -90)
+        e.pitch = 0;
+    
+    return e;
+}
+
+
+/***** Functions to vibrate the motor (non-blocking call) *****/
+void vibrateOff()
+{
+    vibrate = 0;
+}
+
+void vibrateMotor()
+{
+    vibrate = 1;
+    vibrateTimeout.attach(&vibrateOff, 0.1);
+}
+
+
+
+
+int main() {
+    
+    uint16_t x_center = (X_MAX_ABS - X_MIN_ABS)/2;
+    uint16_t y_center = (Y_MAX_ABS - Y_MIN_ABS)/2;
+    uint16_t x_screen = 0;
+    uint16_t y_screen = 0;
+    
+    int loop_counter = 0;
+    int shake_counter = 0;
+    
+   
+    //uint32_t x_origin = x_center;
+    //uint32_t y_origin = y_center;
+    //uint32_t radius = 5000;
+    //uint32_t angle = 0;
+    
+    redLED = 0;
+    bool startupPassed;
+    Euler e;
+    bool down;
+    CalibStatus calStat;
+
+    // Record old state of buttons
+    bool triggerPressed = false;
+    bool movePressed = false;
+
+    // USB HID report to send move up/down
+    kbHIDReport.length = 4;
+    kbHIDReport.data[0] = 1;        // USB ID
+    kbHIDReport.data[1] = 0;        // modifier key
+    kbHIDReport.data[2] = 0;        // don't know
+
+    // Initialize
+    pc.baud(115200);
+    trigger.mode(PullUp);
+    move.mode(PullUp);
+    door.mode(PullUp);
+    centerBut.mode(PullUp);
+    wait(0.8);
+    startupPassed = initBNO055();   // Note: set LED to RED if this fails
+    
+    // Wait until calibration passes
+    
+    while(!calibrated()){
+        wait(0.1);
+        calStat = readCalibrationStatus();
+        printf("MAG: %d ACC: %d GYR: %d SYS: %d\r\n", calStat.mag, calStat.acc, calStat.gyr, calStat.sys);      
+        wait(0.5); 
+    }
+    redLED = 1;
+    greenLED = 0;   
+     
+    pc.printf("Board fully calibrated!\r\n");
+    
+    // Wait until user hits the trigger. Then zero out the readings
+    while(trigger.read() == 1) {
+        wait(0.01);
+    }
+    setZeroPosition();
+
+    // Read orientation values
+    while(true)
+    {
+        // Make sure that there are no errors
+        if(!bno055Healthy())
+        {
+            //wait(0.1);
+            //calStat = readCalibrationStatus();
+            //pc.printf("Heading: %7.2f \tRoll: %7.2f \tPitch: %7.2f Down: %d \tMAG: %d ACC: %d GYR: %d SYS: %d\r\n", e.heading, e.roll, e.pitch,down, calStat.mag, calStat.acc, calStat.gyr, calStat.sys); 
+            pc.printf("ERROR: BNO055 has an error/status problem!!!\r\n");
+        }
+        
+        // Read in the Euler angles
+        e = getEulerAngles();
+        wait(0.001);
+ 
+        // Read in the calibration status
+        calStat = readCalibrationStatus();
+        wait(0.001);
+        
+        // LED red if not calibrated else green
+        if(!calibrated())
+        {
+            redLED = 0;
+            greenLED = 1;
+        }
+        else
+        {
+            redLED = 1;
+            greenLED = 0;
+        }
+            
+/*        
+        // Check if device is pointing down
+        //down = (e.pitch < -70);
+        
+        wait(0.01);
+        char buf[16];
+        buf[0] = BNO055_ACC_DATA_X_ADDR;
+        i2c.write(bno055_addr, buf, 1, false);
+        i2c.read(bno055_addr, buf, 6, false);
+        
+        short int acc_z = buf[4] + (buf[5] << 8);
+        wait(0.01);
+        
+        if(acc_z < -1000 || acc_z > 1000)
+        {
+            shake_counter++;
+            loop_counter++;
+        }
+        else if (loop_counter > 0)
+            loop_counter ++;
+            
+        if(shake_counter > 2 && loop_counter < 20) {
+             key_mouse.scroll(-1);
+             wait(1.5);
+             shake_counter = 0;
+             loop_counter = 0;
+        }
+        else if(loop_counter == 20) {
+           shake_counter = 0;
+           loop_counter = 0;
+        }
+*/           
+/*
+        //if it is down, then change device
+        if(down){
+            key_mouse.scroll(-1);
+            
+            // Wait until up
+            do {
+                wait(0.01);
+                e = getEulerAngles();
+                wait(0.01);
+            } while(e.pitch < -20);
+
+            wait(2);
+            
+            // Re-center heading
+            //setZeroHeading();
+            //wait(0.01);
+        }
+*/        
+        // If trigger state changed
+        if (!trigger.read() != triggerPressed)
+        {
+            // If trigger pressed
+            if(!trigger.read())
+            {
+                //key_mouse.click(MOUSE_LEFT);
+                //key_mouse.keyCode('d');
+                kbHIDReport.data[3] = 0x07;     // UP arrow
+                vibrateMotor();
+                triggerPressed = true;
+            }
+            
+            else {
+                triggerPressed = false;
+                kbHIDReport.data[3] = 0x00;     // UP arrow
+            }
+            key_mouse.sendNB(&kbHIDReport);
+        }
+
+        if (!door.read()){
+            int counter = 0;
+            while(counter<50){
+                key_mouse.keyCode(' ');
+                counter++;
+                wait(0.001);
+            }
+            wait(0.2);
+        }
+        
+        if(!centerBut.read())
+        {
+            wait(0.01);
+            setZeroPosition();
+            wait(0.1);
+        }
+
+        // If move button state changed
+        if (!move.read() != movePressed)
+        {
+            // If move pressed
+            if(!move.read()) {
+                kbHIDReport.data[3] = 0x52;     // UP arrow
+                movePressed = true;
+            }
+            
+            else {
+                kbHIDReport.data[3] = 0x00;     // no press
+                movePressed = false;
+            }
+            
+            key_mouse.sendNB(&kbHIDReport);
+        }
+  
+
+        // move limits
+        float heading_limited;
+        if(e.heading > 90)
+            heading_limited = 90;
+        else if(e.heading < -90)
+            heading_limited = -90;
+        else if(e.heading < 2 && e.heading > -2)
+            heading_limited = 0;
+        //else if (e.pitch < -30)
+        //    heading_limited = 0;
+        else if(e.heading > -20 && e.heading < 20)
+            heading_limited = 16 * e.heading;
+        else
+            heading_limited = 0.8 * e.heading * abs(e.heading);
+
+ 
+
+        //moving the mouse now
+        x_screen = x_center + heading_limited;
+        //x_screen = x_center+(e.heading/180*(X_MAX_ABS-x_center)); //45 was too sensitive
+        y_screen = y_center;
+        
+        printf("Heading: %7.2f \tRoll: %7.2f \tPitch: %7.2f Down: %d \tMAG: %d ACC: %d GYR: %d SYS: %d\r\n", e.heading, e.roll, e.pitch,
+            down, calStat.mag, calStat.acc, calStat.gyr, calStat.sys);
+            
+        key_mouse.move(x_screen, y_screen);
+        wait(0.02);
+    }
+}