はじめに
ソフトウェア開発においては近年、AIエージェントを活用した開発の効率化が進んでいるが、組込み開発の領域においてAIエージェントの活用はソフトウェア領域程は耳にしない印象がありました。
そこでこの記事では、単純なLED点灯から始まり、RGB LEDのカラー制御、そして直感的に操作できるTkinter GUIアプリへと段階的にArduino開発をAIエージェントを活用して実施した一連のプロセスを紹介します。
Antigravityを活用したArduino制御の方法
AntigravityはGoogle DeepMindが開発したエージェント型AIコーディングアシスタントです。VS Codeなどのエディタに統合されており、以下のような操作をチャット形式の自然言語で指示できます。
- コードの生成・編集: 「〜の機能を追加して」と伝えるだけでファイルを直接書き換える
- コマンドの実行: 「このスクリプトを実行して」と指示すると仮想環境上でコマンドを発行する
なので、今回はAntigravityにPythonおよびArduinoのスケッチを作成させる形をとり、Arduinoの制御を行いました。
コード作成とArduinoへのプログラム書き込み時
ユーザー(自然言語で指示)
↓
Antigravity(Pythonおよびスケッチのコード作成)
↓
Arduino IDE(スケッチをArduino UNOに送信)
↓
Arduino
Arduinoの操作時
ユーザー(自然言語で指示)
↓
Antigravity(Pythonのコード修正やPythonプログラムの実行)
↓
Arduino(Pythonプログラムからシリアル通信で制御)
イメージ図
ステップ1: シリアル通信でLEDを点灯させる
最初の目標はシンプルで、PCからシリアル通信でコマンドを送り、Arduinoに接続したLEDを点灯・消灯させることでした。
回路図
Arduinoスケッチ
#include <Servo.h>
Servo myServo;
const int ledPin = 12;
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
myServo.attach(9);
myServo.write(0);
}
void loop() {
if (Serial.available() > 0) {
String command = Serial.readStringUntil('\n');
command.trim();
if (command == "LED_ON") {
digitalWrite(ledPin, HIGH);
Serial.println("LED turned ON");
} else if (command == "LED_OFF") {
digitalWrite(ledPin, LOW);
Serial.println("LED turned OFF");
}
}
}
Python制御スクリプト(control_arduino.py)
import serial, time, sys
PORT = 'COM3'
BAUD_RATE = 9600
def send_command(command):
ser = serial.Serial(PORT, BAUD_RATE, timeout=1)
time.sleep(2) # Arduinoのリセット待ち
ser.write((command + '\n').encode('utf-8'))
time.sleep(0.5)
response = ser.readline().decode('utf-8').strip()
print(f"Arduinoからの返答: {response}")
ser.close()
if __name__ == "__main__":
send_command(sys.argv[1])
コマンドラインから python control_arduino.py LED_ON を実行するとLEDが点灯し、Arduinoから「LED turned ON」と返答が返ってきました。
ステップ2: 単色LEDからRGB LEDへ
単色LEDでは色の表現に限界があるので、次のステップとしてRGB LEDに切り替え、コマンドで色を変えられるように拡張しました。
回路図
Arduinoスケッチ(RGB対応版)
#include <Servo.h>
Servo myServo;
const int redPin = 10;
const int greenPin = 11;
const int bluePin = 12;
void setup() {
Serial.begin(9600);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
myServo.attach(9);
myServo.write(0);
}
void loop() {
if (Serial.available() > 0) {
String command = Serial.readStringUntil('\n');
command.trim();
if (command == "COLOR_RED") {
digitalWrite(redPin, HIGH); digitalWrite(greenPin, LOW); digitalWrite(bluePin, LOW);
Serial.println("LED turned RED");
} else if (command == "COLOR_GREEN") {
digitalWrite(redPin, LOW); digitalWrite(greenPin, HIGH); digitalWrite(bluePin, LOW);
Serial.println("LED turned GREEN");
} else if (command == "COLOR_BLUE") {
digitalWrite(redPin, LOW); digitalWrite(greenPin, LOW); digitalWrite(bluePin, HIGH);
Serial.println("LED turned BLUE");
} else if (command == "COLOR_YELLOW") {
digitalWrite(redPin, HIGH); digitalWrite(greenPin, HIGH); digitalWrite(bluePin, LOW);
Serial.println("LED turned YELLOW");
} else if (command == "COLOR_OFF") {
digitalWrite(redPin, LOW); digitalWrite(greenPin, LOW); digitalWrite(bluePin, LOW);
Serial.println("LED turned OFF");
}
}
}
これにより、python control_arduino.py COLOR_RED のようなコマンドでLEDの色を変えられるようになりました。
ステップ3: TkinterによるGUIアプリへの進化
コマンドライン操作は毎回ターミナルを使う必要があり、直感的ではなかったです。そこでPython標準ライブラリの Tkinter を使い、ボタンひとつで操作できるGUIアプリへ移行しました。
GUIの構成
- RGB LEDカラーボタン: Red / Green / Blue / Yellow / OFF
- ステータスバー: Arduinoからの返答をリアルタイムで表示

