2016/09/27

Arduinoっぽいコーディングを調べる

Arduinoライブラリを作ることになったが、そもそもArduinoをあまり使ったことが無い。
どういうルールで書くとそれっぽくなるのだろう?

 

Arduino - StyleGuide
Arduino - APIStyleGuide
短いけど、読みづらい。。。。
幸い、日本語で訳している人のページがあった。
他のライブラリを見た調査もあって、ありがたい。

Arduinoのコーディングルールと命名規則を調べてみた - Qiita
「個人的にあまり納得のいかないルールもあった」ということだが、どれどれ。。。

ああ、なるほど。
ちょっと、すっきりしないな。。。
まあ、C/C++言語ではなく「Arduinoで使う言語」と割り切るのがよいだろう。

 

整数型の型として、uint32_tのようなものではなく、unsigned longなどを使うよう推奨している。
間違えそうなので、メモ。

整数型以外は省略する。

普通のGCCを使っているようなので、uint32_tなども使うことはできる。
が、推奨はしていないので、少なくともAPIとしては使わない方が良いだろう。

 

また、引数でポインタを取るくらいだったら配列で指定するよう推奨している。

int getName(char *pName)  -> int getName(char[] pName)

配列を引数に取る関数って、そういえば書いたことなかったな。。。
どっちにせよ、C言語としては値渡ししかないので、アドレス値が渡されるだけのことだ。

だまされたっ!

int getName(char *pName)  -> int getName(char pName[])

C/C++なんだから、配列の括弧は名前の後ろじゃ。
公式サイトが間違っているのだけど、なんでこのままになってるんだろう?
実はみんな、普通にポインタで渡してるんじゃないのか??

 

あれ、ということは、参照でもらうのはよろしくないということかい。。。


気になっていることとして、文字列をどう扱うのがよいか、というものがある。
char配列がよいのか、std::stringがよいのか。。

Arduinoのリファレンスページを見ると、「string」と「String」があった。
stringは型ではなくて、char配列を指していた。
Stringはclassで、あるバージョンから使えるようになったらしい。

 

char配列の方は、普通のchar配列のようだ。
でも、一番下にあるExamplesで、

char* myStrings[]={"This is string 1", "This is string 2", "This is string 3", "This is string 4", "This is string 5","This is string 6"};

となっていた。
"文字列"のところは文字列定数だから、const型なのだけど、const無しで受けている。
g++でコンパイルしてみると「deprecated conversion from string constant to 'char*'」の警告が出る。
いくらC言語初心者でも扱えるようにとはいえ、あまりよろしくないと思う。
「お、char型だから書き換えられるやん」、と思って変更すると、ROM領域へのアクセスになるから、何も起こらないか、不正アドレス操作で死んでしまうか、そういう期待しないことになるだろう。

 

一方のString型だが、c_str()があるなどstd::stringっぽい。
新しく作ったということは、こっちを使ってほしいのだろうか?

いや、今回ね、APIから文字列を返すことになるかもしれないのだ。
一時的な文字列だったらライブラリで文字列のメモリを持ちたくないので、戻り値ではなく引数で受け渡しすることを考えていたのだ。
その際に、char配列がよいのか、Stringオブジェクトを参照でもらうのがよいのか、迷いがある。

中身をもらう必要は無いので、コピー渡しにはしたくない。
だから、ポインタか参照で考えていたのだけど、Arduinoで参照型を使っている例があるのかなあ。

それに、私のルールでは、constの参照渡しはするけれども、値を書き換える場合はポインタで渡すようにしていたのだ。
見分けが付きにくいから、というだけの理由だが。
C#みたいにoutとかあるといいんだけどね。

 

うーん、もう少し悩んでみます。

2016/09/26

Arduinoのライブラリを作る

お仕事でArduinoのライブラリを作ることになった。
作る内容はさておき、そもそもどうやってつくるんじゃ?というところを調べておこう。
仕事の内容はネタにできないが、こういう一般的なものであればネタにできるのだよ。


