2014 sift / Mbed 2 deprecated TVDctrller2017_brdRev1_PandA

Dependencies:   mbed

Fork of TVDctrller2017_brdRev1_ver6 by 2014 sift

TVDCTRL.cpp

Committer:
sift
Date:
2016-07-24
Revision:
4:d7778cde0aff
Parent:
3:821e2f07a260
Child:
5:a5462959b3ab

File content as of revision 4:d7778cde0aff:

#include "TVDCTRL.h"
#include "MCP4922.h"
#include "Steering.h"

extern AnalogIn apsP;
extern AnalogIn apsS;
extern AnalogIn brake;
extern DigitalOut LED[];
extern InterruptIn rightMotorPulse;
extern InterruptIn leftMotorPulse;
extern DigitalOut MotorPulse[];
extern MCP4922 mcp;

Timer RightPulseTimer;
Timer LeftPulseTimer;
Ticker ticker1;
Ticker ticker2;
Ticker ticker3;

#define apsPVol() (apsP.read() * 3.3)
#define apsSVol() (apsS.read() * 3.3)

struct {
    unsigned int valA:12;
    unsigned int valB:12;
} McpData;

//各変数が一定値を超えた時点でエラー検出とする
//2つのAPSの区別はつけないことにする
volatile struct errCounter_t errCounter= {0,0,0,0,0,0,0};

volatile int gApsP=0, gApsS=0, gBrake=0;        //現在のセンサ値
volatile int rawApsP=0, rawApsS=0, rawBrake=0;  //現在の補正無しのセンサ値

float convertVoltage(int count)
{
    return (count*(3.3f/0xFFFF));
}

void getCurrentErrCount(struct errCounter_t *ptr)
{
    ptr->apsUnderVolt = errCounter.apsUnderVolt;
    ptr->apsExceedVolt = errCounter.apsExceedVolt;
    ptr->apsErrorTolerance = errCounter.apsErrorTolerance;
    ptr->apsStick = errCounter.apsStick;
    ptr->brakeUnderVolt = errCounter.brakeUnderVolt;
    ptr->brakeExceedVolt = errCounter.brakeExceedVolt;
    ptr->brakeFuzzyVolt = errCounter.brakeFuzzyVolt;
    ptr->brakeOverRide = errCounter.brakeOverRide;
}

int loadCurrentSensor(int sensor)
{
    switch (sensor) {
        case APS_PRIMARY:
            return gApsP;
        case APS_SECONDARY:
            return gApsS;
        case BRAKE:
            return gBrake;
        default:
            return -1;
    }
}

int loadRawSensor(int sensor)
{
    switch (sensor) {
        case APS_PRIMARY:
            return rawApsP;
        case APS_SECONDARY:
            return rawApsS;
        case BRAKE:
            return rawBrake;
        default:
            return -1;
    }
}

int myAbs(int x)
{
    return (x<0)?-x:x;
}

bool loadSensorFlag = false;

//タイマー割り込みでコールされる
void loadSensorsISR(void)
{
    loadSensorFlag = true;
}