(実際のプログラムはサーボモーターの制御も追加していたのでサーボモーター用の制御画面の記載もあります)
最終的なPythonスクリプト(GUI版)
import serial
import time
import tkinter as tk
from tkinter import messagebox
PORT = 'COM3'
BAUD_RATE = 9600
class ArduinoGUI:
def __init__(self, master):
self.master = master
self.master.title("Arduino RGB & Servo Control")
self.master.geometry("300x450")
self.ser = None
self.connect_serial()
# LED制御ボタン
tk.Label(master, text="Select Color", font=("Arial", 14)).pack(pady=5)
tk.Button(master, text="RED", bg="red", fg="white", font=("Arial", 12), command=lambda: self.send_command("COLOR_RED")).pack(fill=tk.X, padx=20, pady=2)
tk.Button(master, text="GREEN", bg="green", fg="white", font=("Arial", 12), command=lambda: self.send_command("COLOR_GREEN")).pack(fill=tk.X, padx=20, pady=2)
tk.Button(master, text="BLUE", bg="blue", fg="white", font=("Arial", 12), command=lambda: self.send_command("COLOR_BLUE")).pack(fill=tk.X, padx=20, pady=2)
tk.Button(master, text="YELLOW", bg="gold", fg="black", font=("Arial", 12), command=lambda: self.send_command("COLOR_YELLOW")).pack(fill=tk.X, padx=20, pady=2)
tk.Button(master, text="OFF", bg="gray", fg="white", font=("Arial", 12), command=lambda: self.send_command("COLOR_OFF")).pack(fill=tk.X, padx=20, pady=2)
# サーボ制御スライダー
tk.Label(master, text="Servo Angle (0 - 180)", font=("Arial", 14)).pack(pady=(15, 0))
self.servo_scale = tk.Scale(master, from_=0, to=180, orient=tk.HORIZONTAL, length=220)
self.servo_scale.set(0)
self.servo_scale.pack(pady=5)
# スライダーを離した時だけ送信(連続送信による通信詰まりを防ぐ)
self.servo_scale.bind("<ButtonRelease-1>", self.on_slider_release)
# ステータス表示
self.status_label = tk.Label(master, text="Status: Connected" if self.ser else "Status: Disconnected",
fg="green" if self.ser else "red")
self.status_label.pack(pady=10)
self.master.protocol("WM_DELETE_WINDOW", self.on_closing)
def connect_serial(self):
try:
self.ser = serial.Serial(PORT, BAUD_RATE, timeout=1)
time.sleep(2)
except Exception as e:
messagebox.showerror("Connection Error", f"Arduinoへの接続に失敗しました:\n{e}")
self.ser = None
def on_slider_release(self, event):
self.send_command(f"MOTOR_{self.servo_scale.get()}")
def send_command(self, command):
if self.ser and self.ser.is_open:
self.ser.write((command + '\n').encode('utf-8'))
self.master.after(100, self.read_response)
else:
messagebox.showwarning("Warning", "Arduinoが接続されていません。")
def read_response(self):
if self.ser and self.ser.in_waiting > 0:
response = self.ser.readline().decode('utf-8', errors='ignore').strip()
self.status_label.config(text=f"Arduino: {response}", fg="blue")
def on_closing(self):
if self.ser and self.ser.is_open:
self.ser.close()
self.master.destroy()
if __name__ == "__main__":
root = tk.Tk()
ArduinoGUI(root)
root.mainloop()
まとめと感想
今回の開発を通じて、以下の技術要素を段階的に実践しました。
| ステップ | 内容 |
|---|---|
| ① | Pythonのpyserialでシリアル通信を介してArduinoを制御 |
| ② | RGB LEDの配線 |
| ③ | Tkinterで直感的に操作できるGUIアプリへ移行 |
Antigravityが開発を加速した点
今回の開発で印象的だったのが、Antigravityとの対話だけで開発サイクルが完結したことです。
-
「LEDを消して」 →
LED_OFFコマンドをターミナルから即時実行し、Arduinoからの返答を確認できました。 -
「RGB LEDに変えて」 →
.inoファイルのピン定義・コマンド処理をすべて自動で書き換え、ハードウェアとしてどういう変更をかけるべきかという指示も出すことができていました。
従来であればリファレンスを調べながら手打ちしていたコード修正や、Arduinoの配線の作業もスクラッチと整合される様に作業していたのですが、AIエージェントが一括で管理、指示できる状況はとなり、ハードウェア開発のハードルを大きく下げてくれました。
感想
今回の例は簡単なLチカに留まりましたが、Antigravityから直接Arduinoの制御ができるということが分かったので、これからできることの可能性が感じられる検証だったかなと個人的に感じています。


