2013年10月29日火曜日

mbeのベタグランド

フリーの基板設計CAD mbeというソフトですが
ガーバー出力ができ、すでに発注を2回していて問題なく使えています

で、今回基板を新しく設計するにあたり
少しはノイズ対策をしよう ということでGNDを強化しようと思いました
本来はちゃんと設計するべきですが、何が影響するのかさっぱりわからないのでとりあえずは気分だけでも ということで



SPIのパターンが上のように並んでいる場合
高周波になると信号が横に並行しているパターンに漏れてしまう可能性があります
これはパターン幅が狭くなれば狭くなるほど強くなる傾向があります
また長距離を伝送した場合はより強くなり
信号周波数が高くなるほど強くなります
この特性は裏面のパターンにも影響されるため非常に複雑で、経験や勘と実際に試した結果を元に最適化していくような場所です

このように並行した長いパターンというのはかなりの数にのぼり、今設計している100x200mmサイズになると相当な長さになってしまいます
一番簡単に対策をするには4層基板等を使って、いわゆる「ストリップライン」という構造にすればいいのですが、今回は2層で設計しているためこの方法は使えません

そのためとりあえず後から追加できる方法として、パターン間にGNDを通すことにしました
この方法ではパラレルATA等のインターフェースで後に採用されています

ざっくりと原理を説明すると
高速な信号は周りに影響を与え、その強度は与える側が低インピーダンスなほど そして与えられる側が高インピーダンスなほど強くなります
そして与える側の横に低インピーダンスな配線がればそこで吸収され、その外側へ与える影響は小さくなります
(という感じに理解しています)

この場合の低インピーダンスな配線とは、GNDに落とした配線となり、ほぼゼロ抵抗でGND電位に保たれます

しかし1本1本ラインで作っていると膨大な手間になり、修正も難しくなります
(信号1本の両側にGNDを通すため配線数は最大で3倍になります)


しかしmbeにはポリゴンという機能があり、これを使うと簡単にベタを作ることができます

この例では5本のパターンが有り外側の2本がGND 内側の3本が信号です
またパターン間隔は1.27mmです

ポリゴンの設定はGAP0.3mm Trace Width0.3mmで、Remove floating patternにチェックが入っています
パターン幅が0.3mmの場合 2本のパターンの間は0.97mmとなり、GAP幅0.3mm2本分の0.6mmにTraceW0.3mmを足した0.9mmよりも余裕があります

上画像の中で白いところはGNDと導通しており、信号線の間にGNDパターンが通っていることがわかります

このようにパターン幅を0.3mmで信号を通せばポリゴンでパターン間にGNDを通すことができます

ただしDRC(Design Ruehl Check)ではベタに対しての評価はされないため、注意が必要です
他にもいろいろ注意点がありますが、とりあえず「こんな使い方もできるよ」ということで

2013年10月27日日曜日

時間の単位

タイトルは"フィクションにおける時間の単位"とかにしようと思っていたんですが
現実の地球ベースなので単に"時間の単位"としました

さて、異世界転生モノの小説とかを読んでいるとよく時間が出てきます
「1日は24時間なのか」とか季節を1年で表す時もあります
しかしその時間というのは正確に現代の地球の時間と一致しているのでしょうか?

元々の時間の由来は
1日:太陽が現れてから次に現れるまで
1年:星座が同じ場所に帰ってくるまで
がベースとなり
1時間:1日を正確に24等分した長さ
1分:1時間を正確に60等分した長さ
1秒:1分を正確に60等分した長さ
となります
なぜ24/60等分するのか や1年を12に分けた月は今回は触れません
(まだ調べていないので。。)

この時間の単位で、他の惑星等で相対的に変化させることにより対応できるのは1日をベースにした単位で、日以外には時間・分・秒です
これは太陽が1回廻る時間が基準になるためです
年は相対的に変化させることができず、実際に観測をして1日の回数を数えるしかありません
例えば地球なら1年はおよそ365日ですが、太陽系第四惑星の火星ではおよそ687日です
これは火星が地球よりも公転半径が長いためであり、円周が長い分1周するための時間も長くなるからです

このように惑星の位置に応じて1年の日数は変化するため、例えば転生した先の恒星や惑星が太陽系と違う場合は1年の日数も変化してしまいます

