hira のすべての投稿

MuPDF 1.2 ライブラリーの C++ ラッパー

MuPDF とは?

MuPDF は、PDF を描画する為のライブラリーで、C で実装されたオープンソースライブラリーである。
非常に軽量で、高速、色々なプラットフォームに対応している。

Adobe の PDF Reader は、はっきり言って「糞」だ、頻繁にバージョンアップを繰り返して、とにかく「ウザイ」し、重いし、良い所は無い。
MuPDF のエンジンを使ったアプリケーションとして、Sumatra PDF がある。
※自分は、AdobeReader はアンインストールして、コレを使っているが、得に不便を感じない。

以前から、自分のフレームワーク(以前から使っていた「glfw」って名称は、GLFW3 と混同しやすいので使えん、新しい名称を考えないと・・・)では MuPDF ライブラリーのラッパーを実装していたが、それはバージョンが 1.0 になる前で、最新は、1.2 となっている。
バージョンアップしたいと思っていたが、API 変わって、書き直す必要があった、最近ようやく、1.2ライブラリーをコンパイルしなおして、ラッパーを書き直した。

コードがかなり洗練され、とても使いやすくなったようだ、ワイド文字列の処理も UTF8 に統一され、レンダリングも簡単になった。

折角なので、簡単な描画サンプルを作ってみた、描画は GLFW3(OpenGL) で、レンダリングされた PDF はテクスチャーとして扱う。
操作方法:
起動したら、PDF ファイルをドラッグ&ドロップ
マウスボタンの右、左でページ移動(PageUp、PageDownキーでも可能)

自分で作成したアプリケーションに PDF を簡単に表示できるのは、色々と便利な事が多い!
このアプリは、サンプルなので、必要最低限の機能しかないのであしからず~

「img_io/pdf_in.hpp」を観てもらえば、大体の使い方は判ると思う。

ソースコード
実行バイナリー

コンパイルに必要なライブラリーパック
※注意 /usr/local/ 以下に展開
※このライブラリーパックに mupdf のライブラリー libfitz.a が同根されています。
※ MuPDF ライブラリーは、freetype2、JPEG、Z-Lib、jbig2dec、OpenJpeg(JPEG2000)などのライブラリーを必要とします。(それも同根してあります)
※JPEG ライブラリーは、x86 アセンブラで高速化してあるバージョンが入っています。

らぶひな PDF
PDF_test1

RX マイコンのPDF
PDF_test2

L6470 ステッピングモータードライバー

例によって秋月で、L6470ステッピングモータードライバーのモジュールを買った(750円)。
※ステッピングモーター駆動のタコメーターを作る予定で買った。

早速動かしてみたので、その報告。

L6470 は、最大 48V、定格 3A のドライバーで、128 マイクロステップが可能なインテリジェントドライバーだ。
制御は SPI で行う。
※このLSIは、位置と速度を管理していて、単なるドライバーとは言えない高機能なものだ。

「マイクロステップ」とは、ステッピングモーターの2つの相に流す電流の比を制御して、より細かいステップで制御する方法で、2相(4相)ステップモーターの相コイルは、丁度90度に直行した構造なので、X、Y軸の関係に等しい。
X、Y軸をそれぞれ、サインとコサインの関係で、電流比を制御すると、理論的には無限大まで分解能を上げられる。
このICはステップモーターの1ステップを128分割まででき、きめ細かな制御が出来る。
注意して欲しいのは、ステッピングモーターに流れる電流は、誘導性負荷なので、速度(回転速度)が速くなると当然流れる電流は少なくなる、なので、制御の精度は、「比」となる、絶対的な電流では無い。

実験には、ATMega88P を使い、SPI の制御を行って、L6470 にコマンドを送って制御した。
※ネットを探すと、Arduino のスケッチが色々見つかるが、純粋に C++ でプログラムを行った。

ステップモーターは秋月で買った物で、定格12Vなのだが、ユニポーラをバイポーラとして駆動する為、12Vで駆動する場合、定格の半分となる。
※最終的にはタコメーターを作る予定なので、12Vで丁度良いと思う。

回路図は書いて無いので、結線は以下のように接続する。
PC0: L6470 STBY/RST
PB2: L6470 /CS
MOSI PB3: L6470 SDI
MISO PB4: L6470 SDO
CLK PB5: L6470 CK

電源は12V、AVRには5Vを印加する。

※他の回路は参考資料にある回路をそのまま使う。
※boot ストラップに使うダイオードはショットキーダイオードを使う。(手持ちの都合で、2A/40V を使った)

IMG_0443s

ソースコード

まだ、実験的コードなので、色々未完成、タコメーターのハード製作に合わせて修正していく予定。

-----
追記:
2013年7月1日(21時25分)
ソースコードを更新しました。
spi.hpp ---> AVR の SPI 通信をクラス化したものです。(まだ不完全です)
L6470io.hpp ---> L6470 の制御をクラス化しました。(まだ不完全ですが、コマンド発行など、より判り易く使えます)

2013年7月1日(22時23分)
L6470io.hpp を更新、これで、アプリケーションから、必要な事が出来るようになった感じ。
※ステータスの読み込みは、まだ未実装

動画をアップ

HIDaspx を作る

AVR を使った電子工作では、ISP プログラマーが必須だ、以前から「ELM さんの AVR ライタ」を使わせてもらっている。
※シリアル→ISPの変換デバイスを USB シリアル変換(FTDI)と組み合わせて、ケースに入れてある。

