Python3でMQTTクライアント

ESP8266でMQTTを喋れるようになったので、受ける側を考えます。自分用のサービスまでしか考えていないので、記述が楽なPythonで作ります。調べると paho というMQTTクライアントがあるようなので、こちらを参考にそれを試してみます。

Python3でvenvを使って仮想環境を作ります。

~$ mkdir python
~$ cd python
~/python$ sudo apt install python3-venv
~/python$ python3 -m venv pytest
~/python$ source ./pytest/bin/activate
(pytest) ~/python$ cd pytest/
(pytest) ~/python/pytest$ 
(pytest) ~/python/pytest$ python -V
Python 3.6.8

pipをバージョンアップします。

(pytest) ~/python/pytest$ pip install --upgrade pip
Collecting pip
  Downloading https://files.pythonhosted.org/packages/5c/e0/be401c003291b56efc55aeba6a80ab790d3d4cece2778288d65323009420/pip-19.1.1-py2.py3-none-any.whl (1.4MB)
    100% |████████████████████████████████| 1.4MB 672kB/s 
Installing collected packages: pip
  Found existing installation: pip 9.0.1
    Uninstalling pip-9.0.1:
      Successfully uninstalled pip-9.0.1
Successfully installed pip-19.1.1
(pytest) ~/python/pytest$ 

pahoをインストールします。

(pytest) ~/python/pytest$ pip install paho-mqtt
Collecting paho-mqtt
  Downloading https://files.pythonhosted.org/packages/25/63/db25e62979c2a716a74950c9ed658dce431b5cb01fde29eb6cba9489a904/paho-mqtt-1.4.0.tar.gz (88kB)
     |████████████████████████████████| 92kB 12.6MB/s 
Installing collected packages: paho-mqtt
  Running setup.py install for paho-mqtt ... done
Successfully installed paho-mqtt-1.4.0
(pytest) ~/python/pytest$ 

Subscriberをテストしてみます。ソースコードは以下のとおりです。

# -*- coding:utf-8 -*-
import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, respons_code):
    topic = '/feeds/sensor/#'
    print('watch %s' % topic)
    client.subscribe(topic)

def on_message(client, userdata, msg):
    print(msg.topic + ' ' + str(msg.payload))

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect('XXX.XXX.XXX.XXX', 1883, keepalive=60)
client.loop_forever()

結果は、

(pytest) ~/python/pytest$ python scbscriber.py 
watch /feeds/sensor/#
/feeds/sensor/0001 b'0001 4C11AEXXXXXX 1970/01/01 08:00:02 28802 0'
/feeds/sensor/0001 b'0001 4C11AEXXXXXX 2019/07/16 01:39:52 1563241192 1'
/feeds/sensor/0001 b'0001 4C11AEXXXXXX 2019/07/16 01:39:53 1563241193 2'
/feeds/sensor/0001 b'0001 18FE34XXXXXX 1970/01/01 08:00:02 28802 0'
/feeds/sensor/0001 b'0001 4C11AEXXXXXX 2019/07/16 01:39:54 1563241194 3'
/feeds/sensor/0001 b'0001 18FE34XXXXXX 2019/07/16 01:39:55 1563241195 1'
/feeds/sensor/0001 b'0001 4C11AEXXXXXX 2019/07/16 01:39:55 1563241195 4'
/feeds/sensor/0001 b'0001 18FE34XXXXXX 2019/07/16 01:39:56 1563241196 2'
/feeds/sensor/0001 b'0001 4C11AEXXXXXX 2019/07/16 01:39:56 1563241196 5'
/feeds/sensor/0001 b'0001 18FE34XXXXXX 2019/07/16 01:39:57 1563241197 3'
/feeds/sensor/0001 b'0001 4C11AEXXXXXX 2019/07/16 01:39:57 1563241197 6'
/feeds/sensor/0001 b'0001 18FE34XXXXXX 2019/07/16 01:39:58 1563241198 4'

ということで、無事に動作しました。

smartconfig+MQTT

