FLINTERS BLOG
🤖

Google Antigravity × ESP32で始めるIoT開発

に公開

こんにちは。FLINTERSの川上です。
この記事はアドベントカレンダー21日目の記事です。

最近AIの成長が止まらないですね。
先月にはGoogle Antigravityがリリースされ趣味で触っていたのですが、コード生成だけでなくUIのテストとWebp動画でUI操作のエビデンスを残してくれてまた人間の仕事は一つ減ったなと感じさせられます。
このまま人間はAcceptを押すだけの存在になってしまうのか...と考えていた所、現実世界において人間が動かなくてはならない開発=IoT開発はまだまだ人間が頑張る必要があるのではないか?と考えAI x IoT開発をこの度行ってみました。

試してみたこと一覧

  1. 基板上LEDの点滅制御
  2. GPSモジュールとの接続
  3. 加速度センサとの接続
  4. 輝度センサ × Wake On Lan

開発環境の準備

環境構築はGoogle Antigravityのみ用意した状態です。
書き込み・シリアルモニタなどは一切ない状態から初めてみましたが、自動的にPlatformIOがインストールされていました。

ESP32はそのへんに転がっていた「ESP32 Devkit V1」を利用しました。

1. 基板上LEDの点滅制御

まずはIoTにおけるHello World、基盤のLEDを光らせるLチカプログラムを書いてもらいました。
ここまでは配線などは必要ないので、コードがしっかりしていれば問題は起らないはずです。

ESP32の基盤のLEDを点滅させるプログラムを書き込んでください

サクッと以下のコードが出てきました。
その後エディタが勝手に書き込みまでしてくれており、

// LED点滅制御
#define LED_BUILTIN 2  // ESP32の内蔵LED

void setup() {
    Serial.begin(115200);
    pinMode(LED_BUILTIN, OUTPUT);
    Serial.println("ESP32 LED Blink Started");
}

void loop() {
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.println("LED ON");
    delay(1000);

    digitalWrite(LED_BUILTIN, LOW);
    Serial.println("LED OFF");
    delay(1000);
}

突然ESP32が光ってました。

人間の労働はプロンプト、Accept、ESP32とPCをつなぐぐらいでした。

2. GPSモジュールとの接続

次は配線が必要なタスクに移ります。
GY-GPS6MV2というGPSモジュールがあるので、接続し現在位置を教えてもらいましょう

次はGY-GPS6MV2を接続してGPSで位置を知りたいです。 配線の指示とコードの書き込みをお願いします、

数秒でレビュー依頼が来たのですが、「以下の配線図に従ってハードウェアの接続をお願いします。」というレビュー依頼に笑ってしまいました。
Acceptを押すだけの人類から配線もこなす人類にステップアップです。

## User Review Required
- **[IMPORTANT] 配線作業**: 以下の配線図に従ってハードウェアの接続をお願いします。

### 配線指示
GY-GPS6MV2 と ESP32 を以下のように接続してください。
ESP32の **Serial2** (Hardware Serial) を使用します。

| GY-GPS6MV2 | ESP32 | 備考 |
| :--- | :--- | :--- |
| **VCC** | **3.3V** (または 5V/VIN) | モジュールは通常3.3V-5V対応ですが、3.3V推奨 |
| **GND** | **GND** | 共通グランド |
| **TX** | **GPIO 16** (RX2) | GPSからの送信をESP32で受信 |
| **RX** | **GPIO 17** (TX2) | 必須ではありませんが接続推奨 |
コード
#include <Arduino.h>
#include <TinyGPS++.h>

