Amazonタイムセール祭りは9/20から開催——クリックして特集記事へ

Raspberry Pi で作った金魚の自動餌やり機をAlexaから声かけでも動作させたい

Amazon
この記事は約9分で読めます。

Raspberry Pi とサーボモーターを組み合わせた「サーボモーターSG90とRaspberry Pi Zero WHで金魚にエサをやる」をcornで自動的に実行させれば指定時間でエサが与えられます。今回は、そこにAlexa gadgetと連携させて、「エサあげて」というウェイクワードで実行できるようにしたいと思います。

そのためにはAlexa gadgetをインストールして前回にPythonで書かれたコードに、連携できるように修正しないとなりません。

先ずはAlexa-Gadgets-Raspberry-Pi-Samplesには5つのサンプルプログラムがありますから、プログラムが分からない非エンジニアとしては、サンプルを動かしてみてコードの内容を理解して取り組んでみます。

サンプルプログラムについてやAlexa Voice Service(AVS)の導入はこれまでの記事を参考にしてください。(記事最下部のリンクへ

スポンサーリンク

サンプルプログラム「Timer Gadget」の実行結果

初めにAlexa-Gadgets-Raspberry-Pi-Samplesのプログラムを理解するためにも、サンプル通りに実行させて、プログラム内容を読み取っていきたいと思います。サーボモーターを使っているTimer Gadgetを実行してみます。

このtimer.pyサンプルは、Echoデバイスに設定されたタイマーに反応するAlexaガジェットです。

なお、サンプルで電源とアース以外の制御部分はGPIOが25番になっています。(以前のサーボをテストした時に動かすのには14番でした)

ここにある動画はGitHub(https://github.com/alexa/Alexa-Gadgets-Raspberry-Pi-Samples/tree/master/src/examples/timer)にあるTimer Gadgetをそのまま実行した結果です。

サンプルではRaspberry Pi Zero Wと同じようなmicroservoを使っています。
今回のテスト環境はSG90microservoとRaspberry Pi 3B+とRaspbianBusterです。最終的にはZeroWで金魚の水槽に設置したいと思います。

実行した動画

サンプル通りに20秒のタイマーをアレクサに指示しました。「アレクサ、20秒のタイマーをセットして」
すると、カウントダウンのように1秒ずつ決まった角度で動きます。最後は時間になると180度に激しく動くようになります。

(外野の音がウルサイですが、最後にアレクサの音も聞こえるかと思います)

Raspberry Pi と連携したAlexaガジェットのTimer Gadgetサンプル

このサンプルプログラムでも時間指定をしてあげて自動餌やり機に仕立てることも可能ですが、既にPythonで書かれた餌やりプログラムがありますし、非エンジニアとしては厄介なので、ウェイクワードのサンプルを待ち受けできるように、作成してある「sg90.py」を修正して実現していきます。

既存のsg90.pyを呼び出してみた

サンプルプログラムのWake Word LED Gadgetは声かけでRaspberry Pi に繋いだLEDを光らせるプログラムです。これをエサをやるサーボ制御のプログラム「sg90.py」に組み込んでみます。

予想通りというか、「アレクサ」と声を掛けただけでサーボが動いてしまうので、このままでは使えません・・・。

単に既存のPythonプログラムを呼び出す方法だけ理解します。

それぞれのプログラムコード全体

import logging
import sys
from gpiozero import LED

from agt import AlexaGadget

logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logger = logging.getLogger(__name__)

GPIO_PIN = 14

LED = LED(GPIO_PIN)

class WakewordGadget(AlexaGadget):
    """
    An Alexa Gadget that turns an LED on and off in sync with the detection
    of the wake word
    """

    def __init__(self):
        super().__init__()

    def on_alexa_gadget_statelistener_stateupdate(self, directive):
        for state in directive.payload.states:
            if state.name == 'wakeword':
                if state.value == 'active':
                    logger.info('Wake word active - turn on LED')
                    LED.on()
                elif state.value == 'cleared':
                    logger.info('Wake word cleared - turn off LED')
                    LED.off()


if __name__ == '__main__':
    try:
        WakewordGadget().main()
    finally:
        logger.debug('Cleaning up GPIO')
        LED.close()
import RPi.GPIO as GPIO
import time

INTERVAL = 0.6
PIN = 14
FREQ = 50

GPIO.setmode(GPIO.BCM)

GPIO.setup(PIN, GPIO.OUT)
servo = GPIO.PWM(PIN, FREQ)

#init
servo.start(0.0)

for i in range(2):
  servo.ChangeDutyCycle(2.5)
  time.sleep(INTERVAL)

  servo.ChangeDutyCycle(12.0)
  time.sleep(INTERVAL)

GPIO.cleanup()

それぞれに手を加えてみます。

先ず、呼び出される「sg90.py」に仕込みます。

import RPi.GPIO as GPIO
import time

def esa():
        INTERVAL = 0.6
        PIN = 25
        FREQ = 50

        GPIO.setmode(GPIO.BCM)

        GPIO.setup(PIN, GPIO.OUT)
        servo = GPIO.PWM(PIN, FREQ)

        #init
        servo.start(0.0)

        for i in range(2):
          servo.ChangeDutyCycle(2.5)
          time.sleep(INTERVAL)

          servo.ChangeDutyCycle(12.0)
          time.sleep(INTERVAL)

        GPIO.cleanup()

if __name__ == '__main__':
    esa()

def esa(): でメインのプログラム部分を囲って定義し、

if __name__ == '__main__':
    esa()

最後に呼び出されたら、定義したesa()の部分を実行するようにしただけです。

だから、3行目と、最下部2行を付け加えました。

次にWakewordGadget.pyにも仕込みます。

import logging
import sys
#from gpiozero import LED
import sg90

from agt import AlexaGadget

logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logger = logging.getLogger(__name__)

#GPIO_PIN = 14

#LED = LED(GPIO_PIN)

class WakewordGadget(AlexaGadget):
    """
    An Alexa Gadget that turns an LED on and off in sync with the detection
    of the wake word
    """

    def __init__(self):
        super().__init__()

    def on_alexa_gadget_statelistener_stateupdate(self, directive):
        for state in directive.payload.states:
            if state.name == 'wakeword':
                if state.value == 'active':
                    logger.info('Wake word active - turn on')
                    sg90.esa()
                elif state.value == 'cleared':
                    logger.info('Wake word cleared - turn off')
                    #LED.off()


if __name__ == '__main__':
    try:
        WakewordGadget().main()
    finally:
        logger.debug('Cleaning up GPIO')
        #LED.close()

不必要な部分(LED制御)はコメントアウトし、import sg90と「sg90.py」をインポートさせ、

                  if state.value == 'active':
                    logger.info('Wake word active - turn on')
                    sg90.esa()

wakewordがアクティブになった箇所に、先程のesa()を実行するように書きました。

基本的にはこれだけで「アレクサ、・・・」と声をかけた時点でモーターがsg90.pyで指定したとおりに動きます。

が!

これでは「アレクサ、」と声をかける度にエサを与えてしまうことになるので、問題です!!

こうなるとスキルを作成して、「アレクサ、エサを与えて」でモーターが動くようにしないとなりませんね。

またスキルを作成してからこの記事に追記したいと思います!(※どうにも上手くいきません・・・。設定項目を理解出来ていないので、もう少しAlexa開発について学ばないと難しいです)

前回までのAlexa gadgetとサーボモーター制御

サーボモーターSG90とRaspberry Pi Zero WHで金魚にエサをやる
使用するのは「OSOYOO マイクロサーボモーターSG90」という格安のサーボモーターです。電子工作のキットに...
ラズパイとAmazonアレクサを連携してAlexa Gadgetを使う
ここではssh経由でMacのターミナルを使いRaspberry Pi 3B+にインストールされたRaspbianへ必要...
Alexaのスキル作成支援にRaspberry Pi でPythonベースのソフトウェアとサンプルプロジェクトを利用する
皆さんはアレクサを体験済みですか? Raspberry Pi とは一見して関係が無さそうに思えるAmazonEchoと...
Twitter、フォーラム、メールで購読
それぞれ更新情報をお伝えしています。
皆様のフォローをお待ちしています!
\ FOLLOW ME /
/ 最新記事をお知らせしています! \
Amazon
スポンサーリンク
フォローをお願いします——ラズパイダ
特集ラズパイ4
スポンサーリンク
こちらの記事もよく読まれています♪
\\ 特集 //
購入するならAmazonセールで
ラズパイダ

コメント

最近のフォーラム投稿

Raspberry Piや記事に関することなどコメント欄の代わりにお使いください。