ブログ

ορεσικα ψομαναι κυσο βλογ

TIの新版Sensor Tagが技術基準適合証明を取得

技適取得機器の調べ方

www.tele.soumu.go.jp

上記ページで調べたいモノの情報の一部を入力すれば検索可能です。「氏名または名称」フォームに「テキサス」と入力して、下の方の送信ボタンを押すと以下のように新版のセンサタグ(CC2650STK)が登録されていることを確認できます。

f:id:XX-Prime:20150801155258p:plain

今年の4月16日にすでに取得されていたようですが、この検索ページに出てきたのは最近だと思います。

これで新版センサタグを日本国内で使用しても暗殺される危険性がなくなりました。

空中線電力の規定

新版センサタグはBLEとZigbeeの両方の通信方式に対応しています。それに応じて、空中線電力の規定も2つあって、

  • F1D 2402~2480MHz(2MHz間隔40波) 0.0012W
  • G1D 2405~2480MHz(5MHz間隔16波) 0.0007W/MHz

となっています。上がBLE、下がZigbee用の規定です。

新版センサタグは、Devpackという安価で小さな基板を使って簡単に自作プログラムをアップロードできますが、出力電波強度を変更する際に上の規定を守るにはどの定数を選べばよいか調べてみます。

出力電波強度の設定

センサタグはファームウェアソースコードIDE(クラウドコンパイラもある)が手に入るのでサルでも簡単に開発ができます。センサタグアプリのApplicationディレクトリにあるSensortag.cで出力電波強度の設定ができます。デフォルトでは以下のようにGAP_ADTYPE_POWER_LEVELで0dBmが指定されています。

// GAP - SCAN RSP data (max size = 31 bytes)
static uint8_t scanRspData[] =
{
// complete name
0x11, // length of this data
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
'C', 'C', '2', '6', '5', '0', ' ', 'S', 'e', 'n', 's', 'o', 'r', 'T', 'a', 'g',

// connection interval range
0x05, // length of this data
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),
HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),
LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),
HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),

// Tx power level
0x02, // length of this data
GAP_ADTYPE_POWER_LEVEL,
0 // 0dBm
};

実はこれは実際の強度設定ではなく、BLEスキャンコマンドへの応答データの文字列を設定しているだけです。 

実際の強度設定は、

HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_MINUS_21_DBM);

というように強度設定関数をSensortag.cのSensorTag_init(void)の中で書けばOKです。

参考:

c - How to modify the TI SensorTag Firmware to advertise indefinitely? - Stack Overflow

上のリンクの情報は旧版センサタグのもので、設定可能な値が異なりますが問題なく機能します。

新版で指定可能な値は、Includeディレクトリにあるhci.hで確認できます。

#if defined( CC26XX ) || defined( CC13XX )
#define HCI_EXT_TX_POWER_MINUS_21_DBM LL_EXT_TX_POWER_MINUS_21_DBM
#define HCI_EXT_TX_POWER_MINUS_18_DBM LL_EXT_TX_POWER_MINUS_18_DBM
#define HCI_EXT_TX_POWER_MINUS_15_DBM LL_EXT_TX_POWER_MINUS_15_DBM
#define HCI_EXT_TX_POWER_MINUS_12_DBM LL_EXT_TX_POWER_MINUS_12_DBM
#define HCI_EXT_TX_POWER_MINUS_9_DBM LL_EXT_TX_POWER_MINUS_9_DBM
#define HCI_EXT_TX_POWER_MINUS_6_DBM LL_EXT_TX_POWER_MINUS_6_DBM
#define HCI_EXT_TX_POWER_MINUS_3_DBM LL_EXT_TX_POWER_MINUS_3_DBM
#define HCI_EXT_TX_POWER_0_DBM LL_EXT_TX_POWER_0_DBM
#define HCI_EXT_TX_POWER_1_DBM LL_EXT_TX_POWER_1_DBM
#define HCI_EXT_TX_POWER_2_DBM LL_EXT_TX_POWER_2_DBM
#define HCI_EXT_TX_POWER_3_DBM LL_EXT_TX_POWER_3_DBM
#define HCI_EXT_TX_POWER_4_DBM LL_EXT_TX_POWER_4_DBM
#define HCI_EXT_TX_POWER_5_DBM LL_EXT_TX_POWER_5_DBM
#else // CC254x
#define HCI_EXT_TX_POWER_MINUS_23_DBM LL_EXT_TX_POWER_MINUS_23_DBM
#define HCI_EXT_TX_POWER_MINUS_6_DBM LL_EXT_TX_POWER_MINUS_6_DBM
#define HCI_EXT_TX_POWER_0_DBM LL_EXT_TX_POWER_0_DBM
#define HCI_EXT_TX_POWER_4_DBM LL_EXT_TX_POWER_4_DBM
#endif // CC26XX/CC13XX