IMG_0436s
※さすがにかなりくたびれているが、未だ現役。

数年前に、ATtiny2313 を使って、ソフトウェアーだけで、USB クライアントになる ISP プログラマーが発表され、ずっと使ってみたかったのだが、現役のプログラマーで何とかなっていたので、ずっと見送っていた。
千秋ゼミ(AVRマイコンなど)
先日ゲームコントローラーを作るので部品を買った余り(余分に買った)があり、丁度良い機会なので、作ってみる事にした。

HIDaspx は、ATtiny2313 といくつかの部品だけで動作する AVR 用 ISP プログラマーなのだが、非常に洗練されており、ソフトウェアーの機能もてんこ盛りだ(はまった)。
折角なので、単純に AVR の ISP プログラマーを作りたい人の為に、簡単な製作記を残しておこうと思う。

(1) ハードの製作
HIDaspxは、プリント基板を販売しているところがあり、それを使えば簡単なのだがー、いくつかの点で、自分のスタイルに会わない為、今回はパス。

・やはりこの手の物は、ちゃんとケースに入れて、使わないと、ショートしたり、何かとトラブルが起こるもので、前回同様、同じケースに入れる事とした。
・ISP のコネクターは、前回と互換性を持たせ、10ピン仕様とする。
・最近はミニ USB やマイクロ USB が主流で、小さくて、扱いやすいので、ミニ USB コネクター仕様とした。
・電源の切り替えは、前回同様、5V、3.3Vを切り替えできるようにした。
・HIDaspx は、Ready と Busy のランプがある。
以上を踏まえて、ケース内のレイアウトを決め、ケースの加工、基板の切り出し、加工を行った。

IMG_0434s
※この段階では、LED 電源切り替えスイッチの穴は開けてない。
※ミニ USB のコネクターは、既製品の変換アダプターを使った。(かなり昔に買ったもの)
※このケースは、底蓋の面構造が、基板を、コネクターの形状を利用して固定するのに都合良く作られている。

内部に納める基板が出来たら、回路図を見ながら、部品を乗せて行く。

IMG_0437s

IMG_0438s
※緑の LED、VF が 3.2~3.4V なので、3.3V で動作させた場合にLEDが点灯しないのでは無いかと考え、フォトカプラーを間に入れて、常に5Vで駆動するように改修してある。
※他は、ほぼオリジナルの回路準拠
※経験上、三端子レギュレーターの入力側にはコンデンサはを入れていない(無くても、まず発振したりしないし、レギュレーションが悪くなる事も無い)
※緑 LED は超高輝度を使った為(手持ちがそれしかなかった)、電流を少なくしても、直視できないほど刺すような明るさで、失敗・・・、ブルー LED に交換する予定

最後にケースにレタリング

IMG_0439s
※新旧、2台のISP

IMG_0440s
※USB コネクター部分の違い

(2) 動作検査
まず、ファームやツールなどをダウンロードする。

今回使ったのは「hidspx-2012-0326.zip」で、既存の ISP で、2313 にファームを書き込んだ。

hidspx-2012-0326/bin/firmware/main-12.hex

ヒューズの設定は、ここに詳しく書かれている。

さて、一応、配線を確認後、PC の USB ポートに接続する、しばし・・・
問題なく、デバイスドライバーがインストールされた。

※自分の環境は、Windows7 64 ビットだ。
※USB2.0 のハブに接続している。

HIDaspxDeviceMan
※デバイスドライバーは、「HID 準拠デバイス」として認識されているようだ・・

(3) ツールの用意

hidspx-2012-0326/bin/hidspx.exe があるので、cygwin などのシェルを起動して、このコマンドを使ってみる。

↓以下のようにコマンドを打てば、認識したデバイスを表示してくれる。
% ./hidspx -ph?
VID=16c0, PID=05df, [ YCIT], [HIDaspx], serial=[0000] (*)

では、AVR を ISP に接続して、ヒューズビットを読み込んでみよう~
% ./hidspx -ph -d4 -rf
Detected device is ATmega88.

==== ATmega88 ====

Low: 11100110
||||++++-- CKSEL[3:0] システムクロック選択
||++-- SUT[1:0] 起動時間
|+-- CKOUT (0:PB0にシステムクロックを出力)
+-- CKDIV8 クロック分周初期値 (1:1/1, 0:1/8)

High:11-11111
|||||+++-- BODLEVEL[2:0] (111:無, 110:1.8V, 101:2.7V, 100:4.3V)
||||+-- EESAVE (消去でEEPROMを 1:消去, 0:保持)
|||+-- WDTON (1:WDT通常動作, 0:WDT常時ON)
||+-- SPIEN (1:ISP禁止, 0:ISP許可) ※Parallel時のみ
|+-- DWEN (On-Chipデバッグ 1:無効, 0:有効)
+-- RSTDISBL (RESETピン 1:有効, 0:無効(PC6))

Ext: -----001
||+-- BOOTRST (1:Normal, 0:BootLoader)
++-- BOOTSZ[1:0] (11:128W, 10:256, 01:512, 00:1024)

Cal: 182

※何かの拍子に、ISP が認識しなくなる事があるようだ、USB ケーブルをさし直すと直るようだが・・・

----- 注意!注意!注意! -----

hidspx は非常に高機能で、複雑、オプションなど注意を要する、得に、他の ISP プログラマーの機能を取り込んでいる為、他の ISP と混同すると期待した動作はしない。

