勉強しないとな~blog

ちゃんと勉強せねば…な電気設計エンジニアです。

M5Stampをバスおもちゃに仕込む - 5. コード作成、コンパイル

↓ 前回記事

nokixa.hatenablog.com

前回、Wi-Fi接続するプログラムをPlatformIOで作成できたので、今度は当初の目的のアプリケーション(スマホからブラウザアクセス、Webページのボタンを押して、バスおもちゃの音を鳴らす)を作っていく。

概要

生成AIにソースコードとプロジェクト開発手順を作ってもらっているので、それを実機で動かしていく。

ソースコード等

生成AIに作ってもらったのは下記の通り。

バスのボタンへのIO番号は実際の接続に合わせて書き換えている。

  • main.cpp
#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include "index.h" // HTMLコードを別ファイルに分離

const char* ssid = "あなたのWiFi_SSID";
const char* password = "あなたのWiFiパスワード";
const int outputPin = 4;

WebServer server(80);

void setup() {
  Serial.begin(115200);
  pinMode(outputPin, OUTPUT);
  digitalWrite(outputPin, LOW);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.print("Connected to WiFi. IP address: ");
  Serial.println(WiFi.localIP());

  server.on("/", HTTP_GET, []() {
    server.send(200, "text/html", INDEX_HTML);
  });

  server.on("/trigger", HTTP_POST, []() {
    digitalWrite(outputPin, HIGH);
    delay(100);
    digitalWrite(outputPin, LOW);
    server.send(200, "text/plain", "OK");
  });

  server.begin();
}

void loop() {
server.handleClient();
}

  • index.h

#ifndef INDEX_H
#define INDEX_H

const char INDEX_HTML[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>バス停ボタン</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.button {
padding: 40px;
font-size: 24px;
border-radius: 50%;
background-color: #ff4444;
color: white;
border: none;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
cursor: pointer;
}
.button:active {
transform: translateY(4px);
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
</style>
</head>
<body>
<button class="button" onclick="triggerSound()">停車</button>
<script>
function triggerSound() {
fetch('/trigger', {method: 'POST'})
.then(response => console.log('Triggered'))
.catch(error => console.error('Error:', error));
}
</script>
</body>
</html>
)rawliteral";

#endif

index.hの中に、スマホ等からアクセスされたときに返すindex.htmlが丸々含まれている。

index.hは、includeフォルダの中に保存する。

  • 一応、platform.iniに、シリアルポートのボーレートの記述も入れておく。
    実際必要かは分からない。"Monitor"をやるときのコマンド引数で設定できるのかもしれない。
; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:esp32-c3-devkitm-1]
platform = espressif32
board = esp32-c3-devkitm-1
framework = arduino
monitor_speed = 115200

ソースコードでやってること

いまいち仕組みがよく分からなかったが、生成AIに聞くと、こんな感じで回答が出た。

以下の流れで動作しています:

1. *HTMLのボタンクリック時の動作*:
function triggerSound() {
fetch('/trigger', {method: 'POST'})
.then(response => console.log('Triggered'))
.catch(error => console.error('Error:', error));
}
このコードは、ボタンがクリックされたときに`/trigger`というURLにHTTP POSTリクエストを送るだけです。

2. *マイコン側でのIO操作*:
実際のIO操作は、マイコン(ESP8266/ESP32)のプログラムで行っています:

// POSTリクエストを受け取ったときの処理
server.on("/trigger", HTTP_POST, []() {
digitalWrite(outputPin, HIGH); // ここでIOピンをHIGHに
delay(100); // 100ミリ秒待機
digitalWrite(outputPin, LOW); // IOピンをLOWに戻す
server.send(200, "text/plain", "OK"); // ブラウザに応答を返す
});

つまり、動作の順序は:

1. ブラウザでボタンをクリック
2. JavaScriptが`/trigger`にPOSTリクエストを送信
3. マイコンのWebサーバーがリクエストを受信
4. マイコンのプログラムがIO操作を実行
5. 操作完了後、ブラウザに「OK」を返す

なんとなく理解が進んだような気がする。

ビルド

ビルド結果のログは下記の通り。

クリックで開く/閉じる

 *  Executing task: C:\Users\a\.platformio\penv\Scripts\platformio.exe run --environment esp32-c3-devkitm-1 

Processing esp32-c3-devkitm-1 (platform: espressif32; board: esp32-c3-devkitm-1; framework: arduino)
--------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-c3-devkitm-1.html
PLATFORM: Espressif 32 (6.9.0) > Espressif ESP32-C3-DevKitM-1
HARDWARE: ESP32C3 160MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-builtin, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-arduinoespressif32 @ 3.20017.0 (2.0.17)
 - tool-esptoolpy @ 1.40501.0 (4.5.1)
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 33 compatible libraries
Scanning dependencies...
Dependency Graph
|-- WebServer @ 2.0.0
|-- WiFi @ 2.0.0
Building in release mode
Compiling .pio\build\esp32-c3-devkitm-1\src\main.cpp.o
Building .pio\build\esp32-c3-devkitm-1\bootloader.bin
Generating partitions .pio\build\esp32-c3-devkitm-1\partitions.bin
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFi.cpp.o
esptool.py v4.5.1
Creating esp32c3 image...
Merged 1 ELF section
Successfully created esp32c3 image.
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiAP.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiClient.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiGeneric.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiMulti.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiSTA.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiScan.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiServer.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiUdp.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib01d\FS\FS.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib01d\FS\vfs_api.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib371\WebServer\Parsing.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib371\WebServer\WebServer.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib371\WebServer\detail\mimetable.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Esp.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\FirmwareMSC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\FunctionalInterrupt.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\HWCDC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\HardwareSerial.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\IPAddress.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\IPv6Address.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\MD5Builder.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Print.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Stream.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\StreamString.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Tone.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USB.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USBCDC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USBMSC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\WMath.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\WString.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\base64.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\cbuf.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-adc.c.o
Archiving .pio\build\esp32-c3-devkitm-1\lib4ca\libWiFi.a
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-bt.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-cpu.c.o
Archiving .pio\build\esp32-c3-devkitm-1\lib01d\libFS.a
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-dac.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-gpio.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-i2c-slave.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-i2c.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-ledc.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-matrix.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-misc.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-psram.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-rgb-led.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-rmt.c.o
Archiving .pio\build\esp32-c3-devkitm-1\lib371\libWebServer.a
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-sigmadelta.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-spi.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-time.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-timer.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-tinyusb.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-touch.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-uart.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\firmware_msc_fat.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\libb64\cdecode.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\libb64\cencode.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\main.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\stdlib_noniso.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\wiring_pulse.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\wiring_shift.c.o
Archiving .pio\build\esp32-c3-devkitm-1\libFrameworkArduino.a
Linking .pio\build\esp32-c3-devkitm-1\firmware.elf
Retrieving maximum program size .pio\build\esp32-c3-devkitm-1\firmware.elf
Checking size .pio\build\esp32-c3-devkitm-1\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [=         ]  12.0% (used 39284 bytes from 327680 bytes)
Flash: [======    ]  58.5% (used 766746 bytes from 1310720 bytes)
Building .pio\build\esp32-c3-devkitm-1\firmware.bin
esptool.py v4.5.1
Creating esp32c3 image...
Merged 2 ELF sections
Successfully created esp32c3 image.
================================== [SUCCESS] Took 10.90 seconds ==================================
 *  Terminal will be reused by tasks, press any key to close it. 

