cvl-robot's diary

研究ノート メモメモ https://github.com/dotchang/

モバイルバッテリー、有名メーカーの製品が良いと思い込んでいると時代に置いて行かれるかも?

Ankerの大容量モバイルバッテリーが良い、という記事を読んだ。
www.gurinovation.com
まさしくこの機種Anker PowerCore 20100を購入して使っていたので悪くない製品だということは知っているのだが、購入して1年ちょっと経った今、へたってしまってただ大きくて重い物体になってしまっている。

安価なので買い替えてもいいのだが、トランジスタ技術2017年1月号に気になる記事が載っている。
トランジスタ技術 2017年 1月号

151~157ページ、大塚康二さんの書かれた全力実験!No.1モバイルバッテリを探せ!の中で、いくつかのバッテリーの寿命テストとランキングが紹介されている。
詳細は載せられないが、ここで一番だったのは全然知らない中華メーカーRockの製品で、サイクル寿命が長いことが絶賛されていた。

2位はソニーのCP-10A、3位はAnker5。

何が言いたいのかというと、
リチウムイオン電池の性能は日本製が一番!やアメリカが強い!などと思い込んでいると、電池は電子機器の基幹部品なので、あっという間に中国に置いて行かれて没落してしまう危機にあるのではないかということ。

ネットワークの実時間性を保障してほしいので、DDSを調べる

DDSは、RTPSパケットを使って、Pub-Sub形式でネットワーク上のデータをやり取りする仕組み(分散ネットワーキングミドルウェア)だそうです。
https://ja.wikipedia.org/wiki/Data_Distribution_Service

諸悪の根源であるところのCORBAの系統のようなので使い勝手が心配ですが、レイテンシやディレイが一定範囲内であることを期待できるリアルタイムのデータ通信の手法としては本命視されています。
商用やオープンソースでいくつかの実装があるようです。オープンソースで使い勝手のよさそうなものを探していきます。

RTI Connext DDS

https://www.rti.com/products
商用で最も普及しているのがこれです。ただし、150万円ぐらいするようです。
大学や研究機関向けにはオープンソースで機能限定版を申請により提供してくれるようですが、プロジェクトに他の企業からの予算が少しでもついていると、使用できないそうです。
今時の大学は、一生懸命外部予算の獲得に励んでいますから、この使用条件を満たすところなんてほとんどないのではないでしょうか?
登録しようとすると、連絡はアメリカの本社に行きますが、結局日本には日本の代理店があるからそっちに聞いてくれ、と言われます。
ということで、使えません。

openSplice

かつてRTI社と一緒にDDS規格の仕様策定にかかわったThalesという会社が開発していたのを、Prismtechという会社が引き継いでオープンソースで提供されているライブラリです。
一見、良さそうに見えますが、最近はほとんどメンテナンスされていないようなので、開発が止まっているように見えます。
初期にはROS2での採用も検討されていたようですが、外されてしまいました。
http://qiita.com/sobeit@github/items/20d9f1478bbc1a33d096
Hello World exampleを動かしてみようとすればわかりますが、release.batという環境設定用のバッチファイルを実行したコマンドプロンプト窓から実行ファイルを呼び出す必要があります。
やりようによっては要らない作業なのかもしれませんが、よくわからない処理の上に面倒くさいです。
ということで、使えません。

FastRTPS

www.eprosima.com
eProsimaという会社がオープンソースとして管理しているライブラリです。RTPSはパケットの形式でDDSとは謡っていないのですが、RTPSでPub-Sub形式でデータをやり取りするライブラリなので、そのものですね。
ROS2でも採用されるようなので、大本命だと思います。

ROS2では、ほかにもTwin Oaks Softwareという会社のDDSも検討されているようです。
CoreDX DDS Data Distribution Service Middleware | Twin Oaks Computing, Inc
眺めた限り、HelloWorldExampleが一番簡素に書けているのでいずれこれも使ってみたいです。

FastRTPSをちょっと触ってみる

