2018年1月16日火曜日

Echo: Alexa skill 開発環境構築からローカルテスト、デプロイまで

とりあえずメモ。テストが自動化できそう。


環境構築

lambdaの環境だと、requestsパッケージすら入ってないので、virtual envで必要なパッケージをインストールした方が良い
virtual envをインストール

デプロイ前に、ローカルでテストして、構文エラーぐらいは直しておきたい
python lambda localをインストール

作業開始

aws lambdaのページに従い、virtual env環境で作業します

ローカルテスト

コマンド:
$ python-lambda-local -l $VIRTUAL_ENV/lib/python3.6/site-packages/ -f handler src/lambda_function.py event.json

-l には、virtual env上でインストールしたpython packageが入ったディレクトリ、つまりデプロイ時zip化するディレクトリを指定する
-f は、handler名
event.jsonの中身ですが、Alexa Skill Kitのテストタブにある、サービスシミュレータで、「発話を入力」すると、「サービスリクエスト」に出てくるjsonをそのまま使えます。


デプロイ

こちらに従い、Zip化して、lambdaに入れます。
Virtualenv で作成した Python 環境を使用してデプロイパッケージを作成する

開発したAlexa skillが、アプリ上に表示されない場合

Amazon developer console上でスキルを開発しても、スマートフォンアプリの方に表示が出ないことがあります。
私の場合は、Amazon USのアカウントでログイン・開発していたのが原因でした。
IDはUS/JPともに同じもの(メアド)、パスワードだけ違っているので、JPのID/PWでログイン・スキルの追加をすることで、表示されました。
なおUS/JPのDeveloper console間で、開発中・開発したSkillは共有されないようなので、USで作ってしまったらJP site側で再度作り直す必要がありました。

2017年12月3日日曜日

Use Arduino IRRemote library on ATTiny85

--- 日本語は下の方に記載してあります

Arduino IRRemote library supports ATTiny85. ( Official homepageand Github)
But it does not work so far on my environment. To use it for sending IR, some tricks are needed.

  1. Stop interrupt during sending IR.
  2. Modify delay function, IRsend::custom_delay_usec
Background of this modification is simple. IRRemote library uses TIMER0 to control PWM for IR on ATTiny. Arduino time related functions, like micros(), uses TIMER0 for counting time. IRRemote's changing TIMER0 parameters changes its behavior.
And TIMER0 generates interrupt every overflow period to count up arduino timer related values. By IRRemote's change, TIMER0 trigger's overflow interrupt each 13usec period (at CPU clock 8MHz). This breaks PWM frequency since PWM works with TIMER0, too.

So, solution for 1 is that use noInterrupts() and interrupts() before/after IRsend::sendXX();

noInterrupts();
irsend.sendRaw(codeValue, 32);
interrupts();


Solution for 2 is that replace custom_delay_usec()'s wait function to use delayMicroseconds(). delayMicroseconds() does not uses timer interrupts related value to wait. See API reference.

void IRsend::custom_delay_usec(unsigned long uSecs) {
  delayMicrosec(uSecs);
}

I did above two in my sketch by copying IRsend code from IRRemote library code...
It can be achieved by inheriting own class from IRsend, but not tested.

===
ATTiny85でArduinoのIRRemote libraryを使う方法です。
IRRemoteはATTiny85のサポートをしていますが、いくつか修正をしてあげないと動きません。

  1. 赤外線を送信している間、割り込みを禁止する
  2. IRsendのcustom_delay_usec()の修正

--- Follows are japanese.---

IRRemote libraryは、ATTiny85の場合、TIMER0を利用して赤外線送信を行っています。しかし、TIMER0はArduinoのタイマー周り、例えばmicros()の実現のために利用されています。
IRRemote libraryは、赤外線の38KHz, 1/3 dutyを実現するために、PWMを利用しており、ATTiny85の時は、TIMER0で、このPWMを制御しています。
IRRemote libraryが赤外線のためにこのTIMER0を変更しますが、このせいでmicros()あたりの挙動が変わります。
IRsend::custom_delay_usec()はmicros()を利用しているため、期待したwait時間のwaitをしません。
また、この変更による割り込みも影響します。
Arduinoの時間系ライブラリは、TIMER0のOverflow割り込みを使って時間関係の変数を更新します。IRRemoteは、TIMER0のoverflow valueを変えるため、13usecごとに割り込みが発生します。(CPU clock 8MHzのとき)
このoverflowが起きると、割り込みが終わるまでpwmの動作も止まってしまいます。38KHz, 1/3 dutyが壊れるわけです。

1の対処は簡単です。Arduinoの割り込み禁止・許可関数の、noInterrutps()/interrupts()を、IRsend::sendXXの前後で呼び出すだけです。
2の対処ですが、IRRemote libの、custom_delay_usec()の処理を、delayMicroseconds()に置き換えるだけです。delayMicroseconds()は、TIMER0割り込みを使わないように書かれていますので、TIMER0の影響を受けません。
(コードは上の方に)

私の場合、IRRemote libから、sendXX関連のメソッドを自分のsketchにコピーして書き換えました。元のコードをいじらないためです。
IRsend classを継承して、必要なメソッドをoverrideすることでも実現できるはずですが、未確認です。