2016年12月30日金曜日

長征2号

先日打ち上げられた長征2号のTLEです。
JS Orbit

4個の物体が軌道投入されており、A-DまでそれぞれSUPERVIEW-1 01, SUPERVIEW-1 02, BY70-1, CZ-2D R/Bです。

前2個は高景一号01星, 高景一号02星と中国語表記されるようですが、新華社日本語版の紹介によると「リモートセンシング商業衛星」とのことです。

またBY70(八一・少年行)は「中高生40名余りが研究と製作の全過程に参加し」とのことで、教育的な意味合いの強い衛星だそうです。写真を見る限り2Uか3Uくらいのキューブサットだと思います。「八一」は参加した生徒が所属する学校に由来するようです。

リモートセンシング商業衛星「高景1号」が成功裏に打ち上げられ 中国初の中高生の科学普及活動を目的とした小衛星を搭載して打ち上げ_新華網日本語

***

ところで、中国語版wikipediaには長征2号Dの打ち上げリストがあり、今回の打ち上げ(F32)もすでに記載されています。それによると、SUPERVIEWは失敗、BY70は成功とされています。ちなみにそのリストによると今回の打ち上げ以外はすべて成功しており、今回が初めての失敗となるようです。
前述の記事では「成功裏に打ち上げられ」とのことで、SUPERVIEWも成功しているような書き方ですが、続報が待たれるところです。


中国の宇宙開発は日本からも注目されており、またSUPERVIEWは初号機ということもあり、たぶん詳しい誰かがちゃんとしたニュースサイトにまとめてくれると思うので、それを待ちましょう。

***

URLにTLEを入れるのは、手軽という意味では良いと思うんですが、鮮度という意味ではあまり良くないなぁと思い始めてます。とはいえ何か良い方法が思いつくわけでもないんですが。このあたりはもう少し考えてみようと思っています。

2016年12月29日木曜日

JS Orbitの更新

JS Orbitを少し更新しておきました。
JS Orbit

eventsの下にOrbit Statusという項目を追加し、近地点, 遠地点, 軌道長半径, 焦点, 可視範囲を表示するようにしました。


Apogeeが遠地点、Perigeeが近地点でそれぞれ地心からと地表からの距離を表示しています。ただし地表からの距離は地球直径を6378kmとした場合の近似です。そもそもJS Orbitの精度がそれほど高くないのでこれくらいは誤差の範囲ですねッ!
semi-major axisは軌道長半径で、Focalは焦点の位置です。軌道長半径+焦点が遠地点、軌道長半径-焦点が近地点です。
Field of Viewは衛星からどれくらいの範囲が見えるかを示す値です。

緑の円が地球、赤の十字の部分に衛星がいると考えて下さい。1本の水色は衛星と地球の中心を繋ぐ線で、もう1本は衛星の中心と地球の表面を通る線です。Field of Viewは上の図のなかでθと書かれている部分の角度でです。衛星がどんなに離れても90°を超えることはありません。衛星は無限遠よりはるかに近い位置にいますから、さらに狭くなります。例えば静止衛星であれば80°程度、地表400km程度(ISSのあたり)では20°程度です。

今回の更新はこんなところです。

2016年12月27日火曜日

ネタ:チャフ

コンサートのクライマックスでリボンが吹き出すような演出が有りますよね。メタルギアソリッドをプレイしたことが有る人ならわかると思いますが。あれは「チャフ」と呼ばれる装置の1つです。これは戦闘機や大統領専用機にも搭載されている装置で、その性能は折り紙付きです。
用途にはいくつか有りますが、コンサートで用いられているチャフは電波の妨害を目的としており、ワイヤレスマイク等を盗聴している電波に対して妨害を行うことにより、不正な手段で作成されたコンサート音源の流通を防止することに有ります。

というネタを思いついたので家族と紅白歌合戦を見ているときにでも披露してみて下さい。


アルミ蒸着でキラキラしてるやつとか意外とちゃんと使える気がする。
Ω「敵がレーダー誘導爆弾を使おうとしているらしい」
ΩΩΩ「ナッ ナンダッテー」
「任せろ!俺は舞台装置作ってるやつにコネが有るんだ!絶対に阻止してみせる!」
ΩΩΩ「おぉっ!!」
some hours later...
ΩΩΩ「レッツ・ショータイム!!」
みたいなネタでどうぞ。敵の占領下に有る街でコンサートにかこつけてレジスタンスがチャフを打ち上げて防空レーダーを無効化した後に生き残りの軍がヘリで突入するとか。
まぁ、ラストシップではアーレイバークを偽装するのにアルミホイルを使ってましたから、フィクションにアルミ箔ネタは鉄板だと思います。

そういえばレーザープロジェクターを演出で使うときってすっげー面倒な安全管理が必用だけど、チャフの反射波とかはどう扱ってるんだろう。せいぜい一瞬だから悪影響はないってことにしてるのかな。


今更書く必要もないと思うけど、コンサートでチャフ云々はもちろん嘘なのであしからず。
ミクさんマジ天使(マジカルミライBD見てた)。

2016年12月25日日曜日

ふらいとでーたれこーだーっぽい何か


最近、久しぶりにMS FSXをやっています。空母に着艦してみたり、ヘリの練習をしてみたり。半年ぶりくらいかな。しばらくやっていなかったのですっごいヘタになってます。着艦はアタフタしてるしスリングは全然できなくなってるし。

ただ飛行機を飛ばす練習とかしていても、あんまりモチベーションが維持できないので、とりあえずSimConnectで位置や速度をNMEAで吐き出せるアプリを作ってみました。
上の画像は新千歳空港でF/A-18を飛ばしたときの経路です。最後に変な方向に行ってるのは滑走路上に別の機体がいたためです。シミュだからってサボらないでちゃんとATCの許可取らないとダメですね。

NMEAは電子工作でお世話になっていますし、デファクトスタンダードなのでいろいろな用途に使えます。もちろんGoogle Earthにドラッグ・アンド・ドロップで読み込ませることもできます。
電動雲台とか作って自動追尾をやるときのサンプルデータとかにも良いかも。FSXの旅客機なり戦闘機なりヘリなりを追尾できればだいたいの物理法則に則った移動物体は追尾できると思います。RasPiとかでADS-Bの位置情報をNMEAで吐き出せばそのまま実世界のトラッキングにも使えますしね。

とか色々妄想を深めつつ、ちゃんと練習もしなければ。。

2016年12月24日土曜日

アリアン5

スカパーの衛星等を載せたアリアン5の打ち上げがありました。



JS Orbit

wikipediaのアリアン5打ち上げリストによると今回の打ち上げはStar One D1という衛星とJSCAT-15の2機を打ち上げたようです。前者はブラジルの通信衛星、後者は日本の通信衛星です。

打ち上げ時に固体ブースターからパネルがペリペリと剥がれているのが面白いですね。低温燃料が入ってるというわけではないと思うので、霜の付着とかは無いはずなんですが、何のためのパネルなんだろう。
あと管制チームがお揃いでキラキラしてるのも面白いです。


この打ち上げは今年82回目の打ち上げですが、このグループでは4個の物体が打ち上げられています。衛星2機とR/Bが2機だと思われます。

アリアン5は極めて大きなロケットなので、1回の打ち上げで2機の衛星を軌道に投入できるわけですが、ロケット最上段に1個目の衛星を包み込むような構造体(Sylda、シェルダ?)が有り、その上に2個目の衛星が乗っています。フェアリングはシェルダを含めたすべてを包み込む大きさになっています(詳しくは下にある動画リンクで確認して下さい)。

同時2機打ち上げでは、昨年初めに打ち上げられた「オール電化衛星」とも表現されるボーイング702SPバスがあります。この衛星は上下2機を組み合わせて打ち上げられるように設計されており、実際にそのように2機同時打ち上げが行われています。

All-electric Propulsion Satellites

この方法ではシェルダという、ロケット側からすれば「余分なお荷物」を載せる必要はありませんが、下の衛星から見れば打ち上げ時は上に数千kgの重りが乗っていることに耐える必要があり、しかもその強度を確保するための構造材は軌道上で運用する時には余分な重りとして最後までくっついてきますから、軌道変更等では衛星に搭載された限り有る燃料をより大量に使用してしまいます。

それぞれ一長一短が有るわけですが、アリアン5はロケット側で「棚」を用意する選択をし、1回の打ち上げでR/Bが2個発生するのはそういった理由によります。



フェアリングの分離が18分頃、44分頃にStar One D1が分離、46分頃にシェルダを分離し、58分頃にJCSAT-15を分離しています。


JCSATは近地点250kmあたり、遠地点35700kmあたり楕円軌道を回っています。これは典型的な静止トランスファ軌道です。現在のところ軌道傾斜角が6度ほどありますが、これは射場が北緯5度付近に有るためです。

***

最近は打ち上げのたびにJS Orbitのリンクを張ってるだけになってますね。TLEコピペするだけなので楽。そろそろ他のネタを探してこないと。。えーっと、あけおめことよろ?まだ早いか。


追記:2016-12-25
TLEが更新されてR/B等も確定しました。
JS Orbit
1つは"ARIANE 5 R/B"でもう1つが"AREANE 5 DEB [SYLDA]"となっています。前者が最上段、後者がシェルダです。ロケットボディではなくデブリの扱いになるんですね。
それからJCSATの方も静止化が進んでいるようです。前回紹介したときは離心率0.73で平均運動2.3ほどでしたが、今では離心率0.30で平均運動1.5ほどです。それに伴い近地点は16000km、遠地点は36000kmほどになっています。

2016年12月21日水曜日

ERG

ジオスペース探査衛星、ERG(あらせ)のTLEが出ていました。
2016-080A               
1 41896U 16080A   16355.92717683 -.00731813  00000-0 -10074+0 0  9992
2 41896  31.3930 290.1072 7076016 115.6541  66.7571  2.55779060    14
2016-080B               
1 41897U 16080B   16355.84371275  .02432781  00000-0  34047+0 0  9995
2 41897  31.4065 290.1891 7046970 115.4976 353.6704  2.59500923    10
JS Orbit

おそらくAが衛星、BがR/B(イプシロンの3段)だと思います。


離心率0.7という楕円軌道のため、逆行するような動きになっています。


追記:2016/12/22
TLEが更新されました。
SPRINT-B (ERG)          
1 41896U 16080A   16356.60587898  .00530202  00000-0  69308-1 0  9994
2 41896  31.4624 289.8921 7072393 115.9622 332.7906  2.56375098    34
EPSILON R/B             
1 41897U 16080B   16356.20480958  .00001000  00000-0  19929-3 0  9995
2 41897  31.4058 290.0684 7051235 115.6768 330.3194  2.58962011    27
JS Orbit

イプシロン初号機で打ち上げられたひさき(SPRINT-A)の続きの名前で、カッコ内にERGとされています。ちなみにひさきは現在のところ"HISAKI (SPRINT-A)"という名前で登録されています。探せばSPRINT-Bという名前の(あるいはSPRINTシリーズであるとされている)記述はありますが、あんまり一般的には使われていない気もします。TLEの名前が変更されることって有るのかな。まだ衛星の分類もされていませんから、そのあたりの情報更新が楽しみです。

