WindowsUSB-Serial(RS232C)の応答速度(訂正)

FTDIのFT232Rを使ったUSB-Serialで最大3Mbpsの速度が出ることは実証できた。

ただ、WindowsAPIの応答速度(読出しと読出しのインターバル時間)には制限があることに気付いた。

大学の先生に納めたシステムでstm32F407のシリアルポートにFTDIのFT232Rを接続してUSBシリアルでPCと通信する様にしたのだが通信の応答時間が16mS以下に出来ないという指摘があった。

WinAPIの使い方の問題ではないかと考えてあれこれ調べて高速化の手法を探してみたのだが結局、WinAPIを普通に使ったのではUSBシリアルの応答を数mSにすることは出来ないという結論に達した。

当初はDelphi用コンポーネントのCPortで速い応答性が得られていると思っていたが、それはTTimerのインターバルを1mSにしても実際は10mSの周期でしか動いてないための勘違いだった。

USBのデバイスドライバに直接アクセスするDLLを使えば1mS程度のインターバルで通信が出来るのだが、USBシリアル経由で仮想COMを使って通信をするのはタイムクリティカルな制御に向いてないようだ。

※USBシリアルでも高速応答(高速に送受信の切り替え)が可能

結論から言えばFTDIのICを使ったUSBシリアルでも1mS毎に送受信を切り替えて通信出来ることが分かった。

先生からUSBシリアルで接続した高速雲台をPCから制御するために何とか高速で送受信が出来るようにして欲しいとの依頼がありFTDIの ftd2xx.dllの関数を直接呼び出す方式なら応答が速くなるだろうと思ってFTDIのサンプルを参考にしてプログラムを作ってみたが送受信の切り替えを16mS以下にすることはできなかった。

それで、改めて関連する情報をググってみたらどうもICの設定でLatencyTimerというのが影響していてそれを設定すれば応答が速くなるということなのでLatencyTimerを1mSに設定してみたところ無事1mSのサイクルで送受信を切り替えて通信できるようになった :-P

参考にしたサイト

設定部分のソース