※ありがちな事(自分もやった)
・USBaspx と HIDaspx を混同する。
※USBaspx は、libusb-win32 経由でデバイスとやりとりする為、libusb-win32 のツールを使って、デバイスを認識させる必要がある。

・libusb-win32 のツールを使って、HIDaspx を認識させてしまうと、hidspx で認識しなくなる。
※誤って、そうしたら、デバイスドライバーを削除すれば OK。
※HIDaspx はドライバーのインストールなどが一切不要で、直ぐに利用できる、半面、デバイスドライバーのプロパティでは、「HID 準拠デバイス」としか認識されない。

「千秋ゼミ」のページは、情報が多く、初心者には判りずらいかもしれない、しかしながら HIDaspx は非常に素晴らしい ISP なので、AVR のプログラマーを探している人は是非使ったら良いと思う。

追記:
> 何かの拍子に、ISP が認識しなくなる事があるようだ、USB ケーブルをさし直すと直るようだが・・・
外部電源に、数百mA程度を消費するような機器を繋いだ場合に、瞬間的に電源電圧が変動して、ATtiny2313 の機能が止まって認識しなくなるようです。
※Windows のデバイスマネージャーからは、正常に見えている。
そこで、外部電源ラインに、直列にフェライトビーズ「BLM18PG471SN1D」(秋月電子扱い)を入れたら、安定しました。
※470オーム(100MHz)/1000mA/0.2オーム(直流抵抗)

AVRでUSBゲームコントローラーを自作する

自分フレームワークの実装過程で、前回、エミュレーターソースを流用してスペースインベーダーを作成した。

GLFW3 には、標準で、ゲームコントローラーの取得 API があるので、それを使ってみる事にした。

適当な USB ゲームパッドを買っても良いのだがー、備品の中に、ファミコン時代に購入した、「ASCII STICK II TURBO」が埃をかぶっている事を発見したー

IMG_0423s

内部
IMG_0424s
※ボタンの「受け」などは鉄板で補強してあり、筐体はプラスチックだが、必要な剛性を確保してある。
※設計は、当時ナムコの筐体デザインなどをしていた遠山さんと言う噂なのだがー、この創りの良さとこだわりは、実際そうなのだろうと思う。

当時5000円くらいはした覚えがあるが、機能的には、ファミコン用なので、ボタンが少ないのだがー、連射や、4方向、8方向切り替えなど、色々と芸が細かい、
デザインも優れているし、剛性も高く、方向レバーはマイクロスイッチで、価格以上の素晴らしい創りとなっている、今回はこれを改造する事とした。

USB のゲームコントローラーでは当然ながら、制御用マイコンが必要だが、ネットを探すと色々ある、今回利用させてもらったのは「ココ」のサイト。
AVR を使った USB ゲームデバイスで、最近ではあまり馴染みの無い ATMega8 を使っている。
手持ちの ATMega88 とかで出来れば良いのだがー、このコントローラーの制御ソースはアセンブラなので、ATMega8 を別途購入した(秋月で180円)。
そもそも、USB の通信機能が無い AVR でUSB(Low スピード)の通信を行うのはかなりハードルが高い、マシンサイクルを正確に計算して、ソフトウェアーのタイミングループだけで、USB の制御信号を
生成しているのは、クールとしか言いようが無い。

ASCII STICK には、何に使うか最後まで不明な「OPTION」コネクターがある。
丁度良いので、USB コネクターはここに出そうと考えて、工作してみた。

IMG_0429s
※回路は、特に変更はしていないが、USB の差動ラインに入っている68オーム、手持ちが無かったので75オームとした。
※アナログの電源ライン「GND」も回路図ではオープンとなっているが、一応 GND に落としておいた。

----- Fuse ビット書き込み時の注意 -----

ATMega8 は、ピンアサインなどは、ATMega88P などに近いものの、古いデバイスで、注意する点があります。
現在も流通はしているものの、ATMega88Pや上位デバイスに置き換えるのでしょう。
※自分もそれでハマリました・・・
まず、ヒューズビットを書き込む場合ですが、最初に low バイトを書き込んでしまうと、発振機が動作しなくなります。
これは、「fuse.txt」の値が適切とは言えない点と、ATMega8 の仕様によるところにあります。
12MHz のクリスタルを使う場合なので、high バイトの「CKOPT」を変更して、「0」にしておく必要があるようです。

僕は、色々やった結果、high バイトに「0xC9」、low バイトに「0xEF」を書き込んでいます。
※WatchDog は有効にした方が良いかもしれません・・
※fuse.txtでは、low バイトの CKSEL が、「External Low-frequency Crystal」となっていて、これは絶対間違っていると思います。

AVR の痛いところは、fuse の書き込みを失敗すると、再起不能になる場合がありますので、注意が必要です。
クロックの選択を誤った場合は復帰するチャンスはありますが、「RESET」端子とかを無効にしたりすると、ISP でのプログラムは不可能となります。

IMG_0431s

IMG_0433s
※いつものフォーレックスを適当に削って、USB コネクターのカバーにした、基板とLOCTITE で接着してある。

Game_Controler_Dialogjpg
※ゲームコントローラーとして認識したダイアログ(ボタンが多いのは愛嬌)

フレームワークを USB コントローラーに対応した。
ソース
バイナリー

GLFW3と自分FWを使って昔懐かしい「Space Invaders」を作る

