2013年9月29日日曜日

Lightroom4の残念なところ

Lr4の残念なところ というか、「どうしてこの機能はないの?」と思ったところ

Lr4にはスタック機能があって、複数の写真をグループにできたりする機能ですが、コレが弱い


まずスタックしたグループをスタック とかができない
例えば
「イベント○○のプログラム☓☓でグループAが発表している内容」がスタックA
「イベント○○のプログラム☓☓でグループBが発表している内容」がスタックB
とすると 「スタックAとスタックBをまとめたプログラム☓☓のスタック」を作ることができない
やろうとするとスタックAとスタックBが結合されてしまうので、グループAとグループBを分類できなくなってしまう


それと、スタックにタイトルをつけることができない
なので「n枚の写真が含まれたスタック」という情報と あとは周りの写真からそのスタックの内容を推測するしか無い

そもそもLr4の写真の管理の方法が間違っている気がしないでもないけど

もうちょっと写真をグループ分けしやすいようになっていればなぁ と思う次第

Lr5とかではどうなってるのかな?
4からアップグレードするにも微妙な値段で、趣味で写真を撮ってる僕からするとちょっと踏み出せない値段w

大量の写真の分類作業とかしないならLr4は十分に使えるソフトなのよねぇ…
(正直、レンズとか焦点距離で分類とかはいらない機能だと思うんだけどなぁ ズームレンズとか使ってると焦点距離のリストなんてどんどん増えるぞ。。。)

2013年9月28日土曜日

RasPiのピンヘッダ

Raspberry Piの大きなピンヘッダには色々なポートが出力されていますが、基本的には電源とGPIOです
GPIOは例のごとく複数の機能を持ったものがあり、どこに何を繋ぐかが問題になります

僕の例を書いておくと
GPIO25にLEDを吊り下げで接続
GPIO24にタクトスイッチをプルアップ(アクティブL)で接続
GPIO14および15のUARTをピンヘッダに接続
4ピン及び6ピンに電源を接続
という感じになっています
UARTを使うのはSSHで接続できない場合のためで、あまり使うことはありません

電源は通常microUSBコネクタで供給しますが
1) USBポート経由の給電はあまり評判がよろしくない(長時間の安定性がよくないらしい)
2) USB出力の高容量な電源の手持ちが少ない
というような理由により通常のDCジャックから供給しています
ただし電源の逆接や異常な電圧が供給された際の保護がないのでそのあたりは要注意です


他に余ってるポートはSPIやI2Cくらいで、あまり複雑なことはできない、もしくは非常に複雑になってしまいます
例えば、とある応用ページではパラレル接続のモジュールを使うためにシリパラ変換ICを複数個カスケード接続して実現しています
このような規模になってくると、せめて外部に小さなARMマイコンを1個置いてソフトウェアで処理する等の方がはるかにスッキリと実現できますが、そうするとRasPiを使う必要性も薄れるために難しいところではあります

RasPiで実現できる範囲はUSB接続ができるものや、Ethernetを使ったIO それ以外ではRasPi専用に設計されたモジュールくらいが限界のようです

僕の感想としては「帯に短し襷に長し」という感じで
より低レベルなIOが必要なら普通のマイコンで実現したほうが楽だし、データ処理をさせたいなら一般的なPCのほうがはるかに使いやすいです
RasPiの最適な用途はちょっとしたEthernetアクセスのサーバー あたりでしょうか
この場合もあまり高負荷なことはできないはずなので 非常に微妙なところではあります

RasPiをFT232の母艦に

RasPiのUSBポートにFT232を接続してみました
FT232は言わずと知れたシリアル変換ICで、LinuxなどはOSに標準でドライバが入っていたりします
Raspbianでも同じように、ドライバをいれる必要なく接続できました

screenコマンドがなかったため、apt-get install screenで入れてやりましたが、それ以外は特に何も必要ありません
もちろんSSHからscreenを叩いて送受信することもできます

ただ、欠点というかなんというか、僕の環境ではscreenを終了することができませんでした
もちろんsshを終了すれば接続は切れるのですが、デバイスが解放されているわけではないので、次に使うにはrebootが必要になります