Windows10 64bit、VisualStudio 2015の環境です。
ソースも落ちていますが、コンパイルにはboostが必要で面倒くさいので、バイナリ提供版を使います。
上記ページのDownload Now!ボタンを押せばダウンロードページに飛びますが、なぜか異様に重いです。今日ここの環境では4分ぐらいかかりました。簡単なユーザー登録を済ませれば、ダウンロードページに飛びます。
ダウンロードしたexeを実行すればインストールが始まり、特に問題なく進むとは思いますが、そのままでは管理者権限の必要なC:\Program Files\eProsimaフォルダの下にインストールされてしまい、後で少し問題が出ます。できれば、c:\workspaceなど適当な場所にしておいたほうがよさそうに思います。
もっとも簡単そうなC:\Program Files\eProsima\fastrtps 1.3.1\examples\C++\HelloWorldExampleを見てみると,cmake形式でプロジェクトが提供されています。
ProgramFilesフォルダの下にファイルを書き込むことが億劫なので、適当な場所にコピーして適当にcmakeを通してやれば、slnファイルができるので普通にビルドします。
HelloWorldPublisher.bat

HelloWorldExample.exe publisher

HelloWorldSubscriber.bat

HelloWorldExample.exe subscriber

などの適当なバッチファイルを作って2つを実行してやれば、特に問題なくプログラムは動くかと思います。

自前のデータ形式をやり取りするプログラムを書くには。

お、簡単じゃん、などと思いながらソースコードを見てみることにすると、やたらとファイルが多いことに気が付きます。
HelloWorldPublisher.cxxと.h、HelloWorldSubscriber.cppと.hはわかるとしてもまだ余計なものが一杯ありすぎます。
HelloWorld_main.cppをのぞいてみると、これは単に引数によって2つのプログラムの呼び出しを変えているだけのものなので無視していいことが分かります。
残ったHelloWorldPubSubTypes.cxxはなんぞこれと見てみると、わけのわからないことが書かれています。こんなもの、書いてらんないぞ、と焦って頭のほうのコメントをよく見てみると、

This file was generated by the tool fastcdrgen.

なんてことが書かれていて、自動生成されたファイルだということが分かり、胸をなでおろします。
fastcdrgenとは何ぞ、と思ってフォルダの中を探してみても同じファイル名のものはありません。すわ、別のプロジェクトを入れる必要があるのかな、面倒くせーななどと思っていると、
C:\Program Files\eProsima\fastrtps 1.3.1\binの下にfastrtpsgen.bat
という名前がよく似た感じのファイルを見つけることができます。これかなー、と思ってググってみるとコレでした。このムービーを見るとよくわかりますし、最初からちゃんとマニュアルを追っていけば書いてあります。
www.youtube.com
ちゃんとマニュアルは読みましょう、という教訓ですね。

.idlファイルに定義したデータパケットの形式をfastrtpsgen.bat(中でjarが呼ばれているのでjavaプログラム)で、idlをコンパイルするとPub-Subテンプレートファイルが生成される、のでこれを各自で書き換えて使えということのようです。
main関数を乗っ取られた形で提供されるのが、とても気に入らないしスレッドを分けることが必須なのが多少厄介ですが、この枠組みに乗れば簡単に使うことはできるようです。
個人的には、CORBA時代の悪夢を思い出すようでアレルギーが発症しそうなのですが、stringだけをやり取りするように決めてしまって、stringの中をOSCパケットなどにして、openFrameworksなどから呼び出せるようにラップしてしまえば、何とか使えるようになりそうです。

まとめ

使えそうなことはわかったので、性能はどうなんだろう?ということを調べてみると、ちょうどいいことにZeroMQとの性能比較がまとめられていました。
www.eprosima.com
FastRTPSの方が良いよ、と言いたいのだと思いますが、ディレイもレイテンシもほとんど変わりませんね。メッセージサイズが大きいときにはややFastRTPSが有利で、小さいときにはZeroMQのほうが有利と読めます。
ロボットで使われるメッセージは、画像や音を除けば大半は短いコマンドなので、ZeroMQでいいじゃん、ということになります。
ネットワークの管理を厳密にやりたいときはFastRTPSの方がずっと良さそうです。
(が、正直、超絶面倒くさいから、当面はZeroMQでよくってROS2が本格的に動き出したら使わせてもらおう、という結論。)

今日の必要最小限パソコン

一応、日本のメーカーNEC製(中身はレノボに乗っ取られていますが)で、
MicrosoftのOfficeが付いていて、
拡張性は皆無だけど最低限度のスペックがあり、見た目がわりとカッコよくて、ぎりぎり頑張れるぐらいの値段、なので親に使わせるPCとかなら有り、かなぁ、と。

raspberryPi2/3に(オーディオ用では無い)複数の普通のDAコンバータmcp4725を接続して、4ch以上のアナログ出力を得る方法

以前書いた記事の続編です。
cvl-robot.hateblo.jp