2016年12月20日火曜日

妄想:はいふり

ハイスクールフリートネタバレ等々

キューブサット

昨日放出されたキューブサットと思われるTLEが出ていました。

1998-067KR              
1 41895U 98067KR  16354.71778486  .00074048  00000-0  11035-2 0  9999
2 41895  51.6395 212.9464 0004321  14.8409 109.9371 15.54415999    15
JS Orbit

TLEは基本的に「打上年(下2桁)」と「その年の何回目の打ち上げか」と「その打ち上げの何個目の放出か」という情報が書かれています。上のTLEでは98067KRの部分で、1998年の67回目の打ち上げ、304個目の放出、ということになります。
この衛星が宇宙に行ったのは今年ですが、ISSからのキューブサット放出はこのようにちょっと直感的ではない状態になってしまっています。


すでにSTARS-Cのビーコンは取れているようですね。ウチにもUHFのアンテナやワンセグチューナーはあるので、受信しようと思えば取れると思いますが、クソ寒い真冬の北海道なのでこの時期はあんまり気乗りしないです。ここ最近ずーっと天気悪いですし。アマチュアUHF帯は違法無線多いから嫌なんだよなぁ。。


追記:2016/12/21
衛星名がSTARS-Cに更新されました。
STARS-C                 
1 41895U 98067KR  16355.14554096  .00089933  00000-0  13320-2 0  9994
2 41895  51.6402 210.8150 0004357  15.2016 344.9096 15.54497736    82
JS Orbit

それと近いうちに昨日打ち上げられたERGも追加されるはずです。

2016年12月16日金曜日

JSorbitのアップデートとか

【やじうまPC Watch】「旅客機から切り離すロケット」衛星の投入に成功する  - PC Watch

エアロンチのロケットから衛星8機を軌道投入だそうです。衛星名はCYGNSSで、画像検索するとロケットと結合してる写真とか出てきますが、衛星らしくなくて面白いですね。感じとしてはキューブサットに近い搭載方法です。規模としてもそんなもんですが。

TLEデータもすでに出ています。NORAD Two-Line Element Sets
Current Dataの"Last 30 Days' Launches"というテキストファイルです。たぶん16年78回目の打ち上げがこれだと思います。なんかロケットってバンバン打ち上げられてるイメージでしたけど、今年ももう12月半ばでまだ80機未満なんですね。平均すればだいたい4日に1回打たれててると考えるとそれなりに多いのかな?
16-78はA-Jの9セットで、衛星8機+ロケットだと思います。数日中に詳しく更新されると思います。


さて、本題、JS Orbitの件。URLオプションでTLEデータを渡しても表示されない問題を修正しておきました。上記9機のURLはこちら。めっちゃ長いので全文字表示にはしませんでした。また2000飛んで数百文字あるので、Microsoft系のブラウザでは見れないと思います。Chrome等をご利用下さい。


計画性もなくテストもせず一人でチマチマ作ってると思わぬところにバグが有るね。URLでTLE渡すのって前にも別のバグで動かなかったし。

追記:2016/12/17
今朝1時過ぎ(JST)の更新で打ち上げロケット(ペガサス)だけ出てました。
JS Orbit

ロケットと衛星は明らかにRCSが違うだろうから簡単に見分けられるのかな。キューブサットの複数投入だと似た形状がほぼ同じ軌道で放出されるから、見分けるのは大変そう。キューブサットってどうやって判別してるんだろうか。ロケット側から放出したタイミングとか情報もらって、それと軌道を遡って計算して「どうやらこれらしい」とかやってるのかな?

追記:2016/12/18
今日の更新で衛星側の確認もできたようです。
JS Orbit

それとHTVで運ばれたキューブサットの放出もいよいよ1機目が明日に迫っています。それ以降は少し間が開くようですが。
明日放出のキューブサットは2U型で、テザーで2つに分離した後、双方がUHF1chずつ計2chでビーコンを出すようです。10kHz間隔で2chですから、ワンセグチューナー等を使えば双方を同時に受信できますね。

2016年12月12日月曜日

角度の正規化

数ある角度の表現方法の中で、-180度から+180度、もしくは-PIから+PIの範囲への正規化。

public static double DegreesNormalize(double Degrees)
{
    return (RadiansNormalize(Degrees * Math.PI / 180) * 180 / Math.PI);
}

public static double RadiansNormalize(double Radians)
{
    return (Math.Atan2(Math.Sin(Radians), Math.Cos(Radians)));
}

たぶんこれで動くはず。whileやforで回してるわけではないので処理速度は常に一定となる(はず)。おそらく処理系依存ではないと思うけど、ExcelみたいなXとYが逆ってこともあるのでちゃんと確認してから使うように。

2016年12月9日金曜日

Arma3のサプによる弾速への影響

最近Arma3を買ってちょっとハマってます。ウチのArma3めっちゃ落ちやすくて数分ごとに落ちるのでストレスフルですけど。

それはさておき。

Arma3のプレイ動画はyoutubeとかにかなりありますね。特にマルチプレイ。そして「サプを付けてると威力が落ちるから敵にバレたらはずせ」というのが定説なようです。ほんとに?あのArmaが?ということで計測してみました。


レンジ1000mでM18ABRを使用して伏せ撃ち、バイポ使用、通常弾です。ターゲットは1000m先に置いた棚で、射撃は残弾カウンタが変化したフレーム、弾着は棚に当たった破片(煙)が出たフレームです。撃ってる時をGeForce Experienceでキャプチャして後でフレーム数を数えています。
平均速度は銃口初速や弾着の速度ではなく、全体の平均です。本来7.62x51NATOの銃口初速は800m/sほどですから、平均でこの速度ということは弾着時は音速を下回っているはずです。

最初に弾速が変動していますが、たぶん僕の読み取りミスだと思います。それ以外はすべて488m/sで安定していますし。


サプなし1000zはゼロイン1000mでサプレッサーなし、サプなし800zはゼロイン800mでサプレッサーなし、サプあり800zはゼロイン800mでサプレッサーありで射撃しています。すべてレンジは1000mです。

弾速が変化すれば少なからず弾道にも影響があり、弾道が変わればゼロインがズレている場所への弾着にはより大きな影響があります。しかしサプあり・なし共に弾道への影響は気が付きませんでした。弾速が安定していることからも、サプの有無によって弾速への影響は確認できません。
弾丸の威力、すなわち運動エネルギーは弾頭重量と速度にのみ影響を受けますから、弾頭が変化していないと仮定すれば威力への影響も発生していないことになります。

そもそも弾薬が同じであればサプレッサーの有無による運動エネルギーの変化というのは殆どありません。残弾を弾倉1本毎に管理しているArmaが、弾倉の交換も無くサプの着脱だけで装薬量が変わるとは思えません。


話は変わりますが、最近米軍で大規模にサプレッサーを配備しようという動きがあるようです。理由としては心身への影響を含めて様々なものがあり、その中に「過剰な効果があると誤解することを防ぐ」というものがあります。実際にArmaでサプの有無を変えて撃ち比べてみるとわかると思いまますが、サプが付いた静かな銃で撃ってもあまり効果がある射撃をしているとは思えないでしょう。逆に、サプのない騒音を撒き散らす銃であればセミで軽く撃つだけでも効果的な射撃を行っているという実感が有るはずです。Armaでサプの有無による影響が有ると言われているのは、このような精神的な影響が大きいように思います。
あるいは、サプをつけると弾丸の安定性に何らかの影響を与えているかもしれません。その場合、ある程度離れれば散布界も大きくなりますから、通常弾では当たっているはずでもサプ付きでは相手に当たっていないかもしれません。そうなれば当然ダメージもありませんから、サプの威力減に説明がつきます。

もちろんArmaがどのようにダメージを計算しているかはわかりませんから、実際はサプがついていると何らかの影響があるとか、ダメージの計算に運動エネルギーは考慮されていなくて弾速の計測なんて何の意味もないという可能性もあるわけですが。

2016年12月5日月曜日

Three.jsの軌道表示

とりあえず暫定的にThree.jsで軌道を表示するやつをJS Orbitの下に置いときました。
http://www13.plala.or.jp/rian/jsOrbit/three/?autosize

軸とかラベルとか前部表示だとかなり見づらいです。とは言え不要な情報というのはあまりないので、せいぜいECEFのラベルを消すくらいでしょうか。

フォントの関係でラベルはすべて英語です。間違ってても文句言わないで下さい。そもそも軌道の表示自体が間違ってるかもしれませんが(そのためのページタイトル「ThreeJSの練習」です?)。

黒いところでマウスを動かすと視点を動かすことができるので、見やすい視点を探してみて下さい。画面をクリックすればその位置で視点を固定し、もう一度クリックすれば固定を解除します。

視線固定を解除していて、カーソルがブラウザの外にあるときは自動的に視線を回転させます。フルスクリーンで勝手に回しておけばちょっとした癒やし効果がありそうです(個人の感想です)。


軽く見方を説明しておきます。

まず赤、緑、青の軸はそれぞれX, Y, Zの向きを示しています。

ECIはX+が春分点を向き、ECEIはX+が経度0度を向いています。ECI, ECEFはZ+が北極方向、Yはそれらに直行する軸です。

OrbSという軸はOrbit Surfaceの略で、軌道面になります。

中くらいの白い円・楕円は衛星軌道を示しています。

外側の大きなオレンジの円弧は軌道面に至る回転を示しています。Ω Right Ascensionは昇交点を、i Inclinationは軌道傾斜角を、ω Argument of Perigeeは近点角を示しています。



Three.jsをダウンロードしてきたのがおよそ3日前ですから、初めて触ってからたった3日くらいでこれくらいのモノが作れるようになります。なれてれば半日もかからないと思います。Webブラウザでマルチプラットフォームで動くものがこんなに簡単に作れるんですからすごい時代ですね(ウチのモバイル端末はWebGLに未対応なのでマルチプラットフォームの動作確認はしてないですけども)。

Three.jsはObject3Dで入れ子にできますが、JavaScriptでこれを書くのはかなり面倒です。僕はあんまりGUIツールは好きじゃないのですが、このあたりは木構造で簡単にThree.jsのコードを生成できるようなソフトウェアがあればすごい便利だと思います。そういうのがあれば今回のようなテクスチャのないモノなら10分や20分で作れるだろうなぁ。


とりあえず、後は緯度経度の矢印を作ったりとか、そのあたりでしょうか。
本当は昇交点だったり傾斜角だったりを少しずつ増やしていくアニメーションとかも作ってみたいんですが、リアルタイムに書き換えるのをどうすれば良いのかわからないのでもうちょっとThree.jsを調べてからになると思います。メモリリーク怖い。

2016年12月4日日曜日

軌道面