いま(2016/09/26時点)のArduino IDEは、v1.6.12のようだ。
Web Editorというものもあるようだが、IDEでやる。
私はWindows10を使っているので、以下もWindows版についてとなる。

 

IDEでスケッチを作ると、拡張子は.inoになるが、ライブラリは普通のC++形式で作ればよいようだ。
ちなみに、IDEでcppやhを読もうとすると怒られる。

image

テキストエディタで作って、サンプルだけIDEで作ってビルドすることになるか。
ライブラリだからと言って.aとかにするわけではなく、ソース提供するだけになるみたいだ。

 

作る場所は、どこがよいか。
How to write libraries for the Arduino?」では「hardware\libraries」に置きそうなことを書いてあるが、そういうフォルダはない。
だいたい、XPとか書いてあるので、ずいぶん前のことじゃなかろうか。。。

Program Filesに置くものでも無いので、スケッチを置くフォルダが妥当だろう。
最初から「libraries」というフォルダはあるのだが、これはライブラリをインストールしたら配置されるようだ。
ただ、これもIDEがv1.0.5となっているから、古い可能性がある。
試しておくか。

 

まず、librariesフォルダの中に「hiro99ma」というフォルダを作り、Arduino IDEを起動する。
うん、「スケッチ>ライブラリをインクルード」には出てこない。

image

では、この中に「hiro99ma.h」という空ファイルを置いて、IDEを再起動する。
出てきた。

image

「インクルード」だから、ヘッダファイルだけあればよいということか。
選択しても、スケッチの先頭にincludeされるだけのようだ。


では、中身がないうちに、ビルドするexamplesスケッチも用意しておこう。

Arduinoがインストールされるフォルダの中にあるlibraries(うちでは「C:\Program Files (x86)\Arduino\libraries」)には、IDEインストール時に提供されたインクルードできるライブラリが入っているようだ。

見てみると、だいたいがライブラリ名のフォルダの中に、以下が置かれていた。

  • examplesフォルダ
  • srcフォルダ
  • keywords.txt
  • library.properties
  • README.adoc

srcがなく直下に置いてあるもあるし、README.adocじゃなくてreadme.mdのもあったが、まあ傾向としてはこうなっていた。

では、先ほどの「hiro99ma.h」も、srcフォルダを作って移動させて、インクルードする一覧に出てくるかやっておく。
・・・出てこない。
これはちょっと、IDEがよくないと思うが、どうだろうか。

ひとまず、srcフォルダは作らず、直下にソースファイルを置いていく。


こういう構成にした。
examplesにtest1フォルダを作り、その中にtest1.inoというビルド用スケッチを置いた。
hiro99ma.hとhiro99ma.cppは、hiro99maフォルダの中に置いている。

image

順番に、hiro99ma.h、hiro99ma.cpp、test1.inoの内容。


#ifndef HIRO99MA_H__
#define HIRO99MA_H__

class hiro99ma {
public:
    hiro99ma();
    virtual ~hiro99ma() {}

    void hello();
};

#endif /* HIRO99MA_H__ */


#include <Arduino.h>
#include "hiro99ma.h"

hiro99ma::hiro99ma()
{
}

void hiro99ma::hello()
{
}


#include <hiro99ma.h>

void setup() {
  // put your setup code here, to run once:
  hiro99ma h9m;
  h9m.hello();
}

void loop() {
  // put your main code here, to run repeatedly:

}


この内容でIDEの「検証」を行うと、エラーは発生しなかった。
試しにhiro99ma.cppを抜いてみると、ちゃんとエラーが発生したので、ビルドしているようだ。

ただ、IDEでtest1.inoを変更して保存しようとすると、書込禁止扱いになってしまった。
テキストエディタでは編集できるし、ファイルの属性も問題なさそうなので、libraries以下にあるものは書込禁止扱いにしているのかもしれない。

また、もしかしたらcppファイルはsrcフォルダに置いてもビルドしてくれるのではないか、と期待したが、ダメだった。
では、zipファイルに固めたらいけるんじゃなかろうか?