以前から、チクチクとゲーム開発の補助になる自分用フレームワークを作ってきましたがー
GLFW3 がリリースされたタイミングで、glut から GLFW3 に変更していましたが、とりあえずのベータが出来たので、アーカイブを公開します。

自分用フレームワークの完成度を上げるには、一通りの機能を使って、アプリケーションを作る必要があるものです。
また、C++ の熟練度が少しづつ向上して、ソースコードの品質も少しづつではあるけど洗練されてきつつあります。
そこで、何か良い題材は無い物かと考えてましたが、とりあえず、キーボード入力と、サウンド(効果音)が出る、そして簡潔に出来る。
などの理由で、昔懐かしい「Space Invaders」を作る事にしましたww

「作る」と言っても、「Space Invaders」は、mame32 由来のエミュレーターソースをそのまま使います。
※その為、このソースコードもそれらライセンスに従います。

スペースインベーダーは、8ビットのZ80(2MHz)を使い、256×240のモノクロビットマップグラフィクスを使ったゲームで、
当時は、もの凄く洗練されていました。(今でも洗練されていると思う)
エミュレーターは、8080のエミュレーションと、インベーダーのハードをエミュレーションします。
結果は、モノクロビットマップの出力として出てくるので、OpenGL のテクスチャーに貼って、描画します。
インベーダーはアナログシンセサイザーを持っていて、現在では、はサンプリングされたデータを入手出来るので、それを使いSEとして
発音します。

spain

プログラムの動作には、ROMイメージが必要なので、どこかで見つけて下さい。
※このプログラムでは、sounds.zip、invaders.zip の二つのアーカイブを必要とします。
ここが参考になると思います

ソースコード

コンパイルに必要なライブラリー郡、/usr/local 以下に展開

boost_1_53_0 が必要です。

コンパイル済みバイナリー

※操作方法
「1」1プレイヤーボタン
「2」2プレイヤーボタン
「3」コイン
「←」ビーム砲左
「SPACE」ビーム発射
「→」ビーム砲右

GLFW-3.0.1 の機能追加

GLFW ですが、既に 3.0.1 がリリースされてましたーー

Bugfix: The wrong name was used for the CMake variable for the Xxf86vm library
[Cocoa] Bugfix: glfwGetFramebufferSize return the size in screen coordinates
[Cocoa] Bugfix: Messages not supported on Mac OS X 10.6 were used without tests for precence
[Cocoa] Bugfix: Process transformation was not performed if menu bar creation was disabled
[Win32] Bugfix: Context creation was attempted even if no valid pixel formats had been found
[X11] Bugfix: Duplicate window position and window and framebuffer size events were reported

まぁ、基本的にBugFixのようですが・・・

さて、OpenGL のアプリケーションですが、作っていて不便な事があります、アプリケーション・ウィンドウに
ファイルをドラッグ・アンド・ドロップして、ファイル名を受け取る事が出来ない事です。

アプリケーションを作る上で不便なので、GLFW を改造して、この機能を付けましたー

glfw-3.0.1 のパッチ

glfw-3.0.1 のソースを展開して、ルートディレクトリーに異動後、以下のコマンドを入れればパッチが当たると思います。

patch -p0 < glfw_3_0_1-dropfiles.diff で、make すれば OK。 exsamples に dropfiles.c のサンプルがあるので、これを観ればどのようにファイル名を受け取るのか判ると思います。 もっと実用的なサンプルとして、ビューアー・プレイヤーを作りました。
※ソースコードが欲しい方は、連絡下さい、必要なフレームワークの準備に少し時間が必要です。

このアプリケーションは、起動すると、空のウィンドウが開きます、ここに画像ファイル(BMP、PNG、JPEG、JPEG2000)や音楽ファイル(WAV、MP3)を落とせば、それを開きます。
※音楽ファイルは再生します、MP3に画像が含まれている場合は、それを表示します。

※メイン部分だけアップしておきます~

GLFW3.0 を使う

自分のフレームワークとして、「gl_fw」と言うプロジェクトを実装していましたがー

最近(そうでもないかww)、GLFW と言うフレームワークがある事を知りました、現在のところ、OS-X、X11、Windows で使える、マルチプラットホームのフレームワークです。
C、Objective-C(OS-X)で実装されており、シンプルで、良く出来ています。
※「glut」があるのですが、これは、メンテナンスされていないし、色々と痛いところが多いのです。

最近、メジャーバージョンが「3.0」となり、「2.x」から、より洗練された実装になりましたー、まだ機能で欲しい部分は色々あるのですがー、これから追加されていくと思います。

自分のフレームワークも glut から GLFW に変更すべく色々修正中です。
GLFW 3.x で良い部分をいくつか上げると・・・
・マウスホイールのイベントを取得できる。
・クリップボードのやり取りが追加された。
・メインループから綺麗に抜けてくれる。(glutでは、スマートでは無い方法で実装しなければなりません・・)
・ゲームパッドの値を標準的に取得できる。
・キーボードの扱いがゲーム向き。(単純に押したか、押さないを取得できる)
・必要最小限の機能だけ用意してあり、わかり易い。
・ライブラリーをコンパイルするのが簡単。(cygwin の windows クロスコンパイラ i686-w64-mingw32 でコンパイルできるようになった)

現在の「3.0」には、ドロップファイルのイベントを受け取る機能が無いので、これは自分で足そうと思います。
※「2.x」で実装したので、「3.0」風に書き直す感じww

cygwin で glfw-3.0 をコンパイルする手順を書いておきます。

