1200円で買えるマイコン、RaspberryPi PICO WでChatGPTを実装してみました。
ボタンを押すとChatGPTに接続して、なにか気のきいた格言と出典を短く紹介してもらってそれを表示する。というプログラムです。バッテリー単体で動きます。
ソフトウェアのインストール
ChatGPTとの接続には、こちらを参考にさせていただきました。
とてもわかりやすかったです。こちらの記事に書いてありますが、HTTPの平文で送信されるので、APIコードなど漏洩リスクがあるとのこと。
代替としてCiruitPythonの方法が紹介されていますが、今回は以前買ったWaveshareの丸型液晶(1.28インチ丸型LCDディスプレイモジュール(240×240)【WAVESHARE-19192】)を活用するために、
ドライバ用のファームウェアを使用したので、とりあえずMicroPythonで行きました。
WAVESHARE-19192はGC9A01というディスプレイドライバが使用されていたので以下のファームウェアをインストールします。
このRP2ディレクトリにある「firmware.uf2」をブートセルを押しながら接続したPICOにドラッグ&ドロップして、起動します。
エディタにはThonnyを使いました。
スクリプトです。WIFIやAPI部分は書き換えてください。
from machine import Pin, SPI
import gc9a01
from misakifont import MisakiFont
import urequests as requests
import network
import utime
import json
# GPIO0を入力ピンとして設定
button = machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_UP)
# LEDを出力ピンとして設定
led = machine.Pin('LED', machine.Pin.OUT)
#自宅Wi-FiのSSIDとパスワードを入力
ssid = '********************'
password = '*********************'
# OpenAI API key
openai_api_key = "***********************"
# OpenAI Chat Completion APIエンドポイントを設定
ENDPOINT = 'https://api.openai.com/v1/chat/completions'
# GC9A01ディスプレイとMisakiフォントの初期化
SPI_PORT = 1
SPI_BAUDRATE = 60000000
RESET_PIN = Pin(11, Pin.OUT)
CS_PIN = Pin(13, Pin.OUT)
DC_PIN = Pin(12, Pin.OUT)
BACKLIGHT_PIN = Pin(10, Pin.OUT)
TFT_WIDTH = 240
TFT_HEIGHT = 240
FONT_SIZE = 2
FONT_COLOR = gc9a01.WHITE
BACKGROUND_COLOR = gc9a01.BLACK
spi = SPI(SPI_PORT, baudrate=SPI_BAUDRATE, sck=Pin(14), mosi=Pin(15))
tft = gc9a01.GC9A01(spi, TFT_WIDTH, TFT_HEIGHT, reset=RESET_PIN, cs=CS_PIN, dc=DC_PIN, backlight=BACKLIGHT_PIN, rotation=0)
mf = MisakiFont()
def screen_init():
tft.init()
background = gc9a01.BLACK
tft.fill(background)
screen_init()
# wifi接続
def connect_wifi(ssid, password):
# Wi-Fiインターフェースを有効化する
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# Wi-Fiアクセスポイントに接続する
wlan.connect(ssid, password)
# 接続が完了するまで待機する
max_wait = 10
while max_wait > 0:
if wlan.status() < 0 or wlan.status() >= 3:
break
max_wait -= 1
print('waiting for connection...')
utime.sleep(1)
# ボードのLEDにステータスを表示する
def blink_onboard_led(num_blinks):
#led = machine.Pin('LED', machine.Pin.OUT)
for i in range(num_blinks):
led.on()
utime.sleep(.2)
led.off()
utime.sleep(.2)
wlan_status = wlan.status()
blink_onboard_led(wlan_status)
# 接続の成否を確認する
if wlan_status != 3:
raise RuntimeError('Wi-Fi connection failed')
else:
print('Connected')
status = wlan.ifconfig()
print('ip = ' + status[0])
# 漢字フォント表示
def show_bitmap(tft, fd, x, y, color, size):
for row in range(0, 7):
for col in range(0, 7):
if (0x80 >> col) & fd[row]:
tft.fill_rect(int(x + col * size), int(y + row * size), size, size, color)
# Chatbotの応答を取得する関数
def get_chat_response(prompt):
# APIリクエストヘッダーを設定
headers = {
'Content-Type': 'application/json; charset=utf-8',
'Authorization': 'Bearer ' + openai_api_key
}
# APIリクエストデータを設定
data = {
'model': 'gpt-3.5-turbo',
'messages': [{'role': 'user', 'content': prompt }]
}
# APIリクエストを送信
json_data = json.dumps(data)
encoded_data = bytes(json_data, 'utf-8')
response = requests.post(ENDPOINT, headers=headers, data=encoded_data)
# API応答を解析
response_json = json.loads(response.text)
message = response_json['choices'][0]['message']['content'].strip()
return message
# 画面に文字を出力する
def show_message(title,color,size,x,y):
for c in title:
d = mf.font(ord(c))
show_bitmap(tft, d, x, y, color, size)
x += 8 * size
if x >= 220:
x = 20
y += 10 * size
if y >= 220:
y = 20
utime.sleep(0.02)
# メイン処理
def main():
screen_init()
show_message('chatGPT',gc9a01.GREEN,2,60,60)
show_message('接続中..',gc9a01.YELLOW,4,40,100)
wlan = network.WLAN(network.STA_IF)
if wlan.status() != 3:
connect_wifi(ssid, password)
# Chatbotに指示をする
prompt = "気分が明るくなるような格言をひとつください。格言は必ず60文字以内でお願いします。最後に誰の言葉か?も加えて。"
print('User: ' + prompt)
# Chatbotの応答を取得
chat_response = get_chat_response(prompt)
print('Chatbot: ' + chat_response)
screen_init()
show_message("chatGPT",gc9a01.WHITE,2,60,15)
show_message("今日の格言",gc9a01.YELLOW,4,40,40)
show_message(chat_response,gc9a01.WHITE,2,20,80)
# メインループ
while True:
#print(button.value())
if button.value() == 0:
led.on()
main()
utime.sleep(.2)
else:
led.off()
utime.sleep(.2)
ハードウェアの設定
Waveshareのディスプレイは端子が多いのでごちゃごちゃします。
GC9A01ボードの端子 | Picoの端子(GPIO) |
VCC | 3.3V |
GND | GND |
DIN | GP15 |
CLK | GP14 |
CS | GP13 |
DC | GP12 |
RESET | GP11 |
BackLight | – |
操作方法
プログラムを「boot.py」としてPICOに保存し、USBを差し直すと自動的に立ち上がります。PCで接続している場合などは、USBバッテリー電源などに接続してみてください。
ボタンを押すとWIFIに接続しChatGPTよりあらかじめ指定されたPromptの結果を表示します。
Promptを変えたり、表示方法を変えたりして、オリジナルのChatbotで遊んでみてください。