【完全ガイド】ArduinoとPythonで実現するインタラクティブ花火演出システム:タッチセンサー活用の詳細手順&コード解説

Arduino 機器制作



 

Arduino + Python 花火演出システム

以下は、Arduino、Python、そしておすすめのタッチセンサー(例:TTP223 Capacitive Touch Sensor)を用いて、プロジェクション上の「花火打ち上げ前の画像」を表示し、実際に人が壁に触れると花火のアニメーション(打ち上げ)を発生させる仕組みの一例です。

1. システム全体の概要

このシステムは大きく以下の3つのパートに分かれます。

  • ハードウェア部分(Arduino+タッチセンサー)
    人が壁に触れると、タッチセンサー(例:TTP223)が反応し、センサーの出力をArduinoが読み取り、シリアル通信で信号をPCへ送信します。
  • PC側のプログラム(Python+Pygame+pySerial)
    PythonプログラムはArduinoからのシリアルデータを監視し、センサーからの「TRIGGER」信号を検出すると、Pygameで花火のアニメーションを表示します。初期状態では、花火が打ち上げられる前の背景画像をプロジェクションし、トリガーで花火演出に切り替えます。
  • 表示部分(プロジェクター)
    PCで生成された映像をプロジェクターに出力し、来場者に視覚的なインタラクションを提供します。

2. 必要なハードウェアと準備

必要な部品

部品詳細
Arduino Uno(または互換機)Arduinoボード
TTP223タッチセンサーモジュールタッチセンサー(壁に貼るなどして直接タッチを感知)
ブレッドボード・ジャンパーワイヤー回路の配線用
USBケーブルArduinoとPCを接続
(任意)抵抗などセンサーによって必要な部品

配線例

  1. TTP223タッチセンサー
    • VCC → Arduinoの5V
    • GND → ArduinoのGND
    • OUT → Arduinoのデジタルピン(例:ピン2)

※ 配線が確実に行われているか、ジャンパーワイヤーの接続が緩んでいないかを確認してください。

3. Arduino側のプログラム

Arduinoはセンサーの状態を監視し、タッチが検出された際にシリアル通信でPCへ「TRIGGER」メッセージを送信します。以下はそのためのコード例です。

Arduinoスケッチ例


// Arduino用タッチセンサー検出プログラム
const int touchPin = 2;  // タッチセンサーのOUTが接続されるピン
bool triggered = false;  // 連続検出を防ぐためのフラグ

void setup() {
  Serial.begin(9600);        // シリアル通信開始(ボーレート:9600bps)
  pinMode(touchPin, INPUT);  // タッチセンサー用ピンを入力モードに設定
}

void loop() {
  int sensorValue = digitalRead(touchPin);  // センサーの状態を読み取り
  if (sensorValue == HIGH && !triggered) {
    // センサーが反応した場合(HIGH)かつ直前にトリガーされていない場合
    triggered = true;
    Serial.println("TRIGGER");  // シリアル経由で「TRIGGER」メッセージを送信
    delay(1000);  // 1秒間待機し、連続検出を防止
  }
  if (sensorValue == LOW) {
    // センサーがオフになったらフラグをリセット
    triggered = false;
  }
}
    

花火ではありませんが、圧センサーを押すと、光が様々な方向へ飛び交います。

→動画参照 IMG_0766

これはリハビリ場面であれば、リーチ訓練などで壁に触れると花火が上がるなどのフィードバックとして用いることができます。

掲載している動画は圧センサーを利用した物です。その場合のコードも記載しておきます。





// 圧センサー用のピン設定(A0を使用)
int sensorPin = A0;  
int threshold = 500;  // 圧力の閾値(適宜調整してください)

void setup() {
  Serial.begin(9600);  // シリアル通信を開始
}

void loop() {
  int sensorValue = analogRead(sensorPin);  // センサーの値を読み取る
  Serial.println(sensorValue);  // センサー値をシリアルモニタに出力(デバッグ用)

  // センサーの値が閾値を超えたら "TRIGGER" を送信
  if (sensorValue > threshold) {
    Serial.println("TRIGGER");
    delay(1000);  // トリガー後、1秒待機して多重送信を防止
  }
  
  delay(100);  // 少し待機してから再度読み取り
}

 