(0) cygwin に i686-w64-mingw32-gcc、cmake などをインストールしておく。
(1) glfw-3.0 のソースアーカイブを取得して展開する。
(2) glfw-3.0 に移動
(3) 「cmake -DCMAKE_TOOLCHAIN_FILE=CMake/i686-w64-mingw32.cmake」
(4) 「make」
※何も指定しないとスタティックリンクライブラリーが作られるようです。(DLL にする意味は無いと思う)

これでおしまい!(ああ、何て簡単なんだろ・・)

(5) 「make install」で、/usr/local/以下にインストールされます。

では動かしてみましょう!


#include <stdlib.h>
#include <GLFW/glfw3.h>

int main(int argc, char** argv);
int main(int argc, char** argv)
{
    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();

    return 0;
}

※ cygwin のコンパイルで重要なのは、リンクライブラリーとして、glfw3、opengl32、glu32、gdi32 を加える事です。

さて、ゲームなどで必要なのは、サウンド、スレッド、画像の読み込み等ですが、GLFW のポリシーでは、「これをフレームワークに含め無い方が良い」との考えのようです。

自分もそう思います、自分は、以下のように解決しています。
・サウンド ---> OpenAL を使うのが良いでしょう~
・スレッド ---> POSIX のスレッド pthread を使う。(OS-X、Linux、mingw では標準です、VisualStudio を使う場合は、pthread-win32 ライブラリーを使います)
・画像 ---> libpng、などを使えば良いし、読み込みをサポートするライブラリーやソースは沢山あるので、自分に合った物を選べば良い。

「gl_fw」(紛らわしいけど、GLFW を知る前からなので・・・)の改修が終わったら、またブログを書きます。
※gl_fw は、C++ を使ったフレームワークで、サウンド(単音、ストリーム)を扱うクラス、画像ファイルを単一的に扱うクラス、フォント(漢字)、GUI、などそこそこ高機能な物です。
ソースコードは、テストが済み次第取得できるようにしますが、興味のある人は連絡下さい~
githubから取得出来ます。
※glfw3には、ドロップファイルを受け取る改修をしています(windows版のみ)、Libraries にlibファイルとヘッダーを用意しています。

9XR 送信機と FrSky テレメトリー

自分は、以前に JR の7チャネル送受信機を買ったのだがー、マルチコプターと、ヘリコプターを購入して、受信機を買い足す必要が出てきたー
それに、マルチコプターの本格的運用では7チャネルでは少し足りない感じもする・・・
残念な事に JR の受信機だけ買い足すのも、割高な強気値段で、どうしたもんかなーと考えていたらー、9チャネル送信機が5000円!、えっ?!

そうなんですー、モジュール式の送信機だけなら海外では格安で売られているのですー、品質はそれなりなのかなーと思ったら、そんな事もなさそうだしー
JR は DMSS に対応した物を購入したのですがー、実際、センサーなどのモジュールが割高で、テレメトリーとして運用するには、かなり厳しい・・
テレメトリーのモジュールを自分で作りたいけど、プロトコルは非公開だし、リバースエンジニアリングするのも億劫だし。

TURNIGY 9XR は JR 用モジュールが使えるようになっている。
TURNIGY 9XR

それから、格安の FrSky のテレメトリーモジュールも購入した。
※それでも、JR の受信機買うのとあんまし代わらないお値段。
FrSky DJT

FrSky D8R-II PLUS

FrSky のテレメトリーモジュールは、プロトコルが公開されており、自分で簡単に作る事も出来る。
そこで、とりあえず、送信機側表示モジュールを作って、実験してみようと思う。

基本的構成はいつもの AVR 、今回は ATMega328P を使った(250円)、それと、DJT とシリアル通信を行う為の RS232C のラインドライバー(ADM3202)、表示は、秋月の128×64ピクセルの液晶

9XR はオープンソースもあり、ファームを書き換えする事も出来るので、DJT からのテレメトリープロトコルを突っ込んで、9XR の液晶に表示させれば、シンプルでクールなのだがー、本体を多少改造しないと駄目なので、今回はパスする事にした。
まず、表示用液晶として、秋月電子で売られている128 x 64 のドットマトリックス液晶、この液晶、そこそこ小さく、手頃な価格で良いのだがー、痛いとこもある、接続が、2mm ピッチで自作向きでは無い、そこで、まず、付属のコネクターをユニバーサル基板に接着し、強度を増す為、スタビライザーみたいな物を追加した。
※2本なら、2mmピッチを無理やり2.54mmピッチに差し込める。

128x64 接続A
128x64 接続B

完成した基板
TelemetryBoadTop
TelemetryBoadBottom

とりあえず、ソフトウェアーは、アナログポートの数値を読み込むだけの物を仮に作ってみた。
DJT から送られてくるプロトコルは、以下の通り(ヘッダー、ターミネーター 0x7E、アナログポートのID:0xFE)

0x7E、0xFE、PORT1、PORT2、Link_quality(2)、0x00、0x00、0x00、0x00、0x7E
※FrSky のマニュアルでは、Link_quality は1バイトで zero が5バイト続くとなっているが、Link_quality は2バイトで、zero は4バイトのようだ。