//関数内処理時間より短い時間のタイマーのセットは禁止
void loadSensors(void)
{
    if(true == loadSensorFlag) {
        loadSensorFlag = false;
        static int preApsP=0, preApsS=0;            //過去のセンサ値
        static int preBrake=0;
        int tmpApsP=0, tmpApsS=0, tmpBrake=0;       //補正後のセンサ値
        int tmpApsErrCountU=0, tmpApsErrCountE=0;   //APSの一時的なエラーカウンタ

        //Low Pass Filter
        tmpApsP = (int)(apsP.read_u16()*ratioLPF + preApsP*(1.0f-ratioLPF));
        tmpApsS = (int)(apsS.read_u16()*ratioLPF + preApsS*(1.0f-ratioLPF));
        tmpBrake = (int)(brake.read_u16()*ratioLPF + preBrake*(1.0f-ratioLPF));

        //生のセンサ値取得
        rawApsP = tmpApsP;
        rawApsS = tmpApsS;
        rawBrake = tmpBrake;

        //センサーチェック
        //APS上限値チェック
        if(tmpApsP > APS_MAX_POSITION + ERROR_TOLERANCE) {
            tmpApsP = APS_MAX_POSITION;         //異常時,上限値にクリップ
            tmpApsErrCountE++;
        }
        if(tmpApsS > APS_MAX_POSITION + ERROR_TOLERANCE) {
            tmpApsS = APS_MAX_POSITION;         //異常時,上限値にクリップ
            tmpApsErrCountE++;
        }
        if(0 == tmpApsErrCountE)
            errCounter.apsExceedVolt = 0;       //どちらも正常時エラーカウンタクリア
        else
            errCounter.apsExceedVolt += tmpApsErrCountE;

        //APS下限値チェック
        if(tmpApsP < APS_MIN_POSITION - ERROR_TOLERANCE) {
            tmpApsP = APS_MIN_POSITION;         //下限値にクリップ
            tmpApsErrCountU++;
        }
        if(tmpApsS < APS_MIN_POSITION - ERROR_TOLERANCE) {
            tmpApsS = APS_MIN_POSITION;         //下限値にクリップ
            tmpApsErrCountU++;
        }
        if(0 == tmpApsErrCountU)
            errCounter.apsUnderVolt = 0;        //どちらも正常時エラーカウンタクリア
        else
            errCounter.apsUnderVolt += tmpApsErrCountU;

        //センサー偏差チェック
        if(myAbs(tmpApsP - tmpApsS) > APS_DEVIATION_TOLERANCE) {    //偏差チェックには補正後の値(tmp)を使用
            errCounter.apsErrorTolerance++;
        } else {
            errCounter.apsErrorTolerance = 0;
        }

        //小さい方にクリップ
        //APS値は好きな方を使いな
        if(tmpApsP > tmpApsS) {
            tmpApsP = tmpApsS;
        } else {
            tmpApsS = tmpApsP;
        }

        //Brake上限値チェック
        if(tmpBrake > BRK_OFF_VOLTAGE + ERROR_TOLERANCE) {
            errCounter.brakeExceedVolt++;
            tmpBrake = BRK_OFF_VOLTAGE;
        } else {
            errCounter.brakeExceedVolt = 0;
        }

        //Brake下限値チェック
        if(tmpBrake < BRK_ON_VOLTAGE - ERROR_TOLERANCE) {
            errCounter.brakeUnderVolt++;
            tmpBrake = BRK_ON_VOLTAGE;
        } else {
            errCounter.brakeUnderVolt = 0;
        }

        //brake範囲外電圧チェック
        if((tmpBrake < BRK_OFF_VOLTAGE - ERROR_TOLERANCE) && (tmpBrake > BRK_ON_VOLTAGE + ERROR_TOLERANCE)) {
            errCounter.brakeFuzzyVolt++;
            tmpBrake = BRK_OFF_VOLTAGE;
        } else {
            errCounter.brakeFuzzyVolt=0;
        }

        //APS固着チェック
        if((preApsP == tmpApsP) && (tmpApsP == APS_MAX_POSITION))
            errCounter.apsStick++;
        else
            errCounter.apsStick=0;

        //ブレーキオーバーライドチェック
        if((tmpApsP >= APS_OVERRIDE+APS_MIN_POSITION) && (tmpBrake > BRK_ON_VOLTAGE)) {
            errCounter.brakeOverRide++;
        } else {
            errCounter.brakeOverRide=0;
        }

        //センサ値取得
        gApsP = tmpApsP;
        gApsS = tmpApsS;
        gBrake = tmpBrake;

        //未来の自分に期待
        preApsP = rawApsP;
        preApsS = rawApsS;
        preBrake = rawBrake;
    }
}

int gRightPulseTime=100000, gLeftPulseTime=100000;
bool loadVelocityFlag = false;

void countRightPulseISR(void)
{
    //Do not use "printf" in interrupt!!!
    static int preTime=0;
    int currentTime = RightPulseTimer.read_us();

    gRightPulseTime = currentTime - preTime;

    if(gRightPulseTime < 40)  //25000rpm上限より早い場合
        gRightPulseTime = 40;

    if(currentTime < 1800000000) {
        preTime = currentTime;
    } else {    //30分経過後
        RightPulseTimer.reset();
        preTime = 0;
    }
}

void countLeftPulseISR(void)
{
    //Do not use "printf" in interrupt!!!
    static int preTime=0;
    int currentTime = LeftPulseTimer.read_us();

    gLeftPulseTime = currentTime - preTime;

    if(gLeftPulseTime < 40)  //25000rpm上限より早い場合
        gLeftPulseTime = 40;

    if(currentTime < 1800000000) {
        preTime = currentTime;
    } else {    //30分経過後
        LeftPulseTimer.reset();
        preTime = 0;
    }
}