新版では最強の+5dBmから最弱の-21dBmまで設定可能なようです。

上で見たとおり、TIが取得した技適では0.0012Wが上限なので、0.8dBmが上限ということになります。よって、日本国内で問題なく設定可能なのはHCI_EXT_TX_POWER_0_DBMが上限です。それより大きい値を設定すると逮捕・監禁・打首・獄門の憂き目にあうので注意しましょう。

まとめ

技適取得から検索ページに出てくるまでのタイムラグ(約3ヶ月?)をなんとかしてほしい。

mbed HRM1017の電池駆動

HRM1017とは

mbedでBLEペリフェラルデバイスの開発が簡単に行えるボードで、技適マークが付いているので使っていることを公表しても逮捕・監禁・拷問されることはありません。

www.switch-science.com

ただし、電波強度の設定によっては違法な強度の電波が出ることもある(かもしれない)ので、プログラムで電波強度パラメータを調整する際には注意が必要です。

電源電圧の取得方法

Measuring battery voltage with Nordic nRF51x devices | mbed

上記のリンク先の方法で電源電圧を取得できます。USB給電の場合は、レギュレート済みの3.2V程度の値が取得できます。

単三電池二本での駆動結果

取得した電圧の値をセントラル側に返すサービスを実装して、セントラル側から一分に一回電圧値を取得してXivelyに送信して電池電圧の降下状況を記録してみました。

使用した単3アルカリ乾電池はオーム電機のV-アルカリ乾電池です。これを選んだ理由は単純に安くてどこでも売ってるからです。

省電力のためのコード上の工夫を全くしていない状態で、駆動時間は9日と12時間でした。

f:id:XX-Prime:20150615101842p:plain

終端電圧は1680mVで、1789mVを下回ったあたりから通信の失敗が発生し始めるので、安全に使用可能な範囲は1800mV程度まででしょうか。それを考慮すると、寿命は9日と2時間程度です。

感想

ちょっとこのままの状態だと電池駆動は実用的でないと思います。一日に一回充電が必要なマヌケな腕時計にくらべればだいぶマシではありますが。

コードの工夫でどこまで消費電力を絞れるかが興味ある点です。しかし、ざっと調べてみた限り、寿命が1年に伸びるといったような劇的な改善はあまり期待できそうにありません。

まとめ

現時点ではちょっとがっかり。酒飲んでふて寝でもするか。

mbedにPocketGeiger Type5を接続する

mbed触りだしてみました

使いやすいですmbed。オンラインIDEで使いたいボードなりチップを選ぶとピン配置図が出て配線が簡単に確実にできます。とても賢い人達が作っているのがわかります。某マイコンボード陣営が内部分裂でグダグダやってる内に嫌気が差してmbedに移るユーザもいるのではないでしょうか。

触ってるのはこれ

www.switch-science.com

BTつきのモノとかいくつか買ってみたのですが、いま私が主に触ってるのはLPC1114FN28です。プログラムをアップロードした後は石だけ取り出して電源を与えるだけでも動き出すという素敵な構成で、石単体なら200円ちょっとで手に入ります。すごい。

PocketGeiger Type5をつないでみる

mbedに慣れる目的で、PocketGeiger Type5をLPC1114FN28につないで放射線センサデータを取れるかどうか試してみました。といっても、arduino用のコードがすでにRadiation-Watch.orgから入手できるので、移植は私程度のクズでも簡単にできるはずです。

f:id:XX-Prime:20150503174907p:plain

オンラインIDEでLPC1114FN28を選んでPinoutを見てみると、dp25とdp26が空いているのでこれらをデジタル入力として使うことに決めました。PocketGeiger Type5からは信号線として放射線検出信号とノイズ信号の二本がデジタル出力として出ており、これらを取り扱う必要があります。

arduinoからmbedへ移植

