0

ble-firmata npmにBLEの自動再接続機能を付けた

node.jsからBluetooth Low EnergyでArduinoをリモートコントロールできるble-firmata npmに、v0.1.1から自動再接続機能がついた。

BLEは有線のシリアル通信よりも接続切断は頻繁におこる。
見通し20メートルぐらいまで問題なく通信できるけど、家のドアなど金属製の遮蔽物があると切断される。そういう場合でも自動再接続されて、回線を意識せずロジックのプログラミングに集中できるようにした。


https://www.npmjs.org/package/ble-firmata

インストール

% npm install ble-firmata


注意


on ‘connect’イベントはデバイスが再接続される毎に呼ばれるので、その中でsetIntervalとかすると良くない。

once ‘connect’を使うとかすると良い。


BLEの切断


切断を検知するとarduino.on ‘disconnect’をemitするようにしておいた。

切断は色々な要因で起こる。

  • BlendMicroの電源が落ちる
  • BlendMicroが遠く離れて、電波が届かなくなる
  • BlendMicro側からnRF8001を切断する
  • node側でarduino.close()する
  • Macのbluetoothメニューで、[デバイス名]→[接続解除]を選択する
  • Macのbluetoothメニューで、bluetoothを「切」にする

いずれの場合も自動再接続が働く。


自動再接続を無効にする


reconnect = falseすれば自動再接続しない。一瞬接続して、切断して、しばらくしたらまた接続するような用途の場合は無効にすればいい。

arduino = new BLEFirmata().connect()
arduino.reconnect = false

0

ble-firmata npm作った

前:blendmicro npm 作った


作った

https://github.com/shokai/node-ble-firmata
https://www.npmjs.org/package/ble-firmata

node.jsからBLE上のfirmataプロトコルでarduinoを操作できるのを作った。
firmataはarduino側にあらかじめファームウェアを書き込んでおいて、PCからリモコンするというもの。プログラムがPC側だけで完結するのでシンプルになって良い。

既存のfirmata(Arduino IDEのスケッチ例に入ってるやつ)はシリアル通信だけど、BLEが使えるBlendMicroというArduinoMicro派生ボードと通信できるようになった。

あと試してないけど、同じRedBearLabが出してるBLE Shieldとも通信できると思う。

スクリプト言語でハードウェアやるのは、最近はnodeが一番色々と揃ってたり、やってる人が多かったりする感じある。


BlendMicro


インストール


node側
% npm install ble-firmata

arduino側
sketch exampleに入っているBLEFirmataSketchは動かないので、 firmwareディレクトリの下に置いておいたファームウェアを書き込む必要がある。

詳しくはInstallの項目を読むといいと思う。

一応プルリクだしておいたので、そのうち取り込まれるかもしれない。


使う


こんな感じで接続して使う。
digitalRead、servoWriteやanalogWrite、sysexもある。
BLEFirmata = require 'ble-firmata'

arduino = new BLEFirmata().connect()

arduino.on 'connect', ->
console.log "connect!"
console.log arduino.boardVersion

digitalWrite 13, true
console.log analogRead 0


複数使う

arduinoに書き込むファームウェアの上の方に
#define BLE_NAME "BlendMicro"
というのがあって、これが名前になっている。最大10文字まで。

new BLEFirmata().connect(“shokai1”) みたいな感じで、指定したBlendMicroに接続できる。
デフォルト値は”BlendMicro”。

Macbook Airで試したところ、1つのnodeプロセス内で2つのBlendMicroに接続はできた。しかし2つnodeプロセスを立ててそれぞれでBLEを使おうとすると、BLEのラッパーがエラーだして落ちた。どうやらMacの中にハードウェア的に1つしかBluetoothモジュールが無いのが、複数プロセスで共有できないらしい。


socket.ioと一緒に使う

他にもサンプルにはsocket.ioでブラウザからarduino(サーバーとはBLEでつながっている)を操作できるのも入っているので、サンプル見るとだいたいわかると思う。

0

Bluetoothが載ってるArduino派生ボード「BlendMicro」とNode.jsでBLEした

追記:npmにしたり、firmata作った




Mac OSXで動かしてるNode.jsとBluetoothで通信できるようになった。無線でArduino制御するの超簡単になっちゃった。
もうXBeeとか無くていいと思う。ミニ四駆とかに乗せるのに良さそう。

試したのはちゃんとコネクションはって双方向通信するやつ。次はAdvertisementパケットにセンサーの値でも乗せて垂れ流すのをやってみたい。

ソースコードとかはgithubにおいてある
https://github.com/shokai/blendmicro-study


