勉強しないとな~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

ここまで

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

大幅変更になりそう。