2016年10月31日月曜日

VisualStudioでSTM32のコードをいじりたい

STM32のコードをVisual Studioでいじりたい。Visual Studioは普段C#を書くのに使っていて慣れてるし、コード補完とかもあるので組み込みもVisual Studioで書けると便利。

結論から言うと、今のところ完全に実用な状態にはなっていない。


とりあえず最低限必用なのはいくつかのマクロとかを定義してやる必要がある。
__STATIC_INLINE, __IO, __Iが必要になる。__Oは使われていないがとりあえず定義しておいた。
それとuint8_tとかはstdint.hで読み込む必要がある。ただし32bitについてはVisual Studioに付属しているstdint.hには定義されていないので自前で定義する必要がある。ただこのあたりが非常に面倒で、エラーチェックではuint32_tが定義されていないが、includeで読み込まれるstdint.hにはuint32_tが定義されている。ということで多重定義とか面倒なので、#defineで定義しておくことにする。
そして__STATIC_INLINEだが、これはstatic inlineと定義されているが、Visual Studio的にこの修飾子は嫌がられるらしい。Visual Studioではビルドはせず、単純に構文が正しいかのみをチェックするので、とりあえず空のdefine定義を追加するのみとしている。


あとはメイクファイルプロジェクトでインクルードパスを設定してやればエラー類は出ず、コード補完もちゃんと使うことができるし、構造体のメンバの型をマウスオーバーで表示することもできる。
ということで一応Visual Studioで書いたりはできるようになったわけだが、Visual Studioでビルドすることはできていない。またmakefileで定義しているマクロも読み込んでいないから、例えばMPUを指定していないというエラーが出たりしている。


Win10のAniv UpdateでBoUoW10が追加され、Bashでmakeコマンドとかが一通り揃ったことから、Win10でARMの開発環境を構築するのはかなり簡単になった(apt-getでgcc-arm-none-eabiをインストールするだけで終わり)。Visual Studio CodeではBashを使えるようになったらしいし、こっちを使えばいいのかも。

あとAniv Updateつながりでもう1つメモ。Bash on Ubuntu on Windows 10ではdfu-utilは使用できない。インストール自体は問題なくできるが、libusbが使えないため。ということでJTAGデバッガを使うか、Windowsのdfuwを使用することになる。なぜかウチのWin10のコマンドプロンプトはほとんどのexeを起動できないため、dfuwのGUIラッパーを作ったりしているわけだが、それはさておき。

やりたいことはあれやこれやと色々有るのだが、なかなかそっちまで手が回らない。

2016年10月25日火曜日

C#のGraphicsで透過色を描き込む

何回も忘れて必要になるたびにググってるのでメモ。

C#のGraphicsは完全に透明な色で何かを書くと、何も書かれない、という挙動になっている。ペイントソフトで切り抜いてPNGの透過みたいなことができない。

それをやりたいときはCompositingModeを変更する。デフォルトではSourceOverだが、SourceCopyに設定すれば透過を描き込むことができる。

Graphics.CompositingMode プロパティ (System.Drawing)


あとあんまり関係ないけど、Clipboard.SetImage/GetImageでは透過はやり取りできないみたい。少なくともC#から透過率100%の画像をクリップボードに入れると、その部分はライトグレー(#D3D3D3)に置換されている。透過率50%の白だとライトグレーよりも白に近い色になる。

今簡単なペイントソフトっぽいのを作ってるんだけど、他の(ちゃんとした)ペイントソフトに画像を渡そうとすると一旦ファイルに保存する必要があるっぽい。少なくともPaint.Netに対してClipboard.SetImageで透過を含んだままで画像を渡すことはできない。
それとControlのPaintイベントでe.Graphicsに対して透過率100%を指定すると完全な黒になる。
ControlのPaintで処理すれば色々楽ができるかなと思ったけどそう簡単ではないらしい。

遊びで小さなプログラム作ってるばっかりでちゃんとしたプログラムは作ったことがないので、ちょっとしたことでも一々引っかかって作りたいものがなかなか作れない。

C#のXmlSerializer

XmlSerializerを使うにはSystem.Xml.Serializationの名前空間が必用。あとファイルに保存したりするのでSystem.IOも必用。
XmlSerializerは完全にpublicなclassしか使えない点に注意。例えばprivateクラスの中にあるpublicクラス等も使用できない。
前回書いたとおりFontとかColorもSerializeできない。FontConverterとかColorConverterとかを使う必要がある。その際はConvertToStringとかConvertFromStringを使う。

その他Serialize周りでは色々例外が投げられたりする場合もあるので適切に処理するように。

C#の色の名前を得る

C#のXmlSerializerで色を扱いたかったんだけどうまく扱えなかったので自分でARGBを持つクラスを作った。ついでなのでColor.Nameで得られる名前も得てみたくなった。