ArduinoMicroにBLE(Bluetooth Low Energy)を追加したBlend Microというボードが先月末に出たので、買って試した。
1枚$36なので、2枚買った。注文して1週間ぐらいで届いた。
普通のArduinoMicroより1000円高いだけなので、(各言語から通信できるライブラリが揃ってくれば)とても良いと思う。


Blend Micro


Blend Micro — RedBearLab

ほぼArduino Microなマイコン基板に、BLEのチップ(Nordic nRF8001)が追加されている。
ATMegaからはACIというSPIに似たプロトコルで通信して制御する。その部分はArduinoライブラリになっている

BlendMicro


Arduino Microと比べて少し小さい。小さいのはnRF8001の制御にピンを使っているからその分をIOピンに引き出していないからだと思う。多分。
VCCが5Vではなく3.3Vになっている。nRF8001の動作のためにUSB 5Vを3.3Vに落としている。

BlendMicro


セットアップ

チュートリアルをよく読んで、ライブラリを追加したり、Arduino IDEの中のファイルを置き換えたりとかする必要がある。ちょっと面倒。
Getting Started – Blend Micro — RedBearLab

Arduino IDE側の環境が整ったら、サンプルスケッチのBLEControllSketchをBlendMicroに書き込んで、AndroidアプリiOSアプリから操作してみるといい。

やってみた



Node.jsと通信する


nodeからBLEでデバイス見つけて、文字列を書き込んで、BlendMicroが受信して、nodeにエコーする、というのを作ってみた。
Bluetoothの仕様全然知らないし、ドキュメントとか無かったけどソース読んでたら理解できてきてnodeで書けた。



通信しているところ。「かずどん」「ざんまい」などの文字列を送ると、
「echo>」が頭に付いて返ってくる。日本語が普通に通ってしまった。



nodeでのBLEはnoble npmを使った。

通信方法はドキュメントが無いので、AndroidアプリのChatサンプルのコードと、
BlendMicro内で使ってるNordicSemiconductor/ble-sdk-arduinoRedBearLab/nRF8001などのライブラリを読んだ。
ペリフェラル(デバイス)は名前で探して、その中のserviceリストとservice内のcharacteristicsリストから、nRF8001のRX/TXになってる奴をUUIDで識別すればいいだけだった。

複数のデバイスを接続する場合はarduino側でble_set_nameメソッドで名前を個別に変えて、それをnode側でperipheral.advertisement.localNameで探すとよさそう。

0

node.jsとarduinoでジョグシャトルのシャトルを取得


ジョグシャトル


ジョグシャトルは昔のビデオデッキのリモコンや、パチンコのハンドル部分についている回転部品。
「ジョグシャトル」でGoogle検索するとパチンコの攻略動画がたくさんでてくる。


内側の無限回転するジョグダイヤルと、外側の左右に30〜45度くらいまで回転するシャトルで構成される。

shuttleというのはシャトルランという英語のように「左右に素早く動く」という意味がある。
シャトル部分は左右にどれだけ回転させたかを細かく取得する事ができるアナログ入力装置で、今でもUSB接続のジョグシャトルがプロ用のビデオ編集機器として売られている。



ハードオフなどでビデオデッキのリモコンを買ってきて分解すると、こういうジョグシャトル部品が得られる。
ピンが8本出ているが、そのうち3本はnode.jsとarduinoでロータリーエンコーダーで書いたロータリーエンコーダで、のこり5本のがジョグシャトルのシャトル部分になっている。


この5本のピンが現在のシャトルの回転状態を2進数で表していると思いきや、グレイコードで表している。

グレイコード


グレイコードとは (グレイコードとは) [単語記事] – ニコニコ大百科
グレイコード – Wikipedia


かならず1桁ずつピン状態が変わるコードで、まあたしかにCPU等を持たない入力センサー側に搭載しやすそうだし変なチャタリングでなそう。

wikipediaより4bitのグレイコード

0000
0001
0011
0010
0110
0111
0101
0100
1100
1101
1111
1110
1010
1011
1001
1000



回路

ロータリーエンコーダと同じく、1つのピンがコモンなのでそこに5Vを入れる(基板のパターンを読めばどれかわかる)
残り4ピンを10KΩでGNDにプルダウンしつつ、Ardunoのデジタルピン(今回は5,6,7,8ピン)に入れた。


arduinoでジョグシャトルの制御

arduino-firmata npmを使った。


内側のジョグダイヤルは、ロータリーエンコーダのclassを使えばいい。2つ同時に使えるように実装してある。

