STM32F103C8にArduinoのスケッチを書き込む

結局、ブートローダとか関係なくArduinoのスケッチを書き込む方法が一番簡単そうです。この方法ならブートローダの書き込みも要らないはずです。

1.環境準備

Arduino IDEを起動したら、ボードマネージャで「Arduino SAM Boards (32-bits ARM Cortex-M3) bu Arduino」をインストールします。その後、以下の手順で ~/Arduino/hartdware の下にライブラリを追加します。

~$ sudo apt install stm32flash 
~$ cd Arduino/hardware 
~/Arduino/hardware$ git clone https://github.com/rogerclarkmelbourne/Arduino_STM32

追加したら、 ~/Arduino/hardware/Arduino_STM32/tools/linux/serial_upload を修正します。

#!/bin/bash
#$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1" 
stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1" 

2行目がもとの行で、3行目が修正した行です。要は、aptでインストールしたstm32flashを使うように修正します。

完了したら、スケッチ例で Blink を開きます。Blinkを開いたら、使用するポートをPC13に書き換えます。また、ボードマネージャではボードに合わせてGeneric STM32F103C Seriesを選択します。

  • ボード : STM32F103C8またはSTM32F103CBを選択
  • Upload method : Serial
  • シリアルポート : /dev/ttyUSB0

に設定します。

2.ボード側の準備

ボード側はUSBシリアルケーブルと接続します。

  • USBシリアルのVcc ⇔ STM32F103ボードの+5V
  • USBシリアルのGND ⇔ STM32F103ボードのGND
  • USBシリアルのTX ⇔ STM32F103ボードのA10
  • USBシリアルのRX ⇔ STM32F103ボードのA9

接続したら、BOOT0のジャンパを1側にセットして、PCに接続します。電源もUSBシリアルから供給します。

3.ビルドと書き込み

ボード上のリセットスイッチを押してブートローダを待機させます。その状態で Arduino IDE の書き込みボタンをクリックします。

しばらくすると書き込みに成功してプログラムが動作を始めるはず・・・・です。

2回目以降の書き込みはリセットボタンを押してブートローダを待機させて、Arduino側で書き込み操作をすれば行けるようです。

STM32F103C8ボードのSTM32duino化

いろいろ調べたところ、どうやらブートローダーは書き換える必要があるようです。以下に手順を記録します。

1.フラッシュ書き込みツールのインストールと準備

フラッシュへの書き込みツールは以下の手順でインストールします。

$ sudo apt install stm32flash

ツールの書き込みができたら、USBシリアルケーブルと接続します。

  • USBシリアルのVcc ⇔ STM32F103ボードの+5V
  • USBシリアルのGND ⇔ STM32F103ボードのGND
  • USBシリアルのTX ⇔ STM32F103ボードのA10
  • USBシリアルのRX ⇔ STM32F103ボードのA9

接続したら、BOOT0のジャンパを1側にセットして、PCに接続します。

2.ブートローダのダウンロードと書き込み

以下の手順でブートローダをダウンロードして書き込みます。

~$ git clone https://github.com/rogerclarkmelbourne/STM32duino-bootloader
Cloning into 'STM32duino-bootloader'...
remote: Enumerating objects: 796, done.
remote: Total 796 (delta 0), reused 0 (delta 0), pack-reused 796
Receiving objects: 100% (796/796), 905.37 KiB | 1.18 MiB/s, done.
Resolving deltas: 100% (548/548), done.
~$ cd STM32duino-bootloader/
~/STM32duino-bootloader$ cd binaries/
~/STM32duino-bootloader/binaries$ sudo stm32flash -f -v -w generic_boot20_pc13.bin /dev/ttyUSB0
stm32flash 0.5

http://stm32flash.sourceforge.net/

Using Parser : Raw BINARY
Interface serial_posix: 57600 8E1
Version      : 0x22
Option 1     : 0x00
Option 2     : 0x00
Device ID    : 0x0410 (STM32F10xxx Medium-density)
- RAM        : 20KiB  (512b reserved by bootloader)
- Flash      : 128KiB (size first sector: 4x1024)
- Option RAM : 16b
- System RAM : 2KiB
Write to memory
Erasing memory
Wrote and verified address 0x08005294 (100.00%) Done.

~/STM32duino-bootloader/binaries$ 

書き込んだらPCからUSBシリアルを外して、ジャンパを戻します。