ということでMSDNから色の値と名前をコピペしてswitchで返すようなプロパティを作ってみた。一部重複したモノがあって、それはスイッチできないので世間一般で使われているはずの方を残してそれ以外はコメントアウトした。また名前が存在しない場合はColorのName準拠、つまりConvert.ToStringで16進に変換した文字列を返す。

C#のXmlSerializer、クラスにSave/Loadメソッドを作っておけば大抵はそのままクラスのデータを簡単に保存・読み込みできるから楽なんだけど、ColorとかFontとかよく使うモノがシリアライズできなくて不便。

今回は自前でクラスを作ったけど、本来はFontConverterとかColorConverterを使ったほうが良いかも。というかせっかく標準で用意されてるので積極的に使うべき。
c# - convert font to string and back again - Stack Overflow

2016年10月17日月曜日

防衛省規格 用語

防衛省規格 用語 site:http://www.mod.go.jp/atla/nds/Y/ - Google 検索

PDF資料で様々なジャンルの用語がある。主に小火器かな。日本語、意味、参考英訳があるので用語の意味を調べたいときとか、それを指す英語を調べたいときに便利。もっとも役所の面倒な言い回しを多用した辞書という感じなので、それを詳しく調べるには向かないけど。
総火演の映像とか見ながら何を行ってるのか調べつつ、というのに良いかも。

黒点的25m



JGSDFの訓練で使われている?的っぽいやつ。予備自衛官補の訓練とかで使われてるみたいです。本物の背景はダンボールっぽい色になります。コンビニ印刷とかだと色に関係なく一律1枚いくらなので、そういうところで印刷する場合は背景を適当な色で塗りつぶして下さい。本物はもうちょっと肩が人間っぽい形をしてます。射距離は25mで、4点の円が直径10MOAくらいになるみたいです。1クリック1MOAのサイトなら、グルーピングが肩にあれば逆方向に5クリック分、とかそういう感じです。
大きさはなんとなくなので、全然違ってたらごめんなさい。

肩幅11cmくらいで25m先なので、4分の1くらいの大きさになります。100m先の人間と同じくらいの大きさです。アサルトライフルなら100mくらいが平均的な距離なのかな。結構離れてるような気もしますが、Google Earthとかで歩きなれた場所を測ってみるとかなり短い距離です。叫べば聞こえる距離ですし、走ればあっという間です。

2016年10月16日日曜日

FRESULT

FatFsのFRESULTを文字列に変換する関数。
文字列はff.hの構造体のコメントをそのまま使用。現在の最新版である0.12bを使用しているが、リビジョンが変わった場合はエラーになる。

この間まで動いてたはずなのに別のところ色々いじってたら動かなくなって絶賛デバッグ中。

2016年10月13日木曜日

TeraTermの設定ファイル

TeraTermの設定ファイルは基本的に C:\Program Files (x86)\teraterm\TERATERM.INI となる。インストール時の初期設定だと微妙に使いづらいのでちょっと変更。

上の行が初期値、下が変更した値。

CRReceive=CR
CRReceive=AUTO

CRSend=CR
CRSend=CRLF

BaudRate=9600
BaudRate=115200

VTColor=255,255,255,0,0,0
VTColor=0,0,0,255,255,255

デフォルトだと受信改行コードがCRなのでLF(\n)で改行されない。なのでAUTOとする。
送信改行コードも変更。\nで改行できるようにCRLFを送る。この設定はLFのみで改行しCRは読み飛ばす相手に対して有効。CRとLFどちらかでも改行してしまう場合は使えない。
それと僕が使うのは115200baudが多いのでそれも変更。

それとグレア液晶だと背景黒だと色々反射して不都合なので、その場合はVTColorで背景色とテキストを変更。色はカンマ区切りでRGB順、先に文字、後に背景色となる。

他の設定として、Port=tcpipという設定がある。これをserialにするといきなりデフォルトの設定でシリアルポートに接続される。欲しい機能は起動時の接続先ダイアログでシリアルポートが選択されてることなんだけど、ラジオボタンのクリック1回くらいサボるなと言うことらしい。COMポートが1個だけPCに内蔵されていて、それしか使わないというときには便利かもしれない。古いノートPCの内蔵RS232ポートでネットワーク機器のコマンド叩くみたいな想定なのかな。FT232とかだとたまにポート番号が変わるのであまり使えないと思う。そもそもCOMポートが常に2-4個PCにあるので都度設定したいし。