外側のシャトルは、グレイコードから10進数の数値に変換するのは面倒そうだし、そもそもハードオフで買ってきたリモコンのシャトルだからどのピンが何番ピンかわからない。
よく考えたら16通りしか無いので、ちょっとずつ回転させながら全部確かめてJogShuttle.codes配列にメモした。

JogShuttle.coffee
events = require 'eventemitter2'
ArduinoFirmata = require 'arduino-firmata'

module.exports = class JogShuffle extends events.EventEmitter2
constructor: (@arduino, @pinA, @pinB, @pinC, @pinD) ->
console.log "set jogshuffle pin : #{@pinA}, #{@pinB}, #{@pinC} and #{@pinD}"

if @arduino.isOpen()
@initPins()

@arduino.on 'connect', =>
@initPins()

@arduino.on 'digitalChange', (e) =>
@pastState = @state
@state = @getState()
if @state isnt @pastState
@emit 'shuttle', @state ## shuttleイベントを発行

initPins: ->
@arduino.pinMode @pinA, ArduinoFirmata.INPUT
@arduino.pinMode @pinB, ArduinoFirmata.INPUT
@arduino.pinMode @pinC, ArduinoFirmata.INPUT
@arduino.pinMode @pinD, ArduinoFirmata.INPUT

getState: ->
@code = [@pinA, @pinB, @pinC, @pinD].map (i) =>
if @arduino.digitalRead i then 1 else 0
.join ''
return @codes.indexOf(@code) - @codes.length/2

codes: [
"1001"
"1101"
"1111"
"1011"
"0011"
"0111"
"0101"
"0001"
"0000" # neutral
"0100"
"0110"
"0010"
"1010"
"1110"
"1100"
"1000"
]


JogShuttle classを使う。
回転させるごとに”shuttle”イベントが発行され、初期状態が0、左に回すほどに-1,-2,-3…-7と減り、右に回すほど1,2,3…7と増えていく。
path = require 'path'
ArduinoFirmata = require 'arduino-firmata'
JogShuttle = require path.resolve 'JogShuttle'

jogshuttle = new JogShuttle arduino, 5, 6, 7, 8 ## digital pin 5,6,7,8 を使う

## 回転した時のイベントを受信
jogshuttle.on 'shuttle', (state) ->
console.log state

arduino-firmata npmのon “digitalChange”イベントを使うと、ジョグシャトルみたいな謎の入力インタフェースもかんたんにnodeらしくイベント駆動で使えて便利。

0

node.jsとarduinoでロータリーエンコーダー

ロータリーエンコーダー

2相出力のふつうの秋月で200円で売ってるやつを使った


マウスのホイールなどの中にも入っているセンサーで、上のツマミの部分を回すと両端の2つのピンからon-on・on-off・off-on・off-offの4状態を送ってくる。
中央のピンに5V入れて、両端の出力ピンは10kΩの抵抗でGNDにプルダウンしてArduinoのデジタルIOピンに入れた。

以前にも使ったことある。


プログラム

nodeとarduino-firmata npmでarduinoを制御した


こういうRotaryEncoderクラスを作った。回転させると”rotate”イベントを発行してくれる。

RotaryEncoder.coffee
events = require 'eventemitter2'
ArduinoFirmata = require 'arduino-firmata'

module.exports = class RotaryEncoder extends events.EventEmitter2
constructor: (@arduino, @pinA, @pinB) ->
console.log "set rotary encoder pin : #{@pinA} and #{@pinB}"
@state = 0

if @arduino.isOpen()
@initPins()

@arduino.on 'connect', =>
@initPins()

@arduino.on 'digitalChange', (e) =>
@pastState = @state
@state = @getState()
if (@state+3+1)%3 is @pastState
@emit 'rotate', 'right'
else if (@state+3-1)%3 is @pastState
@emit 'rotate', 'left'

initPins: ->
@arduino.pinMode @pinA, ArduinoFirmata.INPUT
@arduino.pinMode @pinB, ArduinoFirmata.INPUT

getState: ->
if @arduino.digitalRead @pinA
if @arduino.digitalRead @pinB
return 2
else
return 0
else
if @arduino.digitalRead @pinB
return 1
else
return 3


使う
path = require 'path'
ArduinoFirmata = require 'arduino-firmata'
RotaryEncoder = require path.resolve 'RotaryEncoder'

arduino = new ArduinoFirmata().connect()
rotenc = new RotaryEncoder arduino, 4, 3 ## digital pin 4,3を使う

rotenc.on 'rotate', (direction) ->
console.log "#{direction}に回った"

arduino-firmata npmはデジタルIOピンの状態が変化した時に発行してくれる、on “digitalChange”イベントがあるのでこういうハードウェアも簡単にイベント駆動で扱える。