Three.jsで作ってる衛星軌道の概要を表示するやつ、とりあえずECI, ECEF, Orbit Surfaceの情報を表示できるようになってきました。ということで経過報告。といってもECIとECEFはジャマなので消してますが。

青の矢印が地球の中心(ECI, ECEF, 軌道面すべての原点)です。その周りの円と、長半径が同じ楕円は地球の大きさを示しています。
その外側に有る円と楕円は軌道の大きさです。楕円が実際の衛星軌道、外側の円は衛星軌道に外接する真円です。

赤が衛星軌道に外接する真円の原点で、緑の矢印は衛星の位置によって移動しますが、緑の矢印の部分にあるオレンジと赤の線は常に直角です。
水色の矢印で示した、オレンジの線と楕円の交点に衛星がいます(ラベルの位置が不適切なので真円のところに衛星がいるように見えてしまいますが)。


他の言語で直接3Dを作るよりはThree.jsを使ったほうが簡単なんでしょうけども、それでも結構面倒です。特にpositionやquaternionが思い通りに設定できないのが面倒。いちいちObject3Dで入れ子にしたりとかしてて、なんかもうちょっとうまくできないものかなぁと。

メモ:離心率から短半径と超半径の比率を計算

楕円のパラメータには超半径a, 短半径b, 焦点c, 離心率e, 扁平率f等がある(らしい)。abからcやeやfを計算する式はちょっと探せばいくらでも出て来るが、eから計算する方法はあんまり見つからなかった。そういう計算を必要とする人がいないからどこにも書いてないのかもしれないけど、せっかく苦労して調べたのでメモしておく。


たったこれだけの計算式を調べるのにだいぶ時間を使ってしまった。こういうところで色々不足してるのが思い知らされる。

2行軌道要素だと離心率が与えられるし、長半径を計算するのも簡単だけど、短半径がないと楕円を作れない、というところでこういう計算が必要になる。

/*
ぜんぜん関係ないけど、いまディスカバリーの怪しい伝説でテレビゲームを扱ってる。フルーツニンジャとかDOOMとか。このDOOMみたいなのやったら楽しいだろうなぁ。夏休みとか人集まるような時期にお化け屋敷みたいなふうにやってみたい。「超人的な狙撃手」でやってた、紙で作った部屋でやるサバゲも楽しそうだよね。ちゃんとした壁は邪魔者でしかないから、どっかのだだっ広いところに垂木とかでフレームを作って、模造紙で壁を作る、そんな感じでやるならエアガンを撃てる部屋を探す必要もないし、広いことについては定評のある北海道だから、壁の有る部屋を作るのは簡単だろう。ただ天井もないから、雨とか降ったら最悪なことになる。そうでなくても前日に雨が降るだけでも問題。ほんとは単管とかで2階フロアとか作って、ラペリングとかもやってみたいけど、安全確保が大変だからお化け屋敷みたいな人を集めるイベントでは無理だろうなぁ。まぁこのあたりは準備中にスタッフだけで遊ぶとかもできるだろうし。やるにしたって7月か8月になるだろうから、もうちょっとじっくり考えてみよう。
*/

2016年12月3日土曜日

衛星の軌道面とか軸の話

文字だけで軌道の座標とか説明するのはかなりつらいので、試しにCADで書いてみた。


まだ無理があるかな、という感じ。そもそも3次元を2次元画像に押し込むのが無理がある。
マウスで視点をグリグリ動かすとなんとなく3次元形状を把握できるようになるので、試しにThree.jsで表示してみた。


「5分でできるThree.js入門」とか言っておきながらThree.js本体をダウンロードするのに30分かかるじゃねぇか!!とか毒づきながらも、丸1日でここまでできるんだから楽なもんだなぁとも思ったり。


今回は離心率が約0.49、平均運動が7.4くらい、軌道傾斜角が63くらいの衛星を表示してみた。
勝手な思い込みでQZSは結構離心率が大きい印象だったけど、実際には0.075くらいしかない。これくらい小さい離心率でもあんな動きになるんだねぇ。


最終的にはTLEを渡したら表示できるような感じになると面白いかなーとか考えながらも。もうちょっと色々表示を追加したい。いくらライブラリにまとまって簡単とはいえ、やはりそのままだと文字の表示とかが大変なのでこのあたりはうまくラッパー関数を作ってやる必要があるのかな。

2016年11月30日水曜日

第4回:関数電卓で行う衛星位置の計算

さて、「関数電卓で行う衛星位置の計算」シリーズは前回で一応の完結をみました。が、前回最後に書いたとおり、せっかく衛星の位置がわかったんだからどの方向に見えるかも計算してみたいと思います。

しかし前回計算した南緯51度, 西経10度というのは日本から見ればほとんど地球の裏側であり、さすがにこれの方位や仰角を計算しても面白くないでしょう。
ということで、前回、前々回の復習も兼ねてもう一度衛星の位置を計算してみましょう。確実にISSが見える位置にいてほしいので、とりあえずJAXAのWebサイトで可視な時間を調べておきました。

軌道要素は以下を使用して下さい。
ISS (ZARYA)             
1 25544U 98067A   16331.50278528  .00003330  00000-0  58332-4 0  9995
2 25544  51.6438 328.6268 0006073 257.1648 241.1942 15.53732614 30231

観測日時:2016/12/04 17:01:30 JST

まずは第1回を参考に各要素を取り出してみて下さい。その後、第2回、第3回の手順のとおりに計算し、ECEF座標を計算して下さい。BLHまで計算する必要はありません。

まずはECIです。答えを書いておくと、僕が計算した結果はX = 4549, Y = -2653, Z = 4280といったあたりです。PreviSatの結果はX = 4543, Y = -2639, Z = 4287といったあたりです。だいたい17kmくらいの差がありますが、誤差の範囲だと考えましょう。

充分に問題のない数字であれば、ECEFまで計算を行って下さい。何百kmもズレているようであればどこかおかしいはずなので、もう一度計算してみて下さい。

参考までに、ECEFはおよそX = -3776, Y = +3671, Z = +4280あたりになります。

観測地点の決定

さて、いよいよ方位と仰角の計算に入ります。が、その前にまずは観測地点が何処かを決めておく必要があります。とりあえず北緯35.71, 東経139.81を使用して計算しようと思います(おおよそ東京スカイツリーのあたりです)。

緯度経度は今後頻繁に使うので、メモリに保存しておきます。といってもA, B, Cは衛星のECEFを保存していますし、x, yは今後使用しますから、D, E, Fのいずれかになります。とりあえずDに緯度、Eに経度を保存しておきましょう。

[35.71][STO][sin]

[139.81][STO][cos]

観測地点の位置ECEFを求め衛星との差をとる(ECEF)

まずは衛星と観測地点の差を計算します。衛星のECEFから観測地点のECEFを引いた差を求めることになります。
本来は観測地点のECEFを計算した後に差を求めるのがわかりやすいのですが、現在自由に使えるメモリが限られているので、観測地点のECEFを計算しつつ、同時に衛星との差も計算していきます。

緯度経度からECEFを求めるにはRec関数を使用します。Rec関数は半径rと角度θからx, y要素を計算するもので、sinとcosを同時に計算する事ができる関数です。sinとcosを個別に計算しても良いのですが、せっかくRec関数があるのでそれを使用します。

まずは緯度からECEFのZを求めます。
[SHIFT][-][6371][SHIFT][)][ALPHA][sin][=]
x = 5173.135203
y = 3718.643997

yがECEFのZとなるので、衛星のECEF、メモリCから引いた差をメモリCに入れておきます。
[ALPHA][x-1][-][ALPHA][S←→D][STO][x-1]
C = 561.235594

次に経度からECEFのXとYを求めます。
[SHIFT][-][ALPHA][)][SHIFT][)][ALPHA][cos][=]
x = -3951.802836
y = 3338.350217

メモリx, yはそれぞれECEFのX, Yです。Zと同じように衛星との差をそれぞれのメモリに入れておきましょう。
[ALPHA][(-)][-][ALPHA][)][STO][(-)]

[ALPHA][°'"][-][ALPHA][S←→D][STO][°'"]
A = 175.3075856
B = 332.5032403

ENUを求める

ENUは適当な日本語訳が見当たりませんでした。近い概念としてはEND, 局地水平座標系がありますが、最後の1文字が違う通り、1軸の解釈が違います。ENUはEast, North, Upの略で、東にいくら、北にいくら、上にいくら、という情報です。対してENDはEast, North, Downの略で、東にいくら、北にいくら、下にいくら、という情報です。
ベクトルの減算と回転で得られる値はENUですから、ここではENUを使います。

さて、ENUの計算ですが、これは「ベクトルの減算と回転」により計算します(他の方法もありますが、関数電卓向きではないのでここでは扱いません)。
ベクトルの減算はすでに先程済ませたので、あとは回転を行うのみです。ベクトルの回転は第3回で行ったECIやECEFの計算と同じです。ただしその時はX軸とZ軸の回転を使いましたが、今回はY軸とZ軸の回転です。

まず最初にZ軸で-Lon分を回転させ、その次にY軸でLat分を回転させます。

LonはメモリEに入っていますが、ZはLonの逆に回転させる必要がありますから、まずはLonを反転させます。
[-][ALPHA][cos][STO][tan]

[ALPHA][(-)][cos][ALPHA][tan][)][-][ALPHA][°'"][sin][ALPHA][tan][STO][)]

[ALPHA][(-)][sin][ALPHA][tan][)][+][ALPHA][°'"][cos][ALPHA][tan][STO][°'"]

[ALPHA][)][STO][(-)]

次にLatの回転を行います。
[ALPHA][x-1][cos][ALPHA][sin][)][-][ALPHA][(-)][sin][ALPHA][sin][STO][)]

[ALPHA][x-1][sin][ALPHA][sin][)][+][ALPHA][(-)][cos][ALPHA][sin][STO][(-)]

[ALPHA][)][STO][x-1]
A = 393.07277, B = -367.13236, C = 408. 636965

以上でENUの計算が終了です。ただし軸の取り方がちょっと直感とは違うと思います。A(X)がUp, B(Y)がEast, C(Z)がNorthの方向になります。

方位と仰角を求める

お疲れ様でした、あとは方位と仰角、ついでに距離の計算を残すのみです。これはECEFからBLHを計算したときとほぼおなじ計算です。

まずは方位を計算します。
[SHIFT][+][ALPHA][x-1][SHIFT][)][ALPHA][°'"][=]
x = 549.3362752
y = -41.93752609

yが方位ですが、負数になっているので360に方位を加算して最終的な方位とします。とりあえずメモリDにでも入れておきましょう。
[360][+][ALPHA][S←→D][STO][sin]
D = 318.0624739

次に仰角を計算します。
[SHIFT][+][ALPHA][)][SHIFT][)][ALPHA][(-)][=]
x = 675.4824545
y = 35.5852838

yが仰角なので、メモリEあたりに入れておきましょう。
[ALPHA][S←→D][STO][cos]

そしてxに入っている数字が彼我の距離となります。ついでなのでメモリFあたりに入れておきましょう。
[ALPHA][)][STO][tan]