僕としてはよほどのことがない限りデフォルトの設定で使い続けるタイプの人間なので、あんまり設定をいじることはない。理由は環境が変わったときに自分に合わせて設定を変更するのが面倒(いちいち設定を変えたときにバックアップするのが面倒)という理由なんだけど、普段から設定ファイルに触ることがないので、いざ新しい環境で設定を変更しようとしたときにどうやって設定するか忘れてしまうという問題が有る。ということで備忘録でした。

2016年10月9日日曜日

TLC5940でサーボ制御

最近思うところあって、というかドローンをやりたくなって多チャンネルのサーボ制御を試しています。ドローンというと最近はマルチコプターが多勢ですが、昔からあるRQ-11レイヴンとかケタリング・バグみたいなああいうドローンです。


さて、タイトルの件ですが、ネットでググると沢山の製作例がヒットします。というのも、Arduino日本語リファレンスにTLC5940を使ったLEDドライバが書かれており、これから派生してサーボ制御になったものと思われます。
が、これらの情報(Arduinoを使った例)は全く参考になりませんでした。

というのも、Arduinoはユーザーが制御を意識せずに使えるため、ライブラリの中身を見ない限りはどういう制御をしているのかがわからないためです。これはある面では大きな利点ですが、別の面では欲しい情報が見つからないどころか、検索の邪魔になる欠点もあります。


TLC5940というICのおさらいですが、本来は多チャンネルLEDドライバとして作られたICです。IC自体の動作電圧範囲は3-5.5Vですが、出力が定電流オープンドレインのため、LEDの電源は17Vまで耐えられます。シンク電流は最大120mA(IC電源電圧による制限あり)で、小型のハイパワーチップLED程度なら充分にドライブできます。
最近のLEDバックライトな液晶テレビは、バックライトをタイル状に分割し、「暗い部分はバックライトで暗くする」という方法でコントラストを稼いでいたりします。旧来の画面全体に対して1セットの光源ではテレビ1台に対してドライバが1個あれば済みますが、このような方法を使う場合は多チャンネル(ただし1個自体の電力は少なめ)というドライバが必要になり、そのような場所にTLC5940を始めとした多チャンネルドライバは最適な選択肢となりえます。実際、TLC5940の用途にはディスプレイバックライトも含まれています。
他にもいろいろな用途がありますが、もちろん今回はLEDドライバとしては使いません。





TLC5940はオープンドレインですが、適当な抵抗でプルアップすればPWMを出力することも可能です。今回はプルアップに1kOhmを使用し、IREFに3.3kOhmを使用しました。プルアップ電流は電圧に応じて4-9mA程度、シンク電流は12mA程度です。

TLC5940はオープンドレインですから、アクティブLowとなります。GSCLKに入れるPWMが安定であれば設定したLowパルス幅をきれいに出力できますが、Highのパルス幅を正確に制御しようとした場合、次のGSCLKのタイミングも合わせる必要があります。

STM32F1のタイマはマスタ・スレーブを利用して定期的にTIMを走らしたり止めたりができますから、この機能を利用してPWMを送ることにします。
パルス幅のソースはGSCLKですが、GSCLKのカウンタをリセットするためにBLANKも定期的に送り込む必要があります。GSCLKを4096パルス送った後にBLANKを送ります。このタイミングはTIMで作ろうとすると面倒なのと、BLANKは直接タイミングに影響することは無いため、TIM3のOCを2個使用して割り込みでGPIOをSet,Resetしています。またこのOC割り込みの中でTIM2のアップデートイベントを発生させています。このイベントによりTIM2のプリスケーラを含めたカウンタがクリアされるため、常に同じ位相を維持できます。
またTIM3の別のOCを使用してTIM2を4096パルス分だけ動かしています。TIM自体はワンショットか連続かを選択できますが、n回だけ走らせる、というような動かし方をする場合、大抵は別のTIMからENAを制御する必要があります。1Hz100回程度であればUpdateイベントでカウンタを監視し、一定回数でTIMを止めるといったことも可能ですが、今回は1MHzで走らせているのでソフトウェアで行うことは不可能と考えました。

データの転送にはSPIを使用し、XLATはSPI転送終了後にGPIOでトグルします。IC自体は30MHzまで受けれるようですが、STM側の都合から18MHzで転送しています。またDMAを使用せず、ソフトウェアでポーリングして転送しているため、かなり遅いです。ただ16chであればせいぜい24バイトですから、あまり気にしないことにします。


基本的にサーボの制御は50Hz程度のPWMを送信します。しかし今回は制御の都合から約222HzのPWMを送信しています。もっと複雑な制御を行えば50Hzに合わせることも可能でしょうが、SG92Rで試したところ、一応パルス幅通りに動いたため問題ないと判断しました。