【参考】
https://ht-deko.com/arduino/stm32f103c8t6.html

ST-LINK V2 用Toolをインストール

stm32duinoでビルドが通らない件は、STM32 Cores by STMicroelectronicsのバージョンを1.6.1から1.6に落としたらビルドはできるようになりました。その後、アップデートで1.6.1にしたら今度はビルドが通ります。

・・・が、ST-LINK V2ではまだ書込みができません。(シリアルなら書けそうな気がしますが・・)

そこで、githubにあるOpenSource版のST-LINK V2用のツールをインストールしてみます。

~/$ git clone https://github.com/texane/stlink.git
~/$ cd stlink
~/stlink$ sudo apt install cmake libusb-1.0.0-dev
~/stlink$ make
~/stlink$ cd build/Release/
~/stlink/build/Release$ sudo make install
~/stlink/build/Release$ cd ../..
~/stlink$ cd etc/udev/rules.d
~/stlink/etc/udev/rules.d$ sudo cp 49-stlinkv2.rules /etc/udev/rules
~/stlink/etc/udev/rules.d$ sudo udevadm control --reload-rules
~/stlink/etc/udev/rules.d$ sudo udevadm trigge
~/stlink/etc/udev/rules.d$ ls /dev/stlink*
/dev/stlinkv2_2

でインストールすることはできました。

・・・が、arduinoは認識はしてくれないようです。

調べていくうちに、STM32F103C8をArduinoで扱う方法は少なくとも2種類あるようです。

【その1】stm32duinoで、追加のボードマネージャのパスを設定した後、ボードマネージャで「STM32 Cores by STMicroelectronics」を追加する方法。
前回の記事の方法)

【その2】ボードマネージャで「Arduino SAM Boards (32-bits ARM Cortex-M3) bu Arduino」をインストールした後、~/Arduino/hardware の下にライブラリを追加する方法。(Arduino_STM32)
https://github.com/rogerclarkmelbourne/Arduino_STM32

いずれにしても、まだうまく行きません・・・。

ST-LINK V2のバージョンアップ

ST-LINK V2のファームウェアバージョンアップはSTmicroelectronicsのサイトからSTSW-LINK007というツールをダウンロードしてきて行います。(要メールアドレス)

ダウンロードしたら、ツールを展開してUSBデバイスを認識させるための設定を行います。(別途実施してあれば不要)

~$ unzip en.stsw-link007.zip 
~$ cd stsw-link007/AllPlatforms/StlinkRulesFilesForLinux
~/stsw-link007/AllPlatforms/StlinkRulesFilesForLinux$ sudo cp 49-stlinkv2.rules /etc/udev/rules.d
~/stsw-link007/AllPlatforms/StlinkRulesFilesForLinux$ sudo udevadm control --reload-rules

その後、

~$ cd stsw-link007/AllPlatforms
~/stsw-link007/AllPlatforms$ java -jar STLinkUpgrade.jar

としてツールを起動します。

こんな感じの画面が開くので、Refresh device listやOpen in update modeをクリックして認識させます。(上記は認識させたところです)

Upgradeを押すとファームウェアをアップデートしてくれます。

STM32F103C8で遊ぼうと思ったが・・・

STM32が結構使えるよ、という話を聞いたので、しばらく前にAliexpress でSTM32F103C8が載ったボードとST-LINK V2を注文してみました。

デバッグ用?のST-LINK V2とボード2枚で送料込みで$5を切る価格だったと思います。

開発環境はとりあえず Core2 Quad 6600 + メモリ4GB + LinuxMint19 MATE 64bit にArduino環境を突っ込みます。

Arduino 1.8.9 64bit 版をホームディレクトリに展開して

~/arduino-1.8.9$ sudo ./install.sh
~/arduino-1.8.9$ ./arduino-linux-setup.sh $USER

とします。デスクトップへのショートカット作成には失敗してしまいますが、メニューには追加成功するので、そこからデスクトップにショートカットを追加しました。

Arduino IDEを起動したら、ファイル⇒環境設定で「追加のボードマネージャのURL」に

https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json

を追加したあと、ボードマネージャで「STM32 Cores by STMicroelectronics」をインストールします。

完了したら、スケッチ例で Blink を開きます。

32.768kHzのクリスタルがはじめから載っているのが嬉しい