void loadVelocityISR(void)
{
    loadVelocityFlag = true;
}

int getPulseTime(SelectMotor rl)
{
    static int preRightPulse, preLeftPulse;

    if(loadVelocityFlag == true) {
        loadVelocityFlag = false;

        preRightPulse = (int)(gRightPulseTime*ratioLPF_V + preRightPulse*(1.0f-ratioLPF_V));
        preLeftPulse = (int)(gLeftPulseTime*ratioLPF_V + preLeftPulse*(1.0f-ratioLPF_V));
    }

    if(rl == RIGHT_MOTOR)
        return preRightPulse;
    else
        return preLeftPulse;
}

float getVelocity(void)
{
    int rightPulse=0, leftPulse=0;
    int avePulseTime;

    rightPulse = getPulseTime(RIGHT_MOTOR);
    leftPulse = getPulseTime(LEFT_MOTOR);

    if(rightPulse > 100000)
        rightPulse = 100000;
    if(leftPulse > 100000)
        leftPulse = 100000;

    avePulseTime = (int)((rightPulse+leftPulse)/2.0f);

    if(avePulseTime < 40)    //最低パルス時間にクリップ
        avePulseTime = 40;

    return (M_PI*TIRE_DIAMETER / ((avePulseTime/1000000.0f)*TVD_GEAR_RATIO));
}

void generatePulse(void)
{
    static bool flag = false;
    flag = !flag;
    MotorPulse[0] = MotorPulse[1] = LED[0] = flag;
}

int distributeTorque(float velocity, float steering)
{
    int disTor = 0;
    float sqrtVelocity = velocity*velocity;
    float Gy=0;

    Gy = (sqrtVelocity*steering) / ((1.0f+STABIRITY_FACTOR*sqrtVelocity)*WHEEL_BASE);

    if(Gy > 9.8f)
        Gy = 9.8f;

    if(Gy < 1.0f) {
        disTor = 0;
    } else if(Gy < 4.9f) {
        disTor = ((float)MAX_DISTRIBUTION_TORQUE / (9.8f-4.9f) * Gy);
    } else {    //0.5G以上は配分一定
        disTor = MAX_DISTRIBUTION_TORQUE;
    }

    return disTor;
}

//トルク値線形補間関数
int interpolateLinear(int torque, int currentMaxTorque)
{
    return (int)( ((double)(DACOUTPUT_MAX-LINEAR_REGION_VOLTAGE)/(currentMaxTorque-LINEAR_REGION_TORQUE)) * torque ) + LINEAR_REGION_VOLTAGE;
}

unsigned int calcTorqueToVoltage(int torque, SelectMotor rl)
{
    int outputVoltage=0;
    int pulseTime=0;
    int rpm=0;
    int index=0;

    if(torque <= LINEAR_REGION_TORQUE) {         //要求トルク<=2.5Nmの時
        outputVoltage = (int)((double)LINEAR_REGION_VOLTAGE/LINEAR_REGION_TORQUE * torque);
    } else {
        pulseTime = getPulseTime(rl);
        rpm = (int)((1.0/pulseTime) * 1000000.0 * 60.0);  //pulseTime:[ms]

        if(rpm < 3000) {        //3000rpm未満は回転数による出力制限がない領域
            outputVoltage = interpolateLinear(torque, MAX_MOTOR_TORQUE);
            //outputVoltage = (int)((DACOUTPUT_MAX-LINEAR_REGION_VOLTAGE)/(MAX_MOTOR_TORQUE-LINEAR_REGION_TORQUE) * torque) + LINEAR_REGION_VOLTAGE;
        } else if(rpm <=11000) {
            index = (int)((rpm - 3000)/10.0);    //マップは10rpm刻みに作成

            if(calcMaxTorque[index] < torque) {   //要求トルクが現在の回転数での最大値を超えている時
                outputVoltage = DACOUTPUT_VALID_RANGE;  //現在の回転数での最大トルクにクリップ
            } else {
                outputVoltage = interpolateLinear(torque, calcMaxTorque[index]);
                //outputVoltage = (int)((DACOUTPUT_MAX-LINEAR_REGION_VOLTAGE)/(calcMaxTorque[index]-LINEAR_REGION_TORQUE) * torque) + LINEAR_REGION_VOLTAGE;
            }
        } else if(rpm < 12000) {
            if(MAX_REVOLUTION_TORQUE < torque) {    //要求トルクが現在の回転数での最大値を超えている時
                outputVoltage = DACOUTPUT_VALID_RANGE;
            } else {
                outputVoltage = interpolateLinear(torque, MAX_REVOLUTION_TORQUE);
                //outputVoltage = (int)((float)(DACOUTPUT_MAX-LINEAR_REGION_VOLTAGE)/(MAX_REVOLUTION_TORQUE-LINEAR_REGION_TORQUE) * torque) + LINEAR_REGION_VOLTAGE;
            }
        } else {
            //outputVoltage = 0;  //回転上限のため出力停止
        }
    }

    outputVoltage += DACOUTPUT_MIN;   //最低入力電圧でかさ上げ

    return (unsigned int)(FIX_DACOUTFORM * outputVoltage);  //DACの分解能に適応(16bit->12bit)
}