ということで、16chまでのサーボ制御はできるようになりました。以前にGPIOに対してDMA転送して16chパルスを生成しましたが、この方法ではRAMを大量に食う、データバスを大きく専有する、といった問題点がありました。TLC5940を使えば1xSPI、2xTIMが必要になりますが、CPUリソースはあまり専有せずに16chを制御できます。またTLC5940は任意個数をカスケード接続できますから、サーボが50個とか100個必要になっても多少の変更で対応できます。



最後になりますが、TLC5940を使う際(LEDドライバとして含め)に気をつけるべきこととか。

基本的に各ピンはプルアップ・プルダウンを適切に挿入しておくべきです。少なくともSCLKをプルダウン、BLANKをプルアップで固定しておきます。BLANKがHの場合は出力が止まりますから、LEDが点灯しっぱなしになるようなことはありません。ただ念のため他の入力端子も固定しておきましょう。SIN,XLAT,GSCLKですが、これらはプルダウンとなります。これらが不適切な場合は、マイコンがリセットされているときにICに触れるとLEDがチカチカするという挙動を示すことになります。静電気にも弱くなりますから、可能な限り浮動しないようにしましょう。

TLC5940はCMOSレベルです。例えばTLC5940を5V、マイコンを3.3Vで動かした場合、直結することはできません。バッファを挟むか、TLC5940も3.3Vで動作させる必要があります。ただしTLC5940を3.3Vで動作させた場合はシンク電流は60mAに制限されます。3.3Vで60mAを超えて流した場合は発熱します。

そして重要なことですが、LEDとTLC5940の間に抵抗を挟んでも電流が制限されることはありません。無駄な抵抗というか、損失が多くなるだけですから、LEDと直列に抵抗を挟んで電流を制限することはやめましょう。順方向電流の違うLEDを混在させたい場合は一番電流が少ないLEDに合わせましょう。それが嫌ならDC(Dot Correction)を使って電流を制限することもできます。ただしこの場合はDCが不適切に設定された環境ではLEDが破壊される可能性があることに留意しましょう。
DC自体は起動時にEEPROMから読み込まれるため、DCを使用しない場合は初期化する必要はありません。EEPROMでは3Fhに初期化され、これはIREFで設定した電流値の100%を流すことができます。

あとはまぁ、詳しくはデータシートを読めということでひとつ。


/*
せっかく多チャンネルの制御ができるようになったのですから、色々遊びたいです。例えば主翼にフラップとエルロンで4サーボ、水平尾翼はエレボンで2サーボ、垂直尾翼で2サーボ、動力は2系統で2ESC、計12ch、とか。これくらい動かすものがあるとCCV的な制御もできそうです。
でもRQ-11って3chしか無いんですよね。カメラジンバルだって無いし。ということで目指す形はF-22みたいな感じになると思います。まずはセスナみたいな高翼単発機でしょうけども。いずれはEDFもやりたいなぁと思いつつ。

昔にラジコン飛行機をやっていた頃は国内メーカーの3ch入門機が1.5-2万円くらいでしたが、最近はそのクラスの機体は見かけない気がします(あんまり調べてないですが)。そのメーカーは「最初から上手な人はいません」と入門機の重要性を説いていましたが、最近では高価な機体しか作っていないですね。
ホビー界隈が全体的に高価格化して新規ユーザーの獲得はあんまり考えていないような気がします。メーカーからすればお前には言われたくねぇよって感じでしょうけども。
*/

2016年10月2日日曜日

Google EarthでNMEAを表示したい(場合に予めやっておくこと)

Google EarthでNMEA0183を表示しようとすると、世間一般ではGPS Babelに食わすことが一般常識化しています。でもGoogle EarthだってNMEA0183は直接食えます。
一旦別ソフトを通すのって面倒ですよね?ということで予めGoogle Earthで食えるデータにしておきましょう。

といっても特別なフォーマットに変換して保存するといった事は必要ありません。
Google EarthでNMEAを読み込むために必要なデータは日付・時間・緯度・経度です。高度は必要ありません。
上記のデータを満たすにはGPRMCがあれば十分です。ただしGPRMCには高度情報がありませんから、地上を動き回るローバー系であれば問題ありませんが、缶サットのような飛びもの系では高度情報が必要となります。ということで高度情報を含むGPGGAも出しておきましょう。

ただ、GPGGAとGPRMCを出力する、というのは予めGPSモジュールを設定しておく必要があります。これが不可能で、GPGGAしか出ていない(日付情報が無い)といった場合にはGPS Babel等で変換する必要があります。


ということで、予めGPSモジュールを設定しておけば楽だよ!という話でした。
「GPSモジュールのコンフィグなんて面倒だよ!」という人もいるかもしれませんが、GPSのコンフィグはGPSモジュールを買ったときに1回だけ行えば済みますが、GPSデータの変換は計測毎に行う必要が有るため、大抵の場合は予め設定したほうが楽だと思います。