ボードに合わせてGeneric STM32F1 Seriesを選択します。選択後、細かい設定ができるようになっていますので、以下のようにしてみました。

ST-LINK V2と基板の各端子を接続して、ST-LINK V2をPCに接続すると予め書き込まれているプログラムが起動するのか、緑のLED(PC13)が点滅します。

ここで、Blinkスケッチの LED_BUILDIN をすべて PC13 に書き換えます。

ビルドしようとすると・・・

Arduino:1.8.9 (Linux), ボード:"Generic STM32F1 series, BluePill F103C8, STM32CubeProgrammer (SWD), Enabled (generic 'Serial'), None, Low/Full Speed, Smallest (-Os default), Newlib Nano (default)"

/home/tom/arduino-1.8.9/arduino-builder -dump-prefs -logger=machine -hardware /home/tom/arduino-1.8.9/hardware -hardware /home/tom/.arduino15/packages -tools /home/tom/arduino-1.8.9/tools-builder -tools /home/tom/arduino-1.8.9/hardware/tools/avr -tools /home/tom/.arduino15/packages -built-in-libraries /home/tom/arduino-1.8.9/libraries -libraries /home/tom/Arduino/libraries -fqbn=STM32:stm32:GenF1:pnum=BLUEPILL_F103C8,upload_method=swdMethod,xserial=generic,usb=none,xusb=FS,opt=osstd,rtlib=nano -ide-version=10809 -build-path /tmp/arduino_build_288179 -warnings=none -build-cache /tmp/arduino_cache_521720 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arm-none-eabi-gcc.path=/home/tom/.arduino15/packages/STM32/tools/arm-none-eabi-gcc/8.2.1-1.7 -prefs=runtime.tools.arm-none-eabi-gcc-8.2.1-1.7.path=/home/tom/.arduino15/packages/STM32/tools/arm-none-eabi-gcc/8.2.1-1.7 -prefs=runtime.tools.STM32Tools.path=/home/tom/.arduino15/packages/STM32/tools/STM32Tools/1.3.0 -prefs=runtime.tools.STM32Tools-1.3.0.path=/home/tom/.arduino15/packages/STM32/tools/STM32Tools/1.3.0 -prefs=runtime.tools.CMSIS.path=/home/tom/.arduino15/packages/STM32/tools/CMSIS/5.5.1 -prefs=runtime.tools.CMSIS-5.5.1.path=/home/tom/.arduino15/packages/STM32/tools/CMSIS/5.5.1 -verbose /tmp/arduino_modified_sketch_654796/Blink.ino
/home/tom/arduino-1.8.9/arduino-builder -compile -logger=machine -hardware /home/tom/arduino-1.8.9/hardware -hardware /home/tom/.arduino15/packages -tools /home/tom/arduino-1.8.9/tools-builder -tools /home/tom/arduino-1.8.9/hardware/tools/avr -tools /home/tom/.arduino15/packages -built-in-libraries /home/tom/arduino-1.8.9/libraries -libraries /home/tom/Arduino/libraries -fqbn=STM32:stm32:GenF1:pnum=BLUEPILL_F103C8,upload_method=swdMethod,xserial=generic,usb=none,xusb=FS,opt=osstd,rtlib=nano -ide-version=10809 -build-path /tmp/arduino_build_288179 -warnings=none -build-cache /tmp/arduino_cache_521720 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arm-none-eabi-gcc.path=/home/tom/.arduino15/packages/STM32/tools/arm-none-eabi-gcc/8.2.1-1.7 -prefs=runtime.tools.arm-none-eabi-gcc-8.2.1-1.7.path=/home/tom/.arduino15/packages/STM32/tools/arm-none-eabi-gcc/8.2.1-1.7 -prefs=runtime.tools.STM32Tools.path=/home/tom/.arduino15/packages/STM32/tools/STM32Tools/1.3.0 -prefs=runtime.tools.STM32Tools-1.3.0.path=/home/tom/.arduino15/packages/STM32/tools/STM32Tools/1.3.0 -prefs=runtime.tools.CMSIS.path=/home/tom/.arduino15/packages/STM32/tools/CMSIS/5.5.1 -prefs=runtime.tools.CMSIS-5.5.1.path=/home/tom/.arduino15/packages/STM32/tools/CMSIS/5.5.1 -verbose /tmp/arduino_modified_sketch_654796/Blink.ino
Using board 'GenF1' from platform in folder: /home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1
Using core 'arduino' from platform in folder: /home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1
bash -c "[ -f /tmp/arduino_modified_sketch_654796/build_opt.h ] || (mkdir -p /tmp/arduino_build_288179/sketch && touch /tmp/arduino_build_288179/sketch/build_opt.h)"
Detecting libraries used...
/home/tom/.arduino15/packages/STM32/tools/arm-none-eabi-gcc/8.2.1-1.7/bin/arm-none-eabi-g++ -mcpu=cortex-m3 -mthumb @/tmp/arduino_build_288179/sketch/build_opt.h -c -Os -w -std=gnu++14 -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -I/tmp/arduino_modified_sketch_654796 -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/avr -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/stm32 -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/stm32/LL -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/stm32/usb -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/stm32/usb/hid -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/stm32/usb/cdc -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Drivers/STM32F1xx_HAL_Driver/Inc/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Drivers/STM32F1xx_HAL_Driver/Src/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/STM32F1xx/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Middlewares/ST/STM32_USB_Device_Library/Core/Inc -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Middlewares/ST/STM32_USB_Device_Library/Core/Src -w -x c++ -E -CC -DSTM32F1xx -DARDUINO=10809 -DARDUINO_BLUEPILL_F103C8 -DARDUINO_ARCH_STM32 "-DBOARD_NAME=\"BLUEPILL_F103C8\"" -DSTM32F103xB -DHAL_UART_MODULE_ENABLED -I/home/tom/.arduino15/packages/STM32/tools/CMSIS/5.5.1/CMSIS/Core/Include/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/gcc/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/variants/PILL_F103XX /tmp/arduino_build_288179/sketch/Blink.ino.cpp -o /dev/null
Error while detecting libraries included by /tmp/arduino_build_288179/sketch/Blink.ino.cpp
Generating function prototypes...
/home/tom/.arduino15/packages/STM32/tools/arm-none-eabi-gcc/8.2.1-1.7/bin/arm-none-eabi-g++ -mcpu=cortex-m3 -mthumb @/tmp/arduino_build_288179/sketch/build_opt.h -c -Os -w -std=gnu++14 -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -I/tmp/arduino_modified_sketch_654796 -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/avr -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/stm32 -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/stm32/LL -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/stm32/usb -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/stm32/usb/hid -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino/stm32/usb/cdc -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Drivers/STM32F1xx_HAL_Driver/Inc/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Drivers/STM32F1xx_HAL_Driver/Src/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/STM32F1xx/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Middlewares/ST/STM32_USB_Device_Library/Core/Inc -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Middlewares/ST/STM32_USB_Device_Library/Core/Src -w -x c++ -E -CC -DSTM32F1xx -DARDUINO=10809 -DARDUINO_BLUEPILL_F103C8 -DARDUINO_ARCH_STM32 "-DBOARD_NAME=\"BLUEPILL_F103C8\"" -DSTM32F103xB -DHAL_UART_MODULE_ENABLED -I/home/tom/.arduino15/packages/STM32/tools/CMSIS/5.5.1/CMSIS/Core/Include/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/system/Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/gcc/ -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/cores/arduino -I/home/tom/.arduino15/packages/STM32/hardware/stm32/1.6.1/variants/PILL_F103XX /tmp/arduino_build_288179/sketch/Blink.ino.cpp -o /tmp/arduino_build_288179/preproc/ctags_target_for_gcc_minus_e.cpp
/home/tom/.arduino15/packages/STM32/tools/arm-none-eabi-gcc/8.2.1-1.7/bin/arm-none-eabi-g++: error while loading shared libraries: libiconv.so.2: cannot open shared object file: No such file or directory
exit status 127
ボードGeneric STM32F1 seriesに対するコンパイル時にエラーが発生しました。