解説:

  • setup()関数: Serial.begin(9600);でPCとのシリアル通信を開始し、pinMode(touchPin, INPUT);によりピン2を入力として設定。
  • loop()関数: digitalRead(touchPin)でタッチセンサーの状態を読み取り、HIGHの場合に「TRIGGER」と送信。delay(1000);により連続発生を防止。

4. Python側のプログラム

PC側のPythonプログラムは以下の2つの役割を持ちます。

  1. シリアル通信の監視: pySerialライブラリを使用してArduinoからのデータを受信。
  2. 花火アニメーションの表示: Pygameを利用して花火のアニメーションを生成・表示。初期状態では背景画像(花火打ち上げ前の画像)を表示し、トリガー後に花火演出に切り替え。

必要なライブラリのインストール

pip install pyserial pygame

Pythonコード例

import serial
import pygame
import sys
import random
import time
import math

# --- シリアル通信の設定 ---
# ※ Windowsの場合は 'COM3' など、Linux/macOSの場合は '/dev/ttyACM0' などに書き換えてください。
SERIAL_PORT = 'COM3'
BAUD_RATE = 9600

try:
    ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)
except Exception as e:
    print(f"シリアルポート {SERIAL_PORT} に接続できませんでした: {e}")
    sys.exit()    # --- Pygameの初期設定 ---
pygame.init()
WIDTH, HEIGHT = 800, 600  # ウィンドウサイズ(必要に応じて調整)
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Fireworks Animation")
clock = pygame.time.Clock()

# 背景画像の読み込み(花火打ち上げ前の画像)
# ※ あなたの環境に合わせた画像パスに変更してください。
try:
    background = pygame.image.load("background.jpg").convert()
    background = pygame.transform.scale(background, (WIDTH, HEIGHT))
except Exception as e:
    print("背景画像が見つかりません。背景を黒で表示します。")
    background = None

# --- 花火のパーティクルアニメーションのクラス ---
class Firework:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.particles = []
        # 複数のパーティクルを初期化(50個程度)
        for _ in range(50):
            angle = random.uniform(0, 2 * math.pi)
            speed = random.uniform(2, 5)
            vx = speed * math.cos(angle)
            vy = speed * math.sin(angle)
            # パーティクルは[x座標, y座標, x速度, y速度, サイズ]
            self.particles.append([x, y, vx, vy, random.randint(2, 4)])
    
    def update(self):
        # 各パーティクルの位置とサイズを更新
        for p in self.particles:
            p[0] += p[2]  # x座標の更新
            p[1] += p[3]  # y座標の更新
            p[3] += 0.1   # 重力効果:y方向の加速度
            p[4] -= 0.1   # サイズを徐々に縮小
        # サイズが0以下になったパーティクルは除去
        self.particles = [p for p in self.particles if p[4] > 0]
    
    def draw(self, surface):
        # 各パーティクルを円で描画(色はランダムに)
        for p in self.particles:
            color = (255, random.randint(100, 255), random.randint(100, 255))
            pygame.draw.circle(surface, color, (int(p[0]), int(p[1])), int(p[4]))

# 花火を管理するリスト
fireworks = []