mcp4725は、安価で簡単に12ビット分解能のアナログ出力を得ることができる良いICなのですが、I2Cアドレスが0x60,0x61の2つからしか選択できません。
したがって、素直に使うと2chの出力しか得られません。
このページでは、もっと多くの出力数が必要で困る場合の対処方法を紹介します。

FXMA2102のOEピンを制御して時分割でI2Cの出力先を切り替える

4chの場合の参考回路図を載せておきます。
今回の回路図では、5V出力ではなく3.3V出力ですので注意してください。VCCBに5V電源をつないでやれば5V出力も取れます。
もっと数を増やしていくこともできますが、FXMA2102の数に応じて応答時間がどんどん遅くなることに留意してください。
f:id:cvl-robot:20170125225552p:plain
スルーホール基板でも、ほとんどジャンパ飛ばすことなく回路が引けます。

参考ソースコード

2つのFXMA2102のOEピンをそれぞれ、4番ピンと11番ピンに接続した場合の例です。
I2Cバスを切り替えたときに、毎回EEPROMに焼きこまなくても、稼働中は出力電圧をちゃんと維持してくれます。

#include <stdio.h>
#include <unistd.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>

#define BCM_4  4
#define BCM_11 11

void setDACVoltage(int deviceid, int voltage, int writeToEEPROM)
{
        int fd = wiringPiI2CSetup(deviceid);

        voltage = (voltage > 4095) ? 4095 : voltage;
        voltage = (voltage >> 4);

        if(writeToEEPROM)
                wiringPiI2CWriteReg16(fd, 0b01100000, voltage);
        else
                wiringPiI2CWriteReg16(fd, 0b01000000, voltage);

        close(fd);
}

int main(int argc, char* argv[])
{
        if(wiringPiSetupGpio() == -1){
                printf("wiringPi GPIO error\n");
                return -1;
        }

        pinMode(BCM_4, OUTPUT);
        pullUpDnControl(BCM_4, PUD_OFF); // PUD_OFF, PUD_UP, PUD_DOWN
        pinMode(BCM_11, OUTPUT);
        pullUpDnControl(BCM_11, PUD_OFF);

        while(1){
                for(int i=0; i<4096; i++){
                        digitalWrite(BCM_4, 0);
                        digitalWrite(BCM_11, 1);
                        setDACVoltage(0x60, i, 0);
                        setDACVoltage(0x61, i/2, 0);

                        digitalWrite(BCM_11, 0);
                        digitalWrite(BCM_4, 1);
                        setDACVoltage(0x60, 4095-i, 0);
                        setDACVoltage(0x61, (4095-i)/2, 0);
                }
        }
        return 0;
}

今日のオシロスコープ

今、趣味に毛が生えたレベルでオシロスコープを買うなら、これしか無いでしょう!
4chで5万円台は、(一昔前の感覚からすれば)驚異的です。
RIGOL(リゴル) デジタルオシロスコープ 50MHz 4ch 1GSa/s DS1054Z

半精度浮動小数点(2バイト)と単精度浮動小数点(4バイト)のC言語での変換方法を調べる

Tiのマイコンで使われているfloat_t型は2バイトで与えられています。一般に知られているfloat型は4バイトの単精度浮動小数点です。
2バイトで表現される浮動小数点は半精度浮動小数点(half)と呼ばれ、最近では、レンダリング機械学習の用途で需要が増えているそうです。
しかし、普通のC言語には簡単に変換する方法は提供されていません。これを簡単に変換する方法を調べてみたいと思います。

半精度浮動小数点について

半精度浮動小数点数 - Wikipedia

素敵な情報源

  1. C++用の半精度(16bit)浮動小数点ライブラリって無いですか? 環… - 人力検索はてな
  2. 単精度浮動小数点数 - Wikiwand
  3. Search · half float · GitHub

OpenEXRで使われているライブラリは、ilmbase-2.2.0の中のHalfフォルダにあります。BSDライセンスとのことなので自由に使えそうです。ただし、c++実装です。
matlabが配布しているソースコードは、mex前提みたいなので借りてきて使うのは面倒そうです。

c言語向けでは、githubにあるramenhutさんのhalfライブラリがc++で書かれてはいるのですが、きれいで簡単でよさそうです。

というわけで、ramemhutさんのライブラリを改造して試してみたいと思います。

GitHub - ramenhut/half: IEEE 754 16-bit Float

テストコード。ただし、メンバー変数のm_uiFormatをpublicにしてある。

#include <iostream>
#include "half.h"

using namespace std;