ということで、「libiconv.so.2」がない、というエラーになってしまいます。

・・・・・うーむ。

(参考)
https://github.com/stm32duino/Arduino_Core_STM32

Ender3でフィラメントの色を途中で変える

Twitterで教えていただいたのですが、1ノズルの3Dプリンタで出力中に一時停止して、途中でフィラメントを交換することで多色出力(ただし層単位)が可能であることを教えていただきました。

早速試してみました。出力するのは4月1日に菅官房長官が持っていたアレです。

これを途中でフィラメントを変更して出力しました。

バッチリ!!(出力終了後のひげがちょっと残っていますが・・・)

方法は普通に生成したGcodeファイルをテキストエディタで開いて、

G0 X107.275 Y108.257
G0 X107.548 Y106.986
G0 X106.458 Y106.458
;TIME_ELAPSED:1418.568451
;LAYER:11
;MESH:reiwa.stl
G0 X106.458 Y106.458 Z1.85
;TYPE:FILL
G1 F2400 E976.10839

というようなレイヤーの境目にある ;LAYER:xx というコメントを探します。

その直後に、以下のコードを挿入します。このコードは教えていただいたこちらのページのコメント欄にあるものです。

; begin layer pause code
G91 ; Put in relative mode
G1 Z10 ; Lower bed by 10mm
G90 ; Put back in absolute mode
G1 X0 Y0 ; Zero (home) the X & Y
M84 S0 ; Disable the stepper motor timeout
M0 Click To Restart ; Pause and wait for the user
M84 S60 ; Reenable the default timeout
G91 ; Put in relative mode
G1 Z-10 ; Raise the bed back up 10mm
G90 ; Put back in absolute mode
; end layer pause code

