本文へ移動
AIとRaspberry Pi。
「動かす・表示する・遊ぶ」20種類のコード。
GPIOを使って、サーボやモーターで「動かす」、LCDや7セグメントで「表示する」、ブザーやゲームで「遊ぶ」、シリアル通信やファイル保存で「やり取りする・覚えておく」ためのPythonコードを20本集めました。AIへのプロンプトの作り方も、サーボモーター制御の実例であらためて解説します。

「動かすコード」をAIに書かせる意味
センサーは「値を読むだけ」なので比較的シンプルですが、サーボモーターやDCモーター、LCDや7セグメントのような出力デバイスは、決まった手順(ライブラリの初期化、I2C・SPIの設定、PWMのタイミング)を守らないと正しく動きません。この「お作法」はライブラリのドキュメントを読めば分かりますが、量が多くて最初は大変です。AIはこうした定型部分の下書きを素早く作ってくれるので、「思いついたアイデアをすぐ動く形にする」のを助けてくれます。
Raspberry Pi本体のGPIO仕様はRaspberry Pi公式ドキュメント ↗、GPIO制御ライブラリの関数はgpiozero公式リファレンス ↗など、各ライブラリのドキュメントで最終確認してください。
- 初期化の定型処理:AngularServo()、SMBus()などのおまじない部分
- 状態遷移の設計:信号機やゲームのような「今どの状態か」を管理する仕組み
- デバッグの壁打ち:モーターが動かない、表示が化けるといった症状からの原因整理
サーボ制御プロンプトの設計図
モーターや表示器のようなアクチュエータ系では、「ボード」「部品とGPIOピン」「動く条件・動きのパターン」「安全上の制約」を必ず伝えます。
| 要素 | 内容 | 例 |
|---|---|---|
| ボードと制約 | 機種、電源、GPIO電圧 | Raspberry Pi 4 / USB-C給電、GPIOは3.3Vロジック |
| ハードウェア | アクチュエータ・入力・GPIOピン | SG90サーボ(信号線=GPIO18)、押しボタン(GPIO2) |
| 動きの条件 | 角度、速度、きっかけ | ボタンを押すと0°→90°へゆっくり動く |
| 非機能要件 | ライブラリ指定、コメントなど | gpiozeroを使用、time.sleep()でループ管理、日本語コメント付き |
「どんな速さで」「どのタイミングで」「動作中に別の入力が来たらどうするか」まで指定すると、実際に組み込みやすいコードになります。
生成されたコード全文

プロンプトから生成した「ボタンで開閉する自動ドア風サーボ」のコードです。後半の20選とは別に、AI生成コードを読む教材として掲載しています。
# ボタンで開閉する自動ドア風サーボ
from gpiozero import AngularServo, Button
from time import monotonic
SERVO_PIN = 18
BUTTON_PIN = 2
CLOSED_ANGLE = 0
OPEN_ANGLE = 90
STEP_INTERVAL = 0.015 # 1度動かす間隔(秒)
HOLD_OPEN_S = 3 # 開いたまま待つ時間(秒)
servo = AngularServo(SERVO_PIN, min_angle=0, max_angle=180)
button = Button(BUTTON_PIN, pull_up=True)
# 状態は文字列で管理する(CLOSED / OPENING / HOLDING / CLOSING)
state = "CLOSED"
current_angle = CLOSED_ANGLE
last_step_time = monotonic()
hold_start_time = 0.0
servo.angle = current_angle
while True:
now = monotonic()
# 閉まっている時だけボタンを受け付ける(動作中は割り込ませない)
if state == "CLOSED" and button.is_pressed:
state = "OPENING"
print("Door: opening")
if state == "OPENING" and now - last_step_time >= STEP_INTERVAL:
last_step_time = now
current_angle += 1
servo.angle = current_angle
if current_angle >= OPEN_ANGLE:
state = "HOLDING"
hold_start_time = now
print("Door: holding open")
if state == "HOLDING" and now - hold_start_time >= HOLD_OPEN_S:
state = "CLOSING"
print("Door: closing")
if state == "CLOSING" and now - last_step_time >= STEP_INTERVAL:
last_step_time = now
current_angle -= 1
servo.angle = current_angle
if current_angle <= CLOSED_ANGLE:
state = "CLOSED"
print("Door: closed")
コード解説:ブロック単位で読む
time.sleep()で全体を止めず、monotonic()で経過時間を測りながら少しずつ角度を変えることでゆっくりした動きを表現しています。Arduinoのmillis()と同じ考え方です。AngularServoの基本操作です。角度(0〜180程度)を代入するだけで、内部の複雑なPWMパルス制御を隠してくれます。モーター・表示系コードにありがちな落とし穴