int main(void){
    // Here your code !
    FLOAT16 a = 0.222;
    FLOAT16 b = 0;
    unsigned char upper, lower;
        
    upper = ((unsigned short)a.m_uiFormat >> 8) & 0xff;
    lower = (unsigned short)a.m_uiFormat & 0xff;
    b.m_uiFormat = (upper << 8) + lower;
    
    cout << a << endl;
    cout << (int)lower << " " << (int)upper << endl;
    cout << b << endl;
    
    return 0;
}

結果
0.221924
26 51
0.221924

Ti C2000 F28027FやF28069MマイコンにRS485を接続する方法

TIのInstaSPINマイコンを汎用モータードライバに使いたいとき、インターフェースのショボさが致命的な欠点になります。
モータは複数台を同時に使いたい場面が多くあると思うのですが、SCI(UART)ピンは出ているもののTX,RXしか出ていません。
汎用ピンが一杯余っていればいいのですが、モータードライバボードをマウントしてしまうと、片手ほども余っていません。
どうすればいいのかなー、と思って掲示板を見ていたら答えがありました。

Reference

TIDA-00540 RS-485 / RS-232 Multiprotocol Transceiver Reference Design | TI.com

ま、こんな面倒でコストがかかりそうな物、いちいち作っていられませんね。売ってくれ~。
F28069MのCANを使う方向で検討します。


この回路を作れば行けそう!
RS232C-RS485変換機

F28027用RS485Interface 追記2017/01/27

一応、設計し直してみました。
一応、動くことを確認しました。
9600bps用に約2msecのRTS信号を作っているので、通信速度を変更するときはCRの作るtwを確認して調整する必要があります。
74HC123のメーカーやパッケージによってtwが異なることがあるようなので、データーシートをよく確認してください。
送信は大丈夫なようなのですが、受信でエラーがやたらと多いので何か間違いがあるかもしれません。

f:id:cvl-robot:20170127162214p:plain
中途半端な実態配線図みたいな回路図で、見にくくてすみません。

今日のはんだごて

普通のやつを2~3本買うぐらいなら、覚悟を決めてこれ一本持っていた方が良い。
ハッコー(HAKKO) 小型温調式はんだこて デジタルタイプ FX888D-01SV

モータドライバをシリアル通信で制御するためにInstaSPINの重要パラメータの確認

F28027Fのproj_lab05bのmain.hを参考にします.
gMotorVarsという構造体変数に重要なパラメータがまとめられています.

typedef struct _MOTOR_Vars_t_
{
  bool Flag_enableSys;
  bool Flag_Run_Identify;
  bool Flag_MotorIdentified;
  bool Flag_enableForceAngle;
  bool Flag_enableFieldWeakening;
  bool Flag_enableRsRecalc;
  bool Flag_enableUserParams;
  bool Flag_enableOffsetcalc;
  bool Flag_enablePowerWarp;
  bool Flag_enableSpeedCtrl;

  bool Flag_enableRun;
  bool Flag_RunState;
  bool Flag_enableFlyingStart;

  CTRL_State_e CtrlState;         // Read Only
  EST_State_e EstState;           // Read Only

  USER_ErrorCode_e UserErrorCode;

  CTRL_Version CtrlVersion;

  _iq IdRef_A;
  _iq IqRef_A;
  _iq SpeedRef_pu;
  _iq SpeedRef_krpm;
  _iq SpeedTraj_krpm;             // Read Only
  _iq MaxAccel_krpmps;
  _iq Speed_krpm;                 // Read Only
  _iq OverModulation;
  _iq RsOnLineCurrent_A;
  _iq SvgenMaxModulation_ticks;
  _iq Flux_Wb;                    // Read Only
  _iq Torque_Nm;                  // Read Only

  float_t MagnCurr_A;             // Read Only
  float_t Rr_Ohm;                 // Read Only
  float_t Rs_Ohm;                 // Read Only
  float_t RsOnLine_Ohm;
  float_t Lsd_H;                  // Read Only
  float_t Lsq_H;                  // Read Only
  float_t Flux_VpHz;              // Read Only

  float_t ipd_excFreq_Hz;
  _iq     ipd_Kspd;
  _iq     ipd_excMag_coarse_pu;
  _iq     ipd_excMag_fine_pu;
  float   ipd_waitTime_coarse_sec;
  float   ipd_waitTime_fine_sec;

  _iq Kp_spd;
  _iq Ki_spd;

  _iq Kp_Idq;
  _iq Ki_Idq;

  _iq Vd;
  _iq Vq;
  _iq Vs;
  _iq VsRef;
  _iq VdcBus_kV;                   // Read Only

  _iq Id_A;
  _iq Iq_A;
  _iq Is_A;

  MATH_vec3 I_bias;
  MATH_vec3 V_bias;

  _iq SpeedSet_krpm;

  _iq angle_sen_pu;
  _iq angle_est_pu;
  _iq speed_sen_pu;
  _iq speed_est_pu;

  _iq speedHigh_hall2fast_pu;
  _iq speedLow_hall2fast_pu;
}MOTOR_Vars_t;