/*
   This sample sketch demonstrates the normal use of a TinyGPS++ (TinyGPSPlus)
   object. It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
// ESP32 HardwareSerial
// RX: GPIO 16 (Connect to GPS TX)
// TX: GPIO 17 (Connect to GPS RX)
#define RXD2 16
#define TXD2 17

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);

  Serial.println(F("ESP32 GPS Sample"));
  Serial.println(F("Connecting to GPS module..."));
}

void loop() {
  // This sketch displays information every time a new sentence is correctly
  // encoded.
  while (Serial2.available() > 0) {
    if (gps.encode(Serial2.read())) {
      if (gps.location.isValid()) {
        Serial.print(F("Location: "));
        Serial.print(gps.location.lat(), 6);
        Serial.print(F(","));
        Serial.print(gps.location.lng(), 6);
        Serial.print(F("  Date/Time: "));
        Serial.print(gps.date.month());
        Serial.print(F("/"));
        Serial.print(gps.date.day());
        Serial.print(F("/"));
        Serial.print(gps.date.year());
        Serial.print(F(" "));
        Serial.print(gps.time.hour());
        Serial.print(F(":"));
        Serial.print(gps.time.minute());
        Serial.print(F(":"));
        Serial.print(gps.time.second());
      } else {
        Serial.print(F("Location: INVALID"));
      }
      Serial.println();
    }
  }

  if (millis() > 5000 && gps.charsProcessed() < 10) {
    Serial.println(F("No GPS detected: check wiring."));
    delay(1000);
  }
}

無事配線が済みましたが、ESP32とGPSモジュールが接続されていないエラーが出てしまいました。
やはりAIはまだまだダメだなと思っていた所、以下の提案がなされました。

1. **配線の再確認**: RXとTXが逆になっていませんか?
    - GPSの **TX** を ESP32の **GPIO 16** (RX2) に繋ぐ必要があります。
    - 試しにTXとRXの線を入れ替えてみてください。

確認した所、完全にそのとおりでした。配線ミスをする愚かな人類を優しく諭して頂けました。カメラでもついているのかと思いました。
配線修正後、無事緯度経度が表示されました。

35.695394,139.689741

35.695394,139.689741はFLINTERS本社の位置となっています。

3.加速度センサとの接続

引き続き配線の必要のあるGY-521という加速度センサを接続してもらいます。
ちなみに数年前このセンサを使い、pythonを使って腰痛を改善しようとしていました。

さてまずはプロンプトでコードと配線図を提案してもらいます。

次はGY-521で加速度などの情報を取得してみたいです。 配線の指示とコードの書き込みをお願いします、

今回も同じ様に配線接続依頼レビューをこなしてしていきます。

## User Review Required
- **[IMPORTANT] 配線作業**: 以下の配線図に従ってハードウェアの接続をお願いします。

### 配線指示
GY-521 と ESP32 を I2C で接続します。

| GY-521 | ESP32 | 備考 |
| :--- | :--- | :--- |
| **VCC** | **3.3V** | モジュールによっては5V対応ですが、3.3V推奨 |
| **GND** | **GND** | 共通グランド |
| **SCL** | **GPIO 22** | I2C クロック |
| **SDA** | **GPIO 21** | I2C データ |
コード
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Arduino.h>
#include <Wire.h>

Adafruit_MPU6050 mpu;

void setup(void) {
  Serial.begin(115200);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("Adafruit MPU6050 test!");

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  // set accelerometer range to +-8G
  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);

  // set gyro range to +- 500 deg/s
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);

  // set filter bandwidth to 21 Hz
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);

  Serial.println("");
  delay(100);
}

void loop() {
  /* Get new sensor events with the readings */
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  /* Print out the values */
  Serial.print("Acceleration X: ");
  Serial.print(a.acceleration.x);
  Serial.print(", Y: ");
  Serial.print(a.acceleration.y);
  Serial.print(", Z: ");
  Serial.print(a.acceleration.z);
  Serial.println(" m/s^2");

  Serial.print("Rotation X: ");
  Serial.print(g.gyro.x);
  Serial.print(", Y: ");
  Serial.print(g.gyro.y);
  Serial.print(", Z: ");
  Serial.print(g.gyro.z);
  Serial.println(" rad/s");

  Serial.print("Temperature: ");
  Serial.print(temp.temperature);
  Serial.println(" degC");

  Serial.println("");
  delay(500);
}

今回は配線ミスが無いように確認し、配線した所一発で加速度が取得できました。

加速度の情報は実際にセンサを現実世界で動かさないと確認ができないので、terminalで以下のコマンドを実行し、加速度をモニタリングすることにしました。

pio device monitor -b 115200

今回人間がAIに頼らず行ったコード実行はこれだけかな〜と思いながら加速度の確認ができたので再度Antigravityを触ると突然killコマンドを実行したいという提案をされました。

kill 24378

AIの反乱だー!と思いましたが、先程のコマンドが実行され続けているためAntigravityとESP32の通信ができないからkillしたいとのことでした。
本当に気が利くAIですね。

4.輝度センサ × Wake On Lan