単純にzipにすると、まずライブラリとして受け入れてくれなかった。
library.propertiesファイルを置いて、適当に埋めると、インストールに成功した。
見え方は、さっきのインクルードと同じ。
ちゃんと、librariesフォルダに「hiro99ma」が展開されていた(zipインストール前に作っていたフォルダは消しておいたので、新たにインストールされたものだ)。

zipはこういう構成で、Windows標準のZIP圧縮で固めただけだ。

hiro99ma
│  library.properties

├─examples
│  └─test1
│          test1.ino

└─src
        hiro99ma.cpp
        hiro99ma.h

ちゃんとexamples\test1も「ファイル>スケッチの例」に入っていた。
ビルドすると、library.propertiesのcategoryを適当に書いたため警告が出たが、エラーは出なかった。


あれ、じゃあ、library.propertiesを置いておけば、zipじゃなくてlibrariesフォルダに置いておいてもsrcにCPPファイルを置いておけたんじゃないだろうか?

だめだ・・・。
インクルードできるライブラリの一覧に出てこない。

あまり納得できんが、zipでインストールしたときだけsrcフォルダが有効になると言うことと覚えておくことにする。

2016/09/25

[nrf52]Secure DFU Bootloaderを試す (2)

みんな忘れていたと思うし、私も忘れていたが、前回の続きだ。
体調がよいときに書いておかねば。。

今は、SoftDevice S132 の v3.0.0が焼かれている(nRF5 SDK v12に入っていたもの)。
nRFgo Studio v1.21.2ではまだバージョンが出てこないようだ。

image

(今気付いたが、SDKに入っているビルド済みHEXファイルは、SoftDeviceも含んだ形なんだな。)

 

examplesのBLE Secure DFU Bootloaderをgccでビルドするのと、DFUで送るZIPファイルを作成しようとするまでが前回だった。

まずは、ZIPファイルの作成を行う。
公開鍵はブートローダに埋め込んであるので、指定する秘密鍵もそれに対応するものでないとダメだろう。
が、秘密鍵と思われる情報がSDKに入っていないので、自分で作るのは無理そうだ。
自分で秘密鍵から作るのは後にして、examples/dfu/ble_dfu_send_hexに入っているファイルを使おう。
名前からすると、HRMサンプルのようだ。


では、ファイルは準備できたので焼いていこう。

まずは、ブートローダをnRF52832に焼く。
これはnRFgo Studioを使う。
タブの一番右が「Program Bootloader」なので、それでよいだろう。

image

以前のブートローダと同じく、一番後ろに配置された。

 

次に、ZIPファイルをスマートフォン側に置く。
dfu_test_app_hrm_s132.zipを使うことにした。
うちはAndroidで、nRF Connectをインストール済みだ。

 

nRF52832をリセットしてやると、ブートローダが見える。

image

CONNECT。

image

右上のDFUをタップ。

image

ZIPでOKし、置いたZIPファイルを選択。

image

うまくいった。

が、これだと何だかわからないので、普通にZIPファイルを作った場合もやっておこう。

> nrfutil pkg generate --application nrf52のHRSサンプル.hex test.zip

"--key-fileが無い"と怒られた。
そして、以前のdfu genpkgは無くなっているようだ。
しょうがないので、nRFgo Studioの中に入っているnrfutilを使って作成。

あー、そしてちゃんとしたapplicationが焼かれているとブートローダは動かないので、ボタン4を押しながら起動しないといかん。
BUTTON_4は16になっているので、GPIO16とGNDをスイッチで接続(内部でプルアップされてるはず)。

ボタンを押しながらnRF52を起動するとDfuTargが見えるので、同じ手順でDFUを実行。
そうすると、グラフの画面までは進むのだが、すぐに切断されて終わった。
うん、まあうまくいったというか、うまく失敗したと思ってよいのかな。


では、自分で秘密鍵を作るところからやってみよう。
書いてあるとおりにやる。