arduinoのソースはほぼプログラミング言語Cそのものですが、以下の三点がarduino独自の方言です。

  1. ピン設定
  2. シリアル通信
  3. タイマー

この方言をmbed用のCに翻訳するだけで移植は完了します。

1. ピン設定(と読み取り)

これは簡単です。

arduino

//設定

//信号検出ピンの設定
pinMode(signPin,INPUT);
digitalWrite(signPin,HIGH);
//ノイズ検出ピンの設定
pinMode(noisePin,INPUT);
digitalWrite(noisePin,HIGH);

//読み取り

// 信号のローデータ 通常:High 検出時:Low
int sign = digitalRead(signPin);

// ノイズのローデータ 通常:Low 検出時:High
int noise = digitalRead(noisePin);

をmbedでは

//設定

DigitalIn signPin(dp25);
DigitalIn noisePin(dp26);
signPin.mode(PullUp);
noisePin.mode(PullUp);

//読み取り

// Raw data of Radiation Pulse: Not-detected -> High, Detected -> Low
int sign = signPin;

// Raw data of Noise Pulse: Not-detected -> Low, Detected -> High
int noise = noisePin;

と書きます。mbedは関数すら呼ばずにピンの状態を変数に直接代入しているようにみせてます。すごい。

2. シリアル通信

これも簡単です。

arduinoでは

Serial.begin(9600);

//シリアルで送信
Serial.println(msg);

 などとしますが、mbedでは

Serial pc(USBTX, USBRX); // tx, rx

pc.puts(msg);
pc.puts("\r\n");

などとします。\rを付けずに\nだけ付加しているmbedプログラムをよく見かけますが、多くの環境(というかシリアル通信端末プログラム)で\rがないと改行後に左端にカーソルが移動せずに出力が乱れてしまいます。

3. タイマー

これも簡単。

arduinoでは

//現在の時刻を取得
currTime = millis();

ですが、mbedでは

Timer t;

    t.start();

    currTime = t.read_ms();

 とすれば一対一対応します。

動かしてみたが、止まる。

移植はすぐ終わったのですが、いざ動かしてみると短時間で動作を停止してしまうことがわかりました。どうやらノイズピンに信号があると動作停止するようです。移植元のarduinoソースコードを真面目に読んでみたところ、怪しげな部分を見つけました。

//10000回ループを回ったら、計測値を計算して、シリアルで出力する
if(index==10000) //Arduino Nano(ATmega328)で160-170ms程度
{

  //省略
  
  //ノイズが10000回のループの中でまったく検出されないとき
  //ノイズが検出されたときは、処理をしない
  if(noiseCount == 0)
  {
  
    //省略
  
    //シリアルで送信
    Serial.println(msg);
  
    index=0; // <-えっ???ここで?
  }
  
  // 省略
  
}
index++;

 つまり、ノイズがない時だけ、indexが正常に0に初期化されるロジックになっているので、ノイズがあるとindexが初期化されずに増加しすぎておかしな挙動につながる、と思われます。よって

  if(noiseCount == 0)
  {
  
    //省略
  
    //シリアルで送信
    Serial.println(msg);
  
    //index=0; // <-ここをやめて
  }

  index=0; // <- ここにする
  

 としました。これでmbedでも正常に動作し続けることを確認できました。

f:id:XX-Prime:20150503182752p:plain

なぜarduinoでは問題が起こらないのか?

起きてるような気もしますが、とりあえずわかりません。intのサイズの違いかなあ。

追記(2015/05/05)

Radiation-watch.orgの問い合わせフォームから、上記のコード部分について質問してみたところ、やはりバグであることが判明しました。現在ダウンロードできるarduinoコードは修正済みのものなので、もし現在古いコードを使っている方は新しいもので置き換えることをお勧めします。ノイズピンに信号があった場合の計測値の精度が若干向上します。

arduinoで問題が起こらなかった理由も、Radiation-watch.orgのご担当の方の説明で判明しました。arduinoのintが2バイトであるため、index変数の初期化に失敗しても短時間でオーバーフローして、ある意味で勝手に再初期化が行われるために明確なバグとして発覚していなかったというのが真相です。mbedはintが4バイトなので、オーバーフローまでarduinoの65535倍の時間がかかるために、動作が止まったことがハッキリと認識できたわけです。私がもし賢かったら、移植の際にintのサイズを合わせるためにmbedではshort intを使っていたはずで、その場合はバグが発覚することもなかったでしょう。バカで良かった。