ということで、メモリD, E, Fにそれぞれ方位、仰角、距離が入りました。それぞれ318°, 35°, 675kmとなりました。前例に従いPreviSatの値を例に出すと、それぞれ321°, 34°, 688km と言ったところです。方位で3°ほど、仰角で1°ほど、距離で10数kmほどズレていますが、肉眼で観察しようと言う程度であれば数度の誤差は問題ありません。距離に関しては何割もズレていなければ大して問題になりません。

最後に

以上で全4回に渡って続いた「関数電卓で行う衛星位置の計算」シリーズは終了となります。
実際のところ、既知の衛星の位置を電卓で計算してもあんまり使い所はありません。例えばISSが見れる日時を知りたければJAXAのWebサイトで探したほうが楽ですし確実です。衛星がどこにいるかを調べたい場合でも、PreviSat等を使えば簡単に知ることができます。
しかし、「宇宙?人工衛星?なんか難しそう。分かんないや」と思っていても、実は電卓で計算できるんだよ、というところから宇宙を身近に感じる人がいるかな、と思ってこのシリーズを書いてみました。

2016年11月27日日曜日

第3回:関数電卓で行う衛星位置の計算

前回に続き衛星の位置計算です。

前回は軌道面上の2次元位置を計算しました。今回はBLH(緯度経度高度)の計算までを行います。


2016年11月25日金曜日

第2回:関数電卓で行う衛星位置の計算

さて、前回に引き続き関数電卓で行う衛星位置の計算です。

前回、「次回はECIまで計算するよ」と書きましたが、ECIの前の段階までに変更となりました。ということでECI(からBLHまで)は次回となります。今回は軌道面上での2次元位置を計算するところで終了となります。


まず、その前に、いくつかの前提を説明しておきます。

1. 使用する電卓
使用する電卓はもちろん関数電卓ですが、今回はCASIO fx-JP900というモデルを使用します。変数が最大10個ほど(A-Fとx,yにMとAns, preAnsが)使用できます。
他の電卓には無い機能をつかったりしているかもしれません。その点はご了承下さい。
以降、このシリーズではキーの操作はすべてこの電卓のものです。

2. 精度
今回、衛星の位置は直交座標時の距離で40km、緯度経度時の角度で5度程度の誤差が発生するはずです。天体望遠鏡で撮影したい場合やレーザー通信を行いたい場合は問題が有る精度ですが、そもそもそんなことには使わないと思うので、問題ないこととします。


ということで、実際の計算に入ろうと思います。必用な値は前回書いておきましたので、別ウインドウでその数字をいつでも見れるようにしておくと便利だと思います。


2016年11月22日火曜日

第1回:関数電卓で行う衛星位置の計算

おわび

今シリーズで扱う計算式ですが、式自体に大きな誤りは無いと思いますが、手順に問題があります。既知の問題として、離心率が大きい軌道を計算した場合に不正な値となります。以後で使用する軌道の離心率は充分に小さいので大きな問題とはなりませんが、追って修正したいと思っています。
***


何回かの連載で「関数電卓で行う衛星位置の計算」というネタを扱おうかと思います。途中で失速するかもしれませんが。。。

なお、僕は衛星とか軌道とかちゃんと勉強したこと無いので間違ってたらごめんなさい。


初回の今回は起動計算は行いません。
軌道計算に必用な情報を集めるところから開始します。

これからのシリーズで使うデータは以下のTLEを元にします。

ISS (ZARYA)             
1 25544U 98067A   16326.55347831  .00003030  00000-0  53814-4 0  9995
2 25544  51.6454 353.2810 0006168 238.1568 278.5578 15.53693589 29460

見て分かる通り、ISS(国際宇宙ステーション)のデータです。

軌道計算に必用な要素は1)Epoch Time, 2)BSTAR drag, 3)軌道傾斜角, 4)昇交点赤経, 5)離心率, 6)近地点引数, 7)平均近点角, 8)平均運動 の8要素になります。
さらに、観測日時であるとか、計算に必用ないくつかの定数がありますが、定数については必要になった時に説明していきます。

また、観測日時については2016年11月22日 21時53分15秒(JST)を使用します。このブログを書いている時間です。もっとも、今回は観測日時の情報は使いませんが。


さて、突然ですが参考資料です。
きどうようそのひみつ
・人工衛星位置推算の実際(国土情報処理工学の"人工衛星の位置推算"というリンク)

前者は今回説明することをわかりやすく説明してくれます。まずはここを読めばTLEに何が書いてあるかわかります。
後者で扱っていることは今回は扱いませんが、要素の名前をこの資料と一致させています。


とりあえずTLEから情報を抜き出してみます。

Epoch TimeET16年326.55347831日
BSTAR dragM20.53814*10^-4
軌道傾斜角i51.6454
昇交点赤経Ω0353.2810
離心率e0.0006168
近地点引数ω0238.1568
平均近点角M0278.5578
平均運動M115.53693589

基本的にTLEからのコピペです。同じ数字があるはずですから、探してみて下さい。
例えばBSTAR dragはTLEでは先頭の"0."が省略されています。またこの値は指数ですが、"e"もしくは"*10^"が省略されているので書き加えています。
離心率についても同様で、この値は指数ではありませんが、0以上1未満であることが保証されているため、先頭の"0."は省略されています。
その他、EpochTimeは年の下2桁のみ書かれています。その為1999年から2000年へ切り替わるタイミング等で問題が発生する可能性があります。もっとも、次回は2100年でまだ80年以上先ですから、当分は気にしなくてもいいでしょう。もちろん、「俺の作ったプログラムは100年以上使われるはずだ!」という人はちゃんと考慮しておく必要があります。今回は関数電卓で計算する以上、途中で人間が適切に判断するはずだという期待において気にしないことにします。


地球直径や重力定数といった定数類を除けば、以上の値があれば衛星の位置を計算することができます。というところで、今回はおしまい。
次回は衛星の位置をECIという座標系で表現できるところまでを行いたいと思っています。
その後でECEFやBLHになりますから、おそらく第3回あたりで衛星の位置を緯度経度高度に算出できていると思います。

2016年11月13日日曜日

jsOrbitの隠しコマンドとか近況報告とか

jsOrbitですが、更新履歴を信用するなら5月の更新が最後だそうです。やばい。何がヤバいって軌道表示アプリなのに軌道要素が5月のデータ。

で、jsOrbit側の更新はもう少しあとになりますが、実は隠しコマンドが実装してあって、こいつが役に立つようにローカル側のプログラムを作りました。

隠しコマンドというのが、TLEデータのファイル名を与えるとそのファイルのTLEを読み込むというものです。ただ、いままでそのデータセットを作っていなかったので隠されていました。

今回、TLEデータをフィルタリングして必用なデータだけまとめるプログラムを作って、アップロードまでを一括して行えるようにしました。ということでTLEデータの更新はもうちょっと高頻度にできるかなと思います。

今のところはCubeSatとGeosynchronousOrbitしかありません。
http://www13.plala.or.jp/rian/jsOrbit/?set=CubeSat
http://www13.plala.or.jp/rian/jsOrbit/?set=GeosynchronousOrbit

CubeSatはすべてを網羅しているとは限りません。一応en.wikipediaのリストをコピペしてきましたが、IDの表記がない衛星も有るためです。
GeosynchronousOrbitは静止軌道ですが、これについては平均運動1±0.01かつ軌道傾斜角0±0.1の軌道要素を自動的に抽出しています。


とりあえず、既知の問題としてjsOrbitの不具合により、ファイル名を渡しても正常に読み込まれないという問題があります。
地図上には表示されるのですが、Satellite Listに表示されません。
ユーザーが取れる解決策としては、TLE dataの「読み込み」ボタンを押せば正常に表示されるようになります。
このあたりは近日中に更新しておこうと思っています。


ということでjsOrbitの近況報告でした。

2016年11月12日土曜日

Unityで今見てる物体を探す(あと終末のイゼッタ妄想)

このページを参考にした。
【Unity】視界の中央に入ったら光るCube - ちょっと未来


float minAngle = float.MaxValue;
GameObject selectedItem = null;

foreach (GameObject item in GameObject.FindGameObjectsWithTag("Selectable Items")) {
    float rad = Mathf.Acos(Vector3.Dot((
            item.transform.position -
            camera_.transform.position).normalized,
        camera_.transform.forward));

    if (minAngle <= rad) {
        continue;
    }

    minAngle = rad;
    selectedItem = item;
}

if (selectedItem != null) {
    // ほにゃらら 
}

Tagに"Selectable Items"が設定されてるゲームオブジェクトをすべてスキャンして視線と物体までの角度を計算する。現在のオブジェクトの角度が過去の角度の最小値よりも小さいならそのオブジェクトを変数に突っ込む。変数はnullクリアしてあるので、nullでないなら有効なオブジェクトが存在している。

このコードでは物体までの角度が一番少ないモノを得られるので、視界内に複数のオブジェクトが有るとき、視界の(というか画面の)一番真ん中に近い物体を得ることができる。ただし視界内にオブジェクトがない場合でも、FindGameObjectsWithTagに引っかかるオブジェクトが1個でもあればそれを検出してしまう。
それが嫌な場合、例えば「視線から20度以内に有る物体だけを検出したい」という場合なら、selectedItem != null && minAngle <= 0.35という風にする(minAngleはラジアンなことに注意)。foreachの中で角度の範囲を分岐する必用はない。


Unityはいままでほとんど触ったことが無かったけど、スクリプトをC#で書けるので楽。ドキュメントも結構しっかりしてるし(ウチは回線が細いのでオンラインドキュメントはつらいけど)。

以下終末のイゼッタネタバレ含むかも

Unityで龍脈みたいなの

アニメ妄想から脱線してなぜかUnity入門。でも一歩一歩コツコツとというタイプじゃないのであちこち脱線しながら。


Unityで龍脈みたいなのをどうやって作ろうか、と思ってTerrainを試してみた。



見づらいけど、上が地面の地形、下が「エネルギーレベル」の地形。レベルは高さが1で色もついてないからわかりづらいけど。

地形は画像データで作ってRAWに変換後にUnityのTerrainで読み込んでいるが、同じようにレベルも画像の濃淡で表現している。うっすらざーっと凹凸を作るのはデータ打ち込みだと面倒だけど、画像ならペイントソフトのブラシとかで簡単に作れる。

レベルを取得するには、取得した居場所の座標(X,Z)を引き数に与えてTerrainData.GetHeightを呼ぶ。戻り値はfloatで帰るので、Terrainの高さを1にしていれば0-1に正規化された値になる。
一応Terrainの設定でDrawをfalseにしてあるが、どれくらいリソースを食ってるのかは不明。Drawがfalseでも「不可視の地面」として当たり判定が存在しているので、何らかの形でリソースを食ってるのは間違いない。


この地形データで魔女が魔法を使うのに必用な魔力を持たせるとして、例えば箒で飛んでいるときにいきなり魔力が0になったときとか、どうすれば良いんだろう。いきなり0になることはないだろうから、エネルギーが薄くなってきたら戻って安全に着陸する、という感じになるのかな。