最後に、KY-018という輝度センサーとWOLを組み合わせた複合的な処理をお願いしたいと思います。
機能としては、「一定以上の輝度を検知したらWOLを飛ばす」という処理になっています。
朝目覚めたらすぐにPC起動してほしいからですね。

輝度のしきい値を知りたいので、輝度の確認もモニタリングできるようにログを吐いてもらうコードも指定しました。

次はKY-018とWake on LANを組み合わせたいです
一定の輝度以上になったとき、WOLを送信したいです。
その場合の配線とコードの書き込みをお願いします。wifiの情報やMACアドレス、輝度のしきい値は自分で書き込みます
輝度と値の関係性がわからないので、シリアルモニタから確認できるようにしておいてください

今回はWOLの処理も必要なので、WiFiの情報やMACアドレスを入力する事も求められているリクエストが依頼されました。

## User Review Required
- **[IMPORTANT] ユーザー設定値**: プログラム書き込み後、ソースコード上部の以下の変数をユーザーご自身で書き換えていただく必要があります。
    - WiFi SSID / Password
    - 対象PCのMACアドレス
    - 輝度のしきい値 (Serial Monitorで値を確認後に設定)
- **[IMPORTANT] 配線作業**: 以下の配線図に従ってハードウェアの接続をお願いします。

### 配線指示
KY-018 (光センサモジュール) を ESP32 に接続します。

| KY-018 | ESP32 | 備考 |
| :--- | :--- | :--- |
| **S** (Signal) | **GPIO 32** | アナログ入力 (ADC) |
| **Middle** (VCC) | **3.3V** | 3.3V推奨 |
| **-** (GND) | **GND** | 共通グランド |
コード
#include <Arduino.h>
#include <WakeOnLan.h>
#include <WiFi.h>
#include <WiFiUdp.h>

// ==========================================
// [USER SETTINGS] 以下の設定を書き換えてください
// ==========================================
const char *PROG_SSID = "aaaaaaaa";
const char *PROG_PASS = "aaaaaaaa";
const char *MAC_ADDR = "00:00:00:00:00:00"; // Target PC's MAC Address
int THRESHOLD = 200;                        // Threshold to trigger WoL (0-4095)
// ==========================================

WiFiUDP UDP;
WakeOnLan WOL(UDP);

// Pin definition
const int SENSOR_PIN = 32;

// Variables
bool packetSent = false;

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

  Serial.println("\n\n--- ESP32 WoL & Light Sensor Demo ---");

  // WiFi Connection
  WiFi.begin(PROG_SSID, PROG_PASS);
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi Connected!");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  WOL.setRepeat(3, 100); // Repeat the packet 3 times with 100ms delay
}

void loop() {
  // Read analog value from the light sensor
  int analogValue = analogRead(SENSOR_PIN);

  // Print value for debugging
  Serial.printf("Analog Value: %d  (Threshold: %d)\n", analogValue, THRESHOLD);

  // Check threshold
  // Trigger when value is equal or lower than THRESHOLD (Darker or specific
  // condition)
  if (analogValue <= THRESHOLD) {
    if (!packetSent) {
      Serial.println(">> Threshold exceeded! Sending WoL packet...");
      WOL.sendMagicPacket(MAC_ADDR);
      Serial.println(">> Magic Packet sent!");
      packetSent = true;
    }
  } else {
    // Reset flag if value goes back to normal range (with hysteresis)
    if (analogValue > (THRESHOLD + 100)) {
      packetSent = false;
    }
  }

  delay(1000);
}

ちょっと配線が飛び飛びになってしまっていますが、作成完了しました。
現実世界の効率的な配線も考えてくれると嬉しいですが、製品によってピンも変わるのでそのあたりは人間のインプットも頑張らないといけないですね。

テストで輝度センサにライトを当ててやると、無事PCが遠隔起動できました。
配線もコードも100点満点ですね。

まとめ

さらっと流していましたが、AIがパーツの仕様を理解し、配線を正しく指示できるのは驚かされました。
ここまでできるなら自分が作りたかったCO2測定機、ESP32CAMによる監視カメラ、猫の健康管理...とやりたいことが全て片手間でできるように感じてきました。
興味が出てきたら皆様も年末年始の余暇にIoT開発いかがでしょうか?

明日の記事は野崎絢右さんによるObsidianの使い方記事となります。

FLINTERS BLOG
FLINTERS BLOG

Discussion