ESP8266を便利な(笑)MQTTクライアントにするため、smartconfigと組み合わせてみます。センサーの情報をMQTTで一箇所に集めて、表示できるようにするのが目標です。

1.smartconfigの動作確認

まずベースは以前の記事のsmartconfigです。Androidのアプリ側はESP8266 smartconfigで動作することは確認しました。

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

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

3.ソースの結合

ソースを結合して以下の通りとしました。難しいところはありません。ついでに、NTPでの時刻合わせ、タイマ割り込みの処理も記述も追加しておきました。
トピックは /feed/sensor/番号 にすることにしました。
できればこの際、SSL化もしたかったのですが、mosquittoのブローカ側のSSL化すらうまく行っていないので今回は見送りです。どちらにせよ、プライベートIPアドレスの中での運用なのであまり気にする必要はないのですが。
※あちこちからの切り貼りです。

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include &quot;Adafruit_MQTT.h&quot;
#include &quot;Adafruit_MQTT_Client.h&quot;

/*****************************************************************************/
/* MQTT Client                                                               */

/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER      &quot;10.89.105.1&quot;
#define AIO_SERVERPORT  1883                   // use 8883 for SSL
#define AIO_USERNAME    &quot;username&quot;  // 適当に変更(未使用)
#define AIO_KEY         &quot;password&quot;  // 適当に変更(未使用)
#define SERIALNO        &quot;0001&quot;

/************ 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 ***************************************/
Adafruit_MQTT_Publish motion = Adafruit_MQTT_Publish(&mqtt, &quot;/feeds/sensor/&quot; SERIALNO);
Adafruit_MQTT_Subscribe command = Adafruit_MQTT_Subscribe(&mqtt, &quot;/feeds/command/&quot; SERIALNO);
char macstr[13];    // Station mode MAC address 

/*****************************************************************************/
/* NTP Client                                                                */
#include <time.h>
#define JST     3600*9

/*****************************************************************************/
/* Timer interrupt                                                           */
#define MS2CLK(ms)    (ms * 80000L)
uint32_t nxTim;

// 割り込みハンドラ
void timer0_ISR (void) {
  nxTim += MS2CLK(100); // 100msec 
  timer0_write( nxTim );
  
  // 割り込み処理
  digitalWrite(13, 1-digitalRead(13));   // Blink the LED
}

/*************************** Sketch Code ************************************/
 
void setup() {
  uint8_t cnt = 0;  

  // set for STA mode
  WiFi.mode(WIFI_STA);
  
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.flush();
  Serial.println(&quot;\r\n&quot;);
    
  // led status at pin4
  pinMode(12,OUTPUT);
  digitalWrite(12, HIGH);   // turn the LED on (HIGH is the voltage level)
  
  // led status at pin5
  pinMode(13,OUTPUT);
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  
  //configure pin0 
  pinMode(0, INPUT_PULLUP);

  // deplay for 2 sec for smartConfig
  Serial.println(&quot;2 sec before clear SmartConfig&quot;);
  delay(2000);
  
  // read pullup
  bool isSmartConfig = digitalRead(0);
  if (isSmartConfig == false) {
    // bink for clear config
    blinkClearConfig();
    Serial.println(&quot;clear config&quot;);
    // reset default config
    WiFi.disconnect();

  }

  // if wifi cannot connect start smartconfig
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(&quot;.&quot;);
    if(cnt++ >= 15){
       WiFi.beginSmartConfig();
       while(1){
           delay(500);
           if(WiFi.smartConfigDone()){
             Serial.println(&quot;SmartConfig Success&quot;);
             blinkSmartConfig();
             break;
           }
       }
    }
  }

  Serial.println(&quot;&quot;);

  WiFi.printDiag(Serial);

  // Print the IP address
  Serial.println(WiFi.localIP());

  // タイマ割り込みの設定
  noInterrupts();
  timer0_isr_init();
  timer0_attachInterrupt(timer0_ISR);
  nxTim = ESP.getCycleCount() + MS2CLK(100); // 100msec
  timer0_write( nxTim );
  interrupts();
  
  // time set with NTP
  configTime( JST, 0, &quot;ntp.nict.jp&quot;, &quot;ntp.jst.mfeed.ad.jp&quot;);

  // Setup MQTT subscription for command feed.
  mqtt.subscribe(&command);

  //  
  uint8_t mac0[6];
  WiFi.macAddress(mac0);
  sprintf(macstr,&quot;%02X%02X%02X%02X%02X%02X&quot;, mac0[0], mac0[1], mac0[2], mac0[3], mac0[4], mac0[5]);
}