2016年11月11日金曜日

妄想:終末のイゼッタとか

6話までみた。まさかあんなことに。これだから戦争なんて(ry
前回の続きです。

2016年11月10日木曜日

Unityで地図タイルを読み込む



Unityで国土地理院の標高タイルを読んでみた。といっても座標変換とかやってないので歪んでるけど、まぁシミュレータとかじゃないのであんまり気にしないことにする。

地形考えるの面倒な人はこういう方法もアリですね。
もっとも地理院のデータとか使おうとするとデータ使用許可とか必用だから、外に出さない程度のモノに限定して使うのが無難。

Unityで読めるデータは1点あたり2バイトだけど、標高タイルは1点あたり6バイト以上あるのでデータ量がパない。回線の細い僻地民にはつらい。


C#のPanelでマウスドラッグのスクロールを行う

Panel panel1にPictureBox pictureBox1が乗っている。panel1はAutoScrollがtrueになっており、pictureBox1にはMouseDown, MouseUp, MouseMoveイベントが登録されている。

bool MouseScrollButtonIsDown = false;
Point MouseScrollButton_DownPos;
const MouseButtons MouseScrollButton = MouseButtons.Middle;

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseScrollButton)
    {
        MouseScrollButtonIsDown = true;
        MouseScrollButton_DownPos = pictureBox1.PointToClient(Cursor.Position);
    }
}

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    if (e.Button == MouseScrollButton)
    {
        MouseScrollButtonIsDown = false;
    }
}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (MouseScrollButtonIsDown)
    {
        Point currentPos = pictureBox1.PointToClient(Cursor.Position);

        panel1.AutoScrollPosition = new Point(
            -panel1.AutoScrollPosition.X + MouseScrollButton_DownPos.X - currentPos.X,
            -panel1.AutoScrollPosition.Y + MouseScrollButton_DownPos.Y - currentPos.Y
            );
    }
}

簡単に説明しておくと、まずpictureBox1の上でマウスを押下するとMouseDownイベントが呼ばれる。この際に指定したボタン(今回はスクロールホイール)かどうかを確認し、一致する場合は押下フラグがセットされる。この時、マウスが押下された位置を変数に保存する。また、ボタンを離すとMouseUpイベントが呼ばれ、フラグがクリアされる。
次にマウスが動いた場合、MouseMoveイベントが呼ばれる。この際に先程の押下フラグを確認し、押下されていない場合は処理を行わない。
スクロールをする場合、現在のカーソル位置と、押下されたときに保存したカーソル位置の差分を取り、その値を現在のスクロール位置に加算する。AutoScrollPositionはgetは負数で、setは正数で与える必要がある。

処理の内容を考えると、マウスが押下された位置と現在の位置の差分を加算しては加速度的にスクロールしてしまうのでは、と思ってしまう。しかしPanelの挙動からするとこの処理が正しい。

PanelのAutoScrollは、マウスホイールで上下移動は可能だが、縦スクロール専用のマウスでは横方向の移動ができない。ということで自前でスクロール処理を追加してやる必要がある。
この実装では若干GUIから予想した挙動と違う動作になるが、あまり大きな問題になるほどではない。

妄想:終末のイゼッタ

ハードディスクレコーダの容量がピンチで見ないアニメは消さねば、でも1話くらいは見ておこう、と見始めた終末のイゼッタ、結構ハマって何話か見た(まだ追いついてない)。
この魔女をゲームにしたら面白いだろうしすごいやりたいけどメディアミックスとか特に見当たらないので勝手に妄想。


2016年11月9日水曜日

C#のフォームの下にあるモノをクリックする

C#のFormにはTransparencyKeyというプロパティがあり、コレに色を設定するとそのフォーム上ではその色を透過色として扱うことができる(1bitα)。
コレを使うとフォームの後ろにあるボタンとかをクリックできるようになる。



上の画像ではForm1の手前にForm2があり、Form1にはいくつかのボタンが設置してある。
Form2はPictureBoxをDock:Fill, Modifiers:Publicで設置してある。
Form1のソースは以下の通り

using System;
using System.Drawing;
using System.Windows.Forms;

namespace TransparencyKey
{
    public partial class Form1 : Form
    {
        Form2 f2;

        public Form1()
        {
            InitializeComponent();

            f2 = new Form2();

            Bitmap bmp = new Bitmap(400, 400);
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.Clear(f2.BackColor);

                g.FillRectangle(Brushes.Lime, 100, 100, 100, 100);
            }

            f2.Owner = this;
            f2.TransparencyKey = f2.BackColor;
            f2.pictureBox1.Image = bmp;
            f2.Size += bmp.Size - f2.pictureBox1.Size;
            f2.Show();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Button b = sender as Button;

            if (b == null)
            {
                return;
            }

            label1.Text = b.Name;
        }
    }
}

Form2の初期化もForm1のコンストラクタ内で行っているが、Form1自体の動作としてはボタンが押されたらラベルにボタン名を表示しているだけ。
Form2についてはピクチャボックスに幅100x高さ100の塗りつぶし領域を作り、それ以外はBackColorで塗りつぶしてある。またTransparencyKeyにBackColorを指定してあり、BackColorの部分は透過とする。それからOwnerにForm1を指定し、Form1をクリックしても常にForm2が手前に居続けるようにしている。

上の画像では一部のボタンが緑の矩形に隠れているが、見えている部分であればクリックすることが可能。緑色の部分をクリックするとForm2がフォーカスする。
また透過した部分は常に見えている部分にマウスの処理が移動する。例えば後ろにウェブブラウザがあればリンクをクリックしたり、文字を選択したりすることが可能。


今回はPictureBoxに設定した画像はBackColorで塗りつぶしたが、例えばPNG画像で透過に塗りつぶした場所はPictureBoxでForm.BackColorに置き換わり、TransparencyKeyにBackColorが設定されていれば透過となる。


正直、Formの裏をクリックさせたいという需要がどこにあるかさっぱり想像できないが、昔何かをやろうとして調べたときに面倒そうだなぁと思って断念したことが有る。こんなに簡単にできるとは思わなかった。
背景をクリックしたいというのは、例えば半透明のフォームを最前面に常駐させて時計として使うみたいな用途が有るかもしれない。もっとも今回の方法ではそれは実現できないわけだけど。

2016年11月6日日曜日

Paint.NetでPNGやBMPで保存したときに非可逆な処理をされる

画像を加工したりして遊んでるときに気がついたことですが、Paint.Net(V4.0.12)でPNGやBMP等の「可逆圧縮」もしくは「非圧縮」で保存した場合に、細かなデータが消えてしまうことが有りました。ここでの細かいデータというのは高周波なデータという意味ではなく、ある地点と隣の地点の輝度差が赤だけ1明るいというようなデータです。
本来BMPファイルは輝度情報を直接保存しますから、微妙な輝度差が捨てられることは有りえません。PNGのフォーマットは詳しく知りませんが、可逆圧縮を期待して保存している以上は、微妙な輝度差であっても残っていてほしいものです。

結論から言うと、Paint.Netの保存オプションでビット深度を「自動検出」にしていると細かな輝度情報が消えてしまうようです。ということでPNGなら32bitやBMPなら24bitを明示的に指示して保存する必要があります。

この問題は保存フォーマットを自動で検出する際に明らかに使用している色が少ない場合はインデックスカラーが選択されるわけですが、RAWデータからカラーパレットを作る際に、まず輝度を平滑化して細かな輝度情報を捨てるという処理をしているようです。これについてはアルゴリズムの最適化の問題であり、そもそも輝度が1変化することに意味を持つ画像というのはあまりありませんから、バグというよりは道具を使う方の問題です。


あとコレはバグと言うには微妙な問題ですが、保存ダイアログでフォーマットをPNG、ファイル名の拡張子をBMPにした場合、拡張子はBMPでファイルフォーマットがPNGという残念なデータになってしまいます(おそらく他の組み合わせでもそのような挙動になると思います)。
そもそも近年の画像を扱うプログラムでは拡張子は無視してファイルヘッダのマジックナンバー等でフォーマットを見分けており、実質的に拡張子はプログラムに対する関連付け以上の意味を持っていません。ということでこれも使う側の問題といえばそうなのですが。

2016年11月1日火曜日

STBeeでFreeRTOSを走らせる

STBeeMiniのサンプルをベースとしてSTBeeで走るFreeRTOSの雛形を作る。


プロジェクトのトップを./とする。ダウンロードしたFreeRTOSのフォルダは単純にFreeRTOSと表記し、FreeRTOS/Sourceとかになる。

./libにFreeRTOSを作ってsrcとincを作る。
./lib/FreeRTOS/srcにFreeRTOS/Sourceの*.cをすべてコピーする。
./lib/FreeRTOS/incにFreeRTOS/Source/includeの*.hをすべてコピーする。
./incにFreeRTOS/Demo/CORTEX_STM32F103_GCC_RowleyのFreeRTOSConfig.hをコピーする。
./incにFreeRTOS/Source/portable/GCC/ARM_CM3のportmacro.hをコピーする。