コード

改変部分をあえてコメントとして残してある部分もあります。

 

まとめ

mbedすげー。

Arduino yunで放射線センサのデータをxivelyとM2Xにアップロードする

xivelyだけでは不安

xivelyはたまにサービスが止まるので、センサデータをxivelyだけに上げるのは良いアイディアとは言えません。M2Xにも同時に上げてデータロストに備えましょう。

yunのプログラムスペースはやはり小さい

複数クラウドへの同時データアップロードの例として、pocket geiger type5の測定データをarduino yunでxivelyとM2Xの両方に上げるプログラムを書いてみました。当初はxivelyと同様にarduino側のProcessクラス経由のcurlを利用してM2Xにもアップロードしようと試みましたが、パラメータの文字列を用意するためにメモリが足りなくなって断念し、結局linux側のシェルスクリプトにM2Xへのアップロード機能を移しました。また、放射線データ保存用の配列も、デフォルトでは200要素ありましたが、150まで減らしてやっとうまく動作しました。しかしここまで苦労するなら素直に全部linux側でやってしまったほうが良いような気もします。

つかいかた

スケッチの下の方でコメントになっているシェルスクリプトを、yunの/root/にm2x_up.shという名前で作成して実行権限を付与します。スクリプト内の

M2X_DEV_KEY='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
M2X_API_KEY='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
M2X_RADIATION='radiation' # radiation stream
M2X_RAD_ERROR='radiation_error' # radiation error stream

を自分用のM2Xの適切な文字列に変更します。

次にスケッチ内の

#define APIKEY "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
#define FEEDID "000000000"

を自分用のxivelyの適切な文字列に変更してyunにアップロードします。うまくいけば一分に一回の頻度でxivelyとM2Xの両方に放射線センサのデータが上がります。

データ例

以下の様な感じで、両方共アップロードがうまくいっているようです。

f:id:XX-Prime:20150426221329p:plain

f:id:XX-Prime:20150426221340p:plain

これでどちらか(というかxively)が止まっても安心です。

コード

まとめ

シェルスクリプトjsonデータの構築部分がどうしてもうまく行かず、3日くらい試行錯誤したことは人として恥ずべき過去です。

Xively障害発生と復旧

サーバ障害発生

f:id:XX-Prime:20150418212254p:plain

これまでで一番長いダウンタイムかもしれません。先日、しょうもないUIアップデートがありましたが、そんなことやってるヒマがあるなら以下略。

乗り換え先は

M2Xとかどうでしょうか。

xx-prime.hatenablog.com

ちなみに私はAT&Tとは何の関係もないただのアホです。いくつか試してみて、乗り換えが容易だと思えるのがM2Xでした。

念の為に、XivelyとM2Xの両方に同じデータを上げておくと、片方が死んでいても安心です。私は放射線データだけを一つのrubyプログラムからXivelyとM2Xの両方に上げていますが、特に問題は生じていません。更に念押しするなら、3つ目のどこか別のクラウドストレージサービスを同時利用するのも良いかもしれません。クラウド利用は便利ですが、データロストの対策はしておく必要があります。

Xivelyの有料アカウントを利用している人は今回の障害の影響は受けているのでしょうか?

復旧

障害発生日時:2015年15時36分(JST)

障害復旧日時:2015年23時19分(JST)

でした。これまでも一時間程度の障害は度々発生していましたが、7時間以上というのは珍しいです。この先も障害が頻発するのかどうか注視が必要です。

3つのスイッチの状態を一つのアナログポートで検知したい

経緯

あるマイクロコントローラの、自由に使える入力ポートがアナログ1ポートしかないという状況で、ノーマリオープンのスイッチ3つの開閉状態を検知したいという状況が発生しました。スイッチは同時に閉じられることもあるので、2^3 = 8通りの開閉状態を電圧の変化として検知できるかどうかを考えてみました。だいぶ無理がありそうですが。

回路案

cacoo.com

こんなもんしか思いつきませんでした。Rとr1,r2,r3の値をどう選ぶかが問題です。ヘタに選ぶと複数の状態が同じVoutになってしまいそうです。

抵抗の選択

スプレッドシート上でいろいろと計算した結果、以下の組み合わせが良さそうだと思います。

{ \displaystyle R = 1\text{k}, r_1 = 4\text{k}, r_2 = 2\text{k}, r_3 = 1\text{k} }