int calcRequestTorque(void)
{
    int currentAPS;
    int requestTorque;

    currentAPS = ((gApsP>gApsS) ? gApsS : gApsP);   //センサ値は小さい方を採用
    if(currentAPS < APS_MIN_POSITION)
        currentAPS = 0;
    else
        currentAPS -= APS_MIN_POSITION;     //オフセット修正

    if(currentAPS < APS_DEADBAND)   //デッドバンド内であれば要求トルク->0
        requestTorque = 0;
    else
        requestTorque = (int)(((double)MAX_OUTPUT_TORQUE / APS_VALID_RANGE) * (currentAPS - APS_DEADBAND));

    if(requestTorque > MAX_MOTOR_TORQUE)
        requestTorque = MAX_MOTOR_TORQUE;
    else if(requestTorque < 0)
        requestTorque = 0;

    return requestTorque;
}

void driveTVD(void)
{
    int requestTorque=calcRequestTorque();  //ドライバーリクエストトルク
    int distributionTor=0;  //分配トルク
    float torqueHigh, torqueLow;

    loadSensors();      //APS,BRAKE更新
    loadSteerAngle();   //舵角更新
    getPulseTime(RIGHT_MOTOR);  //車速更新(更新時は片方指定コールでOK)

    distributionTor = distributeTorque(getVelocity(), MAX_STEER_ANGLE / M_PI * getSteerAngle());  //トルク分配量計算
    distributionTor /= 2.0f;

    //デバッグ終わったらこの行は消すこと!!!!!
    distributionTor=0;

    if(requestTorque + distributionTor > MAX_OUTPUT_TORQUE)  //片モーター上限時最大値にクリップ
        torqueHigh = MAX_OUTPUT_TORQUE;
    else
        torqueHigh = requestTorque + distributionTor;

    if(requestTorque - distributionTor < 0) {
        torqueLow = 0;
        torqueHigh = (int)(requestTorque*2.0);   //片モーター下限値時,反対のモーターも出力クリップ
    } else
        torqueLow = requestTorque - distributionTor;

    if(getSteerDirection()) {
        //steer left
        McpData.valA = calcTorqueToVoltage(torqueHigh, RIGHT_MOTOR);
        McpData.valB = calcTorqueToVoltage(torqueLow, LEFT_MOTOR);
    } else {
        //steer right
        McpData.valA = calcTorqueToVoltage(torqueLow, RIGHT_MOTOR);
        McpData.valB = calcTorqueToVoltage(torqueHigh, LEFT_MOTOR);
    }

    mcp.writeA(McpData.valA);   //右モーター
    mcp.writeB(McpData.valB);   //左モーター
}

void initTVD(void)
{
    rightMotorPulse.mode(PullUp);
    leftMotorPulse.mode(PullUp);
    rightMotorPulse.fall(&countRightPulseISR);
    leftMotorPulse.fall(&countLeftPulseISR);

    RightPulseTimer.reset();
    LeftPulseTimer.reset();
    RightPulseTimer.start();
    LeftPulseTimer.start();

    ticker1.attach(&loadSensorsISR, 0.01f);    //サンプリング周期10msec
    //ticker2.attach(&generatePulse, 0.03f);
    ticker3.attach(&loadVelocityISR, 0.01f);
}