そして普通に出力すると、挿入したコードのところでベッドが10mm下がり、XY方向は原点に戻って、ユーザーの入力待ちになります。この時に、フィラメントを交換して、ノズルの先がきれいになるように注意しながら、コントローラのノブをクリックして再開させるだけです。

RCWL-0516をテスト

安価なドップラー動体センサーをamazonで見つけたので5個入りのを買ってみました。で、簡単な動作テストをしてみたのですが、どうも感度がバラバラに見えます。しかも再現性がない??

はっきりしないので、治具を作って確認してみました。
作った治具はこんな感じです。(写真は不良品の切り分け後に撮ったので、不良品にはマジックでNGと書いてあります)

大したことはしてなくて、単三電池1本からHT7750Aで5Vを生成、生成した5VをドップラーセンサーモジュールとPIC16F1823に供給しています。ドップラーセンサーの出力端子はPIC16F1823のRC0に入力しています。PIC16F1823はRC0の状態によってRC1に接続したLEDの点灯/消灯制御、RC5(PWM)に接続した圧電ブザーの鳴動の制御(=PWMのデューティの調整)をしているだけです。初期設定を除いて、やることがあまりに少ないので、PICの動作周波数は32kHzとしています。

PICの初期設定はMPLAB XのCode Configuratorでやっているので、記述したコードは、main()の中の

    while (1)
    {
        if(IO_RC0_GetValue()){
            EPWM_LoadDutyValue(1);
            IO_RC1_SetHigh();
        } else {
            EPWM_LoadDutyValue(0);
            IO_RC1_SetLow();
        }
    }

これだけです。
Code Configuratorは簡単に書けるのはいいのですが、ドキュメント化が難しいです。各項目に設定した内容をテキストでリストアップしてくれると嬉しいのですが・・・。

話を戻して、テストしてみると以下のことがわかってきました。

  • 5枚中1枚は動作不良(動作しない)
  • 残りの4枚は正常に動作する。感度も特に差はないようだ。
  • 正常品も電源投入後、反応しない時間帯がある。約15秒位だろうか。
    紛らわしいのは電源投入直後、出力=Hとなり、2秒くらいした後、一瞬出力=Lとなった後、再度出力=Hが2秒位続いて、その後、15秒くらい無反応の時間がある。その後は安定して動作し続ける。感度がバラついて見えたのは、この挙動のせい。
  • 基板の両面に対して感度がある。表も裏もあまり変わらないような気がする。側面にたいしても感度があるが、表面/裏面方向よりも感度は悪そう。反応範囲は4〜5mくらいだろうか。
  • 金属が近くにあると途端に感度が悪くなるようだ。

で、不良品の1枚をよく見てみると、部品が欠品しています。

ICの下に1箇所、部品が欠落した跡があります。

これが何なのか、GitHubに上がっている資料で調べると、22uFのコンデンサのようです。そこで、手持ちの22uFの積層セラミックコンデンサをつけてみました。

これで電源投入してみると、ちゃんと動作するようになりました。

液晶モニタ故障?

突然、液晶モニタ(デュアルモニタで使っている内の1枚)が、XGA以上の表示ができなくなってしまいました。