/*
//
// ComPortを開く
//

BOOL OpenCom(int DevNum)
{
    unsigned dwThreadId;

    //FT_HANDLE ftHandle;
    FT_STATUS ftStatus;
	ULONG Status;

    ftStatus = FT_Open(DevNum,&ftHandle);
    if (!FT_SUCCESS(ftStatus))
        return false;

	ftStatus = FT_ResetDevice(ftHandle);
    if (!FT_SUCCESS(ftStatus)) {
        goto close;
    }

	ftStatus = FT_SetBaudRate(ftHandle, FT_BAUD_460800);
    if (!FT_SUCCESS(ftStatus)) {
        goto close;
    }

    ftStatus = FT_SetDataCharacteristics(
                    ftHandle,
                    FT_BITS_8,
                    FT_STOP_BITS_1,
                    FT_PARITY_NONE
                    );
    if (!FT_SUCCESS(ftStatus)) {
        goto close;
    }

    ftStatus = FT_SetFlowControl(
                    ftHandle,
                    FT_FLOW_NONE, //FlowControl,
                    0, //XonChar,
                    0  //XoffChar
                    );
    if (!FT_SUCCESS(ftStatus)) {
        goto close;
    }

    ftStatus = FT_SetChars(
                    ftHandle,
                    0, //ftData->EventChar,
                    false, //ftData->EventCharEnabled ? (UCHAR) 1 : (UCHAR) 0,
                    0, //ftData->ErrorChar,
                    false //ftData->ErrorCharEnabled ? (UCHAR) 1 : (UCHAR) 0
                    );
    if (!FT_SUCCESS(ftStatus)) {
        goto close;
    }

    FT_SetEventNotification(ftHandle, 0, NULL);

    FT_SetDtr(ftHandle);
    //FT_ClrDtr(ftHandle);

    FT_SetRts(ftHandle);
    //FT_ClrRts(ftHandle);

    FT_SetTimeouts(ftHandle, FT_DEFAULT_RX_TIMEOUT, FT_DEFAULT_TX_TIMEOUT);

	// 高速に送受信切替をしたい場合はこの設定の引数を小さくする
    FT_SetLatencyTimer(ftHandle, 1); // ms

	FT_Purge(ftHandle,FT_PURGE_TX | FT_PURGE_RX);

    //ftStatus = FT_GetModemStatus(ftHandle,&Status);
    //if (!FT_SUCCESS(ftStatus)) {
    //    goto close;
    //}

	return true;
close:
    FT_Close(ftHandle);
    return false;
}
カテゴリー: Delphi, Windows8, マイコン工作Tips | コメントをどうぞ

JDE Ver5.61 メモリマップ情報表示機能追加

JDEにメモリマップ情報表示機能を追加した(Ver5.61)

stm32F429にはRAMが192KB + 64KB内蔵されているが、メモリの機能が特化されているブロックを含むのでリンカスクリプトを書き換えてメモリ割り当てを変更する場合がある。
今まではメモリ配置を確認するのに マップファイル(*.map)を開いて.bssや.data等のセクションを検索してアドレスを確認していたのだがmb1046のデモプログラムになるとマップファイルのサイズが1584KB、ライン数で22239行にもなるのでメモリ配置の確認が面倒な作業になってしまった。

それで、マップファイルを解析して必要な情報だけをメッセージとして表示する機能を追加してみた。 8-)

カテゴリー: JDE, 開発環境 | コメントをどうぞ

JDEでSTM32F429I-EVALのデモプログラムをBuild

STM32F429の評価用に購入したSTM32F429I-EVALのデモプログラムをJDE(arm-eabi-gcc 4.8.3)で構築してみた。

stm32Fシリーズのライブラリは機能が豊富な代わりにソースの数が多くて自分のプロジェクトに組み込むのに結構な手間がかかる。
これまではサンプルプロジェクトをJDEに移植するのに手作業でファイルを一つずつプロジェクトに追加していたが、ライブラリがSTM32Cubeになってさらにソースの数が増えライブラリの場所も分散して手作業でライブラリを組み込んで使うのが大変な作業になってしまった。

それとGUI画面ででピン配置等を定義してテンプレートを自動的に生成してくれるSTM32CubeMXが提供されたのを機にSTM32CubeMXが生成するMDK-ARMとTrueStudioのプロジェクトからソースとインクルードパスをインポートする機能を追加してみた。

MDK-ARMのプロジェクト(Demonstrations->MB1046)からインポートしてGCCで構築したプログラムの実行結果が上の写真。

ちょっと戸惑ったのは、
stm32F429Iは192KByteのRAMを持っているが先頭から112KBのところにEtherNetのワークエリアがあるのでリンカスクリプトにRAM領域112KBを指定すると.bssオーバフローが発生してリンクエラーとなってしまう。それで、このプロジェクトはてっきり外部のSRAMを使っているものだと思い込んで外部SRAMを有効にしてみると上手く動作しないというところだった。

結局、このサンプルはRAMサイズを192KBに指定して構築することで正常に動作することがわかった。

カテゴリー: HUSROBO | コメントをどうぞ

stm32F4シリーズのFPUを使う

stm32F4シリーズのFPUの使い方について大きな勘違いをしていたことが発覚 :roll:

勘違いその1.
Codesourcery G++ Lite (arm-none-eabi-4.7.2)はFPUをサポートしていないと思っていたのだが、本当はしっかりサポートしていた。 :oops:
(今日ねむいさんのブログで見つけた次の情報で気がつきました)

ちなみに-mfloat-abi=※※※※ の意味はそれぞれ以下のように表されます。
1. -mfloat-abi=soft  :浮動小数点の演算に整数命令のみで構成された
浮動小数点演算ライブラリ(soft-float)を使う。
2. -mfloat-abi=softfp :浮動小数点の演算に浮動小数点演算命令を使うが、
floatを引数にする関数の呼び出し規約はsoft-floatと同じく汎用レジスタを
使って値を渡す(ソフトウエア・リンケージ)。
3. -mfloat-abi=hard  :浮動小数点の演算に浮動小数点演算命令を使い、
floatを引数にする関数は浮動小数点レジスタを使って値を渡す。

arm-none-eabi-4.7.2は-mfloat-abi=softfpしか受け付けなくて’softfp’というキーワードからハードウェアFPUは使わないと早とちりしていたのが間違いで、実はパラメータの受け渡し方法が違うだけでしっかりFPUを使っている。 :oops:
それに2番目の方が3番目の方法より少しばかり速いことも確認した。

勘違いその2.
FPUを有効にしたときnewlibの超越関数sin(),cos()等も当然早くなると思い込んでいた
そのためsin()cos()の実行時間を測定して1. 2. 3.どのオプションを較べても同じなのでFPUが有効になってないんじゃないかと思っていた。
stm32F4のFPU(DSP)は超越関数をサポートしていないためあまり速くならないためか、newlibのfpu/libm.aはFPUをサポートしていないみたいです。

newlibのlibm.aだけ構築しなおしてFPUを有効に出来ないかと四苦八苦している途中でDSPに最適化された超越関数や行列演算が別途用意されていることに気が付いた。
それはstMicroが提供しているライブラリの中のCMSIS/DSP_LIbの下にあるarm_sin_f32()、arm_cos_f32()という関数で、これを使うと期待通りsin cosの演算が凡そ一桁速くなることが確認できた。 8-)

FPUの使い方についてのポイントまとめ
1.プログラム開始時にFPUを有効にしなければならない
具体的にはstm32F4のライブラリにあるsystem_stm32f4xx.c中の関数SystemInit()(通常startupxxxxx.sの中で呼び出される)にある

/* FPU settings ------------------------------------------------------------*/
  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
  #endif

