nrf51 で SWDIO がピンリセットとして認識される

SWD経由で書き込んでちゃんと動いて、電源入れ直すと動かなくなってハマった…。VINとGNDのみの配線なら動いてるので、一つ一つ確認するとSWDIOのピンがGND(かLOW)の時に起動せず、HIGHかオープンな時に起動することが解った。

nrf はSWD書き込み直後の起動はdebug mode といわれるモードで起動するらしく、この場合はSWDIOがresetとならない。

なので書き込み直後は動くが、再度電源を入れ直すとSWDIOがLOWに落ちているため、延々と起動しない、ということになる。ちゃんと動かすためには、SWDIOで書き込んでいないときはHIGHにし、書き込み時には繋がないといった回路が必要。

とりあえず開発時でリセットピンを使わない時には

NRF_POWER->RESET = 0;

にセットしておくことで、リセット機能を無効化して起動してる。

nrf51 のファームウェアから SoftDevice を切り離す

mbed 環境でコンパイルすると、現在S130のSoftDeviceが結合されて作成される。SoftDevice は一度書き込めば再度書き込む必要が無く、分離することでSoftDevice書き込みを省略し、高速に書き込める。

nRF51_OTA_strip.py を使う

なお、shabang が #/usr/bin/env python3 になってるので注意(正しくは #!/usr/bin/env python3 )。最初 +x して実行したらエラーであれとなった。

nRF51/nRF52 DK を J-Link のライタとして使う

nRF51-DK や nRF52-DK (Preview含む) から J-Link を使って SWD で書き込む。具体的な方法は

のページに書かれているとおり。P20の八本のインターフェイスから書き込める。

f:id:secondlife:20140929140538j:plain

MicroUSB に近い方から

  • http://doc.lijun.li/misc-use-nrf51-dk-debug-out.html

  • VDD_nRF(電源を nRF5x からとる場合は 3 と一緒に)

  • VIO
  • SH_VTG (必須、ターゲットの電源電圧)
  • SH_SWDIO (必須、データ入出力)
  • SH_SWDCLK (必須、クロック)
  • SH_SWO
  • SH_RESET
  • SH_GND_DETECT (必須、ターゲットの GND )

となっている。書き込みに必要なのは最低4本でOK。なお開発時 nRF5n-DK から電源を取る場合は1も3と同じ場所に繋ぎ、かつnRF5n-DK側のGNDも8(というかターゲットのGND)に繋ぐ必要がある。最初繋がず、プログラム書き込みは出来るけど書き込み先の nRF がうまく動かずハマった…。

JLinkExe から書き込む

から JLinkExe のバイナリを落とし書き込む。JLinkExe が対話型インターフェイスかつ複雑なので、ラッパの AdaLink を使うと何も考えずに JLinkExe のパスさえ通ってれば使える。

$ adalink -v nrf51822 --programmer jlink --wipe --program-hex  firmware.hex

nRFgo Studio から書き込む

noridc が提供してるツール、nRFgo Studio は GUI から書き込むことが出来る。かつ、書き込み先の nrf が認識されればすぐに表示されて解りやすいので、最初はこちらを使うのが良いかも知れない。

f:id:secondlife:20160920173829p:plain

というわけで無事ターゲットの nRF51 に書き込むことが出来た。(写真は RedBear Nano)

USB の Serial Number を調べる

Linux の場合

差すと dmesg に出るので調べる

$ dmesg | grep SerialNumber
...
[351921.174389] usb 1-2: SerialNumber: 5CF37074...

Windows の場合

USBDevice を使う。

差した順にソート等もできるので使いやすく便利。

VirtualBox で同一のUSB機器の片方を自動デバイス認識させたかったので、シリアルナンバーが知りたかった。具体的には同じ BT レシーバ二つ持ってるので、片方だけは VirtualBox の GuestOS へスルーさせたかった。

ESP8266 上で Lua インタプリタが動くファームウェア、NodeMCU を使う

NodeMCU は、Node.js のように非同期でイベントドリブンなコードを書く事が出来る、ネットワークを利用する ESP8266 とは相性が良い開発環境(ファームウェア)。Lua インタプリタが動くので、マイコン上でプログラムを動的に実行できる。また NodeMCU 用のハードウェアも売っているが、ESP8266 シリーズならどれでも動く(もちろんESP-WROOM-02もね!)。NodeMCU という名前がわかりにくいので、名前で損してる感ある…。

また40個以上のモジュールがすでに本家に入っていたり、SSLにも対応していたり、コードが綺麗だったりと、なにやら良さそうなプロジェクトな予感がする。

firmware を取得する

以前は firmwaregithub 上で公開されていたようだが、今は三つの方法で取得する。

クラウド上でのビルド

で、必要なモジュールをチェックすると、ビルド終了時メールにて firmware の URL が送られてくる。

普通はこれを使えばOK。

Docker を使ったビルド

ESP8266 の xtensa のツールチェインをビルドするのは面倒くさい、という人に。

Linux 上でのビルド

ソースから普通にビルドする。Ubuntu 16.04 LTS環境で簡単にできた。

まずは esp nonos

コンパイルする。ドキュメント通りでおk。なお esp8266/Arduino の為に入れていた xtensa のバイナリツールチェインではうまく動かず、新たにコンパイルした。

sudo apt-get install make unrar autoconf automake libtool gcc g++ gperf \
    flex bison texinfo gawk ncurses-dev libexpat-dev python-dev python python-serial \
    sed git unzip bash help2man wget bzip2
sudo apt-get install libtool-bin

これでビルドに必要なパッケージが全部入るのであとは make してしばらく待つ。単体動作するtoolchain 群をコンパイルしてるので遅い。

Xtensa toolchain is built, to use it:

export PATH=$HOME/src/github.com/pfalcon/esp-open-sdk/xtensa-lx106-elf/bin:$PATH

Espressif ESP8266 SDK is installed, its libraries and headers are merged with the toolchain

と書かれてるように、xtensa-* にパスを必要に応じて通す。続いて

https://github.com/nodemcu/nodemcu-firmware

を make すると bin 以下に 0x00000.bin, 0x00001.bin ができあがるので、それを利用する。なお

app/.output/eagle/debug/image/eagle.app.v6.out

に bin ファイル分割前の ELF バイナリができあがってる。

[7]>_<X file app/.output/eagle/debug/image/eagle.app.v6.out
app/.output/eagle/debug/image/eagle.app.v6.out: ELF 32-bit LSB executable, Tensilica Xtensa, version 1 (SYSV), statically linked, not stripped
[7]>_<X xtensa-lx106-elf-size app/.output/eagle/debug/image/eagle.app.v6.out
   text    data     bss     dec     hex filename
 380472    2196   27512  410180   64244 app/.output/eagle/debug/image/eagle.app.v6.out

プログラムサイズは400KB弱(Arduinoは220KB)だけど、利用RAMが初期値で30KB(Arduinoは32KBほど)で、空きRAMが50KBもあるとは、大分コンパクトだなぁ。

なお、app/include/*config*.h を編集する(もしくは適当な環境変数をつけてコンパイルする)ことで、様々な値を変更することが出来る。

また必要な組み込みライブラリは app/include/user_modules.hコメントアウトを適宜編集することで組み込める。組み込むことによってもちろんプログラムサイズは増えるので注意。

firmware の書き込み

あたりに CUI のesptool.py を使った方法、GUI の NodeMCU Flasher を使った方法などなどがのってる。

ただ、前述の Linux 上に firmware のビルド環境を用意した場合

$ make flash
make -C ./app flash
make[1]: Entering directory '/home/yuichi/src/github.com/nodemcu/nodemcu-firmware/app'
../tools/esptool.py --port /dev/ttyUSB0 write_flash 0x00000 ../bin/0x00000.bin 0x10000 ../bin/0x10000.bin
esptool.py v1.2-dev
Connecting...
Running Cesanta flasher stub...
Flash params set to 0x0000
Writing 28672 @ 0x0... 28672 (100 %)
Wrote 28672 bytes at 0x0 in 2.5 seconds (91.8 kbit/s)...
Writing 356352 @ 0x10000... 356352 (100 %)
Wrote 356352 bytes at 0x10000 in 30.9 seconds (92.2 kbit/s)...
Leaving...
make[1]: Leaving directory '/home/yuichi/src/github.com/nodemcu/nodemcu-firmware/app'

で一発。なお esptool.py は --baud オプションをつけないと 115200 で転送するので、Makefile をちょっと修正して --baud 921600 をつけて転送するとあからさまに速い。この速度で転送できるかどうかはチップによるけど。

$ make flash
...
Writing 28672 @ 0x0... 28672 (100 %)
Wrote 28672 bytes at 0x0 in 0.5 seconds (449.4 kbit/s)...
Writing 356352 @ 0x10000... 356352 (100 %)
Wrote 356352 bytes at 0x10000 in 4.8 seconds (591.5 kbit/s)...
...

Hello World!

シリアルコンソールで繋いで Hello World! してみる。標準だとシリアルの baudrate は 115200 なのでそれにあわせる。

$ platformio device monitor -b 115200
--- Miniterm on /dev/ttyUSB0  115200,8,N,1 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
r␘␂␀l��r�␀�#␂�n�␄��␌␘�␌␜��␜p�<���␀�8␂��ǒ��␜p␌␘␌�nn�␂�;�nĒ��␌␛�␌b�$�r␘␂r␘␂p�n��܀␌␜���l␜�␌␜�␌␜�␌b�␄n��n��␎�l�ߌ�8␌␘��nn�␃����␀l`␛��␒�#�n�␄␏r␘␂␎␂nr���;␂��␌?��␜r␘␂p�n��܀␌␜�r�␜��␛␂␌␜�␌␜p␌␘p��<␂��l␜�␌␟p␌␘��nn�␃��␌␘r␘␂�␒�#�n�$��l`␛�`rn|��n�␄��␒�␜�`␛␄�~␂��␌␘�␒�#�n�$��␌␘��nn�␃��l`␛␄nn��܀␌␜�r�␜��␛␂␌␟��8p␌␘p��<␂��␌b�ľ~�n�␃���␜␀l`␛␄�␃␒n�␂��l`␛�`rn|��n�␄���␄�`␛与��;␂��␌?␒b�;�␂���␀�8␂�n��␒r���n�b␌␘�␌␜�l␟r␘␂����I8��␜�␛ ��

NodeMCU 1.5.4.1 build unspecified powered by Lua 5.1.4 on SDK 1.5.4.1(39cb9a32)
lua: cannot open init.lua

最初のスタートアップファイル、init.lua が無いと言われるけど、問題なく繋げる。文字化けしてるのは ESP8266 起動時のメッセージ(baudrate が違うから)だけど無視して問題ない。

> print("Hello World!")
Hello World!

おおお。マイコン上でインタプリタが動くと地味に感動するね。

インタプリタ接続時のヒープの空き容量は

> print(node.heap())
45056

で、44KBほど。それなりにプログラミングできそう。

コードをアップロードして実行

行実行ではなく、書いたソースコードを実行したい。

Java で書かれた IDE、ESPlorer や CUI の nodemcu-uploader を使っての方法が書かれている。

ESPlorer の場合

> file.remove("hello.lua");
> file.open("hello.lua","w+");
> w = file.writelinew([==[print("hello NodeMCU!")]==]);
> file.close();

とエディタ上の文字列をシリアルコンソール経由で書き込んで(!)ファイルとして保存する。その後

> dofile('hello.lua')
hello NodeMCU!

で実行してる。

ちなみに ESPlorer、左がエディタ、右がシリアルコンソールになっていて、すぐ実行結果を見たり、ボタン一つで heap の容量が見れたりと、結構良く出来ている。

nodemcu-uploader

nodemcu-uploader は recv() / send() コマンドの後に、ACK しつつ送信、という一般的なシリアルアップロードの方法でファイルを書き込む。pip でインストールできるので、すぐ使うことが出来る。

に利用方法が載ってるが、

nodemcu-uploader upload hello.lua --do

で転送してそのままファイルを実行したり、

nodemcu-uploader upload *.lua --compile

コンパイルして .lc ファイルにした後アップロードしたりできる。

Lチカする

さて、やっとLチカ…。NodeMCU は冒頭の通り、Node.js のようなイベントドリブンのアーキテクチャを採用しており、メインループを回すのではなく、イベントモデルで実行する。

LED_PIN = 2
gpio.mode(LED_PIN, gpio.OUTPUT)
ledState = gpio.HIGH
gpio.write(LED_PIN, ledState)

toggleLED = function()
  if ledState == gpio.HIGH then
    ledState = gpio.LOW
  else
    ledState = gpio.HIGH
  end
  gpio.write(LED_PIN, ledState)
end

tmr.alarm(0, 1000, tmr.ALARM_SEMI, toggleLED)

タイマー0に関数をセットし、1秒おきに実行することで Lチカを実現している。

もちろん、このLチカが動いているときに、hello world! を再度書き込んで実行しても、Lチカは止まらず実行されている。

なお、GPIO の番号が ESP8266 の pin と NodeMCU では違うので注意。例えば ESP8266 で IO4 のピンは NodeMCU では 2 となる。


今回はLチカまで。触ってみた感じ、やはり良く出来るてる感がある。あとはネットワーク周りと、実アプリケーションを作ったときに、はてして heap を食いつぶさずに作れるのかどうか。

EPS8266 の MQTT subscriber ライブラリ

ESP8266 から MQTT で~、という記事、大体データを publish することしか書かれて無くて、subscribe することについては触れられていることがほとんど無い。というわけで色々試してみたのでメモ。

SSL が必要か

接続でSSLが必要な場合、esp_mqttぐらいしかない。

GitHub - tuanpmt/esp_mqtt: MQTT client library for ESP8266

これを手軽に Arduino で使おうとすると、

GitHub - i-n-g-o/esp-mqtt-arduino

をあわせて使うことになるんだけど、こちらのライブラリが怪しい & セキュアな通信を必要としてなかったので使ってない。

SSL + Arduino 環境

の二つは切断時の再接続や再送といった挙動が不審だった。

は一ヶ月以上 subscriber を動かしているけど、特に問題なく意図した挙動で動き続けている。コードも割とシュっとかける。

mbedで開発出来るようになるかもしれない、2$のWiFi SoC、RTL8710について

NICでお馴染みの realtek 社の WiFI が使える SoC マイコン RTL8710。安価なWiFi SoC は TELEC認証通ってるESP8266あるし、そんなに興味が無かったんだけど、Tiny $2 IoT module runs FreeRTOS on Realtek Ameba WiFi SoC の記事に出ている PADI IoT Stamp というモジュールが

OS: FreeRTOS, ARM® mbed™ (future planning)

とのことで、mbed で開発出来るとなると、ちょっとしたプロトタイピングがとてもやりやすくなるので俄然興味がわいた。

PADI IoT Stamp

お値段 1.99$ (予定)

スペック

PADI のデータシートや、オフィシャルのWebにのってる。

 

RAMは

Based on current SDK SRAM usage, the usable SRAM space is more 48 KB.

とのことで、標準SDKを使うと、約48 KB の領域が利用できる模様。

電源とロジックレベルは

  • VDD: 3.3V (min 3.0-max 3.6)
    • -0.3V~0.25V が LOW、0.75~3.6V が HIGH

で、0.75V~HIGH は割とHIGH判定低そうなんだけど、こんな物なのかなー。

消費電力

  1. Power Consumption

のデータシートより。

  • Transmitting 802.11g, OFDM54Mbps, POUT= +15dBm
    • 180mA
  • Normal Standby
    • 30mA
  • Deep-Sleep
    • 10uA

WiFi 使うとまぁこれぐらいかかるか。たぶん Deep-Sleep は ESP8266 と同じで、指定時間後にリセットがかかるタイプかな。

Note 3: Deep - Sleep is applied to applications that do not require WiFi connection to be active all the time. The application only sends a packet after long time interval, such as in a measurement temperature sensor that only needs to connect every 100 seconds. For example, with the application awake 0.3 s – 1 s to connect AP after every 300 s sleep time, the overall average current consumption can be much lower than 1 mA.

見たいな使い方だと、平均 1mA ほどとのこと。

開発

まだ mbed で提供されてないので、Ameba とよばれる、RealtekSDK を使う。以前は NDA が必要だったようだけど、今は不必要のよう。sdk の zip の中身をさらっと見たら

  • arm-none-eabi-gcc ( 4.8.3-2014q1 )
  • FreeRTOS

も同梱されていた。example にもざっくり色々入ってた。

analogin_voltage gdma gpio_port i2c_epl2590_light i2s_tx_and_rx_only pm_deepstandby spi uart_clock crypto gpio gpio_pulse_measure i2c_epl2590_proximity log_uart_char_loopback pm_sleep spi_pl7223 uart_irq efuse_mtp gpio_irq gtimer i2c_LPS25HB_pressure log_uart_loopback pm_tickless spi_stream_twoboard uart_stream_dma efuse_otp gpio_jtag gtimer_rtc i2c-shtc1 log_uart_stream_loopback pwm spi_twoboard uart_stream_irq ethernet_mii gpio_level_irq i2c i2s nfc pwm-buzzer uart watchdog flash gpio_light_weight i2c_epl2197_heartrate i2s_bypass pm_deepsleep sdio_device uart_auto_flow_ctrl wlan

書き込みやデバッグは、JTAG/SWD で行う。

PADI でない開発ボード

AliExpress や ebay で RTL8710で検索すると、nodemcuぽいピン配置の RTLDUINO(CH340が載ってる?) など、いくつか見つかる。

ESPシリーズと比較して

ESP8266 はすでに技適取得済のボードがあり、また開発には Arduino 互換のAPIを備えたファームウェアがあり、開発も容易なことからエコシステムも発達している。

しかしながらESPはCPUアーキテクチャが xtensa なため、arm 関係の技術を利用することができない。

RTL8710はスペック的にはさほどESP8266シリーズとは変わらないが、アークテクチャが ARM Cortex-M3 なため、もし mbed-os を使って開発が可能になると、一気に再利用できるエコシステムが広がり、2$という価格も相まって、ESP8266よりも人気が出る可能性がある。

ただ残念なこととしては、ハードウェア暗号化チップが載っておらず、ソフトウェア側でエンコードする必要があるため、SSLをつかった通信が果たしてどれだけ現実的かどうか。2016年に出るWiFiが使えるSoCとしては、価格が上がっても載っていて欲しかったなー、と思ったりする。(ESP8266後継のESP32はESP8266に比べ価格が上がりそうとは言え、WiFi+BLEかつハードウェア暗号化が可能だからね)