1日の時間は地球では86400秒ですが、火星ではおよそ88950秒です
このように1日の長さは星ごとに違い、おそらく転生先の星も同様に変化すると思われます
また地球の自転速度も少しずつ変化するため、現在では太陽基準ではなく、セシウム133という原子を基準にしています
原子時計は簡単に作れる装置ではないため、おそらく転生先が剣と魔法の世界であった場合は正確な地球基準の秒を作ることは不可能でしょう
それに魔法が存在する世界であれば現代の物理と全く別の法則である可能性もあります


転生先の星の時間を測るには星座の観察で1年の日数を測定するのが一番簡単だと思いますが、それでも1日の長さが異なるので地球との変換はできません
もしも腕時計などを持ち込むことができればそれでおおよその時間はわかりますが、月差20秒の時計であれば365日で5分以上ズレるため、正確な時間は測定できないでしょう


他の物理単位として、距離の単位"メートル"があり、この単位もよく出てきますが、メートルの単位はそもそも1秒に進む光の距離の299792458分の1と定義されているため、時間単位が「日」とそれを数等分した世界では基準として存在できません
他の方法としては子午線を使う方法がありますが、これは惑星の直径に影響を受けるため使うことができません

他の長さの単位としてフィートが有ります
これはヒトの足のかかとからつま先までを基準とした単位なので、比較的異世界でも使いやすい単位といえます
ただし個人差があるので、予め異世界に行く前に自分の換算値を計測しておく必要があります

重さの単位としてキログラム(1000グラム)がありますが、これは1リットルの水の重さで、まず1リットルを測定するための基準(たとえば正確に10cm立方の箱)が必要なため、異世界で使いやすい単位とは言えないでしょう
他の単位としてはポンドがあり、これはひとりの人間が1日に消費する大麦の重さが基準であり、異世界に都合よく麦が主食とされている場合は比較的使いやすい単位です
もしかしたらすでに「1人が1日に消費する食材」という単位があるかもしれません
(そのような単位があったほうが買い物するときに楽だからです)


フィートやポンドは現代日本では使いづらい印象がありますが
SI単位系は相当技術が進んでいる世界でしか使えなく、基準が1つもない世界ではむしろ使いづらい単位となってしまいます

フィクションで他の惑星に移動するような作品を書く/読む場合は単位の違いも考慮にいれる必要が有ります

2013年10月15日火曜日

STM32F1 CANの速度

STM32F1のリファレンスマニュアル RM0008 Rev5 日本語版によるとCANの速度は以下のように説明されています


Rev14でも同じ内容です

実際にBaudRateを計算してみましょう
まずAPBクロックの周期とは
CAN1が接続されているAPB1のMax36MHzです
これでtPCLK = 36MHzの周期 = 0.027778マイクロ秒となります

次にtqですが ここにはBRP[9:0]というのが出てきます
これはCAN_BTRレジスタの中にあり
標準ペリフェラルライブラリ CAN_Initでは
((uint32_t)CAN_InitStruct->CAN_Prescaler - 1)
が他のレジスタとORで代入されています
つまりCAN_InitTypeDef.CAN_Prescalerに入れた値から1を引いた数が入ります
しかし計算時には1を足しているのでCAN_Prescaler*tPCLKとすることができます

Prescalerを6と仮定した場合
tq = Prescaler * tPCLK = 6 * 0.027778 = 0.166668
となります

tBS1とtBS1もTS1とTS2がありますが、これもCAN_BTRの中にあります
それぞれCAN_BS1_xtqとCAN_BS2_xtqという定数で設定し、1tqは0が 2tqは1が 3tqは2が~ という関係です
しかしこのレジスタも計算時に1を足しているので1tqが1 2tqが2として計算できます
CAN_StructInitではCAN_BS1_4tqおよびCAN_BS2_3tqが代入されるため
tBS1 = tq * BS1 = 0.166668 * 4 = 0.666672
tBS2 = tq * BS2 = 0.166668 * 3 = 0.500004
となります

NominalBitTimeはそれぞれを足し算しているだけですので
NominalBitTime = 1 * tq + tBS1 + tBS2 = 0.166668 + 0.666672 + 0.500004 = 1.333344
となります

BaudRateは1をこの数で割っているだけなので
1 / NominalBitTime = 1 / 1.333344 = 0.75
となり、ビットレートは0.75となります
しかし最初にtPCLKをマイクロ秒としているため、ビットレートの単位を合わせると0.75Mで、750kBit/secとなります
この結果はオシロスコープで実測した値とおおよそ一致します

実際にCANbusを使う場合はプリスケーラ10で450kbpsとなり、東陽テクニカのWebページを参考にした場合で100mほど距離の通信ができます
AWG23-24の線材を使った場合のノード数は100で、これは1m間隔に1ノード程度となります

