ControlMainでの変更に対応して、新しくレポジトリを作りました

Dependencies:   Control_Yokutan_CANver1 XBusServo mbed mbed-rtos

Fork of ControlYokutan2017 by albatross

main.cpp

Committer:
tsumagari
Date:
2017-06-28
Branch:
mpu????????
Revision:
65:e30d198efe71
Parent:
64:9d7582920f50

File content as of revision 65:e30d198efe71:

//翼端can program
#include "mbed.h"
#include "MPU6050.h"
#include "INA226.hpp"
#include "rtos.h"
#include "XBusServo.h"
#include "math.h"

#define TO_SEND_DATAS_NUM 7
#define INIT_SERVO_PERIOD_MS 20
#define WAIT_LOOP_TIME 0.02
#define CONTROL_VALUES_NUM 7
#define TO_SEND_CAN_ID 100
#define SEND_DATAS_LOOP_TIME 0.1
#define RECEIVE_DATAS_LOOP_TIME 0.1

#define MPU_LOOP_TIME 0.01
#define MPU_DELT_MIN 250

#define ERURON_MOVE_DEG_INI_R 14.4//18.0       //degree
#define DRUG_MOVE_DEG_INI_R 0.49
#define ERURON_TRIM_INI_R 0.38633  //値lowerすると頭上げ 0.37で後縁一致
#define DRUG_TRIM_INI_R  0.37

#define ERURON_MOVE_DEG_INI_L -15.52//-19.4     //degree
#define DRUG_MOVE_DEG_INI_L -0.52
#define ERURON_TRIM_INI_L  0.51567  // 値を大きくすると頭上げ
#define DRUG_TRIM_INI_L    0.73//値を小さくすると開く側

/*ドラッグラダー
初期値 0.65
最大角0.99
*/

CAN can(p30,p29);
CANMessage recmsg;
Serial pc(USBTX,USBRX);
I2C ina226_i2c(p28,p27);
INA226 VCmonitor(ina226_i2c);
PwmOut drugServo(p22);
PwmOut eruronServo(p23);
DigitalOut led1(LED1);
AnalogIn drugAna(p20);
AnalogIn eruronAna(p19);
DigitalIn IsRPin(p11);
DigitalIn setTrimPin(p12);
DigitalIn EDstatePin(p14);
DigitalIn setMaxDegPin(p15);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
Ticker sendDatasTicker;
//Ticker toStringTicker;
Ticker receiveDatasTicker;
MPU6050 mpu6050;
Timer t;

//Set up I2C, (SDA,SCL)
I2C i2c_mpu(p9,p10);

char toSendDatas[TO_SEND_DATAS_NUM];
char floatValues[10];
float eruronTrim;
float drugTrim;
float eruronMoveDeg;
float drugMoveDeg;
float eruronfloat = 0.0;
unsigned short ina_val;
double V,C;
bool SERVO_FLAG;
bool INA_FLAG;
bool MPU_FLAG;
int gyroX;
int gyroY;
int gyroZ;
float sum = 0;
float drugInput = 0.0;
uint32_t sumCount = 0;

char gyro_c[6] = {0,0,0,0,0,0};

void toString();
void receiveDatas();
void WriteServo();
void MpuInit();
void mpuProcessing(void const *arg);

Ticker gTimer;

bool servoInit()
{
    drugServo.period_ms(INIT_SERVO_PERIOD_MS);
    return true;
}

void sendDatas()
{
    if(can.write(CANMessage(TO_SEND_CAN_ID, toSendDatas, TO_SEND_DATAS_NUM))) {
    }
}

void MpuInit()
{
    i2c_mpu.frequency(400000);  // use fast (400 kHz) I2C
    t.start();
    uint8_t whoami = mpu6050.readByte(MPU6050_ADDRESS, WHO_AM_I_MPU6050);  // Read WHO_AM_I register for MPU-6050
    if (whoami == 0x68) { // WHO_AM_I should always be 0x68
        Thread::wait(100);
        mpu6050.MPU6050SelfTest(SelfTest); // Start by performing self test and reporting values
        Thread::wait(100);
        if(SelfTest[0] < 1.0f && SelfTest[1] < 1.0f && SelfTest[2] < 1.0f && SelfTest[3] < 1.0f && SelfTest[4] < 1.0f && SelfTest[5] < 1.0f) {
            mpu6050.resetMPU6050(); // Reset registers to default in preparation for device calibration
            mpu6050.calibrateMPU6050(gyroBias, accelBias); // Calibrate gyro and accelerometers, load biases in bias registers
            mpu6050.initMPU6050(); //pc.printf("MPU6050 initialized for active data mode....\n\r"); // Initialize device for active mode read of acclerometer, gyroscope, and temperature
            Thread::wait(200);
        } else {
        }
    } else {
        //pc.printf("out\n\r"); // Loop forever if communication doesn't happen
    }
}