が有効になっていればOK
2.arm_sin_f32()等を使うときはシンボル ARM_MATH_CM4 を定義しておくこと

で、どのくらい早くなったかというと次のコードでテストしてみたら

/*
  FPUテスト
  sin(),cos()1万回の計算時間を測定し、その後データを連続出力
*/
void xTestFPU(void)
{
  int i,t;
  volatile float d,d0,d1;

  t = timer_1ms;
  for(d=i=0; i<10000; i++){
    //d0 = sin(d);
    d0 = arm_sin_f32(d);
    //d1 = cos(d);
    d1 = arm_cos_f32(d);
    d += 0.001;
    if( M_PI*2 < d ) d = 0;
  }
  t = timer_1ms - t;
  for(d=0;;){
    printf("%d,%0.3f,%0.3f\r\n",t,sin(d),cos(d));
    d += 0.001;
    if( M_PI*2 < d ) d = 0;
    vTaskDelay(1);
    sensebrk();
  }
}

arm-eabi-4.7.2の場合
-mfloat-abi= (1.)(2.)のどちらでもsin(),cos()1万回の実行時間 -> 344mS

arm-eabi-4.8.3の場合
-mfloat-abi= (1.)(3.)のどちらでもsin(),cos()1万回の実行時間 -> 347mS

arm_cos_f32(), arm_sin_f32()を使ったとき 1万回の実行時間 -> 39mS

という結果となりDSPタイプのFPUでも超越関数のスピードアップに有効なことが確認できました :-D

カテゴリー: CPUボード, stm32F4xx | コメントをどうぞ

JDEをVer5.60にバージョンアップしました

JDEをVer5.60にバージョンアップし、大幅な改定をしました

(使い勝手向上)
書き込みツール選択画面を整理、JTW32の設定を常時可能にした
oocdJTAGの書き込みコマンドを選択して設定できるようになった
環境が変わった時の「ツールを読み込みますか?」確認を廃止
ヘッダファイル検索をボタンをクリックした時だけにした
BootWrite等の今後使わないと思われるボタンを削除

