Renamed to program to Doom_Controller.
Dependencies: DebounceIn USBDevice mbed
Fork of BNO055_reader by
Diff: main.cpp
- Revision:
- 0:a59b1f819776
- Child:
- 1:38cd433ff221
diff -r 000000000000 -r a59b1f819776 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Sep 18 00:40:26 2015 +0000 @@ -0,0 +1,319 @@ +#include "mbed.h" +#include "USBMouseKeyboard.h" +//LEDs to indicate clibration status +DigitalOut redLED(LED_RED); +DigitalOut greenLED(LED_GREEN); + +//pushbuttons inputs +DigitalIn trigger(D11); +DigitalIn move(D8); +DigitalIn door(D4); + +//USBMouseKeyboard +//do we need absolute or relative mouse? +USBMouseKeyboard key_mouse(ABS_MOUSE); + +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; + +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); +} + + +/** + * 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; + + return e; +} + + +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; + + //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; + + // Initialize + pc.baud(115200); + trigger.mode(PullUp); + move.mode(PullUp); + door.mode(PullUp); + wait(0.8); + startupPassed = initBNO055(); // Note: set LED to RED if this fails + + // Wait until calibration passes + + while(!calibrated()){ + wait(0.1); + CalibStatus 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 == 1) { + wait(0.01); + } + setZeroPosition(); + + // Read orientation values + while(true) + { + // Make sure that there are no errors + if(!bno055Healthy()) + wait(0.1); + CalibStatus 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); + + // Check if device is pointing down + down = (e.pitch < -70); + + //if it is down, then change device + if (down){ + key_mouse.click(MOUSE_RIGHT); + wait(0.3); //do we need to change the wait time + } + if (!trigger){ + key_mouse.click(MOUSE_LEFT); + wait(0.05); //0.3 was too long + } + if (!door){ + int counter = 0; + while(counter<50){ + key_mouse.keyCode(' '); + counter++; + } + wait(0.5); + } + if (!move){ + int count = 0; + while (count<100){ + key_mouse.keyCode('a'); + count++; + } + } + //moving the mouse now + + 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.05); + } +}