$ nrfutil keys generate priv.pem
Generated private key and stored it in: priv.pem
$ nrfutil keys display --key pk --format code ./priv.pem --out_file dfu_public_key.c
$

できたdfu_public_key.cをオリジナルと置き換えてmake。

できたpriv.pemを使って、HRSサンプルのZIPを作成。

$ nrfutil pkg generate --application nrf52832_xxaa.hex --key-file priv.pem test2.zip
Error: --hw-version required.

まだダメらしい。
表では例として52とあったので、nRF52の52なのか。
ただ、これを指定しても、--sd-reqと--application-versionが要求された。

$ nrfutil pkg generate --application nrf52832_xxaa.hex --key-file ../priv.pem --hw-version 52 --sd-req 0x8c --application-version 0xff test2.zip
Zip created at test2.zip

0xffにするとスキップされるようだが、--sd-reqはよくわからん。
nRFgoで表示されたFirmwareのIdが0x008cだったので、そうしてみた。

これでブートローダを焼いてやってみると・・・だめだった。
さっきと同じで、すぐに切断されてしまった。
ちゃんと読もう。

・・・うん、どうもブートローダをpca10040_debugの方でビルドしたのがよくなかったようだ。
ifdefでNRF_DFU_DEBUG_VERSIONを見ているようで、先ほど置き換えたdfu_public_key.cも、おそらくifdefで分けられていた。
ソースの方でも使っていたので、何かあるのだろう。

ともかく、ブートローダをpca10040の方でビルドして焼き直すと、作ったZIPファイルでDFUできた。
examplesに入っていたZIPファイルを指定すると、ちゃんと失敗するので、うまくいっているのだろう。

[ble]Secure Gateway Kit

Windows10 64bit環境に、Secure Gateway Kitをインストールして動かした。

  • Bluetoothドングル : Planex BT-Micro4
  • Node.js : v4.5.0のwin-x64
  • Visual Studio 2015 (Community?)
  • Python 2.7

VSとPythonはインストール済み。
zadigも既にある。

 

Node.jsを適当に解凍。

管理者権限でコマンドプロンプトを開いて、Node.jsにパスを通し、インストール

> npm install --global --production windows-build-tools

ScriptAndSourceCodeでコマンドプロンプトを開いて、Node.jsにパスを通し、インストール

> npm install bluetooth-hci-socket
> npm install -g node-gyp
> npm install noble

Node.jsをよく知らないのだが、npm installはコマンドプロンプトと同じ場所にインストールするのかな。
「node_modules」というフォルダができていた。

そして、ScriptAndSourceCode/gatewayで管理者権限のコマンドプロンプトを開き、インストール。

> npm install

別の管理者権限のコマンドプロンプトをScriptAndSourceCode/navibleで開き、インストール。

> npm install

そして、それぞれのコマンドプロンプトで開始させる。

> npm start

そうすると、navibleの方にアクセスするURLが出てくるので、ブラウザで開く。
ユーザ名とパスワードを訊かれるので、とりあえず両方に「user1」を打ち込むと、こういう画面が表示された。

image

赤いところにはMACアドレスが表示されている(たぶん、お隣さんのデバイスだと思うので隠した)。
nRF52を起動させて、右上の「Scan」を押すと、少しぐるぐる回るアニメーションが出た後、更新された。

image

 

Nordic_BDSをクリックすると、詳細画面に遷移した。
横幅を狭くするとレイアウトが崩れるので、ほどほどに広くしたほうがよい。

image

Connectをクリックすると、ちゃんと接続された。

image

一番下が自作のServiceなのでクリックすると、展開される。
レイアウトが、どうやっても崩れてしまう。。。
Firefoxだからかと思ってChromeに変更してみたが、同じだ。

image

また、ReadやWriteしても、うまく行かなかった。
でも、Generic AccessのDevice Nameは読めたので、なんかあるのか、単にnRF52に焼いているソフトが変なのか。。。

 