ただその辺りを解決できれば ピンヘッダに出ているシリアルポート以外に、USB接続でシリアルポートを使うこともできるはずです


参考
http://tomono.eleho.net/2011/02/28/646/


2013年9月23日月曜日

C語でC++のclassっぽい関数呼び出し

C言語でC++等のclassっぽい関数呼び出しを試してみたので忘れないうちに書いておきます
以下コードが幾つか続くので、"もっと読む"で展開してください


2013年9月22日日曜日

気圧と海抜から海面気圧を求める

現在地の気圧[hPa]と現在地の海抜[m]から海面気圧[hPa]を求める式

P0 = P * pow((1 - (1 / (((T + 273.15) / (0.0065 * H)) + 1))) , -5.257);

P0 : 海面気圧[hPa]
P : 現在地の気圧[hPa]
T : 現在地の気温[degC]
H : 現在地の標高[m]
それぞれdoubleで宣言されています
pow関数を使用しているためmath.hも必要です

例えばmbedにGPSと気圧センサ そして液晶モジュールを接続すれば
GPSの絶対高度を使用して海面気圧を把握することも可能となります
この場合のGPS高度や現在位置の気圧は応答性よりも正確性が優先されるため、適切な平均化処理などが必要とされるはずです

整数で気圧高度の計算

整数だけで気圧高度を計算するライブラリを作ってみました
実際には浮動小数点のようにある程度正確な数値ではなく
予め作られた2つのテーブルを使用しているのでかなり容量を使います
テーブル1が800バイトと少し
テーブル2がおよそ15キロバイト
とかなり大容量になっています(ビルド後のサイズ/ソースはもっとデカい)

精度はどうかというと、さすがにちゃんとした固定小数点数等を使っているわけではないので浮動小数点数(double)には劣りますが、おそらく近似値を使った直線よりは高精度なはずです

縦軸が高さ 横軸が気圧 右軸が高度で左軸が誤差(共にm) です
海面気圧は101325Paを使用しました

er軸はdoubleで計算した値からどれくらいズレているかという数値です
1mから9m程度高くでていますが、
 気圧が低ければ誤差は下の方に集まり、
 気圧が高ければ誤差の振れ幅は少ない
という感じになっています

今回は計算のしやすさのために1hPa単位でテーブルを作りましたが
2hPa単位にするだけでテーブル容量ははるかに小さくなるため、気が向いたらその方向の改良もしていこうかと思います

誤差については、さすがに10m前後は見過ごせない大きさではありますが
しばらくは「そういうもの」と割りきって使うことになりそうです
おそらくこの変動はテーブルによる物だと予想していますが、実際に確かめたわけではないので、結局のところ原因は不明です

不正な値が入力された場合の挙動に対応できないことや、負の高度(P0>P)を正確に処理できないという問題があるので そのあたりも課題です

2013年9月17日火曜日

整数で平方根を計算する

整数で平方根の近似値を出力する関数です

int sqr(int sq) {
int j, i;
for (j = 1, i = 0; sq >= j; sq -= j, j += 2, i++);
if (sq > (j / 2)) { i++; }
return(i);
}

実際の計算結果は
上の図のようにある程度正確になっています
およそ±0.5の範囲です
コード中のif分を外せば+0から-1の範囲になります

計算方法は
http://www.wizforest.com/gear/tiger/sqrt/
を参考にしました

実際は別の方法が良いようですが、とりあえずこのコードでも遅い以外のデメリットは特に無いです

で、実効速度の問題ですが
sqr(自作)及びsqrt(math.h)の実行速度を計測してみました
(図中ではpowと書かれていますがsqrtです)

sqrt関数の処理時間はほぼ一定ですが
sqr関数はforでデクリメントしているため、処理時間は一定の法則で伸びていきます

上記コード中のsq,j,iにregisterをつけるとかなり早くなり、30000を超えてもsqrt関数より早くなります