makefileのインクルードパスに./lib/FreeRTOS/incを追加する。
また./lib/FreeRTOS/src/*.cをmakefileのソースに追加する。

とりあえずこの時点でビルドが通るようになってるはず。もちろんFreeRTOSが動くことはないが。もっとも、ビルドに通るとは言えまだまだ足りないものが有るので他にも色々追加していく。


./lib/FreeRTOS/portにFreeRTOS/Source/potable/GCC/ARM_CM3のport.cをにコピーする。またmakefileに追加する。
./lib/FreeRTOS/portにFreeRTOS/Source/portable/MemMangの*.cをすべてコピーする。いくつかのファイルがあるが、実際に使用するのは1つだけとなる。今回はheap_1.cを使用するため、それをmakefileに追加する。

この時点でvTaskCreate等も使えるようになった。が、まだOSを走らせるには足りないので修正を行う必要がある。


まず./inc/FreeRTOSConfig.hの最後に以下の3行を追加する。
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

これにより3個の関数で複数定義エラーが発生するので、./src/stm32f10x_it.cのSVC_Handler, PendSV_Handler, SysTick_Handlerをコメントアウトする。


vApplicationStackOverflowHookの未定義エラーが発生するので、適当なソースファイルにvoid vApplicationStackOverflowHook(xTaskHandle *pxTask, signed portCHAR *pcTaskName)関数を作っておく。これはFreeRTOSがスタックオーバーフローを検出して呼ぶ関数だが、常にこの関数が呼ばれるわけではないことに注意する必要がある。ということでそもそもスタックオーバーフローの検出を無効化しておくことにする。そのためには./inc/FreeRTOSConfig.hのconfigCHECK_FOR_STACK_OVERFLOWを0に設定する。

そしてやっとこの時点でFreeRTOSが最低限動作する状態となった。

FreeRTOSにタスクを追加するにはvTaskCreateを使う。FreeRTOSを開始するにはvTaskStartScheduler()を使う。


あとSTBeeMiniのサンプルはクロックの初期化が間違っている?PLLで6倍しなければいけないところを9倍にしているのでクロックが不適切。
system_stm32f10x.cのSetSysClockTo72関数で、RCC_CFGR_PLLMUL9となっているのをRCC_CFGR_PLLMUL6と変更すればいい。

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データの変換は計測毎に行う必要が有るため、大抵の場合は予め設定したほうが楽だと思います。

2016年9月30日金曜日

チェックサムあれこれ

タイトル的にいろんなチェックサムを網羅的に解説してるような感じですが、あれ(GPS)と、これ(XBee)だけです。

XBeeはAPIモードのチェックサムを、GPSはNMEA-0183の最後についてるやつを扱います。

2016年9月28日水曜日

STM32F1のEXTI

STM32F1のEXTI、所謂「ピン変化割り込み」を使う。
ちなみにEXTIは英語版のRM0008によると"External interrupt/event controller"という章で紹介されている。EXTernal Interruptの略と思われ。


EXTIで割り込みを使う手順としては
1. RCCの供給
2. GPIOの初期化
3. GPIOをEXTIに接続
4. EXTIの初期化
5. NVICの初期化
という感じになる。

僕が試した限りでは下記のコードで動作したが、もしかしたらAFIOのRCCを供給しないと動かないかも。

またハンドラ内では1回の割り込み毎にGPIOを反転させている。今回はパルスのソースにGPSのPPSを接続し、立ち上がりエッジのみを検出するので、LEDを0.5Hzで点滅させていることになる。

EXTIの割り込みハンドラは数字が若いうちはEXTI1本毎にハンドラが1個あるが、数字が増えるとEXTI10-15をまとめて1個のハンドラで、みたいな感じになっているので、GetITStatusの確認も省きたい!という超高精度が要求される場合は若いピンを使うこと。
またひとつのラインではひとつのGPIOしか設定できない。例えばGPIOA0とGPIOB0を同時にEXTIに接続することはできない。つまりSTM32F1でピン変化割り込みを使いたい場合、最大で16chまでとなる。

EXTIは割り込み以外にもイベントを発生させることができ、CPUがスリープに入った状態から復帰するトリガに使うこともできる。

他に、GPIO以外にも電源電圧やRTC等をEXTIのソースとして使用することができる。
更に、それ以外にもソフトウェアからEXTIをキックすることもできる。


STM32F1は自分が作りたい機能にカチッとハマると楽しいんだけど、パズルが複雑でフラストレーションが溜まるよね。


2016年9月26日月曜日

TLC5940の触り



とりあえず簡単なところだけ。

*必要なピン
データを与えるSCLK,SIN,XLATが必要。SCLKとSINはSPIのTxで可能。SOUTも接続すればTLC5940のステータスを読むことができる。
クロックを与えるGSCLK,BLANKが必要。GSCLKに4096個のパルスを与えると設定したデータに応じて最初のパルス数の間電流が流れる。
GSCLKのカウンタは自動的には初期化されないらしいので、BLANKでクリアする必要がある。

*ピンの処理
基本的にピンはプルダウン等で固定しておいたほうが良い。例えばマイコンがリセット状態の時はハイインピーダンスとなるので、ちょっとしたノイズで誤動作する場合がある。
誤動作するとLEDが常に点灯になる場合がある。PWMしか使わない前提で電流を多めに流している場合(PWM10%時の電流値等の設定の場合)はLEDが損傷する可能性がある。
SCLKを固定してデータを受け取らないようにすること、GSCLKを固定してパルスが入力されなようにすること、BLANKを固定してハイインピーダンス時は電流を流さないようにすること、等。

*電流の違うLED
フルカラーLEDを駆動したい場合など、電流値が違うLEDを接続する場合は、電流が一番低いLEDに合わせる必要がある。ICは定電流駆動なので、LEDと直列に抵抗を挟んでも損失が増えるだけで電流値が変わることはない。LEDと並列に抵抗を接続して電流を分岐することも不可能ではないが、あまり良いやり方とはいえない。
Dot Correctionを使えば0-63の64段階で電流値を制限することができるので、電流値の設定を最大電流に合わせ、電流値が低いLEDはDCで制限する、ということも可能。ただ何らかの原因でDCが設定される前に電流が流れることもあるかもしれない。なのであんまりそういう方法は使わないほうが良いはず。

*IOレベル
TLC5940のIOレベルはCMOSとなっている。High-level input voltageは0.8Vccが必要。電源が5Vだと4Vが必要となる。つまり3.3Vレベルのマイコンと直結することはできない。
3.3Vのマイコンを直結したい場合はTLC5940も3.3Vで駆動する必要がある。
ただしTLC5940で120mAを流せるのはVcc>3.6Vの時で、Vcc=3.3Vの時は最大60mAまでとなる。それ以上の設定でも動くには動くが、損失が大きくなるため発熱が増える。

* Dot Correction
TLC5940にはDot Correctionという機能があり、1ch毎に6bitの補正値を設定できる(使ったことがないので詳細は不明)。一番最初にEEPROMから読み込むので、DCの初期化は不要。EEPROMの初期値は0x3F(0b111111)となっている。

*その他
LEDを接続したい場合、BLANKは100Hz以上にすること。50Hzでは明らかにちらつきがわかる。
サーボモータの場合は20-50Hzくらいで良いはず。

2016年9月24日土曜日

TLC5940を使いたい

TLC5940を使いたいので、一番面倒そうなパルス出力部分を作ってみることにします。
結論から言うとTIMのPWM出力をちょこちょこ動かすわけですが。

ZEROPLUSのソフトウェア

電子工作では非常に有用なツールとして、ZEROPLUSのロジアナが挙げられます。OWONの最安帯オシロと同価格帯からあり、電子工作で使用している人も多いと思います。

このソフトウェア、v3.12あたりの頃はプロトコル解析が付属しなくなったりしていた気がしますが、最近のv3.13あたりではすべてのプロトコル解析が無料で使用できるようになりました。
また、最新のv3.14ではソフトウェアの一部が日本語化されています。



正直、ずっと英語版を使用していたので日本語だと違和感がありますが、慣れてしまえば楽かな、と思います。ただ全てが翻訳されているわけではなく、プロトコルの設定などは日本語化されていません。プロトコルについてはプラグインとしての実装のようですから、アナライザ本体のグループがいくら頑張ったところで日本語化できるものでもないと思うので、これはしょうがないかなと思います。

今までもUART, SPI, I2C等の電子工作で使用される3大プロトコルは無料でも解析できていましたが、1-WireやCANのような、使う人はいるけどあんまり多くない、という機能を使用するにはシリアルキーが必要でした。最新版では1-WireやCANのみならず、SDIOやFlexRay、はてはMIL-STD-1553の解析も無料でできるようになりました。
ただし、全てが無料で使える、とはいいつつ、使用できないプロトコルも存在します。例えば僕が使っているのは16chモデルですが、Compact Flashの解析には25ch?以上が必要であり、32chモデルが必要となりますが、プロトコル選択画面に表示されています。


最新版のソフトウェアは以下のページからダウンロードできるようです。
http://www.zeroplus.com.tw/logic-analyzer_en/download.php

過去のバージョンは以下のページからダウンロードできます。このページはロジアナのモデルごとに別れているので、左のDownloadをクリックしてSelect Product TypeからProductにLogic Analyzers、SeriesにLAP-C Series、Modelに使用中のモデルを選択します。モデル名はロジアナの後ろに書いてあります。
http://www.zeroplus.com.tw/logic-analyzer_en_ori_20160331/technical_support.php

ZEROPLUSのWebページは昔の感じのページと、最近の感じのページが有り、またスイスのドメインのWebページもあったりと、ちょっと複雑な感じです。おそらく http://www.zeroplus.com.tw が本家というか、ここから落としてくれば問題ないと思いますが。


ということで、今までも有用なツールだったZEROPLUSのロジアナですが、更に有用なツールとして使えるようになってきたと思います。特に日本語化されたことによりこれから使い始めるという人に有利かもしれません。

追記:2017/11/23
 上記リンクがリンク切れになってる。
 とりあえずこっちからどうぞ。
 http://www.zeroplus.com.tw/logic-analyzer_en/technical_support_search.php
 セッションが切れると表示できないっぽいので、なにも表示されない場合は以下手順5の"Downloadのリンクをクリック"から続きを行ってください。


 リンク切れになったときのために。
1) トップページ(http://www.zeroplus.com.tw/zp/)の"Instruments 電子量測儀器"にマウスを重ねて、ENGLISHをクリック。
2) ProductsのマウスオーバーからLogic Analyzerをクリック。
3) てきとーな製品をクリック(LAP-CでもLAP-Fでもなんでもいい)。
4) Softwareをクリック
5) 各ソフトウェアが表示されもすべて無視して、Downloadのリンクをクリック。
6) ProductでLogic Analyzers、SeriesでLAP-C Seriesを選択し、Softwareにチェックを入れてSearchをクリック
7) ガーッと大量にソフトウェアが表示されるので、SerialがLAP-CになってるソフトのWEBをクリックしてダウンロードする

 これでZIPが落ちてくる。
 なお、5と7で、Serialに"LAP-C(32128)"のような、5桁か6桁の数字がカッコに入っているソフトはバージョンが古く、プロトコル解析が使えないので、特段の理由がない限り避けた方がいい(V3.14以降はすべてのプロトコル解析が無料で使えるようになっている)。
 インストールする際の注意点として、V3.14.0は日本語化されているが、V3.14.3をインストールすると日本語が削除されてしまう。
 ロジアナを初めて使うなら日本語のほうがわかりやすいかもしれないが、古くからあるブログ等に書いてある使い方の情報はすべて英語なので、今後も英語版を使ったほうがいいかもしれない。
 V3.14.3ではいくつかのプロトコルが追加され、今後も追加されていくものと思われる。新しいプロトコルを使いたいなら、最新版の英語表示を使うしかない。

 .0ではJapanese.dllがあり、.3を入れると削除されてしまうので、これをコピーすればいいのか、とも思ったけど、そう簡単ではないらしい。Japanese.dllを入れても日本語は選択できない。.1や.2は試してないが、更新履歴を見ても日本語を削除したとは書いてないから、次のアップデートで復活するといいなぁ。

2016年9月20日火曜日

Ankerのモバイルバッテリー

Ankerのモバイルバッテリー、比較的安価かつ高評価、また入手性も良いということで、計画的な購入では比較対象に上がる製品だと思う。もちろん実際にモバイルバッテリーとして使う分には問題ない性能だと思う。

ただこのモバイルバッテリー、消費電力が少ないと「おまえ充電終わってるよね?電気いらないよね?」ってことで給電を停止するらしい。
モバイルバッテリーとしては自分の電力を温存できるし、充電対象が過充電になることを防ぐことが期待できると、いい事ずくめな機能だと思うけど、電子工作を動かすために使おうとするとちょっと問題になる。

消費電力が少ないとき(スマフォ平常動作時程度?)では給電が止まってしまうので、電子工作のような数十mA程度ではシャットダウンされる。
マブチ130クラスを繋げば問題なく供給されるが、Lチカ程度では足りない。
電子工作をやる(予定がある)人は、Ankerのモバイルバッテリーを買う場合はそのあたりを考えておく必要があると思う。


以前使ったことがあるモノとしては、SANYOのモバイルバッテリーは問題なく使用できた。たぶん今はPanasonicが作ってると思う。

これはスライドスイッチが有り、それが電源となっている。なので勝手にモバイルバッテリーが電源を切ることがない。

他のメーカーでも同じように考えられると思うが、スライドスイッチのような、どう頑張っても内蔵されたマイコンが操作できないスイッチを電源に使っているものは勝手に切られることはないと思う。逆にモーメンタリスイッチを電源にしているモバイルバッテリーは要注意ということで。

IIRフィルタ

IIRフィルタの設計仕様で計算できる係数を使ったフィルタをC#で実装してみた。例によって正しいかどうかは不明。
このWebページではIIRとかFIRの計算が簡単にできるのでおもしろい。

private void IIR(ref double[] datas, double k, double b1, double b2, double a0, double a1, double a2)
{
    double z1 = 0, z2 = 0;

    for (int i = 0; i < datas.Length; i++)
    {
        double x = datas[i] * k;

        x += -(
            z1 * b1 +
            z2 * b2);

        datas[i] =
            a0 * x +
            a1 * z1 +
            a2 * z2;

        z2 = z1;
        z1 = x;
    }
}

タップ数を増やす場合はそれぞれのセクションの係数を与えて繰り返し呼べばいい。
とりあえずセクション数8のLPF(1000Hz,250Hz,300Hz0.5dB,35dBで設計)の結果。




青が乱数をフィルタに通してFFTした結果。赤が設計出力画面の振幅特性。
結構似た感じの傾きになってる気がする。縦軸の扱いがよくわからないけど。

上のメソッドではデータを配列として受け取って処理しているので、リアルタイムでの処理はできない。


確かにFIRよりは急峻なフィルタになっている気がするけど、計算コストも結構高そう。加算と乗算だけでイケるFIRと比較しちゃだめなんだろうが、と思ったけど、IIRも加算と乗算だけだよね。かなり複雑な気がするけど。


サンプリングレートは低くていいので、マイコンのソフト浮動小数点でどれくらいのフィルタが作れるか、試してみないと。

2016年9月16日金曜日

かるまんふぃるた



1軸の姿勢(ピッチ)がほしいので試しに加速度とジャイロのカルマンフィルタを構成してみた。
センサ・フュージョン - 備忘録の1行フィルタを使用。

g+aがジャイロと加速度を使用、gがジャイロの積分のグラフ。センサの本当の姿勢がわからないので、どっちがただしいのかわからないけど、gだけだとオフセット誤差が積分される、と考えると確かにg+aのほうが正しい気がする。開始の姿勢と終了の姿勢が一致してるかも不明だけども。

まぁ、今回の用途ではあんまり精度は要求されないので、様子を見ながら試していく予定。


角速度→誤差が積分されるから長期的な精度はダメだよね
加速度→重力以外の加速度が加わると姿勢の計算できないよね
地磁気→外乱受けやすいよね
9軸センサって辛い

2016年9月15日木曜日

マイクロピザ



餃子の皮でピザっぽいヤツ。

1) 本体を作る
  a) 餃子の皮にケチャップを塗る
  b) とけるチーズをのせる
  c) サラミをのせる
  d) ピーマンを乗せる
2) 加熱する
  a) トースターにアルミホイルを敷く
  b) 3分±20%くらい加熱する
    時間はあくまで目安。縁が変色してきたらちょうどいい頃合いだと思う。
3) おいしくいただく
  *) 複数個をゆっくり食べる場合はホットプレートとかで保温したほうが良さそう

少量を作るだけならすごく簡単。

ウチのトースターは0.8kWか1kWかそれくらいだと思う。そんなに時間はかからないが、結構場所を取るので1回に加熱できる数には限度がある。

ケチャップの量は注意すること。ケチャップは結構主張が激しいので塗りすぎるとマズイ。皮全体に若干ケチャップのいろが付く程度に塗ればいい。
とけるチーズは融解するとかなり密度が高まる。適量だと下のケチャップが見えてきて彩がいい。
サラミやピーマンはチーズと彩がいいので載せたほうが良い。

餃子の皮だけど、あんまりパリッとはならない。縁はパリパリというか、ポロポロになるけど、具材のある部分は加熱が遅いとか、水分が逃げないとか、ケチャップの水分が入ってくるとか、そういう感じでパリッとはならない。


ところで、普段何か撮るときはいつもデジイチを使ってるけど、上の写真はiPhone4(+LRで編集)で撮影した。基本的にスマフォのカメラは使う機会が少ないけど、ぱっと見るだけなら充分だね。

2016年9月13日火曜日

はいふりの通信手段(あるいは自分の居場所を知る手段)

深夜のテンションなので軽く流してくださいな


公式設定でどうなってるのかなとぐぐってみるも、特になさそう。
掲示板のまとめとかが多数ヒットするけど「衛星無いのに通信・測位できるのおかしい リアルタイムでマップ表示できるんだし衛星有るんじゃね? でも行方不明艦探すのに苦労してるよね」というのが結構ある。

では、船でどんぱちしてたWWIIはどうしていたでしょうか。当時飛行機はブンブン飛び回ってたけど人工衛星はありません。V2が使われてるくらいです。
WWII終戦が1945年、スプートニク1号が1957年です。通信衛星が飛ぶようになったのは60年台に入ってからです。
通信衛星がなくても(ものすごい)低速であれば地球の裏とでも充分に通信が可能です。


測位に関してもGPSなど不要で、GPSの前にはロランやオメガ等の地上に有る電波局を使って測位が行われていました。
ロランは1000以上の範囲で測位が可能で、精度はかなり高精度なようです。数百mというと地上ではかなりの誤差に感じますが、1000kmで100mは有効数字5桁ですから、10cmにすれば0.01mmの誤差であり、定規を見てみるとわかると思いますが、10cm定規で0.01mmの誤差というのは非常に小さいと感じられると思います。
オメガの方はさらに広範囲をカバーでき、ロランCでは日本近海だと海岸から2000km程度まででしたが、オメガであれば8箇所の地上局で北半球の洋上をほぼカバーできるようです。ただしロランと比べ精度は悪いですが、それでも有効数字4桁以上と、おおよその位置を知るには十分です。

リアルタイムに作戦地図を更新するには誤差2kmでは困りますが、誰がどこにいるかを知るには充分でしょう。戦争が行われていない世界であればロランCやそれを発展させた技術を各国で配備しているかもしれません。


とりあえずここまでのまとめとしては、「測位も通信も衛星なんて要らないよ」という話でした。

しかしこれでは困ります。僕の妄想が根本から崩れ去ります。

ということでなんとかしてロケットを飛ばしましょう。

といっても簡単で、VLA(Vertical Launch Asroc)があるわけですから、ロケットブースターが有るということです。固体燃料が有るのだから、大きなものを作れば充分に衛星を打ち上げることも可能でしょう。ただ1つ問題が有るとすれば、ロケットの発展は国同士の競争の結果という点です。戦争がなければ現在のように宇宙が利用されることも無かったかもしれません。
ただ、それを言ってしまうと「インディペンデンス級があるのはおかしい」で終わってしまいますから、結局戦争の手段は開発され続けた…という方向に逃げようと思います。

衛星があれば疎な洋上の気象も分かりますから、安全運行に必要不可欠な気象観測も行えます。海運が重要な世界ですから、気象技術の発展とともに宇宙開発も進んだと期待しましょう。

戦争がないなら大陸間高速鉄道輸送が発展するんじゃないのというツッコミはガン無視です。いくら1度に1千トンを輸送できる鉄道といえど、1度に数十万トンを輸送できる船にはかなわないということで。


さて、次の問題に移ります。衛星があるならどうして行方不明艦が出てくるんだ、という話です。
Google Earthで適当な港を見てみると分かりますが、船を認識できる解像度まで拡大すると、表示できる範囲はせいぜい20x10kmくらいの範囲になってしまいます。太平洋の面積は165,200,000km^2とのことですから、80万画面以上の面積になります。いくら海運が重要でもFHD液晶80万枚も使って監視することは不可能でしょう。非リアルタイムにしてもせいぜい100分の1くらいにしかならないでしょう。そんなに大量のPCを用意することも、監視する人間を用意することも、とても現実的とは思えません。
画像解析で探すことも不可能ではないでしょうが、FHD画像80万枚分の画像を解析するのにどれだけのリソースが必要かわかりませんが、とてつもない事になると思います。
そもそもそれだけの画像を見れたとして、全球画像を見れば分かる通り、洋上のかなりの部分に雲があり、海面を見るのは非常に困難でしょう。

ということで、まとめとしては「衛星もそんなに万能じゃねぇよ!」という事になります。
アクション映画でよく軍や情報組織が衛星を使って人間1人をトラッキングしてますが、1機数百億の衛星を躊躇なく使うって相当に重要な目標なんでしょう。
エネミーライン2でアメリカが人工衛星を駆使して苦労している時に、他国の人間が写真を1枚持ってきて決定的な情報を与えるシーンが有りましたね。曰く「アメリカは衛星を使った。我々は人間を送った」と。エネミーライン2を見たのは相当に昔なのでうろ覚えですが。そもそもエネミーライン2かどうかも怪しいんですが。


いろいろぐだぐだ言って、結局「衛星要らねぇじゃん」という話になってしまいました。困りました。

とりあえず「戦争がないなら各国が共同でいろんなことをやりやすいよね。じゃぁ知的探究心を満たすためにいろいろやってるんじゃないかな。宇宙に手を伸ばしても良いんじゃない?」あたりでどうでしょうか。


はいふりはかなり好きな作品なので、他のエピソードとかも読みたいです。
はるかぜ乗員がそっくりアーレイ・バーク級に乗りつつ、艦長の幼なじみが海賊をやっていることが判明し、撃ちたくない!でも撃たなきゃ!みたいになって、でも宇宙人が攻めてきて有耶無耶になって最後は共闘する!とかどうでしょうか。ダメか。

2016年9月12日月曜日

STM32F1のI2Cの初期化でハマった

STM32F1のI2Cは昔慣性ロガーを作った時にかなり苦労して嫌な思い出がある(その時は結局ソフトウェアI2Cで逃げた気がする)。

今回、I2Cで叩けるモータードライバを使ってみたくなり、ついでにペリフェラルのI2Cもやり直そうと考えた。

現状としてはwhileでイベントをポーリングして動かすというダメダメな感じだが、なんとかデバイスに値を送信することはできた。

で、タイトルの通り、初期化でかなりハマってしまった。


I2C_Initの後でレジスタをダンプして調べたところ、BUSYフラグが立っていることがわかった。BUSYはハードウェアで書き込まれ、ソフトウェアから書き込むことはできない。バス上で通信が行われている場合はビジーが1となりる。条件はSDA or SCLがLowの時にSetされ、STOPコンディションを検出してResetとなる。
しかしI2C_Init直後ではマイコンからI2Cを叩いているわけでもないし、バスにはプルアップ抵抗が付いているだけで他のデバイスも未接続なため、STMから動かさないかぎりはバスが動くことはない。

更に詳しく調べると、GPIOをAF_ODで初期化した時点でピンがLowとなり、I2C_InitのあたりでHighに戻ることがわかった。

解決策としてはI2C_Initを行った後にGPIO_Initを行う、という感じらしい。


いまいち動きが理解できないが、GPIO_InitとI2C_Initのタイミングを入れ替えれば動いたり動かなかったりするので、先にペリフェラル、後にGPIOの初期化を行えば正常に動作するようだ。

他のペリフェラル、USARTやSPIであればペリフェラル自体を有効にしなければ動作しないため初期化の順番の問題が表面化してこなかったが、I2Cはペリフェラルを有効にしなくても、クロックを供給した時点?でBUSYのサンプリングが始まるため、順番が厳密になっているのかも。


他にもいろいろ問題がありそう。昔使った時と同様、苦労することになりそうだ。

***
追記:2020/10/02
 だいぶ前のエントリだけど、気がついたので更新。
 これに関する話が、stmcu.jpの資料にある。
 概ね前述した内容はそう間違っていないが、本家の適切な初期化シーケンスが提案されているので、それに従うことをすすめる(資料の内容は会員登録した人向けなので、各自確認のこと)。

2016年9月11日日曜日

スペースプローブコンテストの資料

今年から開催される「スペースプローブコンテスト」の技術発表会の資料が出てた。

スペースプローブコンテスト技術発表会2016

あんまり技術的な話は書いてないと思いますが、ちらっと読んでみると良いと思います。
僕が軽く探した程度では、高校や大学を含め、あまり缶サットの資料というのは出回っていないような気がします。なのでこういう技術交流会の議事録みたいなのが出てくると面白いですね。


スペースプローブコンテストについての詳しい話は以下のリンクを参照してもらうとして。
スペースプローブコンテスト。略するとなんだ?スペプロコン? - 植松努のブログ(まんまだね)




今年は重量1kg程度の大きさですが、次回以降はもっと小型の枠も作るそうです。
参加資格については「親子での参加も可能です。仲間同士で集っての参加も可能です。大学生も、高専も、中学校も小学校も、法人も、個人も、オッケーです。」と書いてあるので、「やりたいならだれでもいいよ」ってことだと思います。

今年は発表から開催までが恐ろしく短いですが、次回大会まではおそらく半年とか1年くらいは有ると思うので、興味のある人は考えてみてはいかがでしょうか。もちろん、今すぐやりたい!という人はまだ間に合うので今年から参加しても良いんですが。

2016年9月10日土曜日

STM32F1のブートローダのUSART

FreeRTOSとかJPEGカメラとかモータードライバとかやりたいんだけど、何を血迷ったかBootloaderのSerialインターフェースを叩いてる。

STBee使ってるなら大抵はDFUを使ってるだろうし、STM32F4ならマイコン自体にUSB DFUが標準搭載だし、JTAGを使ってる人ならJTAGで書くだろうけど、STM32にはチップ自体にFlashを書き換えるプログラムが搭載されている。

このプログラムを呼び出すにはBoot0を1に、Boot1を0にした状態でマイコンをリセットすれば起動し、その後に外から何らかの操作を行えばそれに合わせて更に分岐していく。
例えばリセット後にUSART1に0x7Fを叩けばUSART経由でROMを呼んだり書いたりいろいろできる。

一番最初のプログラムについてはAN2606 "STM32(TM) microcontroller system memory boot mode"という資料が参考になる。
USARTのブートローダについてはAN3155 "USART protocol used in the STM32 bootloader”という資料が参考になる。


さて、USARTを叩いた時にハマった点について。
ちゃんとANに書いてあるから「PDFをよく読め」で一応答えになるけど、もうちょっと詳しく。

2016年9月3日土曜日

STM32F1で多チャンネルのPWMを生成する

STM32F1でPWMを出そうとすれば、大抵の場合はTIMのOCを使用すると思います。これはかなり高精度で、CPUやバスを使用せずに、簡単にPWMを生成できます。ただし弱点はTIM1個あたり4本しか出せない点で、10本欲しいという時はTIMが3個必要になります。TIMは様々な用途に使用しますから、PWMだけにTIMを大量に割り当てるわけにも行きません。
というわけでなにか違う方法が必要となります。

今回はGPIOを使用してPWMを出力してみました。
と言ってもCPUで一々1bitずつ操作していてはタイミングも保証できませんし、CPUリソースの1割を使用してしまうので割に合いません。なので今回はDMAを使用します。

GPIOで任意のデータを吐き出す場合、ODRに書き出すことも可能ですが、パルス幅を変更するたびに大量のビット操作が必要となるため、かなりCPUリソースを使用することが予想されます。ということでSTMのGPIOに搭載されているBSRRというレジスタを使用します。
このBSRRはport Bit Set/Reset Registerの略で、32bitレジスタ1本の下位16bitが1になっているビットはSetされ、上位16bitが1になっているビットはResetされるというレジスタです。StdPeriphLibraryのGPIOビット操作関数はBSRRに引数を投げているだけです。
BSRRを使用してパルス幅を変更したい場合、変更する動作は数回のビット操作で済むので、非常に高速に行えるようになります。

今回はGPIOEの16bitをPWM出力ポートとし、DMA1-1を使用してBSRRに転送、DMAのトリガはTIM4を1MHzで回す、という感じにしました。
DMA1-1を使う理由は、それ以外のDMAを使用した場合、調停負けを起こした場合にパルス幅の正確性を維持できないという理由になります。DMAの調停は4段階の優先度(VeryHigh, High, Medium, Low)で決定され、同時に同じ優先度の転送が発生した場合はチャンネル数の小さい方が優先されます。


今回の方法の利点は上記の通り簡単にパルス幅を設定できたり、比較的高精度にパルスを出力できる点です。
ただ欠点もいくつかあり、バスを高頻度で使用する、大量のメモリが必要、といった点になります。特に後者は深刻で、最大2msecのパルスを出力する場合、およそ8.5kbyteのメモリが必要となります。STBeeは64kのRAMがあるので多少はマシですが、STBeeMiniの場合は20kしかRAMがありませんから、STBeeMiniで複雑な処理を行いながら大量のサーボを制御したいという場合は注意が必要です。


他の方法としては、TLC5940を始めとした、外付けのチップを使用する事も可能です。例えばTLC5940は1個あたり16chを制御でき、カスケード接続すれば64位は簡単に制御できるはずです。これくらいあれば8足歩行ロボットでも作らないかぎりは安心でしょう。ただTLC5940であればSPIやPWM出力、GPIO等が必要になり、プログラムも複雑になりますし、外付け部品が必要になるので難易度は若干上昇します。


とりあえず今回作ったプログラムの一部を以下に貼っておきます。これはFreeRTOSの上で動くモノですが、DMAの操作(Disable, SetCounter, Enable)をタイマ割り込みで行ったりするようにすれば非OS環境でも動作するはずです。


GPIOEをロジアナで覗くと以下のようになります(ジャンパワイヤが足りないので5ch分だけ)。


わかりやすいように100、200、300、400、1500usecとなっていますが、サーボモータを接続する場合は1500±500usecを使用します。


キースイッチ

IDECのキースイッチを買ってみた。

Φ25 TWSシリーズ ASS□K形/鍵操作形 セレクタスイッチ IDEC(和泉電気) (C59949461) - IHC.MonotaRO インターネットホームセンター




IDECのスイッチは押しボタンと緊急遮断スイッチを使ったことがある。5年位前だと思うけど。

キースイッチが欲しかったので買ってみた。
一般的に使われるキースイッチはオルタネイト型が一般的で、車のキーと同じく、位置を保持するというモノ。逆にモーメンタリ型はキーを操作している時だけ通電し、これは車のセルスタータに割り当てられる場合が多い。
今回はモーメンタリ型が欲しかったので、「90° 2ノッチ 右抜け 左リターン 1a1b」というタイプを買った。イマイチわかりづらいが、手で操作するときは左(CCW)に回し、スプリングで右(CW)にリターンし、右(CW)側でのみ抜くことができ、接点はa(NO)とb(NC)が1個ずつ、というモノ。
端子部は3.5mmのプラスネジになっており、3.7mmのY端子や丸端子が適合する。

銅線用 裸圧着端子 (Y形)先開形 ニチフ (C45320414) - IHC.MonotaRO インターネットホームセンター



本題のスイッチだが、操作時のクリック感のようなものは全く無い。
またキー自体はセキュリティ性は無く、すべてのスイッチで同じ鍵が使用されているらしい。なのでこの鍵はマイナスドライバーで簡単に回るようなものではないが、スペアキーも販売されているし、同じキースイッチを買えば同じ鍵が入手できるから、防犯等の用途で使用することはできないと思う。あくまで「ちょっと興味本位の通行人が操作する」位を防ぐ程度だと思う。

個人がこのスイッチを使うのは、例えば自分のPCを起動させるには鍵が必要!みたいなロールプレイ時のみだと思う。もちろんパソコンのカバーを開けて配線を短絡させれば起動させることができるし、上記の通りセキュリティとしては使えないから、操作できる人間を限定するようなことはできない。


ということで、ロールプレイに使うなら高信頼性だし入手性も比較的いいし、使えるんじゃない? という話でした。モデルロケットの点火器とかに使うと面白いと思う。

2016年9月2日金曜日

JA3950(セスナ206)、JA005H(AS365)、JA9639(AS355)、JA6912(ベル430)、JA119L(ベル412)、シリアル不明(OH-6)、シリアル不明(UH-1)

前回(JA04HP(AW139)、JA119L(ベル412)、UH-1、JA7907(R44)、JA001H(SA365))の続き。前回は午前中の2時間に飛んでたヘリのみだったが、その日の午後から今日にかけて。


8月31日 15時50分頃 JA3950(セスナ206)


8月31日 16時0分頃 JA005H(AS365) STV報道ヘリ


8月31日 16時50分頃 JA005H(AS365) STV報道ヘリ


8月31日 17時0分頃 JA9639(AS355)


9月1日 12時50分頃 JA6912(ベル430) HBC報道ヘリ


9月1日 12時50分頃 JA119L(ベル412)


9月1日 14時50分頃 JA6912(ベル430)


9月2日 10時40分頃 シリアル不明(OH-6)


9月2日 16時0分頃 シリアル不明(UH-1) ポッド付


OH-1やUH-1はかなり高頻度で飛んでいる。NHKのニュースでOH-1が捜索しているところや、UH-1のホイストで救助しているシーンが写っていたので、それらに関連するものだと思う。


映像伝送装置付のUH-1のプラモデルが有るらしい。