(GCC)
arm-eabi-gcc-4.8.2, 4.8.3に対応しhard-floatが有効になった

(プロジェクト関連)
インクルードパス一覧をプロジェクトツリーからプロジェクト->ライブラリに移動
cpudefを常にプロジェクト下にコピーする仕様に変更
ソースディレクトリをインクリードパスに含めていたのを取りやめ
(※意図しない同名のヘッダファイルを読み込んでエラーになるため)
TrueStudioプロジェクトインポート機能を追加
MDK-ARMプロジェクトインポート機能を追加

(バグ修正)
画面を最大化するとコンパイル時にエラーが出るバグを修正
キーマップWINDOWSでctrl+Fで検索が呼び出せないバグ修正

カテゴリー: HUSROBO | コメントをどうぞ

ComPort Library for Delphi XE2, XE3, XE5

シリアルポートを扱うDelphi用コンポーネントにComPort Library (TComPort)というのがある。
http://sourceforge.net/projects/comport/ でDelphiXEまでサポート出来るものが公開されていてDelphi7で有難く使わせて貰っている。
最近FT232でCPUのシリアルポートが対応できればかなり早い転送速度を使えることがわかったのでシリアルポートが活躍する機会が増えると思い、
最近出番が増えてきたDelphiXE2以降で使えるように修正してみた。

Delphi7とDelphiXEの間にはAnsiString -> UnicodeStringの溝があってDelphi7で作ったプロジェクトをDelphiXEで使えるようにするためにはちょっとした苦労が必要だが、DelphiXEとDelphiXE2以降の間にも互換性のギャップがある。

DelphiXE2で本格的にマルチプラットフォーム対応となった影響だと思うが、DelphiXE と DelphiXE2の間にはライブラリ名や配置に違いが生じている。
例えばDelphiXEまでの Windows.pas が DelphiXE2では WinApi.Windows.pas  になっているのでuses節の記述を変えてやらなければならない。

手探りであれこれ変更して何とか使えるようになったのでここ(comport411f.zip)に置いておく。

主な変更点

Delphi XE2, XE3, XE5対応

設定できる最高転送速度を拡張 -> 230400, 460800, 512000,921600,1024000,1500000,2000000,3000000
※CPort.pasの下記3カ所を変更すれば任意の転送レートが追加できる。

  TBaudRate = (brCustom, br110, br300, br600, br1200, br2400, br4800, br9600, br14400,
                br19200, br38400, br56000, br57600, br115200, br128000, br256000,
                br230400, br460800, br512000, br921600, br1024000, br1500000, br2000000, br3000000 );
  CBaudRate: array[TBaudRate] of Integer =
    (0, CBR_110, CBR_300, CBR_600, CBR_1200, CBR_2400, CBR_4800, CBR_9600,
     CBR_14400, CBR_19200, CBR_38400, CBR_56000, CBR_57600, CBR_115200,
     CBR_128000, CBR_256000,
     230400, 460800, 512000, 921600, 1024000,
     1500000, 2000000, 3000000 );
// baud rate to string
function BaudRateToStr(BaudRate: TBaudRate): string;
const
  BaudRateStrings: array[TBaudRate] of string = ('Custom', '110', '300', '600',
    '1200', '2400', '4800', '9600', '14400', '19200', '38400', '56000', '57600',
    '115200', '128000', '256000',
    '230400', '460800', '512000', '921600', '1024000',
    '1500000', '2000000', '3000000'
    );
begin
  Result := BaudRateStrings[BaudRate];
end;
カテゴリー: Delphi | コメントをどうぞ

Sentechカメラ用eBus SDKでBaslerのカメラ入力が出来た

木材の節検出システムなどの画像処理装置を構築するのに今までは高価なラインカメラと画像入力ボードでやってきた。
暫く前からエリアカメラを使う画像処理は産業用USBカメラを使っていたが最近はギガビットイーサネットを使うGigEカメラに注目している。