nRF52にHRSサンプルを焼いたが、うーん、やはり動きがあやしい。

値の表示を「string/hex/byte」で切り替えられるのだけど、うまく切り替わらないことがある。
たとえば、Generic AccessのAppearanceをstringでReadすると「A」と表示され、hexにすると「41 03」、byteにすると「65, 3」になるのだけど、最初から「hex」でReadしても「A」なのだ。
ここは、Readした後で切り替えるもの、と思っていた方がよい。

Notificationの有効化はうまくいくようだ。
Heat Rate MeasurementのNotifyにチェックすると、ぱらぱらと値が変わっていた。

しかし、しばらく接続していると急に切断されるようだ。
ブラウザは接続中のままなので、HCIとかそっち側かもしれない。

使えるかと思ったが、うーん、ちょっと微妙な感じだ。
BT-Micro4以外で試せないので、他ので試すとうまくいく、というパターンかもしれない。
サポートしているUSBドングルは、これらとのこと(BT-Micro4は、CSR8510 A10として見えていた)。

develop with blue

Bluetooth SIGに「新機能!」という項目があったので見ていた。
毎日見ているわけではないので、ずいぶん前からあったのかもしれない。。

https://www.bluetooth.com/develop-with-bluetooth/developer-resources-tools

最初に開くと日本語ページだったのだが、サイトの上からEnglishを選んだ方がよい。

「develop with blue」になって、Starter Kitやら、Secure Gateway Kitやらがあった。
いつの間に。

 

Starter Kit

これは、Arduino 101というものらしい。
検索すると、ずいぶん前からあったようだ。
スイッチサイエンスさんにもあった。
アメリカでは"Arduino"で、それ以外の国では"Genuino"だそうだ。
3.3Vというのが、よいですな。

Application Accelarator2.1やBeacon Smarter Kitもあるが、これはこのStarter Kitに対して使うもののようだ。
Accelarator2.1だけダウンロードしたのだけど、Bluetooth Developer Studioのようなものではなく、サンプルソースが入っているだけのようなのだ。
まあそれでも、Windows10でのBLEアプリは作り方を知らなかったので役に立ちそうだ。

 

Secure Gateway Kit

こちらは何も書いていないので、仕方なくダウンロードした。
名前とメールアドレスを入れるだけなのだが、その手間がめんどくさい。。。

解凍すると、PDFとJavaScriptたちが見えた。
どうやら、Raspberry Pi(2 or 3)のBluezとNode.jsをインストールして使うようだ。
こちらはBluetoothSecureGateway-HandsOnLab.pdfに載っていた図だ。

image

PDFの後ろの方に、Windowsにインストールする場合について書かれていた。
zadigを使わせるなど、なかなか楽しいやり方みたいだ。
Node.jsは普通にインストールさせているから、Bluezが使えない分をまかなっているようだ。

ということは、Raspberry Piじゃなくても、Linux系だったらそのまま使えるのだろう。
BluezとNode.jsが動けばよいのかな。

 

中身を余り見ていないのだが、CC2650 SensorTagの管理画面がブラウザで見えているから、BLE peripheralを登録して管理できるのだろうか。
GatewayがPeripheralたちとの仲立ちをして、Explorerで管理、というやりかたか。

図のSecure CommunicationとUnsecure Communicationは、単にペアリングのことを指しているような感じがする。
ただ、Secure Pairingと書いてあるし、BLE Legacyも別に書いてあるので、Core v4.2で追加された"LE Secure Connections"もちゃんと扱えるよ、ということかもしれない。


うちには、PlanexのBT-Micro4というドングルがあるのだが、これでもv4.2がいけるのだろうか。
ドングルってプロトコルスタックを自分で持ってないような気がするので、もしそうならソフト側だけ変更するといけるんじゃなかろうか。

うちのデスクトップPCはBLE開発はできるものの、BLE通信についてはnRF51やTIのドングルを使って読み取るくらいしかやっていないので、使えるのであればありがたいのだ。