port1 のアナログ電圧は4倍して表示してある。
リチウムポリマー電池の電圧を1/4にして入力すれば良い。
グラフィックス液晶の利点を使って、レベルバーも表示してある。
LCD の下に破線が表示されていて、プロトコルを受信している場合に、アニメーションする。
一応、プロトコルの生データを16進で表示している。
この LCD は、アイコンの表示があり、最下位の4ピクセルの On/Off で表示するのだけど、役に立たないので、63ラインは使わない事にする。IMG_0410s

自分で作ると、専用のカスタマイズを作成する事が出来るのが良い。

※ソースコード

※回路は、mainloop.cpp にポートと、LCD の接続をコメントしてあるので、それを参考に。
※液晶は低速で、コマンドを書き込んでから、それが有効になり次のコマンドを発行するまで待たないといけない、一般的には、ステータスを読み取るのだけど、
液晶を外した状態にすると、プログラムが進まなくなるし、ポートの制御が面倒なので、プログラムループで遅延している、その為 R/W は書き込みしか行わないので、GND に落とす。
※シリアルは、RXD、TXD を RS-232C のコンバーターを通して接続する、DJT:RXD と AVR:TXD、DJT:TXD、AVR:RXD となる事に注意されたい。
※そのうち、KiCAD のプロジェクトをアーカイブに含めるつもり。

HK-450 フライバーレス・ヘリコプター(1)

クワッドコプターは、機械的な構造がほぼ無く、巧みな原理で飛行するのでクールで好きだ。
また、コンピューター制御(フライバイワイヤ)と密接に関係していて、電子回路と切っても切れない関係にあるのも良い。
だからと言って、機械的な構造を駆使して飛行するヘリコプターが嫌いな訳では無く(むしろ好き♪)非常に憧れる~(内燃機関が好きな理由も同じような感じだろうか)
前から、自分で飛ばしてみたくて、小型の室内ヘリなど買う寸前までいった事があるけどー、難しそうだし、際限無くはまりそうでスルーしてきたー。

HobbyKingと言うショッピングサイトがある、主に模型関係の部品を扱っているのだけど、
値段が信じられないくらい安くて、日本では買えないパーツや、面白い試みのパーツが盛り沢山、一番の問題は日本からでは送料が割高になってしまう事くらい・・
※幾ら以上だと送料無料とか、日本国内なら安全確実に安い料金で何処でも送れる、この「送料」が高い現実に、何度も躊躇するのだが・・
でも良く考えて「まとめて」買えば、どうにでもなるかもしれないと思い込む事にする、利用しない手は無いww

HobbyKing は色んなとこにリンクが溢れていて、何かの拍子にウィンドウショッピングを繰り返す事も多くて、「欲しい」欲求が抑えられないよー
そんなこんなで「HK-450」このヘリコプターは、450 サイズの規格で作られたヘリなのだがー、え!?、って値段で売られている。マジで・・・
この値段なら買ってもしょうがないなww、で、後先考えずにとりあえず買ってしまった・・
「本体」だけでは、飛ばないので、モーター、バッテリー、サーボ、ジャイロ、ESC 、必要そうな物を全て購入してしまう。
※それなりの出費だけど、マイクロヘリより本格的なヘリが手に出来る。

ヘリコプターの事なんて何も知らないけど・・・

それが、昨日届き、情報を調べながら、組み立て始めたので、その顛末をここに書いておこうと思う。

組み立てがある程度出来てしまったけどー

HK-450 フライバーレス
HK-450 フライバーレス

こんな感じ~

「何故フライバーレスなのかー」
ヘリコプターにはジャイロ(ローター制御)が必須だけどー、フライバーレスは、それより厳密な制御が必要で、より電子化された制御が必要な事からー、クワッドコプターに近いのかもしれない。
「ヘリコプターは飛ばすのが難しい」これは、昔から言われて来た事なのだがー、ジャイロや加速度センサー、マイコンによる姿勢安定制御ソフトウェアーの進歩が、この常識を変えようとしている。
※自分も姿勢制御ソフトウェアーを作ってみたい、研究してみたい~
↑この辺りも、あって研究目的で手を出したのもあるかもしれないwww

「安さと品質の関係」
本体は確かに安いけど、それだけでヘリが飛ぶハズも無い、「安物買いの銭失い」と言う言葉もあるけどー、日本の大手のように、アフターサービスなどコストがかからない分、空気が読める人だけに売る姿勢は、面白い。
キットには説明書は一切入って無い、聞く所によると、部品が足りないとか余分な部品が入っているとか、様々らしい、自分で考えて、調べて、スキルを上げて切り抜ける事が出来る人にだけ楽しめるものかもしれないww
もはや、ヘリを飛ばすのがゴールではない!作る過程がアドベンチャーゲームだwww
しばらくの間、それを含めて楽しむ事にしよう~♪

「キット以外に何が必要なのか?」
・1.5mm スクリューキャップドライバー(レンチ)
・2.0mm スクリューキャップドライバー(レンチ)
※一般的には、「6角レンチ」と呼ばれる事が多いです。
・小型プラスドライバー
・棒ヤスリ
※100近で売っている200円の「ダイヤモンド粉末入り」が良いです。
・2mm のドリル
・外形3mm、内径2mmのアルミパイプ
※サーボの固定は2mmのネジだけど、買ったサーボのマウントはラバーで固定するタイプなので、カラーを自作する。
・ヒシチューブ
※モーターを ESC を接続する場合、「直」で繋ぐので、ヒシチューブを被せる、テープで巻くより綺麗で確実
・バッテリーと接続するコネクター
※ESC には、バッテリーのコネクターが付属しないので、バッテリーに合ったコネクターを別途用意する。
・2×8mmネジ
※サーボホーンにリンケージを固定するビス、短すぎ!、タッピングビス的に使うのかも知れないけど、緩むのが不安なので、ビスとナットで固定。
・他に一般的な工具や材料など

