#author("2018-07-23T23:40:17+09:00","default:aiy_gadget","aiy_gadget") #author("2018-07-29T19:43:36+09:00","default:aiy_gadget","aiy_gadget") * Google AIY Voice Kitを利用した音声制御おもちゃ [#s8217d01] - #youtube(XgzDTKNBak4&t=14s) #youtube(LmaOuKzHcio&t=24s) - IoTLT広島 vol.8 におけるAIY_Gadgetの説明 -- https://www.slideshare.net/takashiyamanoue/aiy-voice-kit-neopixels - Overview -- &ref(AIY_Gadget/overview.png,30%); ** Google AIY Voice Kit [#uadefc15] - Google の人工知能を使った音声認識システムを使って, 自分で音声認識応用システムを作るために Kitです。 - https://aiyprojects.withgoogle.com/voice/ ** 作りかた... The Voice Controlled NeoPixels Stripの場合 [#m79daccd] + Google AIY Voice Kit とRaspberry Pi 3とmicro-SD(16GB以上)を買ってきます。 + Kitに添付された英文のThe MagPi AIY Projects にしたがって、Google Speaker をそのまま最後まで作ります。 ++ 箱を組み立てる必要はないのですが、動作確認のため、MagPiに記載された通りに最後まで作ってPythonのプログラムの動作確認を行うことをお勧めします。 ++ 注意 +++ マニュアル P. 38, STEP 06, "the LED inside the arched button should both indicate the device is running." ... ボタンのLEDは点灯しません. ... https://www.raspberrypi.org/magpi/issues/essentials-aiy-v1/ ++ 参考: https://kureuetan.com/web/raspberrypi/4346/ + + AIY Voice Kit で作った Google Speakerで、MagPi の chapter six の step 01 から step 07 まで、および、chapter seven の step 01 の backup first, step 02 の expect phrase, step 03 の handle phrase を一つずつ理解しながら実行し、p. 55 の cloudspeech_demo.py を作成し動作確認します。部品が手に入れば、step 04, step 05, step 06を実行して、led_demo.py を作成し, 実行します。p.59 のshutdown_demo.py を作成し動作確認します. ++ MagPi P.65の server_demo.py は servo_demo.py の間違いです。servoモータがあれば、これもテストしておくと良いです。 + Arduino Nano とNeoPixels Strip 60cm と100オームの抵抗とブレッドボードとジャンプワイヤの束を買ってきます。 ++ https://store.arduino.cc/usa/arduino-nano +++ Arduino Nanoのバージョンに注意. 3.0だとダメです。Whats Next Purple だとちゃんと動きました。 +++ http://bizright-blog.tumblr.com/post/120520808729/arduino-nano30の落とし穴にはまったお話戸嶋 ++ https://www.adafruit.com/product/1138?length=1 + AIY Voice Kit のRaspberry Pi (以後 Pi)に, Arduino のIDEをインストールします。 ++ https://make.kosakalab.com/make/electronic-work/inst_arduino-ide_raspi/ +++ sudo apt-get install arduino では動かないので、注意。 + PiのUSBコネクタの一つとArduino Nano をUSBケーブルで接続します。 + PiのArduino IDEの[Tool]の[Borad]でArduino Nano を選び、[Tool]の[Port]で /dev/ttyUSB0 を選びます。 + Arduino Nano で IDEのsketch の例の中のBasicのBlink(Lチカ)が動作することを確認します。ここで使うLEDはNano に最初から付いているLEDです。 + Adafruit のNeoPixels のページを参考にして、Arduino Nano と NeoPixels Strip を接続し, サンプルプログラムを動かして動作確認します。 ++ https://learn.adafruit.com/adafruit-neopixel-uberguide/the-magic-of-neopixels + 以下の arduino の sketch を、Raspberry Pi の arduino のIDEで作成し、arduino nano に書き込みます。 #code(C){{ include <Adafruit_NeoPixel.h> #ifdef __AVR__ #include <avr/power.h> #endif #define PIN 6 // Parameter 1 = number of pixels in strip // Parameter 2 = Arduino pin number (most are valid) // Parameter 3 = pixel type flags, add together as needed: // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) // NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products) Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800); // IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across // pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input // and minimize distance between Arduino and first pixel. Avoid connecting // on a live circuit...if you must, connect GND first. byte val=0; int led=13; int np=60; int np=30; uint32_t color=strip.Color(0,0,0); int lr=0; uint32_t pcolor=strip.Color(0,0,0); uint32_t pattern[30]; uint32_t originalPattern[30] ={0,0,1,1,1,0,0,1,1,1, 0,0,1,1,1,0,0,1,1,1, 0,0,1,1,1,0,0,1,1,1}; uint32_t prePattern[30]; int rbp=0; //rainbow position void setup() { // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket #if defined (__AVR_ATtiny85__) if (F_CPU == 16000000) clock_prescale_set(clock_div_1); #endif // End of trinket special code pinMode(led,OUTPUT); Serial.begin(9600); strip.begin(); strip.show(); // Initialize all pixels to 'off' for(int i=0;i<strip.numPixels();i++){ pattern[i]=originalPattern[i]; } } void loop() { if(Serial.available()>0){ String str = Serial.readStringUntil(';'); Serial.print(val); //for debug, echo back if(str.indexOf("original")==0){ lr=0; color=strip.Color(255,0,0,0); setColor2pattern(color,originalPattern); } else if(str.indexOf("rainbow")==0){ setRainbowPattern(); } else if(str.indexOf("red")==0){ color=strip.Color(255,0,0); setColor2pattern(color,originalPattern); } else if(str.indexOf("green")==0){ color=strip.Color(0,255,0); setColor2pattern(color,originalPattern); } else if(str.indexOf("blue")==0){ color=strip.Color(0,0,255); setColor2pattern(color,pattern); } else if(str.indexOf("yellow")==0){ color=strip.Color(255,255,0); setColor2pattern(color,pattern); } else if(str.indexOf("magenta")==0){ color=strip.Color(255,0,255); setColor2pattern(color,pattern); } else if(str.indexOf("cyan")==0){ color=strip.Color(0,255,255); setColor2pattern(color,pattern); } else if(str.indexOf("white")==0){ color=strip.Color(255,255,255); setColor2pattern(color,originalPattern); } else if(str.indexOf("left")==0){ // Some example procedures showing how to display to the pixels: lr=-1; } else if(str.indexOf("right")==0){ lr=1; } else if(str.indexOf("stop")==0){ lr=0; } else if(str.indexOf("off")==0){ for(int i=0;i<strip.numPixels();i++){ prePattern[i]=pattern[i]; } for(int i=0;i<strip.numPixels();i++){ pattern[i]=strip.Color(0,0,0); } } else if(str.indexOf("on")==0){ for(int i=0;i<strip.numPixels();i++){ pattern[i]=prePattern[i]; } } } showCurrent(); } void setColor2pattern(uint32_t c, uint32_t op[]){ for(int i=0;i<strip.numPixels();i++){ if(op[i]==0){ pattern[i]=0; } else{ pattern[i]=c; } } } void showCurrent() { for(uint16_t i=0; i<strip.numPixels(); i++) { strip.setPixelColor(i, pattern[i]); } strip.show(); delay(50); if(lr<0){ uint32_t xc=pattern[0]; for(int i=0;i<strip.numPixels()-1;i++){ pattern[i]=pattern[i+1]; } pattern[strip.numPixels()-1]=xc; } else if(lr>0){ uint32_t xc=pattern[strip.numPixels()-1]; for(int i=0;i<strip.numPixels()-1; i++){ pattern[strip.numPixels()-i-1]=pattern[strip.numPixels()-i-2]; } pattern[0]=xc; } if(rbp>=255){ rbp=0; } else{ rbp++; } } // turn off void turnOff(uint8_t wait){ for(uint16_t i=0; i<strip.numPixels(); i++) { uint16_t c=strip.Color(0,0,0); strip.setPixelColor(i,c); } strip.show(); for(uint16_t i=0; i<strip.numPixels(); i++) { delay(wait); } } void rainbow(uint8_t wait) { uint16_t i, j; for(j=0; j<256; j++) { for(i=0; i<strip.numPixels(); i++) { strip.setPixelColor(i, Wheel((i+j) & 255)); } strip.show(); delay(wait); } } void setRainbowPattern(){ for(int i=0;i<strip.numPixels(); i++){ // strip.setPixelColor(i,Wheel(((i*256/strip.numPixels())+rbp) & 255)); pattern[i]=Wheel(((i*256/strip.numPixels())+rbp) & 255); } } // Slightly different, this makes the rainbow equally distributed throughout void rainbowCycle(uint8_t wait) { uint16_t i, j; for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel for(i=0; i< strip.numPixels(); i++) { strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); } strip.show(); delay(wait); } } //Theatre-style crawling lights. void theaterChase(uint32_t c, uint8_t wait) { for (int j=0; j<10; j++) { //do 10 cycles of chasing for (int q=0; q < 3; q++) { for (uint16_t i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, c); //turn every third pixel on } strip.show(); delay(wait); for (uint16_t i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, 0); //turn every third pixel off } } } } //Theatre-style crawling lights with rainbow effect void theaterChaseRainbow(uint8_t wait) { for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel for (int q=0; q < 3; q++) { for (uint16_t i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on } strip.show(); delay(wait); for (uint16_t i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, 0); //turn every third pixel off } } } } // Input a value 0 to 255 to get a color value. // The colours are a transition r - g - b - back to r. uint32_t Wheel(byte WheelPos) { WheelPos = 255 - WheelPos; if(WheelPos < 85) { return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } if(WheelPos < 170) { WheelPos -= 85; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } WheelPos -= 170; return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); } }} + Arduino IDE の [tool]->[serial monitor] を選んで、「シリアルモニタ」を開きます。シリアルモニタの右下の、通信速度の設定のボタンで、9600 bps を選びます。 ++ シリアルモニタは、シリアルモニタで人間が入力した文字列を1と0の羅列(ASCIIコードの列)に変換し、Arduino に伝え、Arduino 側ではその羅列を受信して文字列に戻します。また、Arduino 側から送られた文字列を、ASCIIコードの列にして、IDEのシリアルモニタに伝え、IDEで文字列に戻します。 ++ シリアルモニタについては、以下などを参考にしてください。&br; http://www.vstone.co.jp/vs_wiki/main/wiki.cgi?page=Arduino+IDE%A4%CE%BB%C8%A4%A4%CA%FD%A4%F2%B3%D0%A4%A8%A4%E8%A4%A6 + シリアルモニタ上で、 white; を入力(;を入力した後, [return]または[enter]キーを入力してください)すると、NeoPixel Strip が飛び飛びに白く光ります。 left; を入力するすると、白く光った部分が左に流れます。この他、white, left 以外にも色々コマンドが使えるので, プログラムの中に書いてあるコマンドを試してみてください。 + Arduino IDEのシリアルモニタで人間がコマンドを入力した代わりに、Google で音声認識した結果、得られたコマンドをシリアル通信でArduino に伝えるようにします。Raspberry Pi で以下のプログラムを作成し、保存します。 #code(python){{ #!/usr/bin/env python3 # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A demo of the Google CloudSpeech recognizer.""" import aiy.audio import aiy.cloudspeech import aiy.voicehat import serial import time def main(): recognizer = aiy.cloudspeech.get_recognizer() recognizer.expect_phrase('turn off the light') recognizer.expect_phrase('turn on the light') recognizer.expect_phrase('blink') recognizer.expect_phrase('red') recognizer.expect_phrase('green') recognizer.expect_phrase('blue') recognizer.expect_phrase('white') recognizer.expect_phrase('yellow') recognizer.expect_phrase('magenta') recognizer.expect_phrase('rainbow') recognizer.expect_phrase('cyan') recognizer.expect_phrase('left') recognizer.expect_phrase('right') recognizer.expect_phrase('stop') recognizer.expect_phrase('turn on the tape') recognizer.expect_phrase('turn off the tape') button = aiy.voicehat.get_button() led = aiy.voicehat.get_led() aiy.audio.get_recorder().start() ser=serial.Serial('/dev/ttyUSB0',9600) time.sleep(2) aiy.audio.say('Hello, I\'m listening.') while True: # print('Press the button and speak') # button.wait_for_press() print('Listening...') text = recognizer.recognize() if not text: print('Sorry, I did not hear you.') aiy.audio.say('Sorry, I did not hear you.') else: print('You said "', text, '"') aiy.audio.say('you said '+text+'.') if 'turn on the light' in text: led.set_state(aiy.voicehat.LED.ON) elif 'turn off the light' in text: led.set_state(aiy.voicehat.LED.OFF) elif 'blink' in text: led.set_state(aiy.voicehat.LED.BLINK) elif 'red' in text: ser.write(b"red;") elif 'green' in text: ser.write(b"green;") elif 'blue' in text: ser.write(b"blue;") elif 'yellow' in text: ser.write(b"yellow;") elif 'cyan' in text: ser.write(b"cyan;") elif 'magenta' in text: ser.write(b"magenta;") elif 'White' in text: ser.write(b"white;") elif 'rainbow' in text: ser.write(b"rainbow;") elif 'left' in text: ser.write(b"left;") elif 'right' in text: ser.write(b"right;") elif 'stop' in text: ser.write(b"stop;") elif 'turn on the tape' in text: ser.write(b"on;") elif 'turn off the tape' in text: ser.write(b"off;") elif 'goodbye' in text: break if __name__ == '__main__': main() }} ---- #counter