void mpuProcessing(void const *arg)
{
    MpuInit();
    while(1) {
        if(mpu6050.readByte(MPU6050_ADDRESS, INT_STATUS) & 0x01) {  // check if data ready interrupt
            mpu6050.readAccelData(accelCount);  // Read the x/y/z adc values
            mpu6050.getAres();
            ax = (float)accelCount[0]*aRes - accelBias[0];  // get actual g value, this depends on scale being set
            ay = (float)accelCount[1]*aRes - accelBias[1];
            az = (float)accelCount[2]*aRes - accelBias[2];
            mpu6050.readGyroData(gyroCount);  // Read the x/y/z adc values
            mpu6050.getGres();
            gx = (float)gyroCount[0]*gRes; // - gyroBias[0];  // get actual gyro value, this depends on scale being set
            gy = (float)gyroCount[1]*gRes; // - gyroBias[1];
            gz = (float)gyroCount[2]*gRes; // - gyroBias[2];
            tempCount = mpu6050.readTempData();  // Read the x/y/z adc values
            temperature = (tempCount) / 340. + 36.53; // Temperature in degrees Centigrade
        }
        Now = t.read_us();
        deltat = (float)((Now - lastUpdate)/1000000.0f) ; // set integration time by time elapsed since last filter update
        lastUpdate = Now;
        sum += deltat;
        sumCount++;
        if(lastUpdate - firstUpdate > 10000000.0f) {
            beta = 0.04;  // decrease filter gain after stabilized
            zeta = 0.015; // increasey bias drift gain after stabilized
        }
        mpu6050.MadgwickQuaternionUpdate(ax, ay, az, gx*PI/180.0f, gy*PI/180.0f, gz*PI/180.0f);
        delt_t = t.read_ms() - count;
        if (delt_t > MPU_DELT_MIN) {
            yaw   = atan2(2.0f * (q[1] * q[2] + q[0] * q[3]), q[0] * q[0] + q[1] * q[1] - q[2] * q[2] - q[3] * q[3]);
            pitch = -asin(2.0f * (q[1] * q[3] - q[0] * q[2]));
            roll  = atan2(2.0f * (q[0] * q[1] + q[2] * q[3]), q[0] * q[0] - q[1] * q[1] - q[2] * q[2] + q[3] * q[3]);
            pitch *= 180.0f / PI;
            yaw   *= 180.0f / PI;
            roll  *= 180.0f / PI;
            //   myled= !myled;
            count = t.read_ms();
            sum = 0;
            sumCount = 0;
        }
        gyro_c[0]=(char)((int)pitch);
        gyro_c[1]=(char)(int)((pitch - (int)pitch)*100);
        gyro_c[2]=(char)((int)roll);
        gyro_c[3]=(char)(int)((roll - (int)roll)*100);
        gyro_c[4]=(char)((int)yaw);
        gyro_c[5]=(char)(int)((yaw - (int)yaw)*100);
        pc.printf("p:%f,r:%f,y:%f\n\r",pitch,roll,yaw);
        Thread::wait(1);
    }//while(1)
}


bool inaInit()
{
    if(!VCmonitor.isExist()) {
        pc.printf("VCmonitor NOT FOUND\n");
        return false;
    }
    ina_val = 0;
    if(VCmonitor.rawRead(0x00,&ina_val) != 0) {
        pc.printf("VCmonitor READ ERROR\n");
        return false;
    }
    VCmonitor.setCurrentCalibration();
    return true;
}

//動かしたいエレボンの角度から、動かしたいサーボホーンの角度を得る。
double ConvertDeg(double servo)
{
    return 0.0011 * pow(servo,3) + 0.017 * pow(servo,2) + 2.3019 * servo - 0.2269;
    //return 0.0003*pow(servo,3)+0.0039*pow(servo,2)+1.746*servo - 0.0105;
}

//ホーンを動かしたい角度から、変化させるアナログ値の幅を得る。3度変化
double GetValueByHorn(double deg)
{
    return deg*(0.10/25.7);
}

double GetFloatByErebon(double erebonDeg)
{
    double servoDeg = ConvertDeg(erebonDeg);
    return GetValueByHorn(servoDeg);
}