※近くのホームセンターで、1本250円で、1.5mm のドライバーを買ったけど、軸がねじれてしまい、思った力で締められない、先端だけ 1.5mm で、中間は太くて剛性がある物が良いでしょうか。
※2mmの方も、ねじれる傾向はあるけど、ギリギリ我慢できるかも。

IMG_0372s

「サーボマウントカラーの製作」
今回買ったローター用サーボは、コストの関係で、HobbyKing 製メタルギアーアナログサーボサーボマウントは、ラバーで固定するタイプなので付属の2mmネジでは全く合わない、そこで、アルミパイプを加工してカラーを作る事にした。
※しかし、1個4.55ドルって・・・安!

まず、外形3mm、内径2mmのアルミパイプを用意する。(近くのホームセンターで、1m、199円でした)
・3mmくらいでカットします。
※カッターを垂直に押し当てながらゴロゴロパイプを転がすと、柔らかいアルミなので意外と綺麗に切れます。
IMG_0373s
IMG_0375s
↑ちょっと失敗、でも、1000mmもあるので、何回でもやり直せますww

・何か丁度良い厚み(1.5mmくらい)の板を用意して、3mmの穴を開け、そこにパイプを入れます。
※電子工作用のユニバーサル基板が1.6mmで、角に3mmの穴が開いているので利用しました。
IMG_0376s
↑パイプの口を広げる為に、先の尖った円錐状の物を用意します、写真に写っているのは、旋盤のレースセンターですが、ポンチのような物で良いでしょう。

・板から飛び出たパイプの先端を、円錐状の物で広げます。
IMG_0377s
IMG_0378s

・さらに、平らな物で先端を潰して完成です。
IMG_0379s

IMG_0380s
力の加減があるのですが、何回かやれば思ったように創れます。

全部で6個必要です。

「テールブレード用サーボマウント」
HK-450 では、テールブレードのピッチ変更用サーボだけ、高速な物を要求しています、理由は良く判りませんが、通常の(フライバーレスでは無い)ヘリコプター用ジャイロが要求する仕様のように思います。
一応、高速タイプのデジタルサーボを選択しました。
トルクが1.8キロなので、少し弱いのかもとも思いましたが、ここに大きな力が働くとも考えられません、しかしながら、サーボのブラケットは大きな物が用意されていて、このサーボはそのままでは取り付けできません。
そこで、アルミの板を切って、サポートを作りました。
IMG_0369s
ホームセンターで売られているアルミは、柔らかく加工が楽で安いので気軽に使えます、但し、このくらいの厚さ(1.5mm)があるとカッターで切る訳にもいかないので鉄ノコで切り、端面をヤスリで仕上げます。

「バッテリーの滑り止め」
工具の滑り止めなどの名目で売られている「例の」シートを、接着剤で、張りました。
IMG_0381s

IMG_0382s
接着剤には、「セメダイン・スーパーX」を使いますww
これを知ったのは、デコ携帯に色々くっつけるのに女子が使っているのを観たのがきっかけですww
意外と柔軟で、何でも良くかなり強く接着します、「瞬間」ばかり多用していた自分には新しいです!、但し、接着には時間がかかります。
※「瞬間」も、最近ではアロンアルファでは無く、ロックタイトを良く使います、アロン何とかは、二回目くらいに使う時に固まって使えない事が多く「損」です、最後まで使えた記憶が殆どありません。
※セメダイン社最高!

「モーターとESCの取り付け」
モーターは、Turnigy Typhoon 2215H Brushless 450-Size Heli Motor 3550kvにしました、特別な理由はありません、kv 値は一応少し気にして、他の人が使っているモーターと同じくらいの物を選びました。
※値段が15ドルと安いです!
ESC は40Aが推奨ですが、以前に研究用に買った30Aの物があり、モーターの最大電流が28Aなのと、薄くてマッチするのでとりあえずそれを取り付けましたが、40Aの物も買ってあります。(かなり大きい)
※足りないようなら、40A品を付けますが、しばらくは、高速で飛行させる事は無いので、多分十分と思います。
BEC出力も2Aありますから、サーボ4個程度なら十分です。

IMG_0384s
※モーターのハーネス、1本だけ、細すぎるチューブを使った為失敗しているww

モーターとの接続は、回転方向があるので注意しなければなりません、仮に繋いでみて、回して、回転方向を確認します。
※メインのスパーギアには、自転車のようなクラッチが入っていて、逆回転だと空回りするので、どちらに回転するのが正しいのか直ぐに判ります。
※逆回転なら、3本のうち2本を入れ替えます。

このモーターには最大28Aもの電流が流れるので、接続はハンダで、ガッチリ行います、接続した部分がショートしないように、ヒシチューブで絶縁します。
ヒシチューブは熱で収縮するのですが、ガス半田コテのホットブローアタッチメントを使って処理します。
IMG_0388s
※コテライザーは、ガス半田こてで、非常に便利です、先端のアタッチメントも色々あり、便利!

今回はここまで~

