ec

Dependents:   F3RC

Fork of EC by ROBOSTEP_LIBRARY

EC.h

Committer:
jack0325suzu
Date:
2016-11-19
Revision:
7:87c135463de7
Parent:
5:4abba4f54406
Child:
8:833757a1df66

File content as of revision 7:87c135463de7:

#ifndef __INCLUDED_EC_H_
#define __INCLUDED_EC_H_

#ifndef M_pi
#define M_pi 3.141592
#endif
/**increment型encoder用class*/

class Ec{
    private:
        int S;  //A相B相のパターン(1~4)
        bool stateA,stateB; //A・B相の状態
        int count;  //カウント数 分解能分で一周
        int pre_count;  //一つ前のカウント
        double precount;    //4倍精度カウント
        int solution;   //分解能
        double dt;  //角速度の計算間隔
        
        //z相用
        bool first;
        int rev;
        double now_time,old_time;
        double RPM,RPM_old;
        
        InterruptIn signalA_;
        InterruptIn signalB_;
        InterruptIn signalZ_;
        
        Timer timer;
        
        void upA();
        void downA();
        void upB();
        void downB();
        void upZ();
        void downZ();
    
    public:
        double omega;   //角速度
        /** コンストラクタの定義
         *  
         *  前の
         *  main関数の前に必ず一度宣言する
         *
         *  使うエンコーダの数だけ設定する必要がある
         *
         *  @param signalA エンコーダA相のピン名
         *  @param signalB エンコーダB相のピン名
         *  @param s エンコーダの分解能(省略可)
         *  @param t 角速度計算の間隔(省略可)  
         */
        Ec(PinName signalA,PinName signalB,PinName signalZ,int s,double t);
        Ec(PinName signalZ);
        
        ///countの値を返す関数(int型)
        int getCount();
        ///omega(角速度 rad/s)の値を計算する関数
        /** @section CAUTION
         *  CalOmega関数は、一定時間ごと(dtごと)に計算される必要があるので、main関数内でタイマー割り込みを設定する必要がある。
         *  @code
         *  #include "mbed.h"
         *  #include "EC.h"        //ライブラリをインクルード
         *
         *  Ec Ec1(PA_0,PA_1,1024,0.05); //分解能1024、計算間隔0.05秒に設定
         *  Ticker ticker;
         *  DigitalIn button(USER_BUTTON);
         *  Serial pc(USBTX,USBRX);
         *
         *  void calOmega(){
         *      Ec1.CalOmega();
         *  }
         *
         *  int main(){
         *      ticker.attach(&calOmega,0.05); //0.05秒間隔で角速度を計算
         *     while(1){
         *          pc.printf(" count1=%d ",Ec1.getCount());
         *          pc.printf(" omega1=%f\r\n ",Ec1.getOmega());
         *          if(!button) Ec1.reset();     //USERボタンを押したらリセット
         *      }
         *  }
         * @endcode
         */
        void CalOmega();
        ///omega(角速度 rad/s)の値を返す関数(double型)
        double getOmega();
        ///四倍精度のcountの値を返す関数(double型)
        double getPreCount();
        ///エンコーダを初期状態に戻す関数 countやomegaの値を0にする
        void reset();
        ///角速度計算の間隔dtを決めることができる(デフォルトは0.05秒)
        void setTime(double t);
        
        double getRPM();
        int getrev();
        
        ///角速度計算の間隔
        static double deftime;
        ///エンコーダの分解能のデフォルト値
        static int defsolution;
        
        
    
};