専用入力ボードが必要なカメラに較べて、USBカメラもGiGEカメラも画像入力ボードが必要ないためカメラ周りの費用が節約できるのとUSB/LANポートがあれば良いので使えるPCの自由度が大きいというメリットがあるので超高速カメラ等の特殊なカメラを除けば産業用カメラも専用入力ボードが不要なタイプに置き換わっていくに違いない。

USBカメラはWebなどの格安カメラで誰でも使ったことがあると思うが、GigEカメラは産業用カメラとしてここ数年で急速にシェアを拡大してきている。
USBカメラとGigEカメラを較べると、GiGEカメラはインターフェースが絶縁されているためノイズに強いことやケーブルが最大100mまで伸ばせることなど産業用として大きな魅力があるし、PCのインターフェースとしてはUSBよりLANの方がより基本的なインターフェースであるため将来的な互換性で安心感があることが産業用としてGiGEカメラが普及している理由だ。

ソフトから見たインターフェースの汎用性を実感したのが今回の件だ、
現在抱えているプロジェクトにSentechのカメラとBaslerのカメラを使ったものがあり、最初にBasler用のソフトを作り今回はSentech用のソフトに取り組んでいたところ、Sentech用のソフトでBaslerの画像キャプチャはもちろんカメラの詳細な設定まで出来ることを発見してしまったのだ
USBカメラではメーカー毎に用意された開発環境でソフトを作らなければならないのが常識と思っていたのでGiGEカメラインタフェースの汎用性は嬉しい驚きだった。  8-O

昨年の夏にGiGEカメラの使い初めとしてBaslerのメーカーから提供されているPylonというSDKを使ってソフトを作った。
私はDelphi使いなのでDLLのCインタフェース用のユニットを書いてDLLの機能を呼び出すようにしてBaslerのカメラは何とか使えるようになった。
Baslerの魅力は5万円前後から入手できるGiGEカメラがあることと、AOI(センサの一部領域だけを読み出すように出来ること)の設定によってはフレームレートがかなり早く出来ることだ。

使ったのはBasler  ACEというタイプで、例えばAOIを2048 x 4 と設定すると1000fps以上の画像取り込みが可能となりラインセンサの置き換えも可能となる。

ラインセンサのCCDに較べてBasler ACEのCMOSセンサは画質も多少落ちるし、センサ画素が小さいのでより明るい照明が必要となるが、もともと適用対象のアプリケーションはラインセンサの画素をかなり間引いて使っていたものなので画像処理上の問題はなかった。
さらに従来のラインセンサカメラではセンサが大きいためNikonマウントが必要となり産業用標準のCマウントが使えないためレンズの選択や入手に苦慮していた問題も解決できた。

今回の画像処理装置では検査装置に500万画素タイプでセンサーサイズが大きいものということでSentechのカメラを選んだが、開発環境を考えるとせっかく使えるようになったPylonを離れて新しくSentech用の開発環境を使わなければならないのは正直なところあまり気乗りはしなかった。

で、やむなく手をつけたSentech 用の入力ソフトがある程度動くようになったところでSentechカメラを組み込んだ装置が評価のために一週間ほど手元を離れることになった。
カメラがないとソフトのデバッグが出来ないので「ひょっとしたら動くかな?」程度の期待で手元に残っていたBaslserAceを接続してみるとなんと、使えるどころかBaslerのカメラでは用意されていた詳細な設定の部分までSentech用のSDKで出来てしまったのだ。

これからしばらくの間は誰に会っても産業用としてはGigEカメラ一択で宣伝しまくると思う 8-)

Delphi XE2 + eBusSDK + OpenCV2.4.6で作った画像処理のベースとなるソフト。

カメラ選択画面としてこのようなWindowを呼び出すことが出来ます

カメラ設定画面、こちらもライブラリに用意された画面を呼び出すだけです。

カテゴリー: 画像処理 | コメントをどうぞ

stm32F407でCANに悪戦苦闘

デバッグ中のstm32F407VGT6搭載モータードライブボードで最後のチェックポイント、
CANのテストが終了した。
以前stm32F105のCANで簡単に出来ていたので楽勝と思っていたが1日近く悪戦苦闘してしまった。