調べていくと、Windows10では表示できるのだけど、LinuxではNG。dmesgで見ると、起動中に EDID invalid というメッセージが出ていました。

一時は買い替えも覚悟しましたが、結局カーネルの起動オプションに

drm_kms_helper.edid_firmware=VGA-1:edid/1920x1080.bin

を書き足して凌ぎました。具体的には、

/etc/default/grub の「GRUB_CMDLINE_LINUX_DEFAULT」の起動時オプションに「drm_kms_helper.edid_firmware=VGA-1:edid/1920×1080.bin」を追加して、

$ sudo grub-mkconfig -o /boot/grub/grub.cfg

として、再起動。こういうときは、Arch Linuxのドキュメントが完成度が高くて参考になります。

ESP8266からMQTT送受信してみる

AdafruitのMQTTライブラリを使ってローカルに立てたブローカー(MQTTサーバー)と通信してみます。

ライブラリのインストール

ArduinoIDEで「ツール→ライブラリを管理」でライブラリマネージャーから「Adafruit MQTT Library」をインストールします。

サンプルプログラムの呼び出し

「スケッチの例→Adafruit MQTT Library→mqtt_esp8266」でサンプルプログラムを呼び出します。

/***************************************************
  Adafruit MQTT Library ESP8266 Example

  Must use ESP8266 Arduino from:
    https://github.com/esp8266/Arduino

  Works great with Adafruit's Huzzah ESP board & Feather
  ----> https://www.adafruit.com/product/2471
  ----> https://www.adafruit.com/products/2821

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Tony DiCola for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

/************************* WiFi Access Point *********************************/

#define WLAN_SSID       "SSID"
#define WLAN_PASS       "PASSWORD"

/************************* Adafruit.io Setup *********************************/

#define AIO_SERVER      "ブローカーのIPアドレス"
#define AIO_SERVERPORT  1883                   // use 8883 for SSL
#define AIO_USERNAME    "username"  // 適当に変更(あまり関係ないっぽい)
#define AIO_KEY         "password"  // 適当に変更(あまり関係ないっぽい)

/************ Global State (you don't need to change this!) ******************/

// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

/****************************** Feeds ***************************************/

// Setup a feed called 'photocell' for publishing.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, "mqtttest");
//Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/photocell");
// AIO_USERNAME "/feeds/photocell" の部分をトピックに書き換えた 

// Setup a feed called 'onoff' for subscribing to changes.
Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt, "mqtttest");
//Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/onoff");
// AIO_USERNAME "/feeds/onoff" の部分をトピックに書き換えた 
// 以降は変更していない

/*************************** Sketch Code ************************************/

// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
void MQTT_connect();

void setup() {
  Serial.begin(115200);
  delay(10);

  Serial.println(F("Adafruit MQTT demo"));

  // Connect to WiFi access point.
  Serial.println(); Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);

  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  Serial.println("WiFi connected");
  Serial.println("IP address: "); Serial.println(WiFi.localIP());

  // Setup MQTT subscription for onoff feed.
  mqtt.subscribe(&onoffbutton);
}

uint32_t x=0;

void loop() {
  // Ensure the connection to the MQTT server is alive (this will make the first
  // connection and automatically reconnect when disconnected).  See the MQTT_connect
  // function definition further below.
  MQTT_connect();

  // this is our 'wait for incoming subscription packets' busy subloop
  // try to spend your time here

  Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(5000))) {
    if (subscription == &onoffbutton) {
      Serial.print(F("Got: "));
      Serial.println((char *)onoffbutton.lastread);
    }
  }

  // Now we can publish stuff!
  Serial.print(F("\nSending photocell val "));
  Serial.print(x);
  Serial.print("...");
  if (! photocell.publish(x++)) {
    Serial.println(F("Failed"));
  } else {
    Serial.println(F("OK!"));
  }

  // ping the server to keep the mqtt connection alive
  // NOT required if you are publishing once every KEEPALIVE seconds
  /*
  if(! mqtt.ping()) {
    mqtt.disconnect();
  }
  */
}

// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
       retries--;
       if (retries == 0) {
         // basically die and wait for WDT to reset me
         while (1);
       }
  }
  Serial.println("MQTT Connected!");
}

これでESP8266に書き込んで実行すると、リスナー側で