コメントのパラメータはループ内で更新されるので、読み込み専用。
これらのデータをシリアルでやり取りするために、それぞれの変数型のメモリサイズを調べておきます。

sizeof(bool)=1
sizeof(CTRL_State_e)=1
sizeof(EST_State_e)=1
sizeof(USER_ErrorCode_e)=1
sizeof(CTRL_Version)=4
sizeof(float_t)=2
sizeof(float)=2
sizeof(_iq)=2
sizeof(MATH_vec3)=6

_iqは標準では、24ビット目に小数点を置く.

#define _IQ24(A) (long) ((A) * 16777216.0L)

計算はこのように行われる.

#include <stdio.h>

long float_to_iq24(float a, unsigned char* lower, unsigned char* upper)
{
    long b = (long)(a * 16777216.0L) >> 8;
    *lower = (b%0x100)&0xff;
    *upper = (b/0x100)&0xff;
    return b;
}

float _iq24l_to_float(long b)
{
    float a = (b<<8)/16777216.0;
    return a;
}

float _iq24_to_float(unsigned char lower, unsigned char upper)
{
    long b = (upper<<8) + lower;
    return _iq24l_to_float(b);
}


int main(void){
    float a = 0.1;
    long b = (long)(a * 16777216.0L) >> 8;
    printf("dec=%f, _iq=%ld, lower_byte=%d, upper_byte=%d\n", a, b, (b%0x100)&0xff, (b/0x100)&0xff);

    unsigned char l, u;
    long lo;
    lo = float_to_iq24(a, &l, &u);
    printf("float_to_iq24: %f %ld %d %d\n", a, lo, l, u);
    
    float f;
    f = _iq24_to_float(l, u);
    printf("_iq24_to_float: %f %d %d\n", f, l, u);
    
    f = _iq24l_to_float(lo);
    printf("_iq24_to_float: %f %ld", f, lo);
}

ちょっとしたテストにはWEBサービスが便利。
Web-based online coding environment | paiza.IO
実行例
dec=0.100000, _iq=6553, lower_byte=153, upper_byte=25

f:id:cvl-robot:20161228215056p:plain
f:id:cvl-robot:20161228215110p:plain


ctrl_state.h

//! \brief Enumeration for the controller states
//!
typedef enum {
  CTRL_State_Error=0,           //!< the controller error state
  CTRL_State_Idle,              //!< the controller idle state
  CTRL_State_OffLine,           //!< the controller offline state
  CTRL_State_OnLine,            //!< the controller online state
  CTRL_numStates                //!< the number of controller states
} CTRL_State_e;

est_state.h

//! \brief Enumeration for the estimator error codes
//!
typedef enum
{
  EST_ErrorCode_NoError=0,               //!< no error error code
  EST_ErrorCode_Flux_OL_ShiftOverFlow,   //!< flux open loop shift overflow error code
  EST_ErrorCode_FluxError,               //!< flux estimator error code
  EST_ErrorCode_Dir_ShiftOverFlow,       //!< direction shift overflow error code
  EST_ErrorCode_Ind_ShiftOverFlow,       //!< inductance shift overflow error code
  EST_numErrorCodes                      //!< the number of estimator error codes
} EST_ErrorCode_e;