def trigger_firework():
    # 画面内のランダムな位置(上半分)に花火を生成
    x = random.randint(100, WIDTH - 100)
    y = random.randint(50, HEIGHT // 2)
    fireworks.append(Firework(x, y))

def main():
    while True:
        # イベント処理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                ser.close()
                pygame.quit()
                sys.exit()

        # 背景の描画:背景画像があれば表示、なければ黒背景
        if background:
            screen.blit(background, (0, 0))
        else:
            screen.fill((0, 0, 0))

        # Arduinoからのシリアルデータを監視
        if ser.in_waiting:
            try:
                line = ser.readline().decode('utf-8').strip()
            except UnicodeDecodeError:
                line = ""
            if line == "TRIGGER":
                trigger_firework()

        # 花火アニメーションの更新と描画
        for fw in fireworks:
            fw.update()
            fw.draw(screen)
        # 完了した花火(パーティクルがなくなったもの)をリストから除去
        fireworks[:] = [fw for fw in fireworks if fw.particles]

        pygame.display.flip()
        clock.tick(60)  # 60FPSでループ

if __name__ == "__main__":
    main()

コードのポイント解説:

  • シリアル通信設定: serial.Serialを用い、Arduinoとの通信ポートを指定。環境に合わせてSERIAL_PORTの値を変更。
  • 背景画像の設定: background.jpgを使用し、画像が存在しない場合は黒背景となる。
  • 花火アニメーション(Fireworkクラス): 50個のパーティクルをランダムな方向・速度で生成し、重力の影響で落下・縮小する様子をupdate()draw()で表現。
  • メインループ: Pygameのイベント処理とシリアル通信の監視を行い、「TRIGGER」メッセージ受信で花火演出を追加。

5. システムの組み立てと実行手順

  1. ハードウェアの接続: ArduinoにTTP223タッチセンサーを接続し、正しく動作するか確認。ArduinoとPCをUSBケーブルで接続。
  2. Arduinoへの書き込み: Arduino IDEを起動し、上記のArduinoスケッチをコピー&ペーストして、正しいシリアルポートに書き込み。
  3. PC側のPython環境のセットアップ:
    • Python 3.xがインストールされていることを確認。
    • コマンドラインから以下を実行してライブラリをインストール:
      pip install pyserial pygame
    • プロジェクト用フォルダに、上記のPythonコードを fireworks.py などのファイル名で保存。
    • 背景画像(例:background.jpg)を同じフォルダに用意(花火打ち上げ前のシーンを表すもの)。
  4. Pythonプログラムの実行: コマンドラインまたはIDEから fireworks.py を実行し、プロジェクターに映し出されることを確認。
  5. 動作確認: 壁に設置したタッチセンサーに実際に触れ、Arduinoが「TRIGGER」メッセージを送信し、Python側で花火アニメーションが発生するか確認。必要に応じてセンサー感度や各パラメータを調整。

6. カスタマイズのヒントとトラブルシューティング

カスタマイズ例

  • 背景画像の変更: プロジェクションの雰囲気に合わせて background.jpg をお好みの画像に変更可能。
  • 花火アニメーションのパラメータ調整: Fireworkクラス内のパーティクル数、速度、サイズ、重力加速度などを変更して、よりリアルまたは派手な花火演出にカスタマイズ可能。
  • センサーの種類: TTP223が合わない場合、静電容量式タッチセンサーや抵抗膜式タッチセンサーに置き換え可能。回路配線とArduinoコードのピン設定を変更するだけで対応できる。



トラブルシューティング

  • Arduino側がシリアル通信できない場合: Arduino IDEのシリアルモニタで出力を確認。接続ポートやボーレートの設定を再確認する。
  • Python側でシリアル通信エラーが発生する場合: SERIAL_PORTの値が正しいか、また他のプログラムが同じポートを使用していないか確認する。
  • Pygameウィンドウが表示されない場合: Pygameの初期化やディスプレイ設定を見直し、エラーメッセージの有無を確認する。

7. まとめ

今回のシステムは、以下の流れで動作します:

  1. タッチセンサーが壁に設置され、人が触れると反応。
  2. Arduinoがタッチセンサーの状態を監視し、触れた際にシリアル通信で「TRIGGER」メッセージを送信。
  3. Pythonプログラムがシリアルポートを監視し、メッセージ受信でPygameを使い花火アニメーションを表示。
  4. プロジェクターにより、観客に視覚的なインタラクティブ体験を提供。

この手順とコードを参考に、各部の動作確認・調整を行えば、実際にインタラクティブな花火演出システムを構築することができます。各パラメータの変更や追加機能の実装により、さらに高度な演出も可能です。ぜひ、このガイドをもとにシステムを作成し、素敵なインタラクティブアートをお楽しみください。

 

特集記事

コメント

この記事へのコメントはありません。

TOP