void init()
{
    if(IsRPin) {
        eruronTrim = ERURON_TRIM_INI_R;
        drugTrim = DRUG_TRIM_INI_R;
        eruronMoveDeg =GetFloatByErebon(ERURON_MOVE_DEG_INI_R);
        drugMoveDeg =DRUG_MOVE_DEG_INI_R;
    } else {
        eruronTrim = ERURON_TRIM_INI_L;
        drugTrim = DRUG_TRIM_INI_L;
        eruronMoveDeg = GetFloatByErebon(ERURON_MOVE_DEG_INI_L);
        drugMoveDeg = DRUG_MOVE_DEG_INI_L;
    }
    SERVO_FLAG = servoInit();
    INA_FLAG = inaInit();
    sendDatasTicker.attach(&sendDatas,SEND_DATAS_LOOP_TIME);
    // toStringTicker.attach(&toString,0.5);
    receiveDatasTicker.attach(&receiveDatas,RECEIVE_DATAS_LOOP_TIME);
}

void updateDatas()
{
    if(INA_FLAG) {
        int tmp = VCmonitor.getVoltage(&V);
        tmp = VCmonitor.getCurrent(&C);
    }

    for(int i = 0; i < TO_SEND_DATAS_NUM - 1; i++) {
        toSendDatas[i] = gyro_c[i];
    }
//    toSendDatas[TO_SEND_DATAS_NUM - 1] = (char)(V/100);
    toSendDatas[TO_SEND_DATAS_NUM - 1] = (char)V;
}

void receiveDatas()
{
    if(can.read(recmsg)) {              //ここの中でpc.printfすると重すぎて固まるので注意
        for(int i = 0; i < 5; i++) {
            floatValues[i] = recmsg.data[i];
        }
        drugInput = recmsg.data[5]- '0';
        eruronfloat = atof(floatValues);
        led1 = !led1;
    }
}

double calcPulse(float analog)
{
    return (0.0006 + (analog)*(0.00240-0.00060) );
}

void WriteServo()
{
    // for(int i = 0; i< 10; i++) {
//        pc.printf("%c",floatValues[i]);
//    }
//    pc.printf(" : %f",eruronfloat);
//    pc.printf("\n\r");
    drugServo.pulsewidth(calcPulse(drugTrim + drugMoveDeg *drugInput));
    eruronServo.pulsewidth(calcPulse( eruronTrim + eruronMoveDeg * eruronfloat));
//    pc.printf("ef:%10f  %5f\n\r",eruronfloat,drugInput);
}

void setTrim()
{
    led2 =  1;
    if(EDstatePin) {
        eruronTrim = eruronAna.read();
        eruronServo.pulsewidth(calcPulse(eruronTrim));
    } else {
        drugTrim = drugAna.read();
        drugServo.pulsewidth(calcPulse(drugTrim));
    }
    //pc.printf("eruronTrim:%f    drugTrim:%f\n\r",eruronTrim,drugTrim);
    pc.printf("eruronTrim:%f    drugTrim:%f    ",eruronTrim,drugTrim);
    pc.printf("eMD:%f   dMD:%f    ei:%d\n\r",eruronMoveDeg,drugMoveDeg,eruronfloat);
}

void setMaxDeg()
{
    led4 = 1;
    float eruronTemp = eruronAna.read();
    float drugTemp = drugAna.read();
    if(EDstatePin) {
        eruronMoveDeg = eruronTemp-eruronTrim;
        eruronServo.pulsewidth(calcPulse(eruronTemp));
    } else {
        drugServo.pulsewidth(calcPulse(drugTemp));
        drugMoveDeg = drugTemp-drugTrim;
    }
    pc.printf("eruronTrim:%f    drugTrim:%f    ",eruronTrim,drugTrim);
    pc.printf("eMD:%f   dMD:%f    ef:%d\n\r",eruronMoveDeg,drugMoveDeg,eruronfloat);
    wait_us(10);
}

int main()
{
    init();

    setTrimPin.mode(PullDown);
    setMaxDegPin.mode(PullDown);
    EDstatePin.mode(PullDown);
    IsRPin.mode(PullDown);
    Thread mpu_thread(&mpuProcessing);

    // start motion
//    gTimer.attach_us(&XbusIntervalHandler, 1000000 / kMotionInterval);

    while(1) {
        while(setTrimPin) {
            setTrim();
        }
        while (setMaxDegPin) {
            setMaxDeg();
        }
        led4 = 0;
        led2 = 0;
        //receiveDatas();
//        sendDatas();
        WriteServo();
        updateDatas();
        led3 = !led3;
        wait(WAIT_LOOP_TIME);
    }
}