void blinkSmartConfig() {
    digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(50);              // wait for a second 
    digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
    delay(50);
}

void blinkClearConfig() {
  int i=0;
  while(i<=3) { digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) delay(100); // wait for a second digitalWrite(13, LOW); // turn the LED off by making the voltage LOW delay(100); i++; } } uint32_t x=0; void loop() { time_t t; struct tm *tm; char msg[64]=&quot;&quot;; bool isSW1 = digitalRead(0); if(isSW1 == false){ for(int i=5;i>0;i--){
      delay(1000);
      Serial.println(i);    
    }
    Serial.println(&quot;Power off&quot;);    
    delay(500);
    pinMode(15,OUTPUT);
    digitalWrite(15, HIGH);   // Power-off the board (HIGH is the voltage level)
    delay(5000);
  }
  digitalWrite(12, 1-digitalRead(12));   // Blink the LED

  /*******/
  /* NTP */
  t = time(NULL);
  tm = localtime(&t);
  sprintf(msg,&quot;%s %s %04d/%02d/%02d %02d:%02d:%02d %ld %d&quot;,
        SERIALNO,macstr,
        tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
        tm->tm_hour, tm->tm_min, tm->tm_sec,
        (long)t,x++);

  /********/
  /* MQTT */
  // 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(1000))) {
    if (subscription == &command) {
      Serial.print(F(&quot;Got: &quot;));
      Serial.println((char *)command.lastread);
    }
  }
 
  // Now we can publish stuff!
  Serial.print(F(&quot;\nSending message : &quot;));
  Serial.print(msg);
  Serial.print(&quot;...&quot;);
  if (! motion.publish(msg)) {
    Serial.println(F(&quot;Failed&quot;));
  } else {
    Serial.println(F(&quot;OK!&quot;));
  }
 
  // 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(&quot;Connecting to MQTT... &quot;);
 
  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println(&quot;Retrying MQTT connection in 5 seconds...&quot;);
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
       retries--;
       if (retries == 0) {
         // basically die and wait for WDT to reset me
         while (1);
       }
  }
  Serial.println(&quot;MQTT Connected!&quot;);
}

ついでに、基板の回路図も再掲載です。

実装部品

ミニマム実装:
 半田面
    GS5 2-3
    GS6 2-3
    C6  0.1u
    C7  22u
    R1  470
    R2  4.7k
    R3  4.7k
    R4  100
    R7  20k
    R8  4.7k 
    R11 0Ω
    R19 22k
    R20 33k
    R21 470
    R22 470
    R23 470
    R24 470
 部品面
    U3  AZ1117-ADJ
    D1  LED
    D2  LED
    D3  LED
    SW1 タクトSW
    SW2 タクトSW
    C5  33u

STM32F103C8でLチカ

STM32F103C8とArduino IDE環境で、とりあえずLチカしてみました。

この状態で消費電流は・・・・・・・・約40mA。動作周波数を72MHzから48MHzまで落としても約32mA。うーん、電池動作には使えん。Arduino環境じゃなければ減らせるんだろうか・・。

LEDについている抵抗は2.2kオームなのでLEDに流れる電流は大したことはありません。

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を使うように修正します。(注:パラメータ -g の後の値は7桁です。うっかり、0x80000000とか8桁書いてしまうと動かなくて悩むことになりますorz)

完了したら、スケッチ例で 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の積層セラミックコンデンサをつけてみました。

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