一旦機器を設置してしまうとビットレートの変更は容易では無いため、実際にビットレートを設定する場合は設置する環境を十分に見積もった上で もしくは簡単にビットレートを変更できるように工夫するべきです
同一のCANバス内で複数のビットレートが混在することは許可されていないため、ビットレートの設定は十分に注意する必要があります

2013年10月14日月曜日

1WireのCRC計算

1WireのCRC生成コードです

      4 /* CRCを含めたデータサイズ(バッファサイズ) */
      5 uint8_t CalcCRC(uint8_t *pData, uint8_t DataSize) {
      6   register uint8_t *pCRC = pData + DataSize -1;
      7   register uint8_t dat;
      8   int i;
      9
     10   if (!*pCRC) { DataSize--; }
     11
     12   for (i = 0; i < DataSize; i++) {
     13     dat = pData[i];
     14
     15     *pCRC = ((dat ^ *pCRC) & 1) ? (((*pCRC ^ 0x18) >> 1) | 0x80) : (*pCRC >> 1); dat >>= 1;
     16     *pCRC = ((dat ^ *pCRC) & 1) ? (((*pCRC ^ 0x18) >> 1) | 0x80) : (*pCRC >> 1); dat >>= 1;
     17     *pCRC = ((dat ^ *pCRC) & 1) ? (((*pCRC ^ 0x18) >> 1) | 0x80) : (*pCRC >> 1); dat >>= 1;
     18     *pCRC = ((dat ^ *pCRC) & 1) ? (((*pCRC ^ 0x18) >> 1) | 0x80) : (*pCRC >> 1); dat >>= 1;
     19     *pCRC = ((dat ^ *pCRC) & 1) ? (((*pCRC ^ 0x18) >> 1) | 0x80) : (*pCRC >> 1); dat >>= 1;
     20     *pCRC = ((dat ^ *pCRC) & 1) ? (((*pCRC ^ 0x18) >> 1) | 0x80) : (*pCRC >> 1); dat >>= 1;
     21     *pCRC = ((dat ^ *pCRC) & 1) ? (((*pCRC ^ 0x18) >> 1) | 0x80) : (*pCRC >> 1); dat >>= 1;
     22     *pCRC = ((dat ^ *pCRC) & 1) ? (((*pCRC ^ 0x18) >> 1) | 0x80) : (*pCRC >> 1); dat >>= 1;
     23   }
     24 }

ROMコードであれば8バイトのバッファとバッファ長8を渡します
バッファはファミリコードが0バイト目 CRCが7バイト目になるような配列です
CRCが0の場合はCRCを生成し
CRCが0以外の場合はCRCを再計算します

CRCを生成する条件で読んだ場合はCRCの部分にCRCデータが入りますが
CRCを再計算する条件の場合は0になれば正常です 0以外の場合はCRCデータを含めいずれかの1つ以上のビットが破壊されています