///速度制御用class 
///Ec classを継承している
/** @section Example
  * @code
  * #include "mbed.h"
  * #include "EC.h" //ヘッダファイルをインクルード
  *
  * SpeedControl motor1(PA_0,PA_1,1024,0.05,PB_8,PB_9); //エンコーダ分解能1024、角速度計算間隔を0.05秒に設定
  * Ticker ticker;  //角速度計算用ticker
  * DigitalIn button(USER_BUTTON);
  * Serial pc(USBTX,USBRX);
  *
  * void calOmega() //角速度計算関数
  * {
  *   motor1.CalOmega();
  * }
  *
  * int main()
  * {
  *    ticker.attach(&calOmega,0.05);      //0.05秒間隔で角速度を計算
  *    motor1.setPIDparam(0.15,0.0,0.15);  //PIDパラメータを設定
  *    motor1.setDOconstant(46.3);         //duty比と角速度の変換係数を46.3に設定
  *    
  *    int kai=0;
  *
  *    while(1) {
  *        motor1.Sc(-10);     //角速度10rad/sで逆回転
  *        if(kai>=500){       //ループ500回ごとに角速度・出力duty比を表示
  *            pc.printf("omega=%f duty=%f \r\n",motor1.getOmega(),motor1.duty);
  *            kai=0;
  *        }
  *        if(!button) break;  //ボタンを押したら停止
  *        kai++;
  *    }
  *    motor1.stop();
  * }
  * @endcode
  */


class SpeedControl : public Ec{
    private:
        double Kv_p,Kv_d,Kv_i;
        double diff,diff_old,integral;
        double out_duty,out;
        //Serial pc(USBTX,USBRX);
    protected:
        
    public:
        PwmOut pwm_F_;
        PwmOut pwm_B_;

        /** constractorの定義
         *  @param signalA encoderA相のピン名
         *  @param signalB encoderB相のピン名
         *  @param s encoderの分解能(省略可)
         *  @param t 角速度計算の間隔(省略可)
         *  @param pwm_F motorを正転させるpwmピン名
         *  @param pwm_B motorを後転させるpwmピン名
         *  motorを正転させるとencoderのcountが正のほうに加算されるようにencoderとmotorを設置する
         */
        SpeedControl( PinName signalA , PinName signalB , PinName signalZ , int s, double t, PinName pwm_F , PinName pwm_B);
        //SpeedControl( PinName signalZ , PinName pwm_F , PinName pwm_B);
        /** duty比を角速度に変換させるための定数
         *
         *  使うモーターやギア比や供給電圧によって変化するので一度duty比と角速度の関係を調べてグラフの傾きから求める
         * 
         *  多少ずれてもPIDが何とかしてくれるのでそこまでの精度は必要ない
         *
         *  デフォルトは45 これは380モータとエンコーダを直結して12V電圧で動かしたときの結果
         *  
         *  
         */
        double C;
        /** 速度制御関数、引数は目標速度
         *
         *  この目標角加速度になるようにモーターを回転させることができる
         *
         *  負の数を代入すれば逆回転することができる
         *
         *  出力できるduty比は最大で0.5までに設定してある
         *  @param target_omega 目標角速度
         *
         *  @section CAUTION(printfについて)
         *
         *  上記のプログラムのように、速度制御ではループ500回ごとにprintfをしている。
         *  
         *  printfはプログラム的に大きな負担がかかり、かなり時間がかかってしまうものである。
         *  
         *  なのでループごとにいちいちprintfをさせると、速度の収束にかなり時間がかかってしまう。
         *
         *  (どんなプログラムにも言えるが、)そのためこのようなprintfの頻度を少なくさせるような工夫が必要になる。
         *
         */
        void Sc(double target_omega);
        /** PIDパラメータ設定関数
         *
         *  引数はそれぞれp,i,dパラメータ
         *
         *  デフォルトは全部0に設定してある
         *
         *  だいたいp=0.15くらいでなんとかなる(知らんけど)
         *  @param p p制御パラメータ
         *  @param i i制御パラメータ
         *  @param d d制御パラメータ
         */
         
        void setPIDparam(double p,double i,double d);
        /** 角速度・duty比変換定数(C)の設定関数
         *
         *  文字通りである 
         *  @param c duty比を角速度に変換させるための定数
         */
        void setDOconstant(double c);
        
        /** モーター停止用関数 */
        void stop();
        
        /** モーター正回転用関数
            @param duty 回転duty比
        */
        void turnF(double duty);
        
        /** モーター逆回転用関数
            @param duty 回転duty比
        */
        void turnB(double duty);
        
        /** 出力duty比
        */
        double duty;
        
        void ScZ(double target_RPM);
        void Accelarate(double target_duty);
};
#endif