GPIOピン1本あたりの出力電流はごくわずかです。サーボやDCモーターを直接GPIOやGPIOの5Vピンにつなぐと、電圧降下で本体が再起動したり、最悪の場合は故障につながることがあります。モータードライバや外部電源を必ず用意してください。
Raspberry PiのGPIOは3.3Vロジックで、Arduinoのように5Vトレラントではありません。5V専用の部品を信号線に直結すると壊れる恐れがあるため、レベル変換が必要か、3.3V対応のモジュールかを必ず確認してください。
I2CやSPIを使う部品(LCD、RTC、ドットマトリクスなど)は、sudo raspi-configで該当インターフェースを有効化しないと動作しません。配線後はi2cdetect -y 1でアドレスが見えているか確認しましょう。
実機で検証し、対話で直す
実行した後は必ずターミナルの出力や実際の動きで確認します。「動かない」だけでなく、配線、使用モデル、部品の型番、エラーメッセージ全文をAIへ伝えると修正が早くなります。
20本を実行する前の共通チェック

- 各コードは1本ずつ別の.pyファイルとして保存し、ターミナルまたはThonnyで実行する
sudo raspi-configで使用するインターフェース(I2C/SPI/Serial)を有効化する- Raspberry Piと外部電源・モジュールのGNDを共通化する
- サーボやDCモーターは、GPIOから直接電源を取らず、外部電源とモータードライバを使う
- I2C部品(LCD、RTCなど)は
i2cdetect -y 1でアドレスを確認する - 仮想環境(venv)を作って
pip installすると管理しやすい - 最初はターミナルに状態を
print()で表示し、動きを確認しながら調整する
サーボ・LED・ボタン・DCモーター・リレーの基本操作は「gpiozero」(Raspberry Pi OSに標準搭載)、7セグは「tm1637」、LCDは「RPLCD」、ドットマトリクスは「luma.led_matrix」、シリアル通信は「pyserial」、RTCとの通信は「smbus2」をpip installで追加します。それ以外は標準ライブラリのみです。GPIO番号はすべてgpiozeroの既定であるBCM表記です。
コピペですぐ試せるRaspberry Piコード集20選 第1弾