Client mosqsub|3941-armbian received PUBLISH (d0, q0, r0, m0, 'mqtttest', ... (1 bytes))
0
Client mosqsub|3941-armbian received PUBLISH (d0, q0, r0, m0, 'mqtttest', ... (1 bytes))
1
Client mosqsub|3941-armbian received PUBLISH (d0, q0, r0, m0, 'mqtttest', ... (1 bytes))
2
Client mosqsub|3941-armbian received PUBLISH (d0, q0, r0, m0, 'mqtttest', ... (1 bytes))

という感じで送信されているのが確認できました。

Arduino IDEのシリアルモニタ側でも

Connecting to xxxxxxxx
...
WiFi connected
IP address: 
xxx.xxx.xxx.xxx
Connecting to MQTT... MQTT Connected!

Sending photocell val 0...OK!
Got: 0

Sending photocell val 1...OK!
Got: 1

Sending photocell val 2...OK!
Got: 2

という感じでPublish/Subscribeの確認ができました。

 

ArmbianにMQTT環境をインストール

syslogサーバになっているArmbianにMQTT環境をインストールします。作業内容はこちらの記事を参考にしました。(というか、そのまま)

注)ローカルネットワーク内でのテストのため、ユーザー認証なしの状態で実施しています。

サーバー (Broker) のインストール

$ sudo apt install mosquitto

サーバー(Broker)の起動

$ sudo systemctl start mosquitto
$ sudo systemctl start mosquitto
$ sudo systemctl status mosquitto
● mosquitto.service - LSB: mosquitto MQTT v3.1 message broker
   Loaded: loaded (/etc/init.d/mosquitto; generated)
   Active: active (running) since Mon 2019-05-13 01:24:52 JST; 40s ago
     Docs: man:systemd-sysv-generator(8)
    Tasks: 1 (limit: 413)
   CGroup: /system.slice/mosquitto.service
           └─3781 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf

 5月 13 01:24:51 armbian systemd[1]: Starting LSB: mosquitto MQTT v3.1 message broker...
 5月 13 01:24:51 armbian mosquitto[3775]:  * Starting network daemon: mosquitto
 5月 13 01:24:52 armbian mosquitto[3775]:    ...done.
 5月 13 01:24:52 armbian systemd[1]: Started LSB: mosquitto MQTT v3.1 message broker.

クライアントのインストール

$ sudo apt install mosquitto-clients

リスナー(Subscribe)を動かす

リスナーの起動はサーバ(Broker)の起動後に行う。下記はその後のPublishをした際の記録を含む。トピックは mqtttest としてみた。

$ mosquitto_sub -d -t mqtttest
Client mosqsub|3941-armbian sending CONNECT
Client mosqsub|3941-armbian received CONNACK
Client mosqsub|3941-armbian sending SUBSCRIBE (Mid: 1, Topic: mqtttest, QoS: 0)
Client mosqsub|3941-armbian received SUBACK
Subscribed (mid: 1): 0
Client mosqsub|3941-armbian received PUBLISH (d0, q0, r0, m0, 'mqtttest', ... (18 bytes))
Hello MQTT world !
Client mosqsub|3941-armbian sending PINGREQ
Client mosqsub|3941-armbian received PINGRESP
Client mosqsub|3941-armbian sending PINGREQ
Client mosqsub|3941-armbian received PINGRESP

今回はローカルのサーバ(Broker)に対して接続(subscribe)しているが、リモートのサーバ(Broker)に対して接続(subscribe)する場合は「-h server名」とする。

別のPCでもクライアントのみ起動してサーバー(Broker)を指定してリスナーを起動すると、Publishした瞬間に同時に両方のリスナーで表示される。

Publishを動かす

$ mosquitto_pub -d -t mqtttest -m "Hello MQTT world !"
Client mosqpub|3942-armbian sending CONNECT
Client mosqpub|3942-armbian received CONNACK
Client mosqpub|3942-armbian sending PUBLISH (d0, q0, r0, m1, 'mqtttest', ... (18 bytes))
Client mosqpub|3942-armbian sending DISCONNECT
$

今回はローカルのサーバ(Broker)に対して接続(Publish)しているが、リモートのサーバ(Broker)に対して接続(Publish)する場合は「-h server名」とする。

サーバー(Broker)を自動起動するように設定

$ sudo systemctl enable mosquitto
mosquitto.service is not a native service, redirecting to systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable mosquitto
$