FPUが使えるシステムでは整数で計算するメリットは全くありませんが、FPUがなく、ソフトウェア的に計算しているCPUや そもそも浮動小数点演算ができない環境ではある程度使えると思います

例えば3軸加速度からその物体にかかっている加速度は
加速度=sqrt((x*x)+(y*y)+(z*z))
で求められるため、缶サットなどで瞬間的にどれくらいの加速度がかかっていたか等を計算することができます
(加速度は単純に x+y+z という計算はしてはいけません)

2013年9月16日月曜日

STM32F1でTIMのパラメータ

STM32F1のTIMのパラメータ
この関数は引数1で与えた周波数になるように引数2と引数3のポインタにパラメーターを書き込む

// 0:成功 
// 1:システムクロックで割り切れない周波数 
// 2:プリスケーラの設定中に丸め誤差が発生した 
uint8_t TIM_GetFreqencyPrameter(uint32_t Freqency, uint16_t *pPeriod, uint16_t *pPrescaler) {
    const uint32_t cSysFreq = 72 * 1000 * 1000;
    uint32_t per, pre;
    
    if (cSysFreq % Freqency) { return(1); }
    
    per = cSysFreq / Freqency;
    pre = 1;
    
    while (per > 0xFFFF) { per /= 10; pre *= 10; }
    
    if ((cSysFreq / per / pre) != Freqency) { return(2); }
    
    *pPeriod    = per - 1;
    *pPrescaler = pre - 1;
    
    return(0);

}

なおシステム周波数はcSysFreq変数に設定され、この例では72MHzとなっている
計算上完璧な周波数以外は1or2が返される
正常な場合は0が返され、ポインタに値が設定される


とりあえず軽く動作確認はしていますが、使うときは自己責任でどーぞ
例えば7Hzや11Hzは作成できません
11Hzは整数で割り切ることができないので1が帰ります
7Hzは整数で割り切ることができますが、0xFFFFより大きな数字になってしまうため、丸め誤差エラーが発生し2が帰ります

ラッパー関数を作ればサクッとタイマの初期化もできますが、信頼性は低いのであまり多様しないように

2013年9月8日日曜日

STM32F103でCAN通信(その2)

CANトランシーバIC"MCP2551"が届いたので
試してみました

ソースコードは以前の流用です


赤がCAN-H 黄色がCAN-L
緑はその差分

上のキャプチャはふたつのMCP2551のTXとRXをキャプチャしたもの

CAN1TXから出力された信号はCAN1RXとCAN2RXから出てきています

上の画像は
000010100101000011010101010010101010000010001111101110000010011000001000111000010110
という感じのビットになっており
分解すると
のようになります

送信したデータは
Idが0xA5のスタンダード
データ長は6で0xAA 0x55 0x00 0xFF 0x01 0x80
です

5bitほど足りませんが、CRCの最後2bitが1であると仮定した場合は辻褄が合います
データの4byte以降が9bitなのはビットスタッフの影響です

今はひとつのマイコンから送信しているだけなので、次は他のマイコンで受信 などをしてみたいですね
それができたらなが~いLANケーブルでも買ってきて長距離通信やってみようかな

2013年9月7日土曜日

文字列バッファの位置を特定する

ある程度長い文字列をテストファイルとして書いたりする場合
「どこまで書けているか」を判断するのは意外と大変です
なぜかというと、charはそもそも8bitとして256種類しか表すことができず、さらに文字となると表すことができる範囲は更に狭くなります

そのため1024byteくらいのバッファをforで0-Fの範囲で埋めると
出てきた文字列がどの場所にいたのか判断しかねる時があります

その時に使える方法

2013年9月2日月曜日

STM32F1で送信バッファ

STM32F103VEで送信バッファを作ってみました
STM以外にも使えると思いますが


ヘッダファイルにdefineでUSART3writeLine(送信バッファを有効化するフラグ)とUSART3writeBufferSizeがあります
また、別の場所では #ifndef USART3writeLine で送信バッファを使わない送信関数もあります

送信バッファは受信バッファと違い、行識別等が不要なので関数2個といくつかの変数だけで実装可能です