すべてRaspberry Pi 4/5(多くはZero 2 Wでも動作)を想定した独立Pythonスクリプトです。今回は「動かす」「表示する」「鳴らす」「遊ぶ・伝える」の4つのテーマでまとめました。検索欄に「サーボ」「LCD」「ゲーム」「通信」などと入力すると対象コードだけに絞れます。
| No. | コード | ライブラリ | 難易度 |
|---|---|---|---|
| 01 | サーボモーターを0〜180度でゆっくり往復させる | gpiozero | 入門 |
| 02 | DCモーターをL298Nドライバで正転・逆転・速度調整 | gpiozero | 入門+ |
| 03 | ステッピングモーター28BYJ-48をULN2003で回す | gpiozero | 基礎+ |
| 04 | ブザーで簡単なメロディーを演奏する(オリジナル音階) | gpiozero | 入門 |
| 05 | 4桁7セグメントLED(TM1637)でカウントアップタイマー | tm1637 | 入門+ |
| 06 | 16x2 I2C LCDにメッセージを表示する | RPLCD | 入門+ |
| 07 | 8x8ドットマトリクス(MAX7219)でハートマークを表示 | luma.led_matrix | 基礎+ |
| 08 | ミニ信号機シミュレーション(赤・黄・青の状態遷移) | gpiozero | 入門 |
| 09 | LEDが左右に流れる「ナイトライダー」風点灯 | gpiozero | 入門 |
| 10 | ボタン早押しゲーム(反応速度を測る) | gpiozero | 入門+ |
| 11 | LEDを使ったサイコロシミュレーター | gpiozero | 入門 |
| 12 | じゃんけんマシン(ボタンでランダムに手を出す) | gpiozero | 入門+ |
| 13 | カウントダウンタイマー(0になったらブザーで知らせる) | tm1637 / gpiozero | 入門+ |
| 14 | モールス信号でメッセージをLEDとブザーで送信 | gpiozero | 基礎+ |
| 15 | ボタンの「短押し・長押し・ダブルクリック」を判定 | gpiozero | 基礎+ |
| 16 | 2台のRaspberry PiをUART(シリアル通信)でつなぐ(送信・受信) | pyserial | 基礎+ |
| 17 | テキストファイルにボタンを押した回数を保存し電源を切っても記憶 | 標準ライブラリ | 基礎+ |
| 18 | RTCモジュール(DS3231)で現在時刻を表示する簡易時計 | smbus2 | 基礎+ |
| 19 | リレーモジュールで豆電球や小型モーターをON/OFF制御 | gpiozero | 入門+ |
| 20 | サーボとボタンで「自動ドア」のような開閉デモ | gpiozero | 基礎+ |
サーボモーターを0〜180度でゆっくり往復させる
角度をゆっくり増減させ、首振りのような動きを作ります。すべてのモーター工作の入り口です。
SG90などの小型サーボモーター
信号線(オレンジ/黄)→GPIO18、+(赤)→5V(テストは短時間のみ、常用は外部電源推奨)、-(茶/黒)→GND
コードを表示・コピー
# サーボを0〜180度でゆっくり往復させる
from gpiozero import AngularServo
from time import sleep
SERVO_PIN = 18
STEP_INTERVAL = 0.015 # 角度を1度動かす間隔(秒)
servo = AngularServo(SERVO_PIN, min_angle=0, max_angle=180,
min_pulse_width=0.0005, max_pulse_width=0.0025)
angle = 0
step = 1
while True:
servo.angle = angle
sleep(STEP_INTERVAL)
angle += step
if angle >= 180 or angle <= 0:
step = -step # 端まで来たら向きを反転
DCモーターをL298Nドライバで正転・逆転・速度調整
2つのピンで回転方向を決め、PWMで速さを変えます。車輪を回す工作の基本です。
DCモーター、L298Nモータードライバモジュール、外部電源
IN1→GPIO23、IN2→GPIO24、ENA→GPIO18(PWM)/L298NのGNDとRaspberry PiのGNDを共通化/モーター用電源はL298NのVCC・GNDへ
コードを表示・コピー
# L298NでDCモーターの向きと速さを制御
from gpiozero import Motor
from time import sleep
motor = Motor(forward=23, backward=24, enable=18, pwm=True)
while True:
motor.forward(0.6) # ゆっくり正転(速度は0.0〜1.0)
sleep(2)
motor.stop()
sleep(0.5)
motor.backward(0.9) # 速めに逆転
sleep(2)
motor.stop()
sleep(0.5)
motor.forward()の数値(0.0〜1.0)が速度です。ステッピングモーター28BYJ-48をULN2003で回す
指定した角度分だけ正確に回転する、位置決めが得意なモーターです。
28BYJ-48ステッピングモーター、ULN2003ドライバボード
ULN2003のIN1〜IN4→GPIO5, GPIO6, GPIO13, GPIO19/ULN2003のVCC・GNDへ外部5V電源を推奨
コードを表示・コピー
from gpiozero import OutputDevice
from time import sleep
PINS = (5, 6, 13, 19)
STEPS_PER_REV = 4096 # 28BYJ-48の1回転あたりステップ数(半ステップ)
outputs = [OutputDevice(p) for p in PINS]
SEQUENCE = [
[1, 0, 0, 0],
[1, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 1, 0],
[0, 0, 1, 0],
[0, 0, 1, 1],
[0, 0, 0, 1],
[1, 0, 0, 1],
]
def step(count, delay=0.0015):
direction = 1 if count >= 0 else -1
phases = SEQUENCE if direction == 1 else list(reversed(SEQUENCE))
for _ in range(abs(count)):
for phase in phases:
for pin, value in zip(outputs, phase):
pin.value = value
sleep(delay)
while True:
print("Forward 1 turn")
step(STEPS_PER_REV) # 1回転、正転
sleep(1)
print("Backward half turn")
step(-STEPS_PER_REV // 2) # 半回転、逆転
sleep(1)
ブザーで簡単なメロディーを演奏する(オリジナル音階)
TonalBuzzerで音の高さを変え、オリジナルの短いメロディーを鳴らします。
パッシブブザー
+→GPIO18、-→GND
コードを表示・コピー
# オリジナルの短いメロディーを演奏する
from gpiozero import TonalBuzzer
from gpiozero.tones import Tone
from time import sleep
buzzer = TonalBuzzer(18)
# ドレミファソラシド(オクターブ4〜5)
notes = ["C4", "D4", "E4", "F4", "G4", "A4", "B4", "C5"]
durations = [0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.6]
while True:
for note, duration in zip(notes, durations):
buzzer.play(Tone(note))
sleep(duration * 1.2) # 音と音の間に少し隙間を空ける
buzzer.stop()
sleep(2)
sudo apt install pigpioでpigpiodを起動し、gpiozeroのPinFactoryをpigpioに切り替えるとなめらかになります。既存曲のメロディーをそのまま真似ると著作権の問題が起きる場合があるため、音の並びは自分で工夫しましょう。4桁7セグメントLED(TM1637)でカウントアップタイマー
実行してからの経過秒数を、大きな数字表示器にカウントアップ表示します。
TM1637搭載4桁7セグメントLEDモジュール
CLK→GPIO23、DIO→GPIO24、VCC→5V、GND→GND
コードを表示・コピー
# pip install tm1637
import tm1637
from time import sleep, monotonic
CLK_PIN = 23
DIO_PIN = 24
display = tm1637.TM1637(clk=CLK_PIN, dio=DIO_PIN)
display.brightness(5) # 0〜7
start_time = monotonic()
while True:
elapsed_sec = int(monotonic() - start_time)
minutes = (elapsed_sec // 60) % 100
seconds = elapsed_sec % 60
display.numbers(minutes, seconds, colon=True) # 中央のコロンを点灯
sleep(0.2)
display.number(elapsed_sec)に置き換えてください。16x2 I2C LCDにメッセージを表示する
2行×16文字の液晶に文字を出す、表示器の定番の一歩目です。
I2Cインターフェース付き16x2キャラクターLCD
SDA→GPIO2(物理3番)、SCL→GPIO3(物理5番)、VCC→5V、GND→GND
コードを表示・コピー
# pip install RPLCD
# 事前に sudo raspi-config で I2C を有効化しておく
from RPLCD.i2c import CharLCD
# アドレスは0x27または0x3Fが多い(不明な場合はi2cdetect -y 1で確認)
lcd = CharLCD('PCF8574', 0x27, cols=16, rows=2)
lcd.clear()
lcd.write_string('Hello, RaspberryPi!')
lcd.crlf()
lcd.write_string('LCD Ready :)')
# 表示は固定のまま。動くコードにしたい時はここでlcd.clear()と
# 新しい表示内容を書き直す
8x8ドットマトリクス(MAX7219)でハートマークを表示
64個の点を1個ずつON/OFFして、絵文字のような簡単な絵を表示します。
MAX7219搭載8x8ドットマトリクスモジュール
DIN→GPIO10(MOSI)、CS→GPIO8(CE0)、CLK→GPIO11(SCLK)、VCC→5V、GND→GND
コードを表示・コピー
# pip install luma.led-matrix
# 事前に sudo raspi-config で SPI を有効化しておく
from luma.core.interface.serial import spi, noop
from luma.core.render import canvas
from luma.led_matrix.device import max7219
serial = spi(port=0, device=0, gpio=noop())
device = max7219(serial, cascaded=1, block_orientation=0)
device.contrast(16)
# ハート型のパターン(1行8ビット×8行)
HEART = [
"01100110",
"11111111",
"11111111",
"11111111",
"01111110",
"00111100",
"00011000",
"00000000",
]
with canvas(device) as draw:
for y, row in enumerate(HEART):
for x, bit in enumerate(row):
if bit == "1":
draw.point((x, y), fill="white")
block_orientationの数値(0/90/-90)を変えて調整します。ミニ信号機シミュレーション(赤・黄・青の状態遷移)
本物の信号機のように、決まった順番と時間でLEDが切り替わります。
赤LED、黄LED、青LED、220Ω抵抗×3
赤→GPIO17、黄→GPIO27、青→GPIO22(各220Ω経由でGNDへ)
コードを表示・コピー
# 赤→青→黄→赤 の順で切り替わる信号機
from gpiozero import LED
from time import monotonic
red = LED(17)
yellow = LED(27)
green = LED(22)
DURATIONS = {"RED": 4, "GREEN": 3, "YELLOW": 1}
state = "RED"
state_start = monotonic()
def apply_state():
red.value = state == "RED"
yellow.value = state == "YELLOW"
green.value = state == "GREEN"
while True:
elapsed = monotonic() - state_start
if elapsed >= DURATIONS[state]:
state = {"RED": "GREEN", "GREEN": "YELLOW", "YELLOW": "RED"}[state]
state_start = monotonic()
apply_state()
LEDが左右に流れる「ナイトライダー」風点灯
複数のLEDを順番に光らせ、光が左右に走っているように見せます。
LED×6、220Ω抵抗×6
GPIO2, 3, 4, 17, 27, 22の6ピンに、それぞれLED→220Ω→GNDの順で接続
コードを表示・コピー
# 6個のLEDが左右に往復する光の帯
from gpiozero import LEDBoard
from time import sleep
leds = LEDBoard(2, 3, 4, 17, 27, 22)
position = 0
direction = 1
while True:
leds.value = tuple(i == position for i in range(len(leds)))
sleep(0.08)
position += direction
if position >= len(leds) - 1 or position <= 0:
direction = -direction # 端で折り返す
ボタン早押しゲーム(反応速度を測る)
LEDが光ってからボタンを押すまでの時間をミリ秒で測定します。
LEDと押しボタン、220Ω抵抗
LED→GPIO17(220Ω経由)/ボタン→GPIO2(内蔵プルアップ使用、反対側はGND)
コードを表示・コピー
# LEDが光ってからボタンを押すまでの時間を測る
from gpiozero import LED, Button
from time import monotonic, sleep
import random
led = LED(17)
button = Button(2, pull_up=True)
while True:
print("Get ready...")
led.off()
sleep(random.uniform(2, 5)) # ランダムな待ち時間でフライングを防ぐ
led.on()
lit_time = monotonic()
print("GO! Press the button!")
button.wait_for_press()
reaction_ms = int((monotonic() - lit_time) * 1000)
led.off()
print(f"Reaction time: {reaction_ms} ms")
sleep(3)
LEDを使ったサイコロシミュレーター
ボタンを押すと1〜6の数字にあたるLEDパターンが一瞬光ります。
LED×6、220Ω抵抗×6、押しボタン
LED×6→GPIO2, 3, 4, 17, 27, 22(各220Ω経由)/ボタン→GPIO8(内蔵プルアップ使用)
コードを表示・コピー
# ボタンを押すとサイコロの目(LED本数)がランダムに光る
from gpiozero import LEDBoard, Button
from signal import pause
import random
leds = LEDBoard(2, 3, 4, 17, 27, 22)
button = Button(8, pull_up=True)
def roll_dice():
result = random.randint(1, 6) # 1〜6
leds.value = tuple(i < result for i in range(6))
print(f"Dice: {result}")
button.when_pressed = roll_dice
pause() # イベント待ちのままプログラムを維持する
when_pressedにはボタンが押された瞬間だけ呼ばれる関数を割り当てられます。pause()でプログラムを終了させずに待機し続けます。サイコロの目の並べ方(LEDの配置)を工夫すると本物のサイコロらしくなります。じゃんけんマシン(ボタンでランダムに手を出す)
ボタンを押すたびに「グー・チョキ・パー」のどれかをLEDで表示します。
赤LED(グー)、緑LED(チョキ)、青LED(パー)、押しボタン
赤→GPIO17、緑→GPIO27、青→GPIO22(各220Ω経由)/ボタン→GPIO2(内蔵プルアップ使用)
コードを表示・コピー
# ボタンを押すとグー・チョキ・パーをランダム表示
from gpiozero import LED, Button
from signal import pause
import random
rock = LED(17)
scissors = LED(27)
paper = LED(22)
button = Button(2, pull_up=True)
HAND_NAMES = ["Rock", "Scissors", "Paper"]
def show_hand():
hand = random.randint(0, 2) # 0:グー 1:チョキ 2:パー
rock.value = hand == 0
scissors.value = hand == 1
paper.value = hand == 2
print(HAND_NAMES[hand])
button.when_pressed = show_hand
pause()
カウントダウンタイマー(0になったらブザーで知らせる)
設定した秒数からカウントダウンし、0になったら音で知らせます。
TM1637搭載4桁7セグメントLEDモジュール、パッシブブザー、押しボタン
CLK→GPIO23、DIO→GPIO24/ブザー→GPIO18/ボタン→GPIO4(内蔵プルアップ、スタート用)
コードを表示・コピー
# pip install tm1637
import tm1637
from gpiozero import Button, TonalBuzzer
from gpiozero.tones import Tone
from time import sleep, monotonic
CLK_PIN = 23
DIO_PIN = 24
display = tm1637.TM1637(clk=CLK_PIN, dio=DIO_PIN)
display.brightness(5)
buzzer = TonalBuzzer(18)
button = Button(4, pull_up=True)
seconds_left = 10 # 10秒からスタート
running = False
last_tick_time = monotonic()
display.number(seconds_left)
while True:
if not running and button.is_pressed:
running = True
seconds_left = 10
last_tick_time = monotonic()
if running and monotonic() - last_tick_time >= 1:
last_tick_time = monotonic()
seconds_left -= 1
display.number(seconds_left)
if seconds_left <= 0:
running = False
buzzer.play(Tone("A4")) # 終了音
sleep(0.8)
buzzer.stop()
モールス信号でメッセージをLEDとブザーで送信
「SOS」を短点・長点のリズムでLEDの点滅とブザー音に変換して送ります。
LED、パッシブブザー、220Ω抵抗
LED→GPIO17(220Ω経由)/ブザー→GPIO18
コードを表示・コピー
# 「SOS」をモールス信号でLEDとブザーで送る
from gpiozero import LED, TonalBuzzer
from gpiozero.tones import Tone
from time import sleep
led = LED(17)
buzzer = TonalBuzzer(18)
DOT_S = 0.2 # 短点の長さ
DASH_S = 0.6 # 長点の長さ(短点の3倍)
GAP_S = 0.2 # 信号同士の間隔
def signal_on(duration):
led.on()
buzzer.play(Tone("A4"))
sleep(duration)
led.off()
buzzer.stop()
sleep(GAP_S)
def send_dot():
signal_on(DOT_S)
def send_dash():
signal_on(DASH_S)
while True:
# S = ・・・
for _ in range(3):
send_dot()
sleep(0.4)
# O = ー ー ー
for _ in range(3):
send_dash()
sleep(0.4)
# S = ・・・
for _ in range(3):
send_dot()
sleep(2) # メッセージ間の長い休み
ボタンの「短押し・長押し・ダブルクリック」を判定
1つのボタンで3種類の操作を区別する、実用的な入力判定の仕組みです。
押しボタン、LED
ボタン→GPIO2(内蔵プルアップ使用)/LED→GPIO17(動作確認用、任意)
コードを表示・コピー
# 1個のボタンで短押し・長押し・ダブルクリックを判定
from gpiozero import Button, LED
from time import monotonic, sleep
from signal import pause
button = Button(2, pull_up=True, bounce_time=0.02)
led = LED(17)
LONG_PRESS_S = 0.6
DOUBLE_CLICK_GAP_S = 0.3
press_start_time = 0.0
last_release_time = 0.0
waiting_second_click = False
def on_press():
global press_start_time
press_start_time = monotonic()
def on_release():
global last_release_time, waiting_second_click
now = monotonic()
duration = now - press_start_time
if duration >= LONG_PRESS_S:
print("Long press")
led.on()
sleep(0.2)
led.off()
elif waiting_second_click and now - last_release_time <= DOUBLE_CLICK_GAP_S:
print("Double click")
waiting_second_click = False
else:
waiting_second_click = True
last_release_time = now
def check_single_click():
global waiting_second_click
if waiting_second_click and monotonic() - last_release_time > DOUBLE_CLICK_GAP_S:
print("Single click")
waiting_second_click = False
button.when_pressed = on_press
button.when_released = on_release
while True:
check_single_click()
sleep(0.02)
2台のRaspberry PiをUART(シリアル通信)でつなぐ(送信・受信)
1台のボタン状態を、もう1台のRaspberry Piへ有線で送ってLEDを光らせます。
Raspberry Piボード2台、ジャンパー線
送信側にボタン(GPIO2)/受信側にLED(GPIO17)/送信側TX(GPIO14)→受信側RX(GPIO15)、送信側RX(GPIO15)→受信側TX(GPIO14)(クロス接続)、GND同士も接続
コードを表示・コピー(送信側)
# pip install pyserial
# 事前に sudo raspi-config で Serial Port を有効化(シリアルコンソールは無効化)
import serial
from gpiozero import Button
from time import sleep
ser = serial.Serial("/dev/serial0", 9600, timeout=1)
button = Button(2, pull_up=True)
while True:
ser.write(b'\x01' if button.is_pressed else b'\x00')
sleep(0.1)
コードを表示・コピー(受信側)
# pip install pyserial
import serial
from gpiozero import LED
ser = serial.Serial("/dev/serial0", 9600, timeout=1)
led = LED(17)
while True:
data = ser.read(1)
if data:
led.value = data == b'\x01'
raspi-configの「Interface Options → Serial Port」で「ログインシェルは無効・ハードウェアは有効」に設定してください。両方Raspberry Pi同士なので信号は3.3Vのまま共通で使えます。テキストファイルにボタンを押した回数を保存し電源を切っても記憶
Raspberry PiにはArduinoのようなEEPROMは無いため、SDカード上のファイルに書き込んで電源断後も値を残します。
押しボタン
ボタン→GPIO2(内蔵プルアップ使用、反対側はGND)
コードを表示・コピー
# EEPROM代わりにJSONファイルへ保存する
from gpiozero import Button
from signal import pause
import json
import os
STORAGE_FILE = "/home/pi/press_count.json"
button = Button(2, pull_up=True)
def load_count():
if os.path.exists(STORAGE_FILE):
with open(STORAGE_FILE) as f:
return json.load(f).get("count", 0)
return 0
def save_count(count):
with open(STORAGE_FILE, "w") as f:
json.dump({"count": count}, f)
press_count = load_count() # 前回の続きから読み込む
print(f"Loaded count: {press_count}")
def on_press():
global press_count
press_count += 1
save_count(press_count)
print(f"Count: {press_count}")
button.when_pressed = on_press
pause()
RTCモジュール(DS3231)で現在時刻を表示する簡易時計
ボタン電池でバックアップされた時計モジュールから時刻を読み取ります。ネットワークに繋がらない環境での時刻保持に便利です。
DS3231 RTCモジュール
SDA→GPIO2、SCL→GPIO3、VCC→5V(モジュールにより3.3V可)、GND→GND
コードを表示・コピー
# pip install smbus2
# 事前に sudo raspi-config で I2C を有効化しておく
import smbus2
from time import sleep
bus = smbus2.SMBus(1)
DS3231_ADDR = 0x68 # i2cdetect -y 1 で確認できるアドレス
def bcd_to_dec(bcd):
return (bcd // 16) * 10 + (bcd % 16)
while True:
data = bus.read_i2c_block_data(DS3231_ADDR, 0x00, 7)
second = bcd_to_dec(data[0] & 0x7F)
minute = bcd_to_dec(data[1])
hour = bcd_to_dec(data[2] & 0x3F)
day = bcd_to_dec(data[4])
month = bcd_to_dec(data[5] & 0x1F)
year = bcd_to_dec(data[6]) + 2000
print(f"{year}/{month}/{day} {hour}:{minute:02d}:{second:02d}")
sleep(1)
リレーモジュールで豆電球や小型モーターをON/OFF制御
小さな信号で、大きな電流が必要な機器のスイッチを入り切りします。
リレーモジュール、豆電球や小型モーターなどの負荷、負荷用の専用電源
IN→GPIO17、VCC→5V、GND→GND/負荷側はリレーのCOM・NO端子を経由して専用電源へ接続
コードを表示・コピー
# リレーで5秒ごとにON/OFFを繰り返す
from gpiozero import OutputDevice
from time import sleep
# 多くのモジュールはLOWでON(active_high=False)。要確認
relay = OutputDevice(17, active_high=False, initial_value=False)
while True:
relay.on()
sleep(5)
relay.off()
sleep(5)
このコードは豆電球や小型のおもちゃモーターのような低電圧の負荷を学習目的で試すためのものです。家庭用コンセント(AC100V)や高電圧・大電流の機器を接続する作業は感電・火災の危険があるため、専門知識のある大人が正しい安全対策のもとで行ってください。
active_highの値を入れ替えてください。サーボとボタンで「自動ドア」のような開閉デモ
第3節で解説した自動ドアのコードを、そのままコピペで使える形にまとめました。
SG90サーボモーター、押しボタン
サーボ信号線→GPIO18、+→5V、-→GND/ボタン→GPIO2(内蔵プルアップ使用、反対側はGND)
コードを表示・コピー
# ボタンで開閉する自動ドア風サーボ(コピペ用まとめ版)
from gpiozero import AngularServo, Button
from time import monotonic
SERVO_PIN = 18
BUTTON_PIN = 2
CLOSED_ANGLE = 0
OPEN_ANGLE = 90
STEP_INTERVAL = 0.015
HOLD_OPEN_S = 3
servo = AngularServo(SERVO_PIN, min_angle=0, max_angle=180)
button = Button(BUTTON_PIN, pull_up=True)
state = "CLOSED"
current_angle = CLOSED_ANGLE
last_step_time = monotonic()
hold_start_time = 0.0
servo.angle = current_angle
while True:
now = monotonic()
if state == "CLOSED" and button.is_pressed:
state = "OPENING"
if state == "OPENING" and now - last_step_time >= STEP_INTERVAL:
last_step_time = now
current_angle += 1
servo.angle = current_angle
if current_angle >= OPEN_ANGLE:
state = "HOLDING"
hold_start_time = now
if state == "HOLDING" and now - hold_start_time >= HOLD_OPEN_S:
state = "CLOSING"
if state == "CLOSING" and now - last_step_time >= STEP_INTERVAL:
last_step_time = now
current_angle -= 1
servo.angle = current_angle
if current_angle <= CLOSED_ANGLE:
state = "CLOSED"
よくある質問とまとめ
はじめてRaspberry Piを触りますが大丈夫ですか?
Raspberry Pi OSのセットアップとPythonの基本文法(変数、if文、while文)が分かれば十分に試せます。まずは部品が少ない「サーボの往復」や「信号機」のような入門コードから始め、慣れてきたら通信やRTCなどのやや複雑なコードに挑戦するのがおすすめです。
モーター系のコードで注意することは?
サーボやDCモーター、ステッピングモーターはRaspberry PiのGPIOピンだけでは電流が不足し、本体の再起動や故障につながることがあります。特にDCモーターやステッピングモーターは、モータードライバと外部電源を使い、GNDをRaspberry Piと共通化してください。
外部ライブラリが必要なコードはありますか?
サーボ・LED・ボタン・DCモーターの基本操作はgpiozero(Raspberry Pi OSに標準搭載)、7セグはtm1637、LCDはRPLCD、ドットマトリクスはluma.led_matrix、シリアル通信はpyserial、RTCとの通信はsmbus2をpip installで導入します。それ以外は標準ライブラリだけで動作します。
Arduinoと違ってEEPROMが無いのはどうすればいいですか?
Raspberry PiにはArduinoのようなEEPROMは搭載されていませんが、SDカード上のファイル(テキストやJSON)に値を書き込むことで、電源を切っても内容を保持できます。RTCモジュールを追加すれば、本体の電源を切っても時刻を刻み続けます。
まずは部品が少ない「サーボの往復」「信号機」「ナイトライダー」のどれか1本を実行し、動きの仕組みを目で確認するところから始めると理解しやすくなります。動いたコードに対して、AIへ「ボタンで動きを止められるようにして」「LEDをブザーに変えて」「速さをボリューム(可変抵抗+ADC)で調整できるようにして」と追加依頼すれば、同じ回路から次の作品へどんどん発展させられます。
コメント