上の*pCRC = ((dat ^...のコードはforで回すべきですが
今回は8回分ベタ書きしています
この最適化がどれくらいに効果があるかは不明ですが とりあえず気分の問題ってことで

2013年10月10日木曜日

VBAで気圧高度

Excel2007のVBA
Officeファミリはかなり昔から使ってますが
VBAなる機能を初めて使いました

気圧から高度に変換する関数です

Function Alt(気圧 As Double, 温度 As Double, 海面気圧 As Double) As Variant
    Dim h As Double
    h = (1013.25 / 海面気圧) ^ (1 / 5.256) * ((海面気圧 / 気圧) ^ (1 / 5.256) - 1) * (温度 + 273.15) / 0.0065
    Alt = h
End Function

一旦変数を書いてから関数に代入する必要があるらしい

あと冪乗計算がPowerじゃないってのにハマった
Cじゃ^記号はXORだし
Excelだって冪乗計算はPowerを使うのに
VBAは^で冪乗計算になる

VBA 便利のような… 便利じゃないような…

2013年10月8日火曜日

STM32F1 standard peripheral CAN

STM32F1のCAN周り覚書

なお古いライブラリ(少なくとも4年以上)を使っているので、最新とは違うかも

CanRxMsgの中身
    uint32_t StdId;
    uint32_t ExtId;
    uint8_t IDE;
    uint8_t RTR;
    uint8_t DLC;
    uint8_t Data[8];
    uint8_t FMI;

・StdId
標準の識別子 0から0x7FFの範囲

・ExtId
拡張識別子 0から0x1FFFFFFFの範囲

・IDE
受信したメッセージの識別子タイプ CAN_identifier_type

・RTR
受信したメッセージのフレームタイプ CAN_remote_transmission_request

・DLC
受信したフレームの長さ 0から8の範囲

・Data[8]
受信したデータ 配列は8バイト確保されている 有効なデータ数はDLC

・FMI
フィルタ関係?


CAN_identifier_typeについて
    #define CAN_ID_STD
    #define CAN_ID_EXT
    #define IS_CAN_IDTYPE(IDTYPE)
CANID_STDとCANID_EXTがある
それぞれ標準IDと拡張IDを示している
IS_CAN_IDTYPEは「引数がSTDかEXTならば0位外を返す」というマクロ
ただCAN_ID_STDもCAN_ID_EXTも中身はuint32_t
STDかEXTかを調べるには自分でifで判断する必要がある


CAN_remote_transmission_requestについて
    #define CAN_RTR_DATA
    #define CAN_RTR_REMOTE
    #define IS_CAN_RTR(RTR)
CAN_identifier_typeと同様

なお (CAN_RTR_DATA == CAN_ID_STD) == true という関係なので
例えばIS_CAN_IDTYPE(CAN_RTR_DATA)とやるとtrueになる(おそらく
このためIS_CAN_IDTYPEやIS_CAN_RTRはあまり信用しない方がいいはず


CAN_MessagePendingについて
宣言は以下のとおり
uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber);

説明は以下
  * @brief  Returns the number of pending messages.
  * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.
  * @param  FIFONumber: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1.
  * @retval NbMessage which is the number of pending message.
要約すると
説明:保留中のメッセージの数を返す
引数:CAN1もしくはCAN2 ペリフェラルを選択
引数:FIFOの選択 FIFO0もしくはFIFO1
戻り値:保留中のメッセージ数

何をする関数かというと、FIFOにたまっているメッセージ数を返す
中身は
(uint8_t)(CANx->RF0R&(uint32_t)0x03)
もしくは
(uint8_t)(CANx->RF1R&(uint32_t)0x03)
を引数に応じて返している

CanRxMsg構造体の中にはデータの有効性を確認するためのレジスタはない
また、CAN_Receive関数の中にもデータの存在を確認する処理はない
FIFOにデータが有ろうが無かろうがReceive関数を呼べばFIFOの中身を返してくる
しかしFIFOの中身が0であれば意味のない値になる
しかし意味がある値日意味のない値かは値から判断することはできない

実際にCANを使う場合は一定期間ごとにCAN_MessagePendingをポーリングして
戻り値>0が真の場合にCAN_Receiveを読んでデータを処理することになる


CANで1つのデータが一番短い時はRTRの37bit
1Mbpsで通信している場合40bitとして1回40マイクロ秒くらい
実際にはもっと長いけど、FIFOが4フレーム分3フレーム分しか無いことを考えるとかなり高速でポーリングする必要があるかも
といってもまぁものすごいクリティカルな用途でもなければ秒数百回程度ポーリングすれば十分なはず

最悪の場合スマートじゃないけどCanRxMsgの配列を作ってCAN受信割り込みでリングバッファに貯めこんで大容量のFIFOを作るってやり方もあるw

2013年10月3日木曜日

Raspberry Piでシリアル通信

Raspberry PiのUSBポートにFT232を接続し、シリアル通信を試してみました

例によってViのキャプチャで申し訳ないです

とりあえずググって出てきたページのコードをほぼそのまま使っていますが
一応通信出来ました

ポート名はcpPortNameに設定され、これは各自の環境で調べてください
例えば ls /dev/tty* コマンドをFT232を接続する前と後に実行し、増えた項目がそのポートのはずです(dmesgでもいいですが)

設定は基本的に初期設定から変更していません
このあたりは追々調べていきます

とりあえずgccでビルドして実行します

正常に通信できれば相手には上のように表示されるはずです


Linuxは最近のパッケージにはFT232のドライバが標準で付属していて、インストールの手間もなくサクッと扱えます これはRasbpianでも同じで、簡単にシリアルポートにアクセスできるようです

USB-TTL UARTの変換にはFT232シリーズがデファクトスタンダードとなっており、秋月のXBeeアダプタストリナのXBeeアダプタはこのICが使用されているため、RaspBiのシリアルポートを消費することなくXBeeを接続することもできるようになります
他にもFT232+レベル変換ICを使えば本来のRS232通信も可能となります