結果からいうとちょっとした勘違いでリファレンスシートをちゃんと読まないで以前のコードをstm32F4xx向けに修正すればOK! となめてかかっていたせい :mrgreen:

内容はCANの初期化で次のように4つのモードが選べるのだが

//CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack; 
//CAN_InitStructure.CAN_Mode = CAN_Mode_Silent_LoopBack;
//CAN_InitStructure.CAN_Mode = CAN_Mode_Silent;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

Silent_LoopBackとLoopBackのループバックモードは全く問題なく動作するのにCAN_Mode_Normalにすると送受信が出来ない。
それでポートの初期化を疑って半日つぶし、次にハードの信号を調べながら半日潰してしまった。

Webで検索すると「LoopBackで簡単に動作したのにMode_Normalにすると全然動かない、なんでやねん!」とstMicroのフォーラムに書いている人が結構いた。

原因は

CANは相手ノードのレスポンスを確認してから送信完了のフラグを返すので、2つのボードを接続しないと、正常に送信できたか否かのテストが出来ないということに気が付かなかった。

もう一つは通信レートを遅くするとアクノリッジが帰る前にタイムアウトしてしまう可能性があること。
UART通信テストの感覚で当初は念のために100Kbps以下の速度でテストをしていたのでこちらにもひっかかっていたこと。

教訓

初心忘るべからず、トラブル発生の時はリファレンスを再確認しましょう -> 自分  :oops:

カテゴリー: HUSROBO | コメントをどうぞ

マクソンモーターの相とホールセンサの関係

モータードライブボードにマクソンモーターを接続してデバッグをしている

モーターは径40mm 長さ72mmくらいの170Wタイプでオプションのエンコーダがついている
巻き線はマクソンジャパンの人によるとデルタ結線になっているそうだ。

センサ信号の確認とFETドライバの動作が確認できたのでエンコーダで位置を見ながらステップ送りをしてホールセンサのパターンを確認してみた。
結果は下図のとおりで、各ステップの止まる位置がホールセンサの切り替わりポイントになっているようだ。

それにしてもマクソンモーターは値段が高いだけあってモータの出来が良い :-P
相撲ロボット用に使っているVORTEX-MR8とはスムーズさが全く違う。

※エンコーダは一回転あたり2000のカウント値で相パターンとホールセンサの値は見易くするために1000を掛けてあります。

カテゴリー: HUSROBO | コメントをどうぞ

FT232で3Mbpsの通信が可能なことに気が付いた

現在stm32F407VGTを使ったモータ制御ボードのソフト開発に取り組んでいる
そのボードにUSBシリアル変換用ICのFT232RLが載っていて今までは通信速度256Kbpsで使っていた。
何かのはずみでFT232RLが通信速度460Kbpsまで対応しているというのを見かけて興味を持って調べて見たところ最大3Mbpsで動作したというレポートを見つけた。

WindowsAPIの方はかなり自由に通信速度を指定できるらしいので試しにJTW32を修正して最大3Mbpsまで対応できるようにしてみたところ、確かに3Mbpsで通信が出来た :-D

JTW32.exe -> Ver4.55で通信速度3Mbpsまで対応
stm32F407の方はUART1と6と他のシリアルポートでもとになるクロックが異なっているためUART6で3MbpsまでOKで、USART2は1.5Mbpsまで通信可能という結果だった。

RS232Cコンバータを通した従来のシリアル通信ではハード的に1Mbpsを超える通信は難しいがボード上にUSBシリアルICを搭載する場合は3Mbpsの速度でも余裕がありそうだ。
USB通信に較べてシリアル通信はプログラムがシンプルで済みCPU不可が少ないので有難い、
このくらいの通信速度まで使えるのならstm32FのUSB機能を使うよりFT232シリーズを使う場合が増えそうだ。

カテゴリー: stm32F4xx, 開発環境 | コメントをどうぞ