今回は、"WebServer.h"のライブラリが追加されている。

Dependency Graph
|-- WebServer @ 2.0.0
|-- WiFi @ 2.0.0
Compiling .pio\build\esp32-c3-devkitm-1\lib371\WebServer\Parsing.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib371\WebServer\WebServer.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib371\WebServer\detail\mimetable.cpp.o

実動作

"Upload and Monitor"をすると、こんな表示になった。

クリックで開く/閉じる

 *  Executing task: C:\Users\a\.platformio\penv\Scripts\platformio.exe run --target upload --target monitor --environment esp32-c3-devkitm-1 

Processing esp32-c3-devkitm-1 (platform: espressif32; board: esp32-c3-devkitm-1; framework: arduino)
---------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-c3-devkitm-1.html
PLATFORM: Espressif 32 (6.9.0) > Espressif ESP32-C3-DevKitM-1
HARDWARE: ESP32C3 160MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-builtin, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-arduinoespressif32 @ 3.20017.0 (2.0.17)
 - tool-esptoolpy @ 1.40501.0 (4.5.1)
 - tool-mkfatfs @ 2.0.1
 - tool-mklittlefs @ 1.203.210628 (2.3)
 - tool-mkspiffs @ 2.230.0 (2.30)
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 33 compatible libraries
Scanning dependencies...
Dependency Graph
|-- WebServer @ 2.0.0
|-- WiFi @ 2.0.0
Building in release mode
Retrieving maximum program size .pio\build\esp32-c3-devkitm-1\firmware.elf
Checking size .pio\build\esp32-c3-devkitm-1\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"       
RAM:   [=         ]  12.0% (used 39284 bytes from 327680 bytes)
Flash: [======    ]  58.5% (used 766746 bytes from 1310720 bytes)
Configuring upload protocol...
AVAILABLE: cmsis-dap, esp-bridge, esp-builtin, esp-prog, espota, esptool, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa
CURRENT: upload_protocol = esptool
Looking for upload port...
Auto-detected: COM3
Uploading .pio\build\esp32-c3-devkitm-1\firmware.bin
esptool.py v4.5.1
Serial port COM3
Connecting....
Chip is ESP32-C3 (revision v0.3)
Features: WiFi, BLE
Crystal is 40MHz
MAC: 68:67:25:b2:d0:54
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00003fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x0000e000 to 0x0000ffff...
Flash will be erased from 0x00010000 to 0x000d0fff...
Compressed 13248 bytes to 9562...
Writing at 0x00000000... (100 %)
Wrote 13248 bytes (9562 compressed) at 0x00000000 in 0.5 seconds (effective 226.6 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 146...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (146 compressed) at 0x00008000 in 0.1 seconds (effective 405.4 kbit/s)...
Hash of data verified.
Compressed 8192 bytes to 47...
Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 552.6 kbit/s)...
Hash of data verified.
Compressed 789456 bytes to 473675...
Writing at 0x00010000... (3 %)
Writing at 0x0001c2eb... (6 %)
Writing at 0x00026126... (10 %)
Writing at 0x000308a3... (13 %)
Writing at 0x00036dce... (17 %)
Writing at 0x0003e31a... (20 %)
Writing at 0x000443ea... (24 %)
Writing at 0x0004a739... (27 %)
Writing at 0x000501eb... (31 %)
Writing at 0x00055f15... (34 %)
Writing at 0x0005c0cb... (37 %)
Writing at 0x00061e8e... (41 %)
Writing at 0x00067e3f... (44 %)
Writing at 0x0006e054... (48 %)
Writing at 0x00073c2f... (51 %)
Writing at 0x000795d1... (55 %)
Writing at 0x0007f8bd... (58 %)
Writing at 0x0008571d... (62 %)
Writing at 0x0008b554... (65 %)
Writing at 0x0009162e... (68 %)
Writing at 0x00097b9c... (72 %)
Writing at 0x0009e024... (75 %)
Writing at 0x000a41ea... (79 %)
Writing at 0x000aa37c... (82 %)
Writing at 0x000b00dc... (86 %)
Writing at 0x000b8262... (89 %)
Writing at 0x000bec19... (93 %)
Writing at 0x000c4dbb... (96 %)
Writing at 0x000cad36... (100 %)
Wrote 789456 bytes (473675 compressed) at 0x00010000 in 13.7 seconds (effective 460.5 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
--- Terminal on COM3 | 115200 8-N-1
--- Available filters and text transformations: colorize, debug, default, direct, esp32_exception_decoder, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd5810,len:0x438
load:0x403cc710,len:0x90c
load:0x403ce710,len:0x2624
entry 0x403cc710
...
Connected to WiFi. IP address: 192.168.1.37

...
Connected to WiFi. IP address: 192.168.1.37

ここで、PCのブラウザからIPアドレスを入力すると、こんな感じでバスのボタンの画面が出た。

このボタンを押すと、バスおもちゃが光って、音も出た。ねらい通り。

www.dropbox.com

ここまで

ひとまず動いたが、この後ハード的な問題があったので、その対処をする。

大幅変更になりそう。

M5Stampをバスおもちゃに仕込む - 4. Wi-Fi接続

↓ 前回記事

nokixa.hatenablog.com

今回は、Wi-Fi接続を確認する。

概要

M5StampでのWi-Fi接続は前やったが、このときはESP-IDFを使ったやり方だった。

nokixa.hatenablog.com

今回のバスおもちゃ改造では、PlatformIOの開発環境を使うので、ここでのWi-Fiの扱い方を確認する。

やったこと

まずは前回記事と同じ手順で、Wi-Fiテスト用にPlatformIOのプロジェクトを作成。

生成AI(Perplexity)に、PlatformIOでの開発方法を聞いている文脈で、「Wi-Fi接続をするプログラム」ということで聞いて、コードを作成してもらった。

あとはPlatformIOにコードを持ってきてコンパイルし、デバイス接続して書き込み、実行しただけ。

結果的に、これで一発で行けた。

生成AIで作成してもらったコード

下記の通り出てきた。

#include <Arduino.h>
#include <WiFi.h>

const char* ssid = "あなたのWi-FiのSSID";
const char* password = "あなたのWi-Fiのパスワード";

void setup() {
  Serial.begin(115200);
  Serial.println("Wi-Fi接続を開始します");

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("Wi-Fi接続に成功しました");
  Serial.print("IPアドレス: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("Wi-Fi接続中");
  } else {
    Serial.println("Wi-Fi接続が切れました");
  }
  delay(5000);
}

※Wi-FiのSSID、パスワードは自宅のWi-Fiルーターのものに置き換える。

生成AIが参照していたサイトも一部書いておく。

platformioでESP32がwifiに接続まで試してみた! - KOKENSHAの技術ブログ

開発環境(ESP-IDF)によるESP32のWiFi機能の使用方法 #ESP32 - Qiita

PlatformIOでコンパイル

上記コードでは、WiFi.hをインクルードしているが、特にPlatformIOでライブラリ追加はいらなかった。
PlatformIOの標準で付いている?
プロジェクト作成時に"Espressif ESP32-C3-DevKitM-1"の選択をしたが、この中に含まれている?

コンパイル時のログは下記の通り。

ログを全部見る

*  Executing task: C:\Users\a\.platformio\penv\Scripts\platformio.exe run --environment esp32-c3-devkitm-1 

Processing esp32-c3-devkitm-1 (platform: espressif32; board: esp32-c3-devkitm-1; framework: arduino)
--------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-c3-devkitm-1.html
PLATFORM: Espressif 32 (6.9.0) > Espressif ESP32-C3-DevKitM-1
HARDWARE: ESP32C3 160MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-builtin, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-arduinoespressif32 @ 3.20017.0 (2.0.17)
 - tool-esptoolpy @ 1.40501.0 (4.5.1)
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 33 compatible libraries
Scanning dependencies...
Dependency Graph
|-- WiFi @ 2.0.0
Building in release mode
Compiling .pio\build\esp32-c3-devkitm-1\src\main.cpp.o
Building .pio\build\esp32-c3-devkitm-1\bootloader.bin
Generating partitions .pio\build\esp32-c3-devkitm-1\partitions.bin
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFi.cpp.o
esptool.py v4.5.1
Creating esp32c3 image...
Merged 1 ELF section
Successfully created esp32c3 image.
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiAP.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiClient.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiGeneric.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiMulti.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiSTA.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiScan.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiServer.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiUdp.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Esp.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\FirmwareMSC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\FunctionalInterrupt.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\HWCDC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\HardwareSerial.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\IPAddress.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\IPv6Address.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\MD5Builder.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Print.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Stream.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\StreamString.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Tone.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USB.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USBCDC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USBMSC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\WMath.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\WString.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\base64.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\cbuf.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-adc.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-bt.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-cpu.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-dac.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-gpio.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-i2c-slave.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-i2c.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-ledc.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-matrix.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-misc.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-psram.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-rgb-led.c.o
Archiving .pio\build\esp32-c3-devkitm-1\lib4ca\libWiFi.a
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-rmt.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-sigmadelta.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-spi.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-time.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-timer.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-tinyusb.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-touch.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-uart.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\firmware_msc_fat.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\libb64\cdecode.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\libb64\cencode.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\main.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\stdlib_noniso.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\wiring_pulse.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\wiring_shift.c.o
Archiving .pio\build\esp32-c3-devkitm-1\libFrameworkArduino.a
Linking .pio\build\esp32-c3-devkitm-1\firmware.elf
Retrieving maximum program size .pio\build\esp32-c3-devkitm-1\firmware.elf
Checking size .pio\build\esp32-c3-devkitm-1\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [=         ]  11.4% (used 37372 bytes from 327680 bytes)
Flash: [=====     ]  54.0% (used 707752 bytes from 1310720 bytes)
Building .pio\build\esp32-c3-devkitm-1\firmware.bin
esptool.py v4.5.1
Creating esp32c3 image...
Merged 2 ELF sections
Successfully created esp32c3 image.
================================== [SUCCESS] Took 11.30 seconds ==================================
 *  Terminal will be reused by tasks, press any key to close it. 

ところどころにWi-Fi関連のログがある。

Dependency Graph
|-- WiFi @ 2.0.0
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiAP.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiClient.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiGeneric.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiMulti.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiSTA.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiScan.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiServer.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\lib4ca\WiFi\WiFiUdp.cpp.o

デバイスつないで書き込み、実行

PlatformIOで、"Upload and Monitor"をやった結果のログ。

ログを全部見る

 *  Executing task: C:\Users\a\.platformio\penv\Scripts\platformio.exe run --target upload --target monitor --environment esp32-c3-devkitm-1 

Processing esp32-c3-devkitm-1 (platform: espressif32; board: esp32-c3-devkitm-1; framework: arduino)
---------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-c3-devkitm-1.html
PLATFORM: Espressif 32 (6.9.0) > Espressif ESP32-C3-DevKitM-1
HARDWARE: ESP32C3 160MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-builtin, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-arduinoespressif32 @ 3.20017.0 (2.0.17)
 - tool-esptoolpy @ 1.40501.0 (4.5.1)
 - tool-mkfatfs @ 2.0.1
 - tool-mklittlefs @ 1.203.210628 (2.3)
 - tool-mkspiffs @ 2.230.0 (2.30)
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 33 compatible libraries
Scanning dependencies...
Dependency Graph
|-- WiFi @ 2.0.0
Building in release mode
Retrieving maximum program size .pio\build\esp32-c3-devkitm-1\firmware.elf
Checking size .pio\build\esp32-c3-devkitm-1\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"       
RAM:   [=         ]  11.4% (used 37372 bytes from 327680 bytes)
Flash: [=====     ]  54.0% (used 707752 bytes from 1310720 bytes)
Configuring upload protocol...
AVAILABLE: cmsis-dap, esp-bridge, esp-builtin, esp-prog, espota, esptool, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa
CURRENT: upload_protocol = esptool
Looking for upload port...
Auto-detected: COM3
Uploading .pio\build\esp32-c3-devkitm-1\firmware.bin
esptool.py v4.5.1
Serial port COM3
Connecting....
Chip is ESP32-C3 (revision v0.3)
Features: WiFi, BLE
Crystal is 40MHz
MAC: 68:67:25:b2:d0:54
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00003fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x0000e000 to 0x0000ffff...
Flash will be erased from 0x00010000 to 0x000c0fff...
Compressed 13248 bytes to 9562...
Writing at 0x00000000... (100 %)
Wrote 13248 bytes (9562 compressed) at 0x00000000 in 0.5 seconds (effective 227.1 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 146...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (146 compressed) at 0x00008000 in 0.1 seconds (effective 408.0 kbit/s)...
Hash of data verified.
Compressed 8192 bytes to 47...
Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 555.3 kbit/s)...
Hash of data verified.
Compressed 723264 bytes to 437404...
Writing at 0x00010000... (3 %)
Writing at 0x0001bd02... (7 %)
Writing at 0x00025ec7... (11 %)
Writing at 0x0002e54a... (14 %)
Writing at 0x00034cc8... (18 %)
Writing at 0x0003bc4d... (22 %)
Writing at 0x00041cff... (25 %)
Writing at 0x00047a25... (29 %)
Writing at 0x0004d6b3... (33 %)
Writing at 0x000536bc... (37 %)
Writing at 0x000596eb... (40 %)
Writing at 0x0005f667... (44 %)
Writing at 0x0006592a... (48 %)
Writing at 0x0006b3b0... (51 %)
Writing at 0x00070ca5... (55 %)
Writing at 0x00077087... (59 %)
Writing at 0x0007cf90... (62 %)
Writing at 0x00082ce4... (66 %)
Writing at 0x00088e1f... (70 %)
Writing at 0x0008f3e4... (74 %)
Writing at 0x00095814... (77 %)
Writing at 0x0009b9c6... (81 %)
Writing at 0x000a1af1... (85 %)
Writing at 0x000a7921... (88 %)
Writing at 0x000af48b... (92 %)
Writing at 0x000b5ea6... (96 %)
Writing at 0x000bc037... (100 %)
Wrote 723264 bytes (437404 compressed) at 0x00010000 in 12.7 seconds (effective 457.2 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
--- Terminal on COM3 | 115200 8-N-1
--- Available filters and text transformations: colorize, debug, default, direct, esp32_exception_decoder, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd5810,len:0x438
load:0x403cc710,len:0x90c
load:0x403ce710,len:0x2624
entry 0x403cc710
Wi-Fi接続を開始します
...........
Wi-Fi接続に成功しました
IPアドレス: 192.168.1.37
Wi-Fi接続中
Wi-Fi接続中
Wi-Fi接続中
Wi-Fi接続中

シリアルコンソールへの表示は下記の通りで、きちんとWi-FiルーターからIPアドレスをもらって、Wi-Fi接続できている。

Wi-Fi接続を開始します
...........
Wi-Fi接続に成功しました
IPアドレス: 192.168.1.37
Wi-Fi接続中
Wi-Fi接続中
Wi-Fi接続中
Wi-Fi接続中

ここまで

PlatformIOでのWi-Fi機能開発のやり方が分かった。
特別なライブラリ追加不要だったので、スムーズだった。

次回は、本番用プログラムを進める。

M5Stampをバスおもちゃに仕込む - 3. 開発環境用意

↓ 前回記事

nokixa.hatenablog.com

前回ハードはできたので、プログラミングを進めていく。

やること

前まで、VSCodeと拡張機能のEspressif IDFで開発していたが、生成AIに今回こんなことをやりたいと聞いた(課金している知り合いに聞いてもらった)ところ、PlatformIOというツールでの開発例を教えてもらったので、PlatformIOをやってみる。

PlatformIOインストール

VSCodeの拡張機能をインストール。

対応しているプラットフォーム、フレームワークの記載もある。
今回のESP32も対応しているよう。

Platforms: Atmel AVR, Atmel SAM, Espressif 32, Espressif 8266, Freescale Kinetis, Infineon XMC, Intel ARC32, Intel MCS-51 (8051), Kendryte K210, Lattice iCE40, Maxim 32, Microchip PIC32, Nordic nRF51, Nordic nRF52, NXP LPC, RISC-V, Silicon Labs EFM32, ST STM32, ST STM8, Teensy, TI MSP430, TI Tiva, WIZNet W7500

Frameworks: Arduino, CMSIS, ESP-IDF, ESP8266 RTOS SDK, Freedom E SDK, Kendryte Standalone SDK, Kendryte FreeRTOS SDK, libOpenCM3, mbed, PULP OS, SPL, STM32Cube, WiringPi, Zephyr RTOS

Espressif 32という表記だが、ESP32と同義と思っていいか?

一応Espressifを調べておく。

Espressif Systemsは中国に拠点を持ち、SoC(システム・オン・チップ)製品、BluetoothおよびWi-Fi通信用モジュールを製造するファブレスメーカーです。
Espressifは2008年に設立され、上海に本社を置いています。Espressifでは、ESP8266やESP32ファミリーに代表される、1つのチップに様々な機能(32ビットマイクロコントローラ、メモリ、無線通信)を搭載するSoC製品を製造しています。同社の製品は、多機能、価格、製品および開発用キットの幅広いラインナップで、愛好家のみならず電子機器開発プロジェクトに携わるプロからも高い評価を得ています。
SoC集積回路およびEspressifのモジュールは、モノのインターネット(IoT)分野で最も多く用いられています。

https://www.tme.com/jp/ja/linecard/p,espressif_1109/

インストールはちょっと時間かかった。

VSCodeの再起動を求められた。

プロジェクト作成

VSCodeの左のバーを見ると、PlatformIOのハチのアイコンができている。
クリックすると、手順がガイドされているよう。

"Create New Project"をクリックすると、こんな画面が出てきた。

"New Project"をクリックすると、"Project Wizard"が出てきた。
ボードを選択できる。

ただ、今回のM5Stamp C3そのものはなく、"M5Stamp-Pico"ならあった。

このサイトによると、"Espressif ESP32-C3-DevKitM-1"を選択すればいいよう。

Arduino勉強会/41-M5Stamp-C3Uをデバッグする(暫定方法) - PukiWiki

ということで、こんな感じで設定。
今回はArduinoのフレームワークにする。生成AIの回答の通りで。
プロジェクトのLocationは、"Use default location"のチェックを外して、今のワークスペースの下にした。
デフォルトのままだと、Windowsのユーザーフォルダの下にできてしまったので。

最後に"finish"をクリック。

ちょっと時間がかかる。

こんな感じでプロジェクトフォルダと、中身ができた。
元のフォルダの下に作ったが、新しく作られたフォルダがVSCodeのワークスペースに追加された形になって、ダブってしまっている。

VSCodeを開き直して、ダブりはなくなった。

サンプルプログラム作成

生成AIに聞きながら、Hello Worldをまずやってみた。

ソースコード編集

srcフォルダにmain.cppがすでにあるが、中身を下記のように書き換え。

#include <Arduino.h>

void setup() {
  Serial.begin(115200);
}

void loop() {
  Serial.println("Hello, world!");
  delay(1000);
}

platform.ini編集

上記のmain.cppでは、シリアルポートを115200のボーレートに設定しているので、下記の設定の追加がおそらく必要。

monitor_speed = 115200

platform.iniの全体は下記のようになっている。

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:esp32-c3-devkitm-1]
platform = espressif32
board = esp32-c3-devkitm-1
framework = arduino
monitor_speed = 115200

デバイス接続

M5StampをPCに接続して、PIO Homeで"Devices"タブを開いてみると、きちんと認識されているよう。

コンパイル、実行

どこのボタンを押せばいいのか?と思ったが、VSCodeの左のバー(アクティビティバー)のハチのアイコン(PlatformIOのアイコン)をクリックすると、"PROJECT TASKS"というのが出ている。まずはPlatformIOのプロジェクトを指定する必要があるよう。

"Pick a folder"をクリックして、さっき作ったプロジェクトを選ぶと、しばらくして表示が変わった。
"Build"とか"Upload"とか、それっぽいボタンが出てきている。

"Build"をクリックすると、ターミナルが起動して、ビルドが成功した表示が出た。

ターミナルの表示全部見る

Executing task: C:\Users\a\.platformio\penv\Scripts\platformio.exe run --environment esp32-c3-devkitm-1 

Processing esp32-c3-devkitm-1 (platform: espressif32; board: esp32-c3-devkitm-1; framework: arduino)
--------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-c3-devkitm-1.html
PLATFORM: Espressif 32 (6.9.0) > Espressif ESP32-C3-DevKitM-1
HARDWARE: ESP32C3 160MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-builtin, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-arduinoespressif32 @ 3.20017.0 (2.0.17)
 - tool-esptoolpy @ 1.40501.0 (4.5.1)
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 33 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
Compiling .pio\build\esp32-c3-devkitm-1\src\main.cpp.o
Building .pio\build\esp32-c3-devkitm-1\bootloader.bin
Generating partitions .pio\build\esp32-c3-devkitm-1\partitions.bin
esptool.py v4.5.1
Creating esp32c3 image...
Merged 1 ELF section
Successfully created esp32c3 image.
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Esp.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\FirmwareMSC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\FunctionalInterrupt.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\HWCDC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\HardwareSerial.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\IPAddress.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\IPv6Address.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\MD5Builder.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Print.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Stream.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\StreamString.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Tone.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USB.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USBCDC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USBMSC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\WMath.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\WString.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\base64.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\cbuf.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-adc.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-bt.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-cpu.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-dac.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-gpio.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-i2c-slave.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-i2c.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-ledc.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-matrix.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-misc.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-psram.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-rgb-led.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-rmt.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-sigmadelta.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-spi.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-time.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-timer.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-tinyusb.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-touch.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-uart.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\firmware_msc_fat.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\libb64\cdecode.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\libb64\cencode.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\main.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\stdlib_noniso.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\wiring_pulse.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\wiring_shift.c.o
Archiving .pio\build\esp32-c3-devkitm-1\libFrameworkArduino.a
Linking .pio\build\esp32-c3-devkitm-1\firmware.elf
Retrieving maximum program size .pio\build\esp32-c3-devkitm-1\firmware.elf
Checking size .pio\build\esp32-c3-devkitm-1\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [          ]   4.2% (used 13748 bytes from 327680 bytes)
Flash: [==        ]  18.9% (used 247460 bytes from 1310720 bytes)
Building .pio\build\esp32-c3-devkitm-1\firmware.bin
esptool.py v4.5.1
Creating esp32c3 image...
Merged 2 ELF sections
Successfully created esp32c3 image.
================================== [SUCCESS] Took 9.23 seconds ==================================
 *  Terminal will be reused by tasks, press any key to close it. 

次に、"Upload"ボタンを押したら、新しいターミナルが表示されて、マイコンにプログラムを書き込んだ表示になった。

ターミナルの表示全部見る

 *  Executing task: C:\Users\a\.platformio\penv\Scripts\platformio.exe run --target upload --environment esp32-c3-devkitm-1 

Processing esp32-c3-devkitm-1 (platform: espressif32; board: esp32-c3-devkitm-1; framework: arduino)
---------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-c3-devkitm-1.html
PLATFORM: Espressif 32 (6.9.0) > Espressif ESP32-C3-DevKitM-1
HARDWARE: ESP32C3 160MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-builtin, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-arduinoespressif32 @ 3.20017.0 (2.0.17)
 - tool-esptoolpy @ 1.40501.0 (4.5.1)
 - tool-mkfatfs @ 2.0.1
 - tool-mklittlefs @ 1.203.210628 (2.3)
 - tool-mkspiffs @ 2.230.0 (2.30)
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 33 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
Retrieving maximum program size .pio\build\esp32-c3-devkitm-1\firmware.elf
Checking size .pio\build\esp32-c3-devkitm-1\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"       
RAM:   [          ]   4.2% (used 13748 bytes from 327680 bytes)
Flash: [==        ]  18.9% (used 247460 bytes from 1310720 bytes)
Configuring upload protocol...
AVAILABLE: cmsis-dap, esp-bridge, esp-builtin, esp-prog, espota, esptool, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa
CURRENT: upload_protocol = esptool
Looking for upload port...
Auto-detected: COM3
Uploading .pio\build\esp32-c3-devkitm-1\firmware.bin
esptool.py v4.5.1
Serial port COM3
Connecting....
Chip is ESP32-C3 (revision v0.3)
Features: WiFi, BLE
Crystal is 40MHz
MAC: 68:67:25:b2:d0:54
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00003fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x0000e000 to 0x0000ffff...
Flash will be erased from 0x00010000 to 0x0004ffff...
Compressed 13248 bytes to 9562...
Writing at 0x00000000... (100 %)
Wrote 13248 bytes (9562 compressed) at 0x00000000 in 0.5 seconds (effective 228.9 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 146...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (146 compressed) at 0x00008000 in 0.1 seconds (effective 414.7 kbit/s)...
Hash of data verified.
Compressed 8192 bytes to 47...
Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 567.7 kbit/s)...
Hash of data verified.
Compressed 258896 bytes to 143444...
Writing at 0x00010000... (11 %)
Writing at 0x0001b29d... (22 %)
Writing at 0x00022d30... (33 %)
Writing at 0x0002993b... (44 %)
Writing at 0x0002f9c9... (55 %)
Writing at 0x00035b90... (66 %)
Writing at 0x0003be8e... (77 %)
Writing at 0x000445bb... (88 %)
Writing at 0x0004a53e... (100 %)
Wrote 258896 bytes (143444 compressed) at 0x00010000 in 4.4 seconds (effective 467.6 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
========================== [SUCCESS] Took 8.99 seconds ==========================
 *  Terminal will be reused by tasks, press any key to close it. 

最後に、"Monitor"をクリックすると、また新しいターミナルが開き、"Hello, world!"が表示された。
作ったプログラムはきちんと動いていそう。

ターミナルの表示全部見る

 *  Executing task: C:\Users\a\.platformio\penv\Scripts\platformio.exe device monitor --environment esp32-c3-devkitm-1 

--- Terminal on COM3 | 115200 8-N-1
--- Available filters and text transformations: colorize, debug, default, direct, esp32_exception_decoder, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!

サンプルプログラム2つ目

このサイト見ると、M5Stampに搭載されているNeoPixelのLEDの点灯方法が書かれている。
ライブラリは必要なよう。

Arduino勉強会/41-M5Stamp-C3Uをデバッグする(暫定方法) - PukiWiki

PIO HOMEを見てみると、左のタブに"Libraries"とあり、見てみると、検索ができるよう。
"neo pixel"で検索すると、Adafruit社のライブラリが出てきた。

このライブラリをクリックしてみると、説明と、"Add to Project"ボタンがある。

"Add to Project"ボタンを押すと、どのプロジェクトに追加するかのダイアログが出るので、今回のプロジェクトを選択して、"Add"をクリックする。

上記の参考サイトのLチカのサンプルコードを使わせていただいて、main.cppに貼り付ける。

Arduino勉強会/41-M5Stamp-C3Uをデバッグする(暫定方法) - PukiWiki

これで、先ほどと同様にビルド、アップロードすると、LEDが赤くチカチカするのが確認できた。

一応、ビルドのときのログも。この中に、NeoPixel用のライブラリをビルドしてる部分もある。

ログを全部見る

Executing task: C:\Users\a\.platformio\penv\Scripts\platformio.exe run --environment esp32-c3-devkitm-1 

Processing esp32-c3-devkitm-1 (platform: espressif32; board: esp32-c3-devkitm-1; framework: arduino)
---------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-c3-devkitm-1.html
PLATFORM: Espressif 32 (6.9.0) > Espressif ESP32-C3-DevKitM-1
HARDWARE: ESP32C3 160MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-builtin, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-arduinoespressif32 @ 3.20017.0 (2.0.17)
 - tool-esptoolpy @ 1.40501.0 (4.5.1)
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 34 compatible libraries
Scanning dependencies...
Dependency Graph
|-- Adafruit NeoPixel @ 1.12.3
Building in release mode
Compiling .pio\build\esp32-c3-devkitm-1\src\main.cpp.o
Building .pio\build\esp32-c3-devkitm-1\bootloader.bin
Generating partitions .pio\build\esp32-c3-devkitm-1\partitions.bin
esptool.py v4.5.1
Creating esp32c3 image...
Merged 1 ELF section
Successfully created esp32c3 image.
Compiling .pio\build\esp32-c3-devkitm-1\libc0e\Adafruit NeoPixel\Adafruit_NeoPixel.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\libc0e\Adafruit NeoPixel\esp.c.o
Compiling .pio\build\esp32-c3-devkitm-1\libc0e\Adafruit NeoPixel\esp8266.c.o
Compiling .pio\build\esp32-c3-devkitm-1\libc0e\Adafruit NeoPixel\kendyte_k210.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Esp.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\FirmwareMSC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\FunctionalInterrupt.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\HWCDC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\HardwareSerial.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\IPAddress.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\IPv6Address.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\MD5Builder.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Print.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Stream.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\StreamString.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\Tone.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USB.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USBCDC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\USBMSC.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\WMath.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\WString.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\base64.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\cbuf.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-adc.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-bt.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-cpu.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-dac.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-gpio.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-i2c-slave.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-i2c.c.o
Archiving .pio\build\esp32-c3-devkitm-1\libc0e\libAdafruit NeoPixel.a
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-ledc.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-matrix.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-misc.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-psram.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-rgb-led.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-rmt.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-sigmadelta.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-spi.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-time.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-timer.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-tinyusb.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-touch.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\esp32-hal-uart.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\firmware_msc_fat.c.o    
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\libb64\cdecode.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\libb64\cencode.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\main.cpp.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\stdlib_noniso.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\wiring_pulse.c.o
Compiling .pio\build\esp32-c3-devkitm-1\FrameworkArduino\wiring_shift.c.o
Archiving .pio\build\esp32-c3-devkitm-1\libFrameworkArduino.a
Linking .pio\build\esp32-c3-devkitm-1\firmware.elf
Retrieving maximum program size .pio\build\esp32-c3-devkitm-1\firmware.elf
Checking size .pio\build\esp32-c3-devkitm-1\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"       
RAM:   [          ]   4.2% (used 13804 bytes from 327680 bytes)
Flash: [==        ]  18.4% (used 241046 bytes from 1310720 bytes)
Building .pio\build\esp32-c3-devkitm-1\firmware.bin
esptool.py v4.5.1
Creating esp32c3 image...
Merged 2 ELF sections
Successfully created esp32c3 image.
========================== [SUCCESS] Took 7.97 seconds ==========================
 *  Terminal will be reused by tasks, press any key to close it. 

以上

開発環境の用意、プロジェクトのビルド、あとはライブラリの追加のしかたも確認できた。

次回は、Wi-Fi接続のプログラムを作ってみる。

M5Stampをバスおもちゃに仕込む - 2. はんだ付け

↓ 前回記事

nokixa.hatenablog.com

前回に引き続き、バスのおもちゃへのM5Stamp組み込みを進めた。
今回ははんだ付け作業。

やったこと

前回の手書き回路図をもとに、部品をはんだ付けした。

結果

こんな感じに配線した。

収納するとこんな感じ。

バスおもちゃ自体のプッシュボタンの回路接続を調べると、なんと片側がVCCに直結していた。
GND接続とプルアップかと思っていたので、想定外。

M5Stampからオープンドレイン出力で制御しようと思っていたが、それだとミスった時に、VCCとGNDがIOピンを介して直結になってしまう。

ということを心配して、IOピンとプッシュボタンピンの間に、家にあった適当な抵抗を入れておいた。

抵抗のカラーコードを見ると、黄、茶、黒のように見えたので、41Ω?そんな変な抵抗値あるか?

E24系列調べなおしたが、やっぱりない。

家のしょぼいテスタで測ってみたが、60~70Ωの値が出て、やっぱり信用ならない。
一応それぐらいの抵抗値ならまあいいか。

これで動かすと、前より元気な感じの声が出るようになった。

www.dropbox.com

USB接続でも動いた。

以上

次からはいよいよプログラミング。

M5Stampをバスおもちゃに仕込む

M5Stampを久しぶりに触る。

子供のおもちゃで、ちょうどいい条件のものがあったので、これにM5Stampを仕込んで、改造してみる。

おもちゃ概要

対象のおもちゃはこれ。
バスの形をしていて、横にボタンが付いていて、押すと「ピンポーン 次、止まります」と音が出る。

]

www.dropbox.com

妻が誰かからもらったものだが、画像検索すると、「げんき」という雑誌の付録のよう。

げんき 2020年 12 月号 [雑誌] |本 | 通販 | Amazon

中を開けてみる(ねじは△だが、マイナスドライバーで無理やり開けた)と、こんな感じ。

  • 中にいい感じのスペースがあって、M5Stamp入れたり、改造のしがいがありそう。
  • LR44のボタン電池2個で動いている。元々は電池が死にかけで、交換できるかと思って開けたのが今回のきっかけ。
  • ボタン電池は高いからあまり使いたくないが、このスペースなら単4電池が入った。
  • 昇圧すれば単4電池1本からでも動かせる。後から考えたが、2本も入りそうだったかも。でもまた電池ボックス買うのが面倒なのでまあいいやということで。
  • プッシュボタンのところから線を引き出してM5Stampにつなげれば、M5Stampからボタンを押す相当のことができそう。

ということで、電池を単4 1本で動かせるようにするのと、そのついでに、M5Stampを仕込んで、スマホ等の操作からピンポン鳴らせるようにしたい。

ã‚„ã‚Šæ–¹

  • おもちゃ内に、単4 1本の電池ボックスを入れる。
  • 昇圧モジュールとして、秋月のXCL103を使ったモジュールを使う。かなり小型でいい感じ。
    akizukidenshi.com
    M5Stampの電源は、基本は5V入力なので、昇圧モジュールは5V出力のものにした。
  • M5Stamp上にレギュレータがあり、3.3V電源を作っていて、これがM5Stamp内の回路のメイン電源になっている。
    docs.m5stack.com

    これでだいたいボタン電池2個相当の電圧になると思うので、これをおもちゃの電源とする。
  • 昇圧モジュールからの電源でM5Stampを動かしたいが、プログラム書き込みやデバッグ中はPCと接続、USBポートからの給電になる。これがぶつかってしまうので、昇圧モジュール側にダイオードを挟んでおく。前にショットキーのダイオード(SD103A)を買ってて、ちょうどいいのでこれを使う。
    超小型ショットキーダイオード 40V350mA SD103A: 半導体 秋月電子通商-電子部品・ネット通販
  • あと、プッシュボタンからM5Stampに配線もつなぐ。

回路構成、手書きだがこんな感じ。

材料は揃えてある。

ここまで

次回、ハードを作るところから進めていく。

ゼロから作るDeep Learningやる - 2章 パーセプトロン

「ゼロから作るDeep Learning」をやって、きちんとDeep Learningの基礎を理解したかったので、購入した。

www.oreilly.co.jp

GitHub - oreilly-japan/deep-learning-from-scratch: 『ゼロから作る Deep Learning』(O'Reilly Japan, 2016)

読んでコードも書きながら、ブログにも記録していく。

2章 パーセプトロン

1章はPython自体とかnumpyとかの説明なので省く。

2章から進める。

内容は、パーセプトロンの説明と、それを使った論理ゲートの実装。

パーセプトロンをクラスで実装して、重みをコンストラクタの引数にすると良いような気がしたので、そんな感じでやってみた。

import numpy as np

クラスでパーセプトロンを実装

class perceptron:
    def __init__(self, w1:float, w2:float, b:float) -> None:
        self.w = np.array([w1, w2])
        self.b = b
    
    def __call__(self, x1:float, x2:float) -> float:
        x = np.array([x1, x2])
        return 1.0 if (self.b + np.sum(self.w * x) > 0.0) else 0.0

ANDゲートの実装

重みは適当。

p_and = perceptron(0.5, 0.5, -0.7)

print(p_and(0, 0))
print(p_and(0, 1))
print(p_and(1, 0))
print(p_and(1, 1))
0.0
0.0
0.0
1.0

NANDゲートの実装

重みを変える。

p_nand = perceptron(-0.5, -0.5, 0.7)
print(p_nand(0,0))
print(p_nand(0,1))
print(p_nand(1,0))
print(p_nand(1,1))
1.0
1.0
1.0
0.0

ORゲートの実装

これも重みを変えるだけ。

p_or = perceptron(0.5, 0.5, -0.2)
print(p_or(0,0))
print(p_or(0,1))
print(p_or(1,0))
print(p_or(1,1))
0.0
1.0
1.0
1.0

XORゲートの実装

3種類のゲートを組み合わせる。

def p_xor(x1, x2):
    return p_and(p_or(x1, x2), p_nand(x1, x2))

print(p_xor(0,0))
print(p_xor(0,1))
print(p_xor(1,0))
print(p_xor(1,1))
0.0
1.0
1.0
0.0

以上

ここからどんどん進めて、理解していきたい。

OpenCVやってみる - 58. Homography訂正

以前の記事で、シャルトル大聖堂の写真を使って、特徴点マッチングとHomography(射影変換)の記事を書いたが、射影変換でカメラ視点変換しようと思うと、被写体が同じ平面上にないといけない(1つの行列で変換できるのは同じ平面にある点に限られる)、というのを今回知ったので、訂正記事として書く。

nokixa.hatenablog.com

前の記事振り返り

上の記事でやったのは、

  • カメラ向きを変えて撮影した3枚のシャルトル大聖堂の写真を使用
  • 特徴点を検出
  • 2枚の写真間で特徴点のマッチングを実施
  • 上記マッチングで、射影変換の行列を算出
  • この行列で、写真間で視点の変換を実施

だが、1つの射影変換行列で視点変換できるのは、実空間で同じ平面上にある点だけということで、また、シャルトル大聖堂の写真で検出した特徴点はそうなっていなさそうで、おそらく不適切な変換になっているかというところ。

下記はOpenCVの公式ドキュメントのfindHomography()関数の説明。

OpenCV: Camera Calibration and 3D Reconstruction

ここでも、引数の説明で、対応点は"original plane"の点と書かれていて、同じ平面にないといけない、とされているよう。

srcPoints Coordinates of the points in the original plane, a matrix of the type CV_32FC2 or vector .
dstPoints Coordinates of the points in the target plane, a matrix of the type CV_32FC2 or a vector .

やること

1つの射影変換行列での視点変換をやるとずれが出るのではと予想されるので、それを確認してみる。

前は変換後画像のブレンディングで見てみたが、これだときちんと確認できないかも。

検出した特徴点を変換して、マッチング先と座標が合うかどうか?で確認できそうに思うので、それをやってみる。

まず元と同じことを実施

シャルトル大聖堂の画像の読み込み、特徴点算出、特徴点マッチングを行う。
今回はJupyter上で。
前回より、若干処理を整理する。

写真は、(i)両方の塔の写真、(ii)右側の塔の写真、(iii)左側の塔の写真、の3つがある。

import cv2
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
def plot_image(img, figsize=(6.4, 4.8)):
    plt.figure(figsize=figsize, dpi=100)
    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    plt.xticks([]), plt.yticks([])
    plt.show()

↑ Jupyterセル上で画像表示するための関数。

img_both = cv2.imread('Chartres_both.JPG')
img_right = cv2.imread('Chartres_right.JPG')
img_left = cv2.imread('Chartres_left.JPG')
img_both = cv2.resize(img_both, None, fx=0.25, fy=0.25, interpolation=cv2.INTER_AREA)
img_right = cv2.resize(img_right, None, fx=0.25, fy=0.25, interpolation=cv2.INTER_AREA)
img_left = cv2.resize(img_left, None, fx=0.25, fy=0.25, interpolation=cv2.INTER_AREA)

plot_image(img_both)
plot_image(img_right)
plot_image(img_left)

sift = cv2.SIFT_create()
kp_both, des_both = sift.detectAndCompute(img_both, None)
kp_right, des_right = sift.detectAndCompute(img_right, None)
kp_left, des_left = sift.detectAndCompute(img_left, None)

bf = cv2.BFMatcher()
matches_right = bf.match(des_both, des_right)
matches_right = sorted(matches_right, key = lambda x:x.distance)
matches_left = bf.match(des_both, des_left)
matches_left = sorted(matches_left, key = lambda x:x.distance)

射影変換行列計算

これも以前と同じだが、変換・比較するマッチング点を増やしたらずれ具合が分かりそうな気がするので、点数を選べるようにして、処理を関数化しておく。
ここでは、(i)両方の塔の写真 → (ii)右側の塔の写真の変換を計算。

def calc_homography_right(n=20):
    kp_both_match_r = np.float32([kp_both[m.queryIdx].pt for m in matches_right[:n]]).reshape(-1,1,2)
    kp_right_match = np.float32([kp_right[m.trainIdx].pt for m in matches_right[:n]]).reshape(-1,1,2)
    mat, mask = cv2.findHomography(kp_both_match_r, kp_right_match, cv2.RANSAC, 5.0)
    return mat, mask, kp_both_match_r, kp_right_match
mat_r, mask_r, kp_both_match_r, kp_right_match = calc_homography_right(n=20)
print(mask_r)
[[1]
 [1]
 [1]
 [0]
 [1]
 [1]
 [1]
 [1]
 [1]
 [0]
 [1]
 [1]
 [1]
 [0]
 [1]
 [1]
 [1]
 [1]
 [1]
 [1]]

以前は全マッチング点inlierになったが、今回はoutlierが出てしまった。
前と比べて、環境を作り直してるが、それで微妙な違いが出たのか?

射影変換実施

(i)両方の塔の写真に射影変換を適用する。

img_both_to_right = cv2.warpPerspective(img_both, mat_r, (750, 1000))
img_right_comp = np.hstack((img_right, img_both_to_right))
plot_image(img_right_comp)

これだと同じような画像になったように見えるが、今回はもうちょっときちんと確認できるように試してみる。

マッチング点描画

マッチングに使用した特徴点を、(ii)右側の塔の写真に描画してみる。
(i)両方の塔の写真の特徴点は、射影変換をかけてから描画する。

(ii)右側の塔の写真の特徴点は太めの緑、(i)両方の塔の写真の特徴点は細めの赤のマークにしている。

kp_right_match = np.array(kp_right_match, dtype=int).reshape(-1, 2)
kp_both_match_r_trans = cv2.perspectiveTransform(np.array(kp_both_match_r, dtype=float).reshape(-1,1,2), mat_r)
kp_both_match_r_trans = kp_both_match_r_trans.reshape(-1, 2).astype(int)
img_r = img_right.copy()
for kp_b, kp_r, mask in zip(kp_right_match, kp_both_match_r_trans, mask_r):
    marker = cv2.MARKER_TILTED_CROSS if mask == 0 else cv2.MARKER_CROSS
    cv2.drawMarker(img_r, kp_b, color=(0,255,0), markerType=marker, markerSize=20, thickness=5)
    cv2.drawMarker(img_r, kp_r, color=(0,0,255), markerType=marker, markerSize=20, thickness=2)
plot_image(img_r, figsize=(12.8, 9.6))

これだとよく分からない。
そんなにずれていないように見えるが?

マッチング点変更

使うマッチング点を増やしたら、ずれる点が見えてこないか?
100点ぐらいにしてみる。

mat_r, mask_r, kp_both_match_r, kp_right_match = calc_homography_right(n=100)

どんな特徴点が出て、どうマッチングされたかも確認したいので、cv2.drawMatches()で描画してみる。

img_match = cv2.drawMatches(img_both, kp_both, img_right, kp_right, matches_right[:100], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
plot_image(img_match, figsize=(12.8, 9.6))

だいたいマッチングしてる感じだが、塔の上のほうは模様がシンプルなせいか、マッチングに失敗している部分も見受けられる。

とりあえずこれで、マッチング点描画をやってみる。

kp_right_match = np.array(kp_right_match, dtype=int).reshape(-1, 2)
kp_both_match_r_trans = cv2.perspectiveTransform(np.array(kp_both_match_r, dtype=float).reshape(-1,1,2), mat_r)
kp_both_match_r_trans = kp_both_match_r_trans.reshape(-1, 2).astype(int)
img_r = img_right.copy()
for kp_b, kp_r, mask in zip(kp_right_match, kp_both_match_r_trans, mask_r):
    marker = cv2.MARKER_TILTED_CROSS if mask == 0 else cv2.MARKER_CROSS
    cv2.drawMarker(img_r, kp_b, color=(0,255,0), markerType=marker, markerSize=20, thickness=5)
    cv2.drawMarker(img_r, kp_r, color=(0,0,255), markerType=marker, markerSize=20, thickness=2)
plot_image(img_r, figsize=(12.8, 9.6))

変換行列計算時にoutlierと判定されたものはxマークで表示するようにしているが、本当にマッチングを失敗してそうなのは置いておいても、塔の先端が全部outlierになっている。

1つの行列で変換しようと思うと整合性が取れないので、outlierとなったのか。

左側の塔でも確認

(ii)右側の塔はマッチングがあまりよくないので、(iii)左側の塔でも試してみる。

def calc_homography_left(n=20):
    kp_both_match_l = np.float32([kp_both[m.queryIdx].pt for m in matches_left[:n]]).reshape(-1,1,2)
    kp_left_match = np.float32([kp_left[m.trainIdx].pt for m in matches_left[:n]]).reshape(-1,1,2)
    mat, mask = cv2.findHomography(kp_both_match_l, kp_left_match, cv2.RANSAC, 5.0)
    return mat, mask, kp_both_match_l, kp_left_match
mat_l, mask_l, kp_both_match_l, kp_left_match = calc_homography_left(n=100)
img_match = cv2.drawMatches(img_both, kp_both, img_left, kp_left, matches_left[:100], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
plot_image(img_match, figsize=(12.8, 9.6))

こっちはマッチングがもうちょっとうまくいっているように見える。

同様にマッチング点を描画してみる。

kp_left_match = np.array(kp_left_match, dtype=int).reshape(-1, 2)
kp_both_match_l_trans = cv2.perspectiveTransform(np.array(kp_both_match_l, dtype=float).reshape(-1,1,2), mat_l)
kp_both_match_l_trans = kp_both_match_l_trans.reshape(-1, 2).astype(int)
img_l = img_left.copy()
for kp_b, kp_l, mask in zip(kp_left_match, kp_both_match_l_trans, mask_l):
    marker = cv2.MARKER_TILTED_CROSS if mask == 0 else cv2.MARKER_CROSS
    cv2.drawMarker(img_l, kp_b, color=(0,255,0), markerType=marker, markerSize=20, thickness=5)
    cv2.drawMarker(img_l, kp_l, color=(0,0,255), markerType=marker, markerSize=20, thickness=2)
plot_image(img_l, figsize=(12.8, 9.6))

(ii)右側の塔よりわかりやすくなった。
右下の点が全部outlierになっていて、ずれも大きくなっている。
写真を見る限り、確かにちょっとカメラ寄りに近い面になっているような。

あと、塔の右上の点、塔の左のでっぱりの点もずれが大きい。
それ以外の点は、比較的同じ平面にあるということかな。

以上

ちゃんと理解せずにHomography(射影変換)を使っていたので反省。
この機に気付けたのはよかった。