//! \brief Enumeration for the estimator states
//!
typedef enum
{
  EST_State_Error=0,            //!< error
  EST_State_Idle,               //!< idle
  EST_State_RoverL,             //!< R/L estimation
  EST_State_Rs,                 //!< Rs estimation state
  EST_State_RampUp,             //!< ramp up the speed
#if !defined(FAST_ROM_V1p6) && !defined(FAST_ROM_V1p7)
  EST_State_ConstSpeed,         //!< constant speed after ramp up
#endif
  EST_State_IdRated,            //!< control Id and estimate the rated flux
  EST_State_RatedFlux_OL,       //!< estimate the open loop rated flux
  EST_State_RatedFlux,          //!< estimate the rated flux 
  EST_State_RampDown,           //!< ramp down the speed 
  EST_State_LockRotor,          //!< lock the rotor
  EST_State_Ls,                 //!< stator inductance estimation state
  EST_State_Rr,                 //!< rotor resistance estimation state
  EST_State_MotorIdentified,    //!< motor identified state
  EST_State_OnLine,             //!< online parameter estimation
  EST_numStates                 //!< the number of estimator states
} EST_State_e;
//! \brief Enumeration for the user error codes
//!
typedef enum
{
  USER_ErrorCode_NoError=0,                           //!< no error error code
  USER_ErrorCode_iqFullScaleCurrent_A_High=1,         //!< iqFullScaleCurrent_A too high error code
  USER_ErrorCode_iqFullScaleCurrent_A_Low=2,          //!< iqFullScaleCurrent_A too low error code
  USER_ErrorCode_iqFullScaleVoltage_V_High=3,         //!< iqFullScaleVoltage_V too high error code
  USER_ErrorCode_iqFullScaleVoltage_V_Low=4,          //!< iqFullScaleVoltage_V too low error code
  USER_ErrorCode_iqFullScaleFreq_Hz_High=5,           //!< iqFullScaleFreq_Hz too high error code
  USER_ErrorCode_iqFullScaleFreq_Hz_Low=6,            //!< iqFullScaleFreq_Hz too low error code
  USER_ErrorCode_numPwmTicksPerIsrTick_High=7,        //!< numPwmTicksPerIsrTick too high error code
  USER_ErrorCode_numPwmTicksPerIsrTick_Low=8,         //!< numPwmTicksPerIsrTick too low error code
  USER_ErrorCode_numIsrTicksPerCtrlTick_High=9,       //!< numIsrTicksPerCtrlTick too high error code
  USER_ErrorCode_numIsrTicksPerCtrlTick_Low=10,       //!< numIsrTicksPerCtrlTick too low error code
  USER_ErrorCode_numCtrlTicksPerCurrentTick_High=11,  //!< numCtrlTicksPerCurrentTick too high error code
  USER_ErrorCode_numCtrlTicksPerCurrentTick_Low=12,   //!< numCtrlTicksPerCurrentTick too low error code
  USER_ErrorCode_numCtrlTicksPerEstTick_High=13,      //!< numCtrlTicksPerEstTick too high error code
  USER_ErrorCode_numCtrlTicksPerEstTick_Low=14,       //!< numCtrlTicksPerEstTick too low error code
  USER_ErrorCode_numCtrlTicksPerSpeedTick_High=15,    //!< numCtrlTicksPerSpeedTick too high error code
  USER_ErrorCode_numCtrlTicksPerSpeedTick_Low=16,     //!< numCtrlTicksPerSpeedTick too low error code
  USER_ErrorCode_numCtrlTicksPerTrajTick_High=17,     //!< numCtrlTicksPerTrajTick too high error code
  USER_ErrorCode_numCtrlTicksPerTrajTick_Low=18,      //!< numCtrlTicksPerTrajTick too low error code
  USER_ErrorCode_numCurrentSensors_High=19,           //!< numCurrentSensors too high error code
  USER_ErrorCode_numCurrentSensors_Low=20,            //!< numCurrentSensors too low error code
  USER_ErrorCode_numVoltageSensors_High=21,           //!< numVoltageSensors too high error code
  USER_ErrorCode_numVoltageSensors_Low=22,            //!< numVoltageSensors too low error code
  USER_ErrorCode_offsetPole_rps_High=23,              //!< offsetPole_rps too high error code
  USER_ErrorCode_offsetPole_rps_Low=24,               //!< offsetPole_rps too low error code
  USER_ErrorCode_fluxPole_rps_High=25,                //!< fluxPole_rps too high error code
  USER_ErrorCode_fluxPole_rps_Low=26,                 //!< fluxPole_rps too low error code
  USER_ErrorCode_zeroSpeedLimit_High=27,              //!< zeroSpeedLimit too high error code
  USER_ErrorCode_zeroSpeedLimit_Low=28,               //!< zeroSpeedLimit too low error code
  USER_ErrorCode_forceAngleFreq_Hz_High=29,           //!< forceAngleFreq_Hz too high error code
  USER_ErrorCode_forceAngleFreq_Hz_Low=30,            //!< forceAngleFreq_Hz too low error code
  USER_ErrorCode_maxAccel_Hzps_High=31,               //!< maxAccel_Hzps too high error code
  USER_ErrorCode_maxAccel_Hzps_Low=32,                //!< maxAccel_Hzps too low error code
  USER_ErrorCode_maxAccel_est_Hzps_High=33,           //!< maxAccel_est_Hzps too high error code
  USER_ErrorCode_maxAccel_est_Hzps_Low=34,            //!< maxAccel_est_Hzps too low error code
  USER_ErrorCode_directionPole_rps_High=35,           //!< directionPole_rps too high error code
  USER_ErrorCode_directionPole_rps_Low=36,            //!< directionPole_rps too low error code
  USER_ErrorCode_speedPole_rps_High=37,               //!< speedPole_rps too high error code
  USER_ErrorCode_speedPole_rps_Low=38,                //!< speedPole_rps too low error code
  USER_ErrorCode_dcBusPole_rps_High=39,               //!< dcBusPole_rps too high error code
  USER_ErrorCode_dcBusPole_rps_Low=40,                //!< dcBusPole_rps too low error code
  USER_ErrorCode_fluxFraction_High=41,                //!< fluxFraction too high error code
  USER_ErrorCode_fluxFraction_Low=42,                 //!< fluxFraction too low error code
  USER_ErrorCode_indEst_speedMaxFraction_High=43,     //!< indEst_speedMaxFraction too high error code
  USER_ErrorCode_indEst_speedMaxFraction_Low=44,      //!< indEst_speedMaxFraction too low error code
  USER_ErrorCode_powerWarpGain_High=45,               //!< powerWarpGain too high error code
  USER_ErrorCode_powerWarpGain_Low=46,                //!< powerWarpGain too low error code
  USER_ErrorCode_systemFreq_MHz_High=47,              //!< systemFreq_MHz too high error code
  USER_ErrorCode_systemFreq_MHz_Low=48,               //!< systemFreq_MHz too low error code
  USER_ErrorCode_pwmFreq_kHz_High=49,                 //!< pwmFreq_kHz too high error code
  USER_ErrorCode_pwmFreq_kHz_Low=50,                  //!< pwmFreq_kHz too low error code
  USER_ErrorCode_voltage_sf_High=51,                  //!< voltage_sf too high error code
  USER_ErrorCode_voltage_sf_Low=52,                   //!< voltage_sf too low error code
  USER_ErrorCode_current_sf_High=53,                  //!< current_sf too high error code
  USER_ErrorCode_current_sf_Low=54,                   //!< current_sf too low error code
  USER_ErrorCode_voltageFilterPole_Hz_High=55,        //!< voltageFilterPole_Hz too high error code
  USER_ErrorCode_voltageFilterPole_Hz_Low=56,         //!< voltageFilterPole_Hz too low error code
  USER_ErrorCode_maxVsMag_pu_High=57,                 //!< maxVsMag_pu too high error code
  USER_ErrorCode_maxVsMag_pu_Low=58,                  //!< maxVsMag_pu too low error code
  USER_ErrorCode_estKappa_High=59,                    //!< estKappa too high error code
  USER_ErrorCode_estKappa_Low=60,                     //!< estKappa too low error code
  USER_ErrorCode_motor_type_Unknown=61,               //!< motor type unknown error code
  USER_ErrorCode_motor_numPolePairs_High=62,          //!< motor_numPolePairs too high error code
  USER_ErrorCode_motor_numPolePairs_Low=63,           //!< motor_numPolePairs too low error code
  USER_ErrorCode_motor_ratedFlux_High=64,             //!< motor_ratedFlux too high error code
  USER_ErrorCode_motor_ratedFlux_Low=65,              //!< motor_ratedFlux too low error code
  USER_ErrorCode_motor_Rr_High=66,                    //!< motor_Rr too high error code
  USER_ErrorCode_motor_Rr_Low=67,                     //!< motor_Rr too low error code
  USER_ErrorCode_motor_Rs_High=68,                    //!< motor_Rs too high error code
  USER_ErrorCode_motor_Rs_Low=69,                     //!< motor_Rs too low error code
  USER_ErrorCode_motor_Ls_d_High=70,                  //!< motor_Ls_d too high error code
  USER_ErrorCode_motor_Ls_d_Low=71,                   //!< motor_Ls_d too low error code
  USER_ErrorCode_motor_Ls_q_High=72,                  //!< motor_Ls_q too high error code
  USER_ErrorCode_motor_Ls_q_Low=73,                   //!< motor_Ls_q too low error code
  USER_ErrorCode_maxCurrent_High=74,                  //!< maxCurrent too high error code
  USER_ErrorCode_maxCurrent_Low=75,                   //!< maxCurrent too low error code
  USER_ErrorCode_maxCurrent_resEst_High=76,           //!< maxCurrent_resEst too high error code
  USER_ErrorCode_maxCurrent_resEst_Low=77,            //!< maxCurrent_resEst too low error code
  USER_ErrorCode_maxCurrent_indEst_High=78,           //!< maxCurrent_indEst too high error code
  USER_ErrorCode_maxCurrent_indEst_Low=79,            //!< maxCurrent_indEst too low error code
  USER_ErrorCode_maxCurrentSlope_High=80,             //!< maxCurrentSlope too high error code
  USER_ErrorCode_maxCurrentSlope_Low=81,              //!< maxCurrentSlope too low error code
  USER_ErrorCode_maxCurrentSlope_powerWarp_High=82,   //!< maxCurrentSlope_powerWarp too high error code
  USER_ErrorCode_maxCurrentSlope_powerWarp_Low=83,    //!< maxCurrentSlope_powerWarp too low error code
  USER_ErrorCode_IdRated_High=84,                     //!< IdRated too high error code
  USER_ErrorCode_IdRated_Low=85,                      //!< IdRated too low error code
  USER_ErrorCode_IdRatedFraction_indEst_High=86,      //!< IdRatedFraction_indEst too high error code
  USER_ErrorCode_IdRatedFraction_indEst_Low=87,       //!< IdRatedFraction_indEst too low error code
  USER_ErrorCode_IdRatedFraction_ratedFlux_High=88,   //!< IdRatedFraction_ratedFlux too high error code
  USER_ErrorCode_IdRatedFraction_ratedFlux_Low=89,    //!< IdRatedFraction_ratedFlux too low error code
  USER_ErrorCode_IdRated_delta_High=90,               //!< IdRated_delta too high error code
  USER_ErrorCode_IdRated_delta_Low=91,                //!< IdRated_delta too low error code
  USER_ErrorCode_fluxEstFreq_Hz_High=92,              //!< fluxEstFreq_Hz too high error code
  USER_ErrorCode_fluxEstFreq_Hz_Low=93,               //!< fluxEstFreq_Hz too low error code
  USER_ErrorCode_ctrlFreq_Hz_High=94,                 //!< ctrlFreq_Hz too high error code
  USER_ErrorCode_ctrlFreq_Hz_Low=95,                  //!< ctrlFreq_Hz too low error code
  USER_ErrorCode_estFreq_Hz_High=96,                  //!< estFreq_Hz too high error code
  USER_ErrorCode_estFreq_Hz_Low=97,                   //!< estFreq_Hz too low error code
  USER_ErrorCode_RoverL_estFreq_Hz_High=98,           //!< RoverL_estFreq_Hz too high error code
  USER_ErrorCode_RoverL_estFreq_Hz_Low=99,            //!< RoverL_estFreq_Hz too low error code
  USER_ErrorCode_trajFreq_Hz_High=100,                //!< trajFreq_Hz too high error code
  USER_ErrorCode_trajFreq_Hz_Low=101,                 //!< trajFreq_Hz too low error code
  USER_ErrorCode_ctrlPeriod_sec_High=102,             //!< ctrlPeriod_sec too high error code
  USER_ErrorCode_ctrlPeriod_sec_Low=103,              //!< ctrlPeriod_sec too low error code
  USER_ErrorCode_maxNegativeIdCurrent_a_High=104,     //!< maxNegativeIdCurrent_a too high error code
  USER_ErrorCode_maxNegativeIdCurrent_a_Low=105,      //!< maxNegativeIdCurrent_a too low error code
  USER_numErrorCodes=106                              //!< the number of user error codes
} USER_ErrorCode_e;
//! \brief Defines the controller (CTRL) version number
//!
typedef struct _CTRL_Version_
{
  uint16_t rsvd;                 //!< reserved value
  CTRL_TargetProc_e targetProc;  //!< the target processor
  uint16_t major;                //!< the major release number
  uint16_t minor;                //!< the minor release number
} CTRL_Version;

proj_lab05bのフローチャート
f:id:cvl-robot:20161221183251p:plain

f:id:cvl-robot:20161221232949p:plain
FlagCtrlStateChangedの中身
f:id:cvl-robot:20161221232610p:plain

mainスレッド
f:id:cvl-robot:20161221230408p:plain

続きを読む