サーボとのリンケージとか、どのように調整するのか不明な事も多く、その辺りは適当に流しましたが、これから地道にやっていこうと思います。
このヘリコプター、意外に軽いのでビックリしますが、剛性が必要な部分はアルミ(ジュラルミン?)の削りだし、フレームもカーボンで出来てます、この造りでこの値段はやはり脅威です、しかし元のヘリコプターの設計が良い事は凄く良く判ります。
上手く飛ばせるようになったら、オリジナルが欲しいですねー

次回は、ジャイロの設定などを中心に紹介する予定です。

RX マイコンでC++

少し間が空いたけど、またまたRXマイコン関連ですー

日本の組み込み(趣味)マイコンでは、まだ「C」が主流で、「C++」の情報が少ないように感じる。
デバイスドライバーもCで書かれたものが殆どで、C++で書かれた物が少ない(日本国内では観た事が無い)
※たとえば、複数チャネルを備えたUARTなど、テンプレートクラスを使えば、拡張性のあるコードがシンプルに書けると思う。

Windows などのアプリケーションプログラマーは別だが、組み込み系プログラマーは、まだC++に対して、「負」の感情を持っているのだろうか?

最近AVRでプログラムする機会があり、C++が実用レベルで扱える事を知ったー
又、arduino を触る機会があり、そのコードはC++が中心である事も知った。
ARM系、海外の組み込みプログラムでは、C++が普通に使われている、何故日本は未だにCなのだろうか?

さて、RXマイコンの開発環境なのだがー、C++でプログラムする場合に必要な事を考えてみたい。

AVRではメモリーの制限からSTLを扱う事が困難だ、RXマイコンなら全てのデバイスでは無理だけど、少なくともRX621など、RAMもROMもある程度豊富にあればSTLも怖くないと思われる。
以前にSH2AでSTLが正しく動作しなかったのだが、それは、静的な初期化関数のコンストラクターが正しく呼ばれていない事に起因するようだった。

ARMの gcc などの情報から、「.ctors」セクションに初期化が必要な関数のコンストラクターテーブルが格納される事は判ったので、リンカースクリプトに.ctorsセクションのロード命令を記述して、簡単なコードを書き、アセンブルリストを観て確認してみた。

typedef unsigned int uint32;

class func {

uint32 count_;

public:
func() : count_(0) { }

void service() { ++count_; }
uint32 get() const { return count_; }
void set(uint32 v) { count_ = v; }
};

func func_;

↑たとえば、こんなクラスを宣言して、静的なクラスを配置する、「func_」は、main 関数が実行される以前にコンストラクターが呼ばれなければならない。
※funcクラスでは、コンストラクターで、count_を0で初期化している。

リンカースクリプトに、以下のように書いたが、mapファイルを観ても、.ctorsのサイズは0となっている・・・
.ctors :
{
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}

最適化を0にして、アセンブラリストを確認すると、初期化関数自体はあるが、当然呼ばれていない・・・

fff80b31 <__GLOBAL__sub_I_func_>:
fff80b31: 7e a6 push.l r6
fff80b33: ef 06 mov.l r0, r6
fff80b35: 66 11 mov.l #1, r1
fff80b37: fb 2e ff ff 00 mov.l #0xffff, r2
fff80b3c: 39 c7 ff bsr.w fff80b03 <__Z41__static_initialization_and_destruction_0ii>
fff80b3f: 3f 66 01 rtsd #4, r6-r6

そこで、C++の標準的リンカースクリプトを参考にしてみたー「/usr/tkdn-20110720/rx-elf/rx-elf/lib/rx.ld」
そして、判ったー、最近の gcc では、別のセクションに格納されているようだー、これは、4.6 くらいからそうなったようだー

PROVIDE (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE (__preinit_array_end = .);
PROVIDE (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE (__init_array_end = .);
PROVIDE (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE (__fini_array_end = .);

※ちなみに簡単に説明すると、「.preinit_array、.init_array」セクションが、コンストラクターの開始アドレステーブルが格納されるセクションであり、「.fini_array」はデストラクターの開始テーブルが格納されるセクションとなっているようだー
又、「KEEP」は、重要なキーワードで、最適化された場合、どこからも参照されないアドレステーブルは、削除される為、それが起こらないようにするものだ。

「__GLOBAL__sub_I_func_」は、「__Z41__static_initialization_and_destruction_0ii」を呼んでいるのだが、コンストラクターとデストラクターが共通になっており、引数を使って呼び分けているようだ。

初期化コードはこんな感じ~

int main(int argc, char**argv);

extern int sbss;
extern int ebss;
extern int idata;
extern int sdata;
extern int edata;

extern int _preinit_array_start;
extern int _preinit_array_end;
extern int _init_array_start;
extern int _init_array_end;

int init(void)
{
// R/W-data セクションのコピー
{
int *src = &idata;
int *dst = &sdata;
while(dst < &edata) { *dst++ = *src++; } } // bss セクションのクリア { int *dst = &sbss; while(dst < &ebss) { *dst++ = 0; } } // 静的コンストラクターの実行(C++ ) { int *p = &_preinit_array_start; while(p < &_preinit_array_end) { void (*prog)(void) = (void *)*p++; (*prog)(); } } { int *p = &_init_array_start; while(p < &_init_array_end) { void (*prog)(void) = (void *)*p++; (*prog)(); } } // main の起動 int argc = 0; char **argv = 0; int ret = main(argc, argv); return ret; } C++ テスト・コード

※今後 rx.ld を解析して、自分のシステムに合った物に修正する必要がある、リンカースクリプトにはまだまだ不明な事が多い・・・

とりあえず今回はここまで。