これらの比率だけが意味を持つので、全体を適当に定数倍してもVoutは変わりません。この組み合わせの結果、Voutは以下のようになります。

0V付近とVcc付近の空きが大きく、右のほうの電位差が小さいなどの欠点はありますが、とりあえず8通りの電圧として分離できているようです。最小の電位差が右端2つの0.036 Vcc [V]なので、分解能が8bitもあれば十分識別できそうです。あ、抵抗の誤差をちゃんと考えないとマズそうな気もします。

もっと良い組み合わせや回路はあるか

ほぼ間違いなくもっと良いアイディアがあるのでしょうが、腐って紫色に変色している私の脳みそではこの程度が限界でした。特にVcc付近がうまく利用できてない点が激しく間抜けです。

スイッチはいくつまで増やせるか?

A/D変換のビット数に応じて、限界が決まると思います。面倒なのでここで思考を停止します。

一応計算式

間違ってるかもしれませんが

https://www.circuitlab.com/

でシミュレートしたら同じVoutになったので多分合っているのでしょう。

{ \displaystyle V_{out}(SW1のみON) = \frac{V_{cc}}{ \frac{1}{\frac{R}{r_1}} + 1} }

{ \displaystyle V_{out}(SW1とSW2が共にON) = \frac{V_{cc}}{ \frac{1}{\frac{R}{r_1} + \frac{R}{r_2}} + 1} }

{ \displaystyle V_{out}(全てON) = \frac{V_{cc}}{ \frac{1}{\frac{R}{r_1} + \frac{R}{r_2} + \frac{R}{r_3}} + 1} }

こうやって具体的に例示すると見やすいですが、例えば

{ \displaystyle V(SWxのみON) = \frac{V_{cc}}{ \frac{1}{\frac{R}{r_x}} + 1} }

とか

{ \displaystyle V_{out}(SWxとSWyが共にON) = \frac{V_{cc}}{ \frac{1}{\frac{R}{r_x} + \frac{R}{r_y}} + 1} }

とか

{ \displaystyle V_{out}(SWkだけが全てON) = \frac{V_{cc}}{\frac{1}{\displaystyle {\sum_{ONになっているSWのk} \frac{R}{r_k}}}+1} }

とかいうふうに一般化した式を書くといきなり分かりづらくなって読む気が失せますね。

まとめ

雨が降って憂鬱だったので、いろんなリンクを埋め込んだり、数式を書いたりしてみたかった。反省はしていない。

 

The Art of Electronics 3rd edition が届いた

表紙ボコボコ

BookDepositoryで予約購入していたThe Art of Electronics 3rd Editionが届きました。郵便受けに無理やり押し込まれていたせいか、表紙が凹んだり折れ目がついたりしてました。配達人さん出てきなさい。背景のビニールシートっぽい袋の中に、薄いダンボール封筒が入っており、その中に本が入っていました。

f:id:XX-Prime:20150407220556p:plain

昔に2nd editionを新品で入手した時も非常に状態の悪いものを掴まされたので、私は何かの罪でも背負っているのでしょうか。だから不思議と腹は立ちません。

あの演習問題は健在

f:id:XX-Prime:20150407220939p:plain

イラストがちょっと新しくなってます。

2ndとの違い

触って5分も経ってませんが、とりあえず気づいた二点だけ挙げておきます

内容的な差

チャプターの最後にReview of Chapter というまとめページが数ページつきました。最初にこのReviewだけざっと読んで、興味をひかれた部分を詳しく読むという使い方ができるようになりました。

物理的な差

総ページ数は1192ページでした。表紙カバーは外れない仕様になったので取り扱いはしやすくなりました。鈍器級の重さは相変わらずです。地震の多い国では保管場所に注意が必要です。

4th は出ないが

PREFACE TO THE THIRD EDITIONに、

In this new third (and final!) edition we have responded to this upheaval with major enhancements:(以下略)

とあります。これが最後の改訂版です。ただ、本に収まらなかったテーマについての補助的な本『The Art of Electronics: The x-Chapters』がこれから出るようです。

また、3rd ed.に対応した副読本もこれから出るようなので気長に待ちましょう。

artofelectronics.net

(**A new 3rd Edition** companion is in preparation: “Learning the Art of Electronics”)とのことですが、これまでの経緯を考えると、まあ当分先でしょう。