nrf51 で SWDIO がピンリセットとして認識される
SWD経由で書き込んでちゃんと動いて、電源入れ直すと動かなくなってハマった…。VINとGNDのみの配線なら動いてるので、一つ一つ確認するとSWDIOのピンがGND(かLOW)の時に起動せず、HIGHかオープンな時に起動することが解った。
nrf はSWD書き込み直後の起動はdebug mode といわれるモードで起動するらしく、この場合はSWDIOがresetとならない。
- SWDIO/nRESET pin "debug mode" - Nordic Developer Zone
- BLE Nano (nRF51822) でどうしても 1mA 以上電流食うぞというとき | tech - 氾濫原
- のエントリーの下の方参考
なので書き込み直後は動くが、再度電源を入れ直すとSWDIOがLOWに落ちているため、延々と起動しない、ということになる。ちゃんと動かすためには、SWDIOで書き込んでいないときはHIGHにし、書き込み時には繋がないといった回路が必要。
とりあえず開発時でリセットピンを使わない時には
NRF_POWER->RESET = 0;
にセットしておくことで、リセット機能を無効化して起動してる。
nrf51 のファームウェアから SoftDevice を切り離す
mbed 環境でコンパイルすると、現在S130のSoftDeviceが結合されて作成される。SoftDevice は一度書き込めば再度書き込む必要が無く、分離することでSoftDevice書き込みを省略し、高速に書き込める。
nRF51_OTA_strip.py を使う
- https://developer.mbed.org/users/jbru/code/intelhex-tools/file/5a3618245257/nRF51_OTA_strip.py
- https://lowreal.net/2016/08/26/2
なお、shabang が #/usr/bin/env python3
になってるので注意(正しくは #!/usr/bin/env python3
)。最初 +x して実行したらエラーであれとなった。
nRF51/nRF52 DK を J-Link のライタとして使う
nRF51-DK や nRF52-DK (Preview含む) から J-Link を使って SWD で書き込む。具体的な方法は
のページに書かれているとおり。P20の八本のインターフェイスから書き込める。
MicroUSB に近い方から
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 が認識されればすぐに表示されて解りやすいので、最初はこちらを使うのが良いかも知れない。
というわけで無事ターゲットの 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 を取得する
以前は firmware が github 上で公開されていたようだが、今は三つの方法で取得する。
クラウド上でのビルド
で、必要なモジュールをチェックすると、ビルド終了時メールにて 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 の書き込み
- https://nodemcu.readthedocs.io/en/master/en/flash/
- https://learn.adafruit.com/building-and-running-micropython-on-the-esp8266/flash-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にのってる。
- https://www.pine64.org/?page_id=917
- http://files.pine64.org/doc/PADI/documentation/padi-iot-stamp-datasheet.pdf
- SoC: RL8710AF
- CPU: ARM Cortex-M3 (83MHz)
- ROM: 1MB
- RAM: 512KB
- FLASH: 1MB
- WiFi: 802.11b : 11 Mbps , 802.11g : 54 Mbps , 802.11n : 150 Mbps
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判定低そうなんだけど、こんな物なのかなー。
消費電力
- 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 とよばれる、Realtek の SDK を使う。以前は 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
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かつハードウェア暗号化が可能だからね)