Successful acro and level mode now! Relying on MPU9250 as base sensor. I'm working continuously on tuning and features :) NEWEST VERSION ON: https://github.com/MaEtUgR/FlyBed (CODE 100% compatible/copyable)
Revision 8:609a2ad4c30e, committed 2015-11-19
- Comitter:
- maetugr
- Date:
- Thu Nov 19 18:47:27 2015 +0000
- Parent:
- 7:90f876d47862
- Commit message:
- made I2C-Sensors working in parallel, added rolling buffer for PID derivative, played with the PID and frequency parameters in main
Changed in this revision
--- a/IMU/IMU_10DOF.cpp Mon Sep 14 12:49:08 2015 +0000 +++ b/IMU/IMU_10DOF.cpp Thu Nov 19 18:47:27 2015 +0000 @@ -1,6 +1,6 @@ #include "IMU_10DOF.h" -IMU_10DOF::IMU_10DOF(PinName MOSI, PinName MISO, PinName SCLK, PinName CS) : mpu(MOSI, MISO, SCLK, CS) +IMU_10DOF::IMU_10DOF(PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName SDA, PinName SCL) : mpu(MOSI, MISO, SCLK, CS), mpu2(SDA, SCL) { dt = 0; dt_sensors = 0; @@ -15,6 +15,7 @@ SensorTimer.start(); // start time for measuring sensors mpu.readGyro(); // reading sensor data mpu.readAcc(); + mpu2.read(); // reading sensor data SensorTimer.stop(); // stop time for measuring sensors dt_sensors = SensorTimer.read(); SensorTimer.reset(); @@ -24,4 +25,5 @@ LoopTimer.reset(); Filter.compute(dt, mpu.Gyro, mpu.Acc, mpu.Acc); + //Filter.compute(dt, mpu2.data_gyro, mpu2.data_acc, mpu2.data_acc); } \ No newline at end of file
--- a/IMU/IMU_10DOF.h Mon Sep 14 12:49:08 2015 +0000 +++ b/IMU/IMU_10DOF.h Thu Nov 19 18:47:27 2015 +0000 @@ -5,12 +5,13 @@ #include "mbed.h" #include "MPU9250.h" // Combined Gyroscope & Accelerometer & Magnetometer over SPI +#include "MPU6050.h" // Combined Gyroscope & Accelerometer #include "IMU_Filter.h" // Class to calculate position angles (algorithm from S.O.H. Madgwick, see header file for info) class IMU_10DOF { public: - IMU_10DOF(PinName MOSI, PinName MISO, PinName SCLK, PinName CS); + IMU_10DOF(PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName SDA, PinName SCL); void readAngles(); // read all sensors and calculate angles float * angle; // where the measured and calculated data is saved @@ -22,6 +23,7 @@ float dt_sensors; // time only to read sensors MPU9250 mpu; // The sensor Hardware Driver + MPU6050 mpu2; private: Timer LoopTimer; // local time to calculate processing speed for entire loop
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IMU/MPU6050/I2C_Sensor.cpp Thu Nov 19 18:47:27 2015 +0000 @@ -0,0 +1,54 @@ +#include "I2C_Sensor.h" + +// calculate the 8-Bit write/read I2C-Address from the 7-Bit adress of the device +#define GET_I2C_WRITE_ADDRESS(ADR) (ADR << 1&0xFE) // ADR & 1111 1110 +#define GET_I2C_READ_ADDRESS(ADR) (ADR << 1|0x01) // ADR | 0000 0001 + +I2C_Sensor::I2C_Sensor(PinName sda, PinName scl, char i2c_address) : i2c(sda, scl), local("local") +{ + I2C_Sensor::i2c_address = i2c_address; + i2c.frequency(400000); // standard speed + //i2c.frequency(1000000); // ultrafast! +} + +void I2C_Sensor::saveCalibrationValues(float values[], int size, char * filename) +{ + FILE *fp = fopen(strcat("/local/", filename), "w"); + for(int i = 0; i < size; i++) + fprintf(fp, "%f\r\n", values[i]); + fclose(fp); +} + +void I2C_Sensor::loadCalibrationValues(float values[], int size, char * filename) +{ + FILE *fp = fopen(strcat("/local/", filename), "r"); + for(int i = 0; i < size; i++) + fscanf(fp, "%f", &values[i]); + fclose(fp); +} + +// I2C functions -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + +char I2C_Sensor::readRegister(char reg) +{ + char value = 0; + + i2c.write(i2c_address, ®, 1); + i2c.read(i2c_address, &value, 1); + + return value; +} + +void I2C_Sensor::writeRegister(char reg, char data) +{ + char buffer[2] = {reg, data}; + i2c.write(i2c_address, buffer, 2); +} + +int I2C_Sensor::readMultiRegister(char reg, char* output, int size) +{ + if (0 != i2c.write (i2c_address, ®, 1)) return 1; // tell register address of the MSB get the sensor to do slave-transmit subaddress updating. + if (0 != i2c.read (i2c_address, output, size)) return 1; // tell it where to store the data read + return 0; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IMU/MPU6050/I2C_Sensor.h Thu Nov 19 18:47:27 2015 +0000 @@ -0,0 +1,36 @@ +// by MaEtUgR + +#ifndef I2C_Sensor_H +#define I2C_Sensor_H + +#include "mbed.h" + +class I2C_Sensor +{ + public: + I2C_Sensor(PinName sda, PinName scl, char address); + + float data[3]; // where the measured data is saved + //TODO: virtual void calibrate() = 0; // calibrate the sensor and if desired write calibration values to a file + + //protected: + // Calibration + void saveCalibrationValues(float values[], int size, char * filename); + void loadCalibrationValues(float values[], int size, char * filename); + + // I2C functions + char readRegister(char reg); + void writeRegister(char reg, char data); + int readMultiRegister(char reg, char* output, int size); + + // raw data and function to measure it + short raw[3]; + + private: + I2C i2c; // original mbed I2C-library just to initialise the control registers + char i2c_address; // address + + LocalFileSystem local; // file access to save calibration values +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IMU/MPU6050/MPU6050.cpp Thu Nov 19 18:47:27 2015 +0000 @@ -0,0 +1,110 @@ +#include "MPU6050.h" + +MPU6050::MPU6050(PinName sda, PinName scl) : I2C_Sensor(sda, scl, MPU6050_I2C_ADDRESS) +{ + // Turns on the MPU6050's gyro and initializes it + // register datasheet: http://www.invensense.com/mems/gyro/documents/RM-MPU-6000A.pdf + writeRegister(MPU6050_RA_PWR_MGMT_1, 0x01); // wake up from sleep and chooses Gyro X-Axis as Clock source (stadard sleeping and with inacurate clock is 0x40) + /* + last 3 Bits of |Accelerometer(Fs=1kHz) |Gyroscope + MPU6050_RA_CONFIG|Bandwidth(Hz)|Delay(ms)|Bandwidth(Hz)|Delay(ms)|Fs(kHz) + ------------------------------------------------------------------------- + 0 |260 |0 |256 |0.98 |8 + 1 |184 |2.0 |188 |1.9 |1 + 2 |94 |3.0 |98 |2.8 |1 + 3 |44 |4.9 |42 |4.8 |1 + 4 |21 |8.5 |20 |8.3 |1 + 5 |10 |13.8 |10 |13.4 |1 + 6 |5 |19.0 |5 |18.6 |1 + */ + writeRegister(MPU6050_RA_CONFIG, 0x03); + writeRegister(MPU6050_RA_GYRO_CONFIG, 0x18); // scales gyros range to +-2000dps + writeRegister(MPU6050_RA_ACCEL_CONFIG, 0x00); // scales accelerometers range to +-2g +} + +void MPU6050::read() +{ + readraw_gyro(); // read raw measurement data + readraw_acc(); + + offset_gyro[0] = -35; // TODO: make better calibration + offset_gyro[1] = 3; + offset_gyro[2] = 2; + + for (int i = 0; i < 3; i++) + data_gyro[i] = (raw_gyro[i] - offset_gyro[i]) * 0.07 * 0.87; // subtract offset from calibration and multiply unit factor to get degree per second (datasheet p.10) + + for (int i = 0; i < 3; i++) + data_acc[i] = raw_acc[i] - offset_acc[i]; // TODO: didn't care about units because IMU-algorithm just uses vector direction + + // I have to swich coordinates on my board to match the ones of the other sensors (clear this part if you use the raw coordinates of the sensor) + float tmp = 0; + tmp = data_gyro[0]; + data_gyro[0] = -data_gyro[0]; + data_gyro[1] = -data_gyro[1]; + data_gyro[2] = data_gyro[2]; + tmp = data_acc[0]; + data_acc[0] = -data_acc[0]; + data_acc[1] = -data_acc[1]; + data_acc[2] = data_acc[2]; +} + +int MPU6050::readTemp() +{ + char buffer[2]; // 8-Bit pieces of temperature data + + readMultiRegister(MPU6050_RA_TEMP_OUT_H, buffer, 2); // read the sensors register for the temperature + return (short) (buffer[0] << 8 | buffer[1]); +} + +void MPU6050::readraw_gyro() +{ + char buffer[6]; // 8-Bit pieces of axis data + + if(readMultiRegister(MPU6050_RA_GYRO_XOUT_H | (1 << 7), buffer, 6) != 0) return; // read axis registers using I2C // TODO: why?! | (1 << 7) + + raw_gyro[0] = (short) (buffer[0] << 8 | buffer[1]); // join 8-Bit pieces to 16-bit short integers + raw_gyro[1] = (short) (buffer[2] << 8 | buffer[3]); + raw_gyro[2] = (short) (buffer[4] << 8 | buffer[5]); +} + +void MPU6050::readraw_acc() +{ + char buffer[6]; // 8-Bit pieces of axis data + + readMultiRegister(MPU6050_RA_ACCEL_XOUT_H | (1 << 7), buffer, 6); // read axis registers using I2C // TODO: why?! | (1 << 7) + + raw_acc[0] = (short) (buffer[0] << 8 | buffer[1]); // join 8-Bit pieces to 16-bit short integers + raw_acc[1] = (short) (buffer[2] << 8 | buffer[3]); + raw_acc[2] = (short) (buffer[4] << 8 | buffer[5]); +} + +void MPU6050::calibrate(int times, float separation_time) +{ + // calibrate sensor with an average of count samples (result of calibration stored in offset[]) + // Calibrate Gyroscope ---------------------------------- + float calib_gyro[3] = {0,0,0}; // temporary array for the sum of calibration measurement + + for (int i = 0; i < times; i++) { // read 'times' times the data in a very short time + readraw_gyro(); + for (int j = 0; j < 3; j++) + calib_gyro[j] += raw_gyro[j]; + wait(separation_time); + } + + for (int i = 0; i < 3; i++) + offset_gyro[i] = calib_gyro[i]/times; // take the average of the calibration measurements + + // Calibrate Accelerometer ------------------------------- + float calib_acc[3] = {0,0,0}; // temporary array for the sum of calibration measurement + + for (int i = 0; i < times; i++) { // read 'times' times the data in a very short time + readraw_acc(); + for (int j = 0; j < 3; j++) + calib_acc[j] += raw_acc[j]; + wait(separation_time); + } + + for (int i = 0; i < 2; i++) + offset_acc[i] = calib_acc[i]/times; // take the average of the calibration measurements +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IMU/MPU6050/MPU6050.h Thu Nov 19 18:47:27 2015 +0000 @@ -0,0 +1,145 @@ +// based on http://mbed.org/users/garfieldsg/code/MPU6050/ + +#ifndef MPU6050_H +#define MPU6050_H + +#include "mbed.h" +#include "I2C_Sensor.h" + +#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board +#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) +#define MPU6050_I2C_ADDRESS 0xD2 // adresses above multiplied by 2 + +// register addresses +#define MPU6050_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN +#define MPU6050_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN +#define MPU6050_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN +#define MPU6050_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS +#define MPU6050_RA_XA_OFFS_L_TC 0x07 +#define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS +#define MPU6050_RA_YA_OFFS_L_TC 0x09 +#define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS +#define MPU6050_RA_ZA_OFFS_L_TC 0x0B +#define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR +#define MPU6050_RA_XG_OFFS_USRL 0x14 +#define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR +#define MPU6050_RA_YG_OFFS_USRL 0x16 +#define MPU6050_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR +#define MPU6050_RA_ZG_OFFS_USRL 0x18 +#define MPU6050_RA_SMPLRT_DIV 0x19 +#define MPU6050_RA_CONFIG 0x1A +#define MPU6050_RA_GYRO_CONFIG 0x1B +#define MPU6050_RA_ACCEL_CONFIG 0x1C +#define MPU6050_RA_FF_THR 0x1D +#define MPU6050_RA_FF_DUR 0x1E +#define MPU6050_RA_MOT_THR 0x1F +#define MPU6050_RA_MOT_DUR 0x20 +#define MPU6050_RA_ZRMOT_THR 0x21 +#define MPU6050_RA_ZRMOT_DUR 0x22 +#define MPU6050_RA_FIFO_EN 0x23 +#define MPU6050_RA_I2C_MST_CTRL 0x24 +#define MPU6050_RA_I2C_SLV0_ADDR 0x25 +#define MPU6050_RA_I2C_SLV0_REG 0x26 +#define MPU6050_RA_I2C_SLV0_CTRL 0x27 +#define MPU6050_RA_I2C_SLV1_ADDR 0x28 +#define MPU6050_RA_I2C_SLV1_REG 0x29 +#define MPU6050_RA_I2C_SLV1_CTRL 0x2A +#define MPU6050_RA_I2C_SLV2_ADDR 0x2B +#define MPU6050_RA_I2C_SLV2_REG 0x2C +#define MPU6050_RA_I2C_SLV2_CTRL 0x2D +#define MPU6050_RA_I2C_SLV3_ADDR 0x2E +#define MPU6050_RA_I2C_SLV3_REG 0x2F +#define MPU6050_RA_I2C_SLV3_CTRL 0x30 +#define MPU6050_RA_I2C_SLV4_ADDR 0x31 +#define MPU6050_RA_I2C_SLV4_REG 0x32 +#define MPU6050_RA_I2C_SLV4_DO 0x33 +#define MPU6050_RA_I2C_SLV4_CTRL 0x34 +#define MPU6050_RA_I2C_SLV4_DI 0x35 +#define MPU6050_RA_I2C_MST_STATUS 0x36 +#define MPU6050_RA_INT_PIN_CFG 0x37 +#define MPU6050_RA_INT_ENABLE 0x38 +#define MPU6050_RA_DMP_INT_STATUS 0x39 +#define MPU6050_RA_INT_STATUS 0x3A +#define MPU6050_RA_ACCEL_XOUT_H 0x3B +#define MPU6050_RA_ACCEL_XOUT_L 0x3C +#define MPU6050_RA_ACCEL_YOUT_H 0x3D +#define MPU6050_RA_ACCEL_YOUT_L 0x3E +#define MPU6050_RA_ACCEL_ZOUT_H 0x3F +#define MPU6050_RA_ACCEL_ZOUT_L 0x40 +#define MPU6050_RA_TEMP_OUT_H 0x41 +#define MPU6050_RA_TEMP_OUT_L 0x42 +#define MPU6050_RA_GYRO_XOUT_H 0x43 +#define MPU6050_RA_GYRO_XOUT_L 0x44 +#define MPU6050_RA_GYRO_YOUT_H 0x45 +#define MPU6050_RA_GYRO_YOUT_L 0x46 +#define MPU6050_RA_GYRO_ZOUT_H 0x47 +#define MPU6050_RA_GYRO_ZOUT_L 0x48 +#define MPU6050_RA_EXT_SENS_DATA_00 0x49 +#define MPU6050_RA_EXT_SENS_DATA_01 0x4A +#define MPU6050_RA_EXT_SENS_DATA_02 0x4B +#define MPU6050_RA_EXT_SENS_DATA_03 0x4C +#define MPU6050_RA_EXT_SENS_DATA_04 0x4D +#define MPU6050_RA_EXT_SENS_DATA_05 0x4E +#define MPU6050_RA_EXT_SENS_DATA_06 0x4F +#define MPU6050_RA_EXT_SENS_DATA_07 0x50 +#define MPU6050_RA_EXT_SENS_DATA_08 0x51 +#define MPU6050_RA_EXT_SENS_DATA_09 0x52 +#define MPU6050_RA_EXT_SENS_DATA_10 0x53 +#define MPU6050_RA_EXT_SENS_DATA_11 0x54 +#define MPU6050_RA_EXT_SENS_DATA_12 0x55 +#define MPU6050_RA_EXT_SENS_DATA_13 0x56 +#define MPU6050_RA_EXT_SENS_DATA_14 0x57 +#define MPU6050_RA_EXT_SENS_DATA_15 0x58 +#define MPU6050_RA_EXT_SENS_DATA_16 0x59 +#define MPU6050_RA_EXT_SENS_DATA_17 0x5A +#define MPU6050_RA_EXT_SENS_DATA_18 0x5B +#define MPU6050_RA_EXT_SENS_DATA_19 0x5C +#define MPU6050_RA_EXT_SENS_DATA_20 0x5D +#define MPU6050_RA_EXT_SENS_DATA_21 0x5E +#define MPU6050_RA_EXT_SENS_DATA_22 0x5F +#define MPU6050_RA_EXT_SENS_DATA_23 0x60 +#define MPU6050_RA_MOT_DETECT_STATUS 0x61 +#define MPU6050_RA_I2C_SLV0_DO 0x63 +#define MPU6050_RA_I2C_SLV1_DO 0x64 +#define MPU6050_RA_I2C_SLV2_DO 0x65 +#define MPU6050_RA_I2C_SLV3_DO 0x66 +#define MPU6050_RA_I2C_MST_DELAY_CTRL 0x67 +#define MPU6050_RA_SIGNAL_PATH_RESET 0x68 +#define MPU6050_RA_MOT_DETECT_CTRL 0x69 +#define MPU6050_RA_USER_CTRL 0x6A +#define MPU6050_RA_PWR_MGMT_1 0x6B +#define MPU6050_RA_PWR_MGMT_2 0x6C +#define MPU6050_RA_BANK_SEL 0x6D +#define MPU6050_RA_MEM_START_ADDR 0x6E +#define MPU6050_RA_MEM_R_W 0x6F +#define MPU6050_RA_DMP_CFG_1 0x70 +#define MPU6050_RA_DMP_CFG_2 0x71 +#define MPU6050_RA_FIFO_COUNTH 0x72 +#define MPU6050_RA_FIFO_COUNTL 0x73 +#define MPU6050_RA_FIFO_R_W 0x74 +#define MPU6050_RA_WHO_AM_I 0x75 + +class MPU6050 : public I2C_Sensor +{ + public: + MPU6050(PinName sda, PinName scl); // constructor, uses I2C_Sensor class + float data_gyro[3]; // where the measured data is saved + float data_acc[3]; // where the measured data is saved + virtual void read(); // read all axis from register to array data + float offset_gyro[3]; // offset that's subtracted from every Gyroscope measurement + float offset_acc[3]; // offset that's subtracted from every Accelerometer measurement + void calibrate(int times, float separation_time); // calibration from 'times' measurements with 'separation_time' time between (get an offset while not moving) + int readTemp(); // read temperature from sensor + + int raw_gyro[3]; + private: + + int raw_acc[3]; + void readraw_gyro(); + void readraw_acc(); +}; + +#endif \ No newline at end of file
--- a/IMU/MPU9250/MPU9250.cpp Mon Sep 14 12:49:08 2015 +0000 +++ b/IMU/MPU9250/MPU9250.cpp Thu Nov 19 18:47:27 2015 +0000 @@ -17,7 +17,7 @@ 5 |10 |13.8 |10 |13.4 |1 6 |5 |19.0 |5 |18.6 |1 */ - writeRegister8(MPU9250_CONFIG, 0x03); + writeRegister8(MPU9250_CONFIG, 0x00); writeRegister8(MPU9250_GYRO_CONFIG, 0x18); // scales gyros range to +-2000dps writeRegister8(MPU9250_ACCEL_CONFIG, 0x08); // scales accelerometers range to +-4g } @@ -35,7 +35,7 @@ int16_t rawGyro[3]; readRegister48(MPU9250_GYRO_XOUT_H, rawGyro); - int16_t offsetGyro[3] = {-31, -15, -11}; // TODO: make better calibration + int16_t offsetGyro[3] = {-31, -16, -12}; // TODO: make better calibration for (int i = 0; i < 3; i++) Gyro[i] = (rawGyro[i] - offsetGyro[i]) * 0.07 * 0.87; // subtract offset from calibration and multiply unit factor to get degree per second (datasheet p.10)
--- a/IMU/MPU9250/MPU9250.h Mon Sep 14 12:49:08 2015 +0000 +++ b/IMU/MPU9250/MPU9250.h Thu Nov 19 18:47:27 2015 +0000 @@ -18,7 +18,7 @@ void readAcc(); // read measurement data from accelerometer float Acc[3]; // where accelerometer measurement data is stored - private: + //private: // SPI Inteface SPI spi; // SPI Bus
--- a/PID/PID.cpp Mon Sep 14 12:49:08 2015 +0000 +++ b/PID/PID.cpp Thu Nov 19 18:47:27 2015 +0000 @@ -31,6 +31,9 @@ // Derivative RollBuffer[RollBufferIndex] = (Error - PreviousError) / dt; + RollBufferIndex++; + if (RollBufferIndex == BUFFERSIZE) + RollBufferIndex = 0; float Derivative = 0; for(int i=0; i<BUFFERSIZE ;i++) Derivative += RollBuffer[i];
--- a/main.cpp Mon Sep 14 12:49:08 2015 +0000 +++ b/main.cpp Thu Nov 19 18:47:27 2015 +0000 @@ -15,7 +15,7 @@ #define PPM_FREQU 495 // Hz Frequency of PPM Signal for ESCs (maximum <500Hz) #define INTEGRAL_MAX 300 // maximal output offset that can result from integrating errors -#define RC_SENSITIVITY 15 // maximal angle from horizontal that the PID is aming for +#define RC_SENSITIVITY 30 // maximal angle from horizontal that the PID is aming for #define YAWSPEED 1.0 // maximal speed of yaw rotation in degree per Rate #define AILERON 0 // RC #define ELEVATOR 1 @@ -34,20 +34,22 @@ bool debug = true; // shows if we want output for the computer bool level = false; // switches between self leveling and acro mode bool RC_present = false; // shows if an RC is present -float P_R = 2.5, I_R = 0.3, D_R = 0; // PID values for the rate controller -float P_A = 2.1, I_A = 0.3, D_A = 0; // PID values for the angle controller P_A = 1.865, I_A = 1.765, D_A = 0 +float P_R = 2.6, I_R = 0.3, D_R = 0; // PID values for the rate controller +float P_A = 1.9, I_A = 0.2, D_A = 0; // PID values for the angle controller P_A = 1.865, I_A = 1.765, D_A = 0 float PY = 2.3, IY = 0, DY = 0; // PID values for Yaw float RC_angle[] = {0,0,0}; // Angle of the RC Sticks, to steer the QC float Motor_speed[4] = {0,0,0,0}; // Mixed Motorspeeds, ready to send Timer LoopTimer; float Times[10] = {0,0,0,0,0,0,0,0,0,0}; -float control_frequency = PPM_FREQU; // frequency for the main loop in Hz +float control_frequency = 800;//PPM_FREQU; // frequency for the main loop in Hz +int counter = 0; +int divider = 20; LED LEDs; -PC pc(USBTX, USBRX, 115200); // USB -//PC pc(p9, p10, 115200); // Bluetooth PIN: 1234 -IMU_10DOF IMU(p5, p6, p7, p19); +//PC pc(USBTX, USBRX, 115200); // USB +PC pc(p9, p10, 115200); // Bluetooth PIN: 1234 +IMU_10DOF IMU(p5, p6, p7, p19, p28, p27); RC_Channel RC[] = {RC_Channel(p8,1), RC_Channel(p15,2), RC_Channel(p17,4), RC_Channel(p16,3), RC_Channel(p25,2), RC_Channel(p26,4), RC_Channel(p29,3)}; // no p19/p20 ! PID Controller_Rate[] = {PID(P_R, I_R, D_R, INTEGRAL_MAX), PID(P_R, I_R, D_R, INTEGRAL_MAX), PID(PY, IY, DY, INTEGRAL_MAX)}; // 0:X:Roll 1:Y:Pitch 2:Z:Yaw PID Controller_Angle[] = {PID(P_A, I_A, D_A, INTEGRAL_MAX), PID(P_A, I_A, D_A, INTEGRAL_MAX), PID(0, 0, 0, INTEGRAL_MAX)}; @@ -103,14 +105,17 @@ if (level) { for(int i=0;i<2;i++) { // LEVEL Controller_Angle[i].setIntegrate(armed); // only integrate in controller when armed, so the value is not totally odd from not flying - Controller_Angle[i].compute(RC_angle[i], IMU.angle[i]); // give the controller the actual gyro values and get his advice to correct + if (counter % 16 == 0) + Controller_Angle[i].compute(RC_angle[i], IMU.angle[i]); // give the controller the actual angles and get his advice to correct Controller_Rate[i].setIntegrate(armed); // only integrate in controller when armed, so the value is not totally odd from not flying - Controller_Rate[i].compute(-Controller_Angle[i].Value, IMU.mpu.Gyro[i]); // give the controller the actual gyro values and get his advice to correct + Controller_Rate[i].compute(-Controller_Angle[i].Value, /*IMU.mpu2.data_gyro[i]*/IMU.mpu.Gyro[i]); // give the controller the actual gyro values and get his advice to correct + //Controller_Rate[i].compute(-Controller_Angle[i].Value, (IMU.mpu2.data_gyro[i] + IMU.mpu.Gyro[i])/2 ); } } else { for(int i=0;i<2;i++) { // ACRO Controller_Rate[i].setIntegrate(armed); // only integrate in controller when armed, so the value is not totally odd from not flying - Controller_Rate[i].compute((RC[i].read()-500.0)*100.0/500.0, IMU.mpu.Gyro[i]); // give the controller the actual gyro values and get his advice to correct + Controller_Rate[i].compute((RC[i].read()-500.0)*100.0/500.0, /*IMU.mpu2.data_gyro[i]*/IMU.mpu.Gyro[i]); // give the controller the actual gyro values and get his advice to correct + //Controller_Rate[i].compute((RC[i].read()-500.0)*100.0/500.0, (IMU.mpu2.data_gyro[i] + IMU.mpu.Gyro[i])/2 ); } } @@ -130,22 +135,22 @@ Motor_speed[3] = throttle +SQRT2*Controller_Rate[ROLL].Value +SQRT2*Controller_Rate[PITCH].Value; // Motor_speed[0] -= Controller_Rate[YAW].Value; + Motor_speed[1] += Controller_Rate[YAW].Value; Motor_speed[2] -= Controller_Rate[YAW].Value; Motor_speed[3] += Controller_Rate[YAW].Value; - Motor_speed[1] += Controller_Rate[YAW].Value; Times[5] = LoopTimer.read(); // 17us if (armed) // for SECURITY! { debug = false; // PITCH - ESC[0] = (int)Motor_speed[0]>50 ? (int)Motor_speed[0] : 50; - ESC[2] = (int)Motor_speed[2]>50 ? (int)Motor_speed[2] : 50; + //ESC[0] = (int)Motor_speed[0]>50 ? (int)Motor_speed[0] : 50; + //ESC[2] = (int)Motor_speed[2]>50 ? (int)Motor_speed[2] : 50; // ROLL //ESC[1] = (int)Motor_speed[1]>50 ? (int)Motor_speed[1] : 50; //ESC[3] = (int)Motor_speed[3]>50 ? (int)Motor_speed[3] : 50; - /*for(int i=0;i<4;i++) // Set new motorspeeds - ESC[i] = (int)Motor_speed[i]>100 ? (int)Motor_speed[i] : 100;*/ + for(int i=0;i<4;i++) // Set new motorspeeds + ESC[i] = (int)Motor_speed[i]>100 ? (int)Motor_speed[i] : 100; } else { for(int i=0;i<4;i++) // for security reason, set every motor to zero speed @@ -156,9 +161,13 @@ LEDs.rollnext(); - Times[7] = LoopTimer.read(); // 7us TOTAL 297us + /*if(counter % divider == 0) { + pc.printf("%.3f,%.3f,%.3f\r\n", IMU.mpu.Gyro[ROLL], IMU.mpu.Gyro[PITCH], IMU.mpu.Gyro[YAW]); + }*/ + counter++; - while(LoopTimer.read() < 1/control_frequency); + Times[7] = LoopTimer.read(); // 7us TOTAL 297us + while(LoopTimer.read() < 1/control_frequency); // Kill the rest of the time TODO: make a better solution so we can do misc things with these cycles Times[8] = LoopTimer.read(); LoopTimer.stop(); LoopTimer.reset(); @@ -167,17 +176,18 @@ if (debug) { pc.printf("$STATE,%d,%d,%.f,%.3f,%.3f\r\n", armed, level, control_frequency, IMU.dt*1e3, IMU.dt_sensors*1e6); //pc.printf("$RC,%d,%d,%d,%d,%d,%d,%d\r\n", RC[AILERON].read(), RC[ELEVATOR].read(), RC[RUDDER].read(), RC[THROTTLE].read(), RC[CHANNEL6].read(), RC[CHANNEL7].read(), RC[CHANNEL8].read()); - //pc.printf("$GYRO,%.3f,%.3f,%.3f\r\n", IMU.mpu.Gyro[ROLL], IMU.mpu.Gyro[PITCH], IMU.mpu.Gyro[YAW]); + pc.printf("$GYRO,%.3f,%.3f,%.3f\r\n", IMU.mpu.Gyro[ROLL], IMU.mpu.Gyro[PITCH], IMU.mpu.Gyro[YAW]); + pc.printf("$GYRO2,%.3f,%.3f,%.3f\r\n", IMU.mpu2.data_gyro[ROLL], IMU.mpu2.data_gyro[PITCH], IMU.mpu2.data_gyro[YAW]); //pc.printf("$ACC,%.3f,%.3f,%.3f\r\n", IMU.mpu.Acc[ROLL], IMU.mpu.Acc[PITCH], IMU.mpu.Acc[YAW]); pc.printf("$ANG,%.3f,%.3f,%.3f\r\n", IMU.angle[ROLL], IMU.angle[PITCH], IMU.angle[YAW]); //pc.printf("$RCANG,%.3f,%.3f,%.3f\r\n", RC_angle[ROLL], RC_angle[PITCH], RC_angle[YAW]); pc.printf("$CONTR,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f\r\n", Controller_Rate[ROLL].Value, Controller_Rate[PITCH].Value, Controller_Rate[YAW].Value, P_R, I_R, D_R, PY); pc.printf("$CONTA,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f\r\n", Controller_Angle[ROLL].Value, Controller_Angle[PITCH].Value, Controller_Angle[YAW].Value, P_A, I_A, D_A); pc.printf("$MOT,%d,%d,%d,%d\r\n", (int)Motor_speed[0], (int)Motor_speed[1], (int)Motor_speed[2], (int)Motor_speed[3]); - pc.printf("$TIMES"); + /*pc.printf("$TIMES"); for(int i = 1; i < 10; i++) pc.printf(",%.3f", (Times[i]-Times[i-1])*1e6); - pc.printf("\r\n"); + pc.printf("\r\n");*/ wait(0.1); } } @@ -209,6 +219,11 @@ if (command == 'd') I_R -= 0.1; + if (command == 'x') + D_R += 0.001; + if (command == 'c') + D_R -= 0.001; + if (command == 'r') P_A += 0.1; if (command == 'f') @@ -224,12 +239,15 @@ if (command == 'h') PY -= 0.1; - /*if (command == 'o') { + if (command == 'o') { control_frequency += 100; + } if (command == 'l') { control_frequency -= 100; - }*/ + + } + pc.putc(command); LEDs.tilt(2);