ラベル ESP8266 の投稿を表示しています。 すべての投稿を表示
ラベル ESP8266 の投稿を表示しています。 すべての投稿を表示

2018年4月13日金曜日

ESP32+Mongoos OS、入れてみました。

まず、ESP-IDFが正しくインストールされている必要があります。

で、ホストMac/PCに環境を構築します。macの場合はターミナルに3行コピペするだけ。1分もかからず終了し、ブラウザにmongoose os環境が立ち上がります。

mongoose osは、ESP上で動くOS(FreeRTOSベース?)、JavaScriptランタイム、フラームワーク、それらと連携するMac/PC上で動くホストツールなどで構成されています。フレームワークはAWS, Google IoTなど各社クラウドサービスに対応していて、お手軽に使えます。

サーバとなっているツール部分がESPと通信しながら動いているので、ブラウザIDEなのにスタンドアローンアプリ形式のIDEと同様に使えます。例えば、こんなダイアログが出てくるので、ESP32 Dev-CモジュールをUSBに接続するとシリアルポートが選べます。選んだらSelectボタン。


次にプラットフォームと書き込むアプリを選んでFlash。書き込みが自動で始まります。書き込みが終わるとデモアプリ「demo-js」が起動して、じわじわとメッセージを流してきます。


このあとSet WiFiで使用場所でのSSIDとPasswordを設定してSetボタンを押せば接続完了。

楽だなー。ESP32用の開発ツールとして一番よく出来ているかも。

JavaScriptとC/C++も簡単に連携できるし、しばらく遊んでみます。ずっと保留したままになっているニキシー管時計、これで作ってみようかしらw

2017年3月31日金曜日

ESP8266のanalogWrite、使用上の注意


ESP8266 / ESP-WROOM-02のanalogWriteでおかしな現象に遭遇しました。回避策も合わせてご紹介します。

■複数analogWrite同時出力でちらつく■

Power LEDをドライバに接続して「じわーっと明るくする」制御をしていたところ、「じわー」のところでちらつく現象が発生しました。調べてみると
  • analogWriteの値を1ch変えただけではちらつかない
  • 2ch以上同時に変えるとちらつく

ことがわかりました。ここにたどり着くまで大変でした……。OTA処理で時間を取られているんじゃないか、温度センサーの読み込みでひっかかるんじゃないか、もしかしてPower LEDドライバに問題があるんじゃないか……。「じわー」のプログラムに問題があるんじゃないか……。など。

以下切り分けのためのコードです。ご覧の通り、単純に値を整数で加算していくので、ちらつくはずないですが、激しくチラつきます。


ここで「もしかして、analogWriteをほぼ同時に複数書き換えると問題が生じるのではないか?」と思い至りました。以前、analogWriteのソースを調べたことがあったのですが、通常のカウンターとコンパレータではなく結構めんどうくさい割り込み処理を使って全部ソフトで処理されていましたので。書き換えの時に処理が追いつかない等でパルス幅が乱れるのだと思います。

で、書き換えたのがこちらです。


問題なく動作します。ESP8288 / ESP-WROOM-02のanalogWriteを複数同時に書き換えるときにはご注意ください。

■CM■

ここで使用しているPower LEDドライバ基板、スイッチサイエンスのESPrや弊社Board1をそのまま挿して、300mA x 3chのLEDを制御できます。オンボードの温度センサーを使って、基板の温度上昇を検知して出力を下げる、なんてこともできます。

どぞよろしく▶Cap1 - LED Drivers for ESP

2016年9月22日木曜日

今更ですがESP-WROOM-02で赤外線リモコン(174円也)

先日、会社でIoT勉強会を実施しました。

勤務先はガチのソフト開発なのですが、やっぱりIoTへの関心は高く、あっという間に定員に達しました。内容的にはESP-WROOM-02+BME280(気温湿度気圧センサー)+PIRセンサー(人感センサー)+空気質センサー+OLEDという有りがちな組み合わせですが、幸いにも好評のうちに勉強会を終えることができました。


勉強会を開催したい!!という方はLinkedIn経由でくらはしまでご連絡ください。材料費は1人前5000円ぐらいです。団地の集会場やコミュニティセンターでやってみたいです。

で、ここからが本題。勉強会参加者の方から、アフターフォローSNSで「エアコンを制御したい」というお題をいただきましたので、さくっと作ってみました。

■部品■

品名Name秋月PN価格購入数量参考バラ単価使用数
赤外線リモコン受信モジュールOSRB38C9AA(2個入)IR_RECEIVERI-046591001501
5mm赤外線LED OSI5FU5111C−40 (5個入)D1, D2I-032611001202
トランジスタ2SC1815GR 60V150mA (20個入)T1I-008812001101
カーボン抵抗(炭素皮膜抵抗) 1/6W 47Ω (100本入)R3, R4R-16470100112
カーボン抵抗(炭素皮膜抵抗) 1/6W 2.2kΩ (100本入)R1, R2R-16222100112
積層セラミックコンデンサ 47μF16V ±10% 5mmピッチ (10個入)C1P-049177001701

秋月で買うと大量に余りますが、特に抵抗とトランジスタは必ず使うので買ってしまってもいいと思います。コンデンサがわりと高いですが、これは無くてもあんまり変わりませんし、同容量の電解コンデンサなら1本10円ぐらいだと思います。

このうち、抵抗とセラミックコンデンサは極性がありません。つまり、どのピンをどっち側につないでもOKです。が、赤外線受信モジュール、LED、トランジスタ、電解コンデンサには極性があります。電解コンデンサは表面に書いてありますし、LEDは長い方の足がプラス電源側になります。トランジスタは仕様書にECBと書いてありますが、それぞれ、エミッター、コレクタ、ベースの略です。2SC1815の場合は、足を下に向け、平らな面(部品番号などが印字されている面)をこちらに向けて、左からECBの順番です。回路図ではトランジスタの左側がB(ベース)、上(矢印のついてないヤツ)はC(コレクタ)、下(矢印)はE(エミッタ)です。

赤外線受信モジュールIR RECEIVERはモノによって違いますが、今回使ったものは足を下に向け、受光窓をこちらに向けた左から1 OUT、2 GND、3 VCCです。違うモジュールを使った場合には仕様書で確認してみてください。

抵抗値は、2.2kΩ(回路図では2k2と表記)は赤赤赤金、47Ωは黄紫黒金です。最後の金は精度を表すもので金は±5%、銀は±10%です。今回のような用途では5%でも10%でも問題ありません。カラーコードについては、ここのページが見やすいかと思います(特に一番下の表)。

■回路■


会社のブログでは私のホワイトボードへろへろ回路図が晒されてしまったので、汚名返上を願ってEagleで書いてみた。

…ツール使ってもヘロヘロだったorz

あ、4u7じゃなくて47uだった。受信プログラムを走らせていると、リモコン操作していなくてもインバータやLEDランプのノイズを出鱈目な信号として誤認識してしまうので、ノイズ対策としてつけてみたんですが、あんまり違いありませんでした。誤読の場合はメーカー識別コードなどが出鱈目になるので対象となる製品のコードでフィルタリングすれば実用上は問題ないかと思います。

47μFの積層セラミックコンデンサは結構高いので、なしでもええんやで、H田さん。

受信機はIO15、LEDはIO16につないでいますが、これは空いていればどこでもOKですが、ソースのIOポート番号をそれに合わせて変更する必要があります。

同じ回路をArduinoで使う場合には、3v3ではなく5vにつなぎ、R3とR4を75Ωに取り替えてください。

■ライブラリ■

Arduinoの定番IRRemoteをESPで使うとAVR.hでひっかかってしまうので、IRRemoteESP8266を使います。原作者の方、ESP8266へポートしてくださった方に感謝致します。

githubからzip落としてArduino IDEに読み込ませます。

IRRemote/IRRemoteESP8266とも、そのままではバッファが小さくてエアコンのデータを扱うことができません。適当なエディタでIRRemoteESP8266.hを開き、RAWBUFの値を100から400に変更255に変更して保存します。

追記(2017年2月6日):400では動かない、ここは8bitなので255が最大値とのご指摘をいただきました。大変申し訳ありません。ご教示いただきありがとうございました。

…ところで何故私のところでは動いていたのでしょう・・・。

■受信プログラム■

コードを解析してバイナリコードで送るのがスマートなんですけど、面倒くさいのでrawコード(信号のon/off時間をそのままベタに記録したフォーマット。とても長い)を受信します。

なお、エアコンの場合、テレビと違ってリモコン信号が正常に送られているかどうか判断するのが難しいです。設定温度を本体に表示してくれるエアコンは別ですが。なので、私はタイマーのon / offで確認しました。タイマーをセットするとエアコン本体の予約ランプが点灯するので、セット / 解除の信号を送って、ランプの点滅で動作確認しようという寸法です。

何その巨大Lチカ。

他にはフィンの向きを使う(左右に切り替える)のも良いかと思います。なおエアコンの頻繁なon/offは電力消費にもエアコン本体の寿命にも悪影響を与えるので、ご注意を。

仕事部屋は古いFujitsuエアコン、IRRemoteのサンプルを改造して、以下のような出力を得ました。Panasonicとか48bitsとか出てますが気にしないように。

26度、風量自動、1時間タイマーON:
8083F
Decoded PANASONIC - Address: 28C6 Value: 8083F (48 bits)

Raw (244): 0xCE4,0x672,0x1C2,0x190,0x1C2,0x190,0x1C2,0x4E2,0x1C2,0x190,0x1C2,0x4E2,0x1C2,0x190,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1F4,0x190,0x190,0x190,0x1C2,0x190,0x1C2,0x1C2,0x1C2,0x190,0x4E2,0x1C2,0x190,0x1C2,0x190,0x1C2,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x190,0x1C2,0x1C2,0x1C2,0x190,0x4E2,0x1C2,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x190,0x190,0x1F4,0x190,0x190,0x1C2,0x4E2,0x1C2,0x190,0x1C2,0x190,0x190,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1C2,0x190,0x190,0x1C2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x1C2,0x190,0x4E2,0x1C2,0x1C2,0x190,0x4E2,0x1C2,0x4E2,0x1C2,0x190,0x190,0x1F4,0x190,0x1C2,0x1C2,0x4E2,0x1C2,0x190,0x1C2,0x190,0x190,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x1C2,0x190,0x190,0x1C2,0x1C2,0x1C2,0x190,0x190,0x190,0x4E2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x190,0x190,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x190,0x1C2,0x4E2,0x1C2,0x190,0x1C2,0x190,0x190,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x190,0x1C2,0x190,0x1C2,0x190,0x190,0x1C2,0x190,0x190,0x190,0x1C2,0x190,0x1C2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x1C2,0x190,0x4E2,0x1C2,0x4E2,0x1C2,0x190,0x190,0x4E2,0x1C2,0x4E2,0x190,

26度、風量自動、タイマー解除:
8083F
Decoded PANASONIC - Address: 28C6 Value: 8083F (48 bits)
Raw (244): 0xCE4,0x672,0x1C2,0x190,0x1C2,0x1C2,0x1C2,0x4E2,0x1C2,0x1C2,0x1C2,0x4E2,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x4E2,0x1C2,0x4E2,0x1C2,0x190,0x1C2,0x190,0x1C2,0x1C2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x190,0x1C2,0x1C2,0x190,0x4E2,0x1C2,0x1C2,0x190,0x190,0x1C2,0x190,0x190,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x4E2,0x1C2,0x1C2,0x190,0x190,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x190,0x1C2,0x4B0,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x4B0,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x190,0x1C2,0x190,0x1C2,0x1C2,0x190,0x4E2,0x1C2,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x190,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x190,0x190,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x190,0x1C2,0x1C2,0x4E2,0x1C2,0x190,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1C2,0x1C2,0x190,0x1C2,0x190,0x190,0x1C2,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x190,0x190,0x190,0x1C2,0x1C2,0x190,0x1C2,0x190,0x1C2,0x190,0x1C2,0x190,0x190,0x1C2,0x190,0x1C2,0x1C2,0x190,0x190,0x1C2,0x1C2,0x190,0x1C2,0x190,0x190,0x1C2,0x1C2,0x190,0x1C2,0x190,0x1C2,0x190,0x190,0x1C2,0x1C2,0x190,0x190,0x1C2,0x1C2,0x190,0x1C2,0x190,0x1C2,0x1C2,0x1C2,0x190,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x4E2,0x1C2,0x190,0x190,0x4E2,0x1C2,0x190,0x1C2,0x1C2,0x190,

長いっすねー。ソースは短いっす。


■送信プログラム■

受信プログラムからシリアルに吐き出されたraw列をコピペして、5秒ごとに送信受信を繰り返すプログラムです。これも元は附属のサンプルを書き換えました。

動きます。動きますが、赤外線LEDの指向性がかなり強いので、向きをちゃんと合わせないと反応してくれません。気をつけてください。

こっちもソース短いです。

2016年8月17日水曜日

ESP+400円あれば10分で作れる睡眠計

ただし送料は別ですw

秋月電子通商のサイトから

これは毎度おなじみのPIRセンサー、赤外線を発する物体が動いたことを検出してくれるセンサーです。主に防犯用途で使われるものですが、安い割には高感度なので鳩の検出や来客の検出など便利に使えます。なお、このHC-SR501は安いんですが、動きを検出したあと信号を数秒〜数分間引き伸ばして出力する仕様です。侵入者を検知してランプを点灯するためのものなので。そういう意味ではSE-10というセンサーの方が正確に把握できるんですが、高いのと5V電源では正常に動作しないので、今回は見送ります。

今回はこの400円のセンサーと無料のThingSpeak.comを使って10分で睡眠記録デバイスを作ってみます。

当然ESP-WROOM-02のモジュールも必要です。それにはぜひ倉橋屋Board1をご検討ください:-)

…他にオス - メスのジャンパワイヤとかブレッドボードが必要ですが、それはさておき。

まず、PIRとESP-WROOM-02を接続します。PIRの電極は、ドームを上、ピンを手前にした状態で左からGnd, Signal, Vccです。GndとESPのGnd、SignalとIO12、Vccと電源(5v以上…Board1をUSBにつないでいる場合はVin、ESPrなどではVOUT)を接続します。Signal出力は約3vなので、ESPと直結しても大丈夫です。なお、PIRによってはもっと電圧の高いものやオープンコレクタのものもあるので、その場合は仕様に従ってください(コメント欄に書いていただければ、わかる範囲でお答えします)。

接続はこれでおしまいです。HC-SR501はボリュームが2つ付いていて、それぞれ感度調整と持続時間調整です。感度はその通り感度で時計回りに回すほど敏感になります。持続時間は一度動きを検出した時にその後何秒出力HIGHを維持するかを設定できます。睡眠計として使うのであれば、感度は最低(時計回り目一杯)+持続時間最小(時計回り目一杯)で良いと思います。あとジャンパが一箇所ありますが、基板の端の方にするとHIGHになっているときに次の動きを検出してもLOWになるタイミングは延長されませんが、基板端から離れた方に挿すと動きを検出した時点でHIGHが延長されます。これ、どっちが良いでしょうね。

ThingSpeak.comのアカウントを登録します。ThingSpeak.comは「チャンネル」という単位で送信されてくるデータを管理します。一つのチャンネルは最大8個までのデータ列を記録することができます。New Channelで新しいチャンネルを登録し、Nameは適当に、Field1に「movement」というタイトルを付けチェックします。下の方の「Save Channel」をクリックすればOKです。次にAPI Keysというタブをクリックし、「Write API Key」の値をコピーしておきます。

あとは、以下のソースをArduino IDEで開き、お使いのWiFiのSSIDとパスワード、それからさっきコピーしたWrite API KeyをapiKeyにセットすればOKです。

一晩走らせてみた結果がこちら。

会社のIoT勉強会で使ったThinkSpeakを流用したのでArkの名前がw

そのままグラフにすると細かすぎてわからないので10分ごとの平均を480分表示させています。SE-10で取得したデータほどすっきり分離されないですが、xx時にベッドに入り、xx頃入眠、xxにトイレに起きてxx時起床というのが(言われれば)おわかりいただけるかと思います。

私は初老なので睡眠導入剤などを使っていますが、とりあえずこういうグラフがあれば「どの食事/運動/薬/サプリが有効なのか」を客観的に知ることができるかなー…と思っています。昼間部長とメールバトルした日などはドキドキして眠れないので、なかなか客観的な評価は難しいのですが(笑)。

小心者指数を計れるデバイスが出たら買います。買うべきです。ま、買っても役に立ちませんががが。

2016年6月21日火曜日

450円でESPでもArduinoでも使える高精度RTC

電子工作でRTCっていうとDS1307 / 1302あたりが定番だと思うんですが、秋月で売ってるRX-8025NBって、なかなか良いと思うんです。TXCO使ったものだともっと精度の高いものもあるんですが(NXPのPCF2129など)、450円で月差13秒程度ってのはなかなかのバランスだと思います。

秋月電子のサイトから

ずっと以前に買ってあったものの使う機会がなくて部品沼に沈んでましたが、在庫リストを見ていたら出てきたので使ってみました。

配線は、SDA - SDA, SCL - SCL, Vcc - Vcc, Gnd - Gndで何のひねりもありません。動作電圧範囲が広いのでmbedでもArduino / ESP8266/ ESP-WROOM-02どれでもそのまま使えます。

欠点としては、バッテリバックアップのラインが別になっていないので、電池やスーパーキャパシタをつなぐときにはSBRダイオードなどで一手間かかってしまいます。

この点、VddとVbatが分かれているDS1307+とかPCF2129は便利なんですよね。

余談ですが、こないだPCF2129で基板を作ったんですが動作しなくて泣いています。その辺の顛末はまたいつかブログに書きます。

■ソース■

こちらの記事を参考にさせていただきました。ありがとうございます。

RTCに多いんですが、年月日時分秒すべて60進数のBCDです。通常の10進をそのままセットするとまともな値が返ってこないので、セット前 / 読み出し後に変換してやる必要があります。fromClockFormatはBCD(60進)から10進、toClockFormatは10進からBCDへの変換を行ってます。

time_t(unix時間:1970年1月1日 00:00:00.000からの経過ミリ秒)とグレゴリアン歴との変換は標準関数で済ませてしまいました。テヘペロ。

起動するとWiFiに接続してsntpから時間を取得してRTCにセットし、あとはRTCから読み込んでは時間を表示しているだけです。

このRTCにはアラームをセットして割り込みを掛けたりする機能もあるのですが、使っていません。ESP-WROOM-02でRSTにつないでやると、deep sleepの後に指定した時刻に立ち上がる、なんてこともできると思います。



いい感じで動いているからあと何個か買っておこう。

…秋月にアフィリエイトがないのが残念です(笑)。

2016年6月19日日曜日

ESP-WROOM-02 : SNTPのAPIで大ハマリ


ESP8266 NON OS SDKには、sntp_get_current_timestamp() というapiが用意されています。その名の通り、ntpサーバにアクセスして時間をもらってくるものです。

ところが。

これが全然値を返してくれません。0ばっかりです。sntp_init()の順番が悪いのだろうか、time zoneを設定しなければいけないのか、upd local portが必要なのだろうか、DNSが動いていないのだろうか…など、2時間ほど試したのですが、ダメでした。

が。

ふと見ると、参考にしていたReferenceはver 1.1と書いてありまして。最新の1.5.4を見ると多少サンプルが違います。1.1と違って、waitが入ってます。

… sntp_get_current_timestampでは、パケット待ってくれないんですね…。referenceにそんなこた何にも書いてねーぞー(血の叫び

以下のコードで普通に動きました。はい、お疲れ様。

uint32_t getTimestamp() {
  configTime(9 * 3600, 0, "ntp.nict.jp", NULL, NULL);

  uint32_t result = 0;
  int cnt = 0;
  while (result == 0) {
    result = sntp_get_current_timestamp();
    delay(100);
    if (++cnt > 10) {
      break;
    }
  }
  return result;
}
ESP8266のサンプルとしてESP8266WiFi/NTPClientなんてのがあるせいか、スクラッチでUDPのntpパケットを扱っている作例が多いのですが、これ使うと簡単です(ハマらなければね)

ご活用くださいませ。

2016年6月14日火曜日

風呂水温計 ver 3.1

前回バージョンを少し改良。電池をもたせるために30度以下なら10分ごと、超えたら5分ごとに測定するようにしました。

…こんなグラフになりました。


沸くの早いな、ほんとに。

改良箇所は、void setup()の直前に次の行を追加し
int waitSec;
deepSleepの行を以下に入れ替えました。
waitSec = temperature > 30.0 ? 300 : 600;
ESP.deepSleep((waitSec - second()) * 1000 * 1000, WAKE_RF_DEFAULT);
さて、風呂に入ろうっと。

■追記 6/15■


前記のように「30度を下回ったら」って仕様に変更したんだけど、お湯に入れたままだと30度以下にならない件。これから暑くなるしなぁ。

2016年6月13日月曜日

100円温度センサー+ESP-WROOM-02でWiFi風呂水温計



ってことで、昨日試した100円温度センサーSTTS751をESP-WROOM-02と電池に接続し、100均のジャム瓶?に入れました。フタの発泡ウレタンを少し切り取ってアルミ地金をむき出し、そこに放熱グリースを塗ってセンサーを貼り付けました。

風呂の中でフタを下にして浮かんで欲しいので、重い電池がフタ側に来るようにするのがコツ?です。ただ、フタが下だとどうしても浸水してしまいます。内部の温度が下がるときに熱膨張(の逆)によって水を吸い込みますので、風呂が湧いたらお湯から出すようにするのが一番効果がありました(経験者は語る)。

対策としては膨張した空気の容積差を吸収すればいいので、もっと柔らかいボトルを使うか、ボトル側に穴をあけてビニールシートで空気室を作ってやるのが一番簡単かなと思います。

また、風呂のフタをしめていれば、それほど大きく温度がズレることもないので、電池をボトル側の底に入れても問題ないかと思います。その辺は使い方に応じて選択してください。


ESP-WROOM-02がdeep sleepから立ち上がった時にWiFi経由でThingSpeak.comへデータを送信します。風呂の温度はそれほど急激に変化するものでもありませんから、送信頻度は5分に1回にしました。以前1分間隔で動かした時には単4白エネループ3本で110時間動きました。今回黒エネループで何とか一ヶ月=720時間程度動いてくれると便利なのですが。

なおSTTS751とのやりとりは、こちらを参考にさせていただきました。ありがとうございます。

以下ソースです。初期化処理にbegin transmissionを追加して、データ受信のところを多少書き換えました。上記のサンプルコードには問題があるので後日修正します(6/24)。ThingSpeak.comへの送信は以前と同じというかほぼコピペです。


■追記■

電池のさらなる長持ちを目指してプログラムを改良しました(風呂水温計 ver 3.1)。

2016年6月10日金曜日

デジタルマイクSPM0405HD4Hがデジタルで動いた!

このまま「またデジタルマイクが動かない」「やっぱりデジタルマイクが動かない」「まだまだデジタルマイクが動かない」と長編化するかと思われたデジタルシリコンマイク、ついに動きました!


■考察■

今までも動いていたけどノイズに埋もれてわからなかった、というのが真相だと思います。

動かなかったバージョンでは100-10000回のカウントを終えるとLoopを抜けていました。これはESP-WROOM-02にはWDTがついていて、約1秒間loop()から抜けないとリセットがかかるのです。

何となくloop()抜けてもすぐに帰ってくるんだろ、ぐらいに考えていたんですが、これが想定以上に大きくて、抜けるたびに処理が止まってノイズとなっていました。loopから抜けるのをやめてESP.wtdFeed()にしたところ、かすかなノイズは入りますがマイクの前の音声がちゃんとADCから出力されるようになりました。

■ソース■

loopの値は100(サンプリング周波数10khz)ぐらいが良いようで、10(100khz)だとDACに出力するためのブランクの比率が著しいノイズとなり1000(1khz)にすると割れて何が何だか、という感じでした。また、countとして++だけでなく--も入れてみたところ、音量がかなり大きくなりました。100の場合で値は-100〜+100まで振れるので、精度は8bit、速度は10khzということになります。





お騒がせしました&ありがとうございました>電子工作部各位殿

もうちょっと高速のCPUが使えれば、DAC出力その他のための中断を回避できるので、もっといい音になると思います。現状で160Mhzクロックの32bit CPUなので、これより上のCPUを用意するよりはFPGAで作るべきものだと思います。約400円で専用チップ売ってるんですけどねw

ちなみにマイクの性能には「14bit相当・10khz」とのこと。うーん、どういう演算処理をすればそういう信号が得られるのでしょう。思いついたらまた試してみます。

■使用部品紹介という名のCM■

今回の実験では、
同社サイトより


同社サイトより

同社サイトより

を使用しました。

マイクモジュールとアンプへの3v3はBoard1搭載の安定化電源から供給しています。何かと電源にシビアなESPですが、(プログラムのバグ以外では)安定して動作しています。

タフな電源にしといてよかった…と設計者は胸をなでおろすのであった(完)。

2016年6月9日木曜日

デジタルマイクが動かない(SPI DAC出力編

Board1 - Mic - ADC+D級AMP

■ノイズしか出ねえ■

前回のあらすじ。秋月で300円のデジタルマイクモジュールを試してみたものの、マイコンからパルスを入れてもそれっぽい信号が取れている気がしない。でも、出力をLPF通してアンプにつないだら音が出ていた。

ということはPDMとしての動作はOKであとはデジタルとしてどうやったら信号を取り込めるか、ということになります。

ESP-WROOM-02を160Mhzで動かし、約1mhzでデューティー比50%近いパルスを入れてダウンエッジから約60nSecぐらいのところで取り込んだデータを集計してDACから出力してみたのですが…雑音しか出て来ませんでしたorz

ということで、以下失敗の記録です。なお、失敗記録を読んでもしょうがない、という方は先にこちら(デジタルマイクSPM0405HD4Hがデジタルで動いた!)をどうぞ。

■SPIと競合しちゃう■

最初GPIO12から信号を読み込んで居たのですが、ずっとゼロでした。SPIライブラリの内部で何かに使っているようです。GPIO5からクロック出力、GPIO4からデータ入力…という形にしたところ、読み込みできました。

なお、DACはMCP4922を使い、配線は以下の通りです。正しく動作しているかどうかは例によってノコギリ波で確認しました。

ESP8266SPM0405HD4HMCP4922
GPIO4DAT
GPIO5CLK
3v3Vcc1, 1, 11, 13
GndGnd, L/R12 GND
GPIO135 SDI
GPIO144 SCK
GPIO153 !CS
GPIO168 !LDAC


■最適化されちゃう■

タイミングやデューティー比を調整するために意味のないインクリメントを入れてみたのですが、localで宣言した意味のない演算は最適化で消されちゃうみたいですね。
for (int i = 0; i < n; i++) {
  int a = 0;
  a++;
  a++;
}
a++を増やしても結果変わりません。

void loop()の外で
int a = 0;
を宣言すると1つあたり25nSec程度の遅延が得られます。

digitalWrite(x, HIGH)で225nSec、digitalWrite(x, LOW)で212.5nSec程度の処理時間がかかります。

■試行錯誤しちゃう■

  • 現在のソースではダウンエッジだがアップエッジでも試す。ダウンエッジとアップエッジをLRライン=LOW/HIGH両方で試す。
  • ループ前にcountを0にして入力HIGHなら加算。あるいはLOWなら加算
    ▶ノイズだけ
  • ループ前にcountを毎回初期化せず、HIGHなら加算, LOWなら減算。あるいは逆
    ▶発散しました
  • ループ回数を減らしたり増やしたり
    ▶ノイズの音質が変わりますw
  • パルス出力からサンプリングまでのタイミングを増やしたり減らしたり
    ▶ノイズの音質が変わりますw
浩一はもう疲れました…。


■ソース■

loop内でforループから抜けた後のSerialは、タイミングなどを確認した後にコメントアウトしてます。処理時間がものすごく長いので。それとArduino IDEではツールメニュー>CPU Frequencyで160Mhzを選んでください。80Mhzだとクロック500khzしか出ませんので。


■そして…■

2016年6月5日日曜日

デジタルマイクが動かない(ESPとFPGAでクロック生成 )◀アナログ出てました

秋月のディジタルシリコンマイクモジュール(細ピンヘッダ版)を試してみました。

秋月のサイトより

このモジュールは1-3.25MHzのクロックを入れればPDMフォーマットでデジタルデータが取り出せます。PDMなのでローパスフィルタを通せばそのままアナログ信号として使えます。しかも300円。素晴らしい。

…しかし使えなければ意味がありません。結果として動作させることができませんでした。

今週は何をやっても動かないなorz

■追記6/6■

電子工作部の方から「LPFの出力をアンプに繋いでみたら何か信号出てるんじゃない?」というアドバイスをいただき、FPGAで作った1.25Mhzのクロックを入れて、LPF出力をカップリングコンデンサ経由で27dBのアンプにつないでみました。

そしたら!

小さいですが確かに音が出ています!! いえええええ!!! アドバイスありがとうございました。うれしー。小さすぎてオシロでは見えなかったけど、信号出てたのね。

というわけで、今週末はデジタルでの処理に再挑戦します。

それまでは以下のマイコンでの試行錯誤からFPGAでのクロック発生回路でアナログとしての取得に成功、最終的にデジタル信号として取り込みDACから音が出るまでのドタバタ劇をお楽しみいただければ幸いですw

■SPIでデジタル入力(失敗)■

今度はSPIです。SPIのクロックを1Mhzに設定し、SPI modeをいろいろ変えたりしてみたのですが、結果は似たようなもので値が123-127の間をパラパラ上下するだけでした。

#include <SPI.h>
const uint8_t BITS_COUNT_TABLE[256] = {
    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
};
int numofbits2(uint16_t bits)
{
    return BITS_COUNT_TABLE[((unsigned char*)&bits)[0]]
         + BITS_COUNT_TABLE[((unsigned char*)&bits)[1]];
}
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  SPI.begin();
  SPI.setFrequency(1000000);
  SPI.setDataMode(SPI_MODE0);
  noInterrupts();
}
static int mabiki = 0;
void loop() {
  // put your main code here, to run repeatedly:
  int num = 0;
  for (int i = 0; i < 16; i++) {
    num += numofbits2(SPI.transfer16(0xffff));
  }
  char buf[6];
  sprintf(buf, "%4d", num);
  if (mabiki == 20) {
    Serial.println(buf);
    mabiki = 0;
  } else {
    Serial.print(buf);  
  }
  mabiki++;
}
なお、ビットカウントはこちらの記事から使わせていただきました。

テーブルを使う方法は思いついたのですが、そのあとに記載されているアルゴリズムは本当にびっくりです。1960年代のコンピュータサイエンスは凄まじいですね。

■GPIOでデジタル入力(失敗)■

GPIOでクロックを生成し、ポートを読み込んで積算する方法を試してみました。帰ってきた値は見事にデタラメでグラフ化しても波形になりませんでした。
#include <Arduino.h>
void setup() {
  // put your setup code here, to run once:
  Serial.begin(230400);

  pinMode(14, OUTPUT);
  pinMode(12, INPUT);
}
void loop() {
  // put your main code here, to run repeatedly:
  int count = 0;
  for (long l = 0; l < 1000; l++) {
    digitalWrite(14, HIGH);
    if (digitalRead(12) == HIGH) {
      count ++;
    }
//    else {
//      count --;
//    }
    digitalWrite(14, LOW);
  }
  Serial.println(count);
}

なお、コメントアウトの部分はLOWならデクリメント、というサンプルを見たので試してみたのですが…結果がマイナスに振れただけで同じでしたたたたた。

■マイコン発振 / アナログ出力(失敗)■

1MHz強のクロックを入れ、出力に約20khzのローパスフィルタ(R=1kΩ,1=10nF)を通してマイク前から信号を入れてみました。ローパスフィルタは出力端子>抵抗>コンデンサ>Gndとつないで、抵抗とコンデンサがつながっているところから出力取ります。1MHz強のクロックはESPを160MHzクロックで動かして、以下のプログラムで生成します。デューティー比50%にならないけど、気にしない。デューティー比を考えれば少しでも演算の早いshortの方が良いのですが、shortだと約32mSecごとにシステム?に戻ってしまうのでオシロで波形見るときに邪魔かなと。
#include <Arduino.h>
void setup() {
  // put your setup code here, to run once:
  pinMode(14, OUTPUT);
}
void loop() {
  // put your main code here, to run repeatedly:
  int count = 0;
  for (long l = 0; l < 1000000; l++) {
    digitalWrite(14, HIGH);
    digitalWrite(14, LOW);
  }
}

さて出力は…見事に直流です。本当にありがとうございましたorz

■FPGA発振 + アナログ出力■

最後にFPGAでちゃんとした1.25 / 2.5MHzのクロックを作って試してみます。でもまだちゃんと作る自信がないので、「FPGA電子工作スーパーキット」のp112ページからの手順やソースをまず動かして見て、そこにクロック生成を追加します(弱気

なお、同誌附属の基板はまだ組み立てていないので、BeMicro MAX10を使います。
  1. Quartus起動
  2. New Project Wizardでディレクトリ,プロジェクト名ClockGenを入力し、BeMicro搭載デバイスの10M08DAF484C8GESを選び、Finish。
  3. Fileメニュー>New...からVerilog HDL Fileを選びOK
  4. Velilogソースを打ち込む
  5. TasksのAnalysis & Synthesisを右クリックしてStartを選ぶ。エラーが出たら直してもう一度
  6. Assignmentsメニュー>Pin Plannerを選び、ピンを割り当てる(下図1)
  7. TasksのCompile Designを右クリックしてStartを選び、コンパイルし、「…Quartus Prime Full Compilation was successful」が出たらOK
  8. Toolsメニュー>Programmerで、Programmerを起動
  9. USB-Blasterが選択されていることを確認(表示されていなかったらHardware Setup...ボタンから選択ダイアログへ)
  10. Add Fileボタンをクリックし、output_filesの中のClockGen.sofを選ぶ。デバイスと書き込みファイルが表示される(下図2)
  11. Startボタンをクリック、瞬時に書き込みが終わり、LEDがチカチカ。


図1

図2
基本動作が確認できたので、2.5Mhzとその1/2, 1/4, 1/8のクロックをPMOD端子から出力するように書きなおします。
  1. QuartusのEntity欄でClockGenをダブルクリックしてVerilogソースを開きます。
  2. ソースを修正して保存します。
  3. 青の「▶」をクリックすると「変更するか?」と聞いてきますのでYES
  4. Full Compilation was successfulが出たらToolsメニューからProgrammer
  5. Startボタンをクリックしてコンフィグ(書き込み)
と、いうわけで、(少し)きれいな1.25Mhzと2.5Mhzが出ました。で、本題のデジタルマイクですが。同じです。ローパスフィルタを通しても何も出ません。

はい終了。

■FPGAのソース■



■最後に■

デジタルマイクは製品として販売されているからには、動くはず。でも何が悪いのかわかりません。もう涙も枯れ果てました…でもFPGAでクロック出すのはうまく行ったから良しとしよう(問題をすり替えてはいけません)。

続きはこちらをどうぞ。

2016年6月4日土曜日

ESP8266:I2S MP3 webradio streaming example(give up)


ESP-WROOM-02でI2Sを動かせないかと思ってググっていたら、上記記事がヒットしました。
Web StreamingがESP8266で出来る!

そりゃあやるしかありませんよね。残念ながら「現在は16bitのモノラル」だけど「サンプル・レートは96-320KBit MP3でテストしてうまくいってるっぽい」そうです。スゴいのか凄くないのかよくわかりませんw

なお、記事をよくみるとSPI RAMはSD_D0など見慣れないピンにつながっています。これ32pinのESPじゃないとダメですね。幸いなことにDACもSPI RAMもなしで動く、と書いてありますので、SPI RAMなしで行きます。ES9023も微妙に高かったので、同じように動作するはずのPCM5102ってのを買いました。ebayで1000円ぐらいでした。

上記リンクの通り配線しますが、ES9023ボードはライン出力なので別にアンプを用意する必要があります。
  • PCM5102(ES9023)ボード用電源(とりあえずUSBから取ります)
  • ブレッド‐ボードなど配線材料

数日間チャレンジしたのですが、動かすことができませんでした。最終的な原因はシリアルのコンフリクトだと思います。私は一旦ギブアップしますが、引き継いでくださる方のために記録を残しておきます。

■ダウンロード&ビルド■

このサンプルはfree-rtosで書かれています。ので、まだfree-rtosの環境がなければ、こちらをご参考にどぞ。

各種設定は mp3/user/playconfig.h で行うことができます。上から順番に見ていきます。

接続先のWIFI SSIDとパスワードをAP_NAMEとAP_PASSに設定します。

MP3_DECODERをダウンロードしたままの状態だとローカルのサーバからMP3をダウンロードする設定になっていますが、面倒なのでやめます。リストされているうちでは icecast.omroep.nl ってところだといい感じに接続できました。そのすぐ上の #if 0 を #if 1 に書き換えます。そして #if 1になっている 192.168.33.128 のところを #if 0 に書き換えます。ご自宅にラズパイなどでストリーミングサーバを立てている場合には、それを活かしてみましょう(動作を確認した後で)。

I2Sをつないでいるので DELTA_SIGMA_HACK をコメントアウトします。 PWM_HACK はそのままコメントアウトですね。

上記の通りSPI RAMは使わないのでFAKE_SPI_BUFFの行のコメントを外します。

ビルドはgithubに書いてあるとおり、コマンドラインで当該ディレクトリに移動してからmakeです。たぶん問題ないと思います。ツールが見つからない旨のエラーが出る場合にはパスを設定していあるか確認してください。make対象がないというエラーはディレクトリが違います。
 make COMPILE=gcc BOOT=none APP=0 SPI_SPEED=80 SPI_MODE=QIO SPI_SIZE=1024
エラーがでなければ、ESP-WROOM-02にダウンロードします。なお、元記事にも書いてありますが、コンパイル後に出る eagle.irom0text.bin---->0x40000 は間違っています。下記のように0XA0000から書き込みをしてください。USBシリアルとESP-WROOM-02をつないでPROGとRESETを一緒にGNDに落とし、RESETを先に離してからPROGを離し、ダウンロードモードにしておきます。Board1の場合には白ボタンと赤ボタンを一緒に押して先に赤ボタンを離してから白ボタンを離します。コマンドラインで
cd mp3
esptool.py --port /dev/tty.usbserial-AH016T8K --baud 115200 \
write_flash 0x00000 ../bin/eagle.flash.bin 0xA0000 ../bin/eagle.irom0text.bin

これでConnecting...以下の表示が出ればOKです。
Connecting...
Erasing flash...
Writing at 0x00009c00... (100 %)
Erasing flash...
Writing at 0x000df800... (100 %)
Leaving...
動作はあまり安定しておらず、起動してすぐにexception、数秒走ってはexceptionが出る…を繰り返して、Rxのランプが点灯しっぱなしになったらGPIO15とRxをオシロで見てみます。数MHzのパルスが出ていればひとまず動いてます。

…ここまでplayconfig.hを試行錯誤して数時間かかりました。

ただ、LR切り替え信号が出てません。この信号がDATAのスタート信号になっているので、これがでないとDAC動いてくれません。

ソースを見ると、Tx / RxをI2Sの信号に使っているのにSerialにprintfでメッセージを出しているのですが…これ問題ないのでしょうか? UART_SetBaudrateをコメントアウトして動作に影響しないようにprintfをコメントアウトしてみましたが、ダメでした。

うーん、あと一歩だと思うのですが…ここまで動かしてギブアップするのは残念です。ただ、I2Sの使い方についてはいい勉強になりました。Tx/RxはDMAでバッファを使えるんですね。当面使う見込みないけどもw

以上お目汚し、失礼しました。

2016年4月24日日曜日

WiFiワイヤレスオーディオ(失敗)

送信側

受信側。手前の補聴器1個15万円ナリ

■やりたいこと■

赤外線ヘッドフォンアダプタが壊れました。私は耳が悪いので、これがないとテレビが見られません。アニメ見られないのは死活問題ですw ただ、最近市販されているワイヤレスヘッドフォンは音量が低すぎてほぼ聞こえません。特にBluetoothものは出力が小さくて先日ヨドバシで試聴してみたのですが、全滅でした。なんせ私はiPhone+標準添付のイヤホンだと最大音量にしても音楽ほぼ聞こえないんです。やぁねぇ、難聴orz

ということで、ESP-WROOM-02を使ってライン入力した音声信号をWiFiで飛ばし、受信側もESP-WROOM-02を使って受けたデータをDACで出力しそれなりに増幅してヘッドフォンへ…ということを試してみました。ラズパイなら簡単なんですが首からラズパイぶら下げるわけにもいきませんしw

ESP内蔵のADCはあまりにも貧弱なのでMCP3204、DACはMCP4922を使いました。どっちも秋月で入手できます。アンプとしてはポタアン用オペアンプを試してみて、音量が出ないようなら適当なパワーアンプを使ってみようと思ってます。

…とスタートしたのですが。

■先に結論■

今のところ、意図したようには動いていません。ADC/DACからのやり取りとESP-NOWまたはUDPでの通信はそれぞれはちゃんと動いているのですが、一緒にするとデータが欠落してしまいます。

サインカーブを送信して受信側の信号をイヤホンで聞いていると、基本的には連続音がずーっと聞こえていて、数秒ごとにバタバタとノイズが入り、ときたまプチっと100mSecぐらい空白ができる…という感じです。HiFiはまったく期待していなかったのですが、ノイズはいかんです。

ADC/DACを扱うためのインターバルがESP-NOW/UDPの送受信処理によってブロックされているようです。FIFOバッファを持ったADC/DACでないと無理かなぁ。

当初の目標に関しては失敗なのですが、とりあえずADC/DACの接続、ESP-NOW/UDPでの伝送などの参考にしていただければ幸いです。

関係ないですが、インターフェース誌のMATLAB特集を読んでフィルタなどを生成できることを知りまして、「あれ、もしかしてMATLABで補聴器作れるんじゃね?」と思ってググってみたら、すでにやってるヒトが。世界は広い。ただ、帯域ごとのコンプレッションは含まれていないので、そこは遊べる余地があるなぁ。

■高速DA変換テスト■

苦手なSPIなので、メモリ上に作ったサイン波形を連続出力してみました。イヤホンを直結すると「ぷー」という200hzの単音が聞こえます。

■高速AD変換テスト■

標準SPIライブラリで読み込み処理を書きました。

昭和臭ただよう可変抵抗器

その簡易的な動作テストとしてボリューム(可変抵抗)をつないですべてのビットが出てくるかを確認します。



これはそのための文字列表示処理
  int a = readADC(kRightCh);
  char buf[32], buf2[32];
  itoa(a, buf, 2);
  sprintf(buf2, "%16s %5d", buf, a);
  Serial.println(buf2);


読み込み処理はMCPのタイミングチャート(page 21)の通りに書けばこうなります。
  digitalWrite(SS, LOW);
  SPI.transfer(0b00000110);
  uint16_t result = word(0x0f & SPI.transfer(0x00), SPI.transfer(0x00));  
  digitalWrite(SS, HIGH);
でも、これだとch選択が分かれてしまって、今ひとつ面倒くさいです。その前のページを見るとスタートビットさえあれば動くっぽいので
  digitalWrite(SS, LOW);
  SPI.transfer(0b00011000 | ch);
  uint16_t result = word(0x3f & SPI.transfer(0x00), SPI.transfer(0x00)) >> 2;  
  digitalWrite(SS, HIGH);
と書きました。ちなみに連続した24bitのパターンが崩れなければいいので、
  digitalWrite(SS, LOW);
  SPI.transfer(0b01100000 | ch << 2);
  uint16_t result = word(SPI.transfer(0x00), SPI.transfer(0x00)) >> 4;  
  digitalWrite(SS, HIGH);
と書いても動きます。計算量は同じなので、どちらでも。

■ESP-NOWについて■

一度に送れるパケット長は最大200バイトです。また、CRCをつけて調べてみたのですが、パケット単位の誤り検出が行われているようで、化けたデータは届きません。

別のESPから送信しっぱなしにしておいてデータを受信したらLEDが点灯する状態で走らせれば、本来なら常時点灯したままになるはずです。しかし、時々0.5-1Hzぐらいの周期でLEDが消えます。これはたぶん他のWiFiからの干渉なのだと思います。本来、WiFiはチャンネルを自動選択しますが、ESP-NOWは固定したままなので、これはどうしようもないですね。

UDPではその現象は起こりません。が、正弦波を流してイヤホンで聞いていると、前記の通り数秒ごとにバタバタとノイズが入ります。ノイズの入り方はESP-NOWでのLEDの点滅と同じような感じなので、共通した原因なのだろうと思います。

■動作テストと考察■

オーバーランやアンダーランの処理を真面目に書いてないですが、テストとして送信側では計算で作ったサインカーブをバッファにセットし、ADC読み込みをスキップした状態でパケットを送ります。受信側は受信したパケットを順次DACに送出して、オシロで波形を見ます。

きれいな正弦波が見えるのですが、ときどき直流になりますw 受信データが化けていないのはCRCで確認済(このソースには含まれていません)なので、WiFiの受信処理によってDACへ出力するためのインターバルが止まっているのが原因と思われます。ただ、送った波形が少なくとも数パケット分なんの障害もなく受信されていることの方が多いので、定常的な受信処理そのものでインターバルがブロックされるわけではなく、それ以外のオーバーヘッドによって止まっているのではないかと推測しています。

一般的に音声信号は微小時間単位で見ると同じパターンの繰り返しなので、パケットの受信にときどき失敗することがあってもDACへの出力が止まらなければ聴覚上それほど酷い状態にはならないのですが、ときどき止まるってのは冒頭に書いたようにわりと耳障りな状態になります。

■ソース■

githubに置いておきます。


■今後■

ESPでI2Sで動作させた事例を見つけたので、DACチップを入手できたら試してみます。

■メモ■

  • ADC/DACともに、CSはずっとLOWにしててもダメです。特にDACはラッチがついているから問題ないんじゃないかと思ったんですが、1データごとにCSを上げ下げしないと動いてくれません。
  • 前にも書いたかもしれませんが、Serialは結構CPUパワーを食いますしTimerの動きも邪魔します。動作の様子を見るためのSerialですが、高速処理にハサむとシュレディンガーの猫的な状態になるので気をつけましょう(経験者・談

2016年4月7日木曜日

回路は仕様通りに動く

AdafruitとSparkfunとSwitchScienceへの報恩

夜中に目が覚めて眠れなくなってしまったので、ESP-WROOM-02で昨日届いた部品のテストをしました。

が、どうもうまく動いてくれません。現象切り分けのために、基本のLチカを走らせてみると…走りません。使ったのは私のESPボードの動作確認用につかっているやつで、IO12 - IO16を同時にLOW/HIGH切り替えるだけのもの。間違えようがありません。

さらに切り分けのために
  • 手持ちの複数のESPボード
  • ブレッドボード
  • ジャンパワイヤ
  • USBシリアル
  • ESP SDK

を取り替えて試しましたがダメです。しかし、Lチカ以外のプログラムは動きます。

…気付きました。手元にあるボードは、先日の「道路工事的点滅デモプログラム」のためにRESET-IO16を接続してあることに。

Lチカプログラムでは起動直後にIO16をLOWにしてます。つまり、起動直後に強制的にリセットかけていたわけです。

…そりゃー動かないよorz

ちなみにテストしたのは、1v -> 3.3vへの昇圧DC/DCコンバータです。200mAの出力容量とのことですが、1000μFの電解コンデンサを付けてもESPは起動できませんでした。1Fのスーパーキャパシタにチャージしてから試してみても一瞬IO13のLEDが光っておしまいでした。手元には5Fのキャパシタもありますが、やめておきます。DC/DCは他のマイコンに使いますわ。

窓の外がそろそろ白んできました。

今日はオフィスで眠いだろなー。サラリーマンは辛いw

2016年3月30日水曜日

ESP-NOW 1:N通信




■ESP-NOWの実験■

手前左がスレーブ(受信)、奥の4つがサーバ(送信)です。スレーブには4台分のMACアドレスを登録し、サーバには受信側のMACアドレスを登録してあります。

送信側:
起動してからsetup()でdigitalWrite(13,LOW)が実行されるまでの間は左側LEDがぼんやり点灯しています(deep sleep中はoff)。右側のシリアルTx LEDの2回目の点灯が送信です(deep sleepからの解除時のシステムメッセージで1回光り、送信時にもう一回光ります)。

受信側:
受信時に光ります。ご覧のとおり、送信側の2回目の点灯と受信側のシリアルの点灯が同期しています。よかったよかった。と思ったら1回明らかに抜けているところがあるなぁ。

フレームのレイヤで誤り検出をしているので、よその電波とぶつかって信号が乱れたらいさぎよく破棄されるのが電波通信の習わしです。きっと他のWiFiなどとの輻輳でデータが壊れたのでパケットが破棄されたのでしょう。

以下ソースは受信側(スレーブ)です。複数のサーバを相手にするために「氾濫原」さんのものに少し変更しました。ありがとうございます。


■怪現象■

なお、最初は4枚をミニブレッドボードに乗せたのですが、その時に奇妙な現象が起こりました。ごく接近した2枚が勝手に同期してしまうのです。最初電源の問題かと思ったのですが、ミニブレッドボードの端と端において離せば再現しません。別電源でも1cm程度に近づけると同期します。何が原因でしょうね。

2016年3月28日月曜日

ESP-WROOM-02の直接通信モードESPNOWを試す


ESP NOWは生パケットをやりとりするモード。DHCPどころかチャンネル自動選択もないので基本的にはチャンネル指定して送りっぱなし。つまり、余計な処理がない分オーバーヘッドも消費電力が少ないということです。

いやー、知りませんでした。何か別のことを調べていたらこの記事がヒットして、そんなことがあったのかー、となった次第。ちゃんとリリースノートを読まないといかんですね。


■ビルドする■

ただし、esp-nowは普通のarduino sdkには含まれていないので、ビルド通りません。設定を変える必要があります。

Arduino IDE : 1.6.5
Board Manager : esp8266 2.1.0

一度Arduino IDEを終了し、
~/Library/Arduino15/packages/esp8266/hardware/esp8266/2.1.0/platform.txt
のcompiler.c.elf.libs=-lm -lgcc -lhal -lphy -lpp -lnet80211 -llwip -lwpa -lcrypto -lmain -lwps -laxtls -lsmartconfig -lmesh -lwpa2という行に -lespnowを追加します。

…って書くと一瞬なんですけどね、ここまでたどり着くのに2日かかりました。makeEspArduinoを試したり、PlatformIOをインストールしたり。まぁその過程でSublime TextからESPをビルドする方法が見つかったりしたので、まったくムダになったというわけではありませんが(空元気

■試す■

まず上記ページに掲載されているソースを試してみます。いやー、シンプルで美しい。なお蛇足ですがESP-WROOM-02が2枚必要です。

スレーブは受信側、常時電源入れっぱなしにしておいてデータが届くのを待つイメージ。コントローラは送信側です。このサンプルでは2.5秒ごとにdeep sleepから復帰して適当な文字データを送っています。Deep Sleepを使うので、RESETとIO16を接続する必要があります

なお、実際に送受信する前に、2枚のESPそれぞれのMACアドレスが必要です。今回のアプリを起動すると自分のStation interfaceとSoft AP interfaceのMACアドレスがシリアルに出力されますので、

Slave : 相手側(Controller)STATION_IFのMACアドレス
Controller:相手側(Slave)SOFTAP_IFのMACアドレス

これをそれぞれのソースの最初の方にあるuint8_t macにセットします。相手側のアドレスを設定して登録するというのがミソ、まぁMACアドレスなんて変更できちゃうんですが、一応世界の一つだけのアドレスということになっているので、これで相手をフィルタリングするわけです。そうでないとご近所のWiFiがたまたま同じチャンネルに送信している時のデータをすべて受けてしまうので使いにくくて死にます。

実行結果はこんな感じ。画面下がController、2.5秒ごとにdeep sleepから復帰してデータを送信してます。画面上はSlaveでIO13のLEDは1秒ごとにLチカ、Controllerからデータが送られるたびにシリアルのLEDが点滅しているのがご覧いただけるかと思います。

データを送信する側は起きてすぐ寝るという感じで、通常TCP/IPなどで送信する場合に接続するだけで2-5秒かかってしまうのと比べるとかなりの消費電力削減が期待できます。




今回はこれで力尽きました(結果としてはよそのWebに紹介されてたプログラムを走らせて終わりなんだけどさ、ビルド通すまでが大変でした)。次回はこれでちゃんとセンサーのデータを送ってみます。

■追記■

1度に送れるデータは200バイトまでです。

…センサーからのデータをまとめて送ろうとしてハマりました。送っても送っても届かなくて、散々調べたらこれが原因でした。ちゃんとエラーステータスを見ましょうね、というお話ですね。とほほ。

2016年3月23日水曜日

ESP-WROOM-02 + BME280、省エネ編

ベランダに置いてたけど、結構汚れるもんだ。

■Deep Sleep■

以前作ったESP-WROOM-02 + BME280の瓶入り気象?センサーを少し改良して、省エネルギー仕様にし、エネループ単3黒3本で駆動してみたところ、17日間動作しました。

ESP-WROOM-02はいつものTareObjects製Board1のプロトタイプ、deep sleepが働くようにIO16とRESETをつないであります。

プログラムは以下の通りです。



約1分ごとのデータ収集ですが、気象データならもっと低頻度で十分かもしれないですね。外に置きっぱなしなので、電池交換頻度は1ヶ月に一度として40日ぐらいは動いて欲しいです。となると3分に1回か…。

■追記6/11日

間隔を5分にしました。104行目を60から300に変えるだけです。あ、黒エネループで17日だったのか…白エネループ入れたので約2ヶ月ってところかしら。

2016年3月16日水曜日

ミニブレッドボード満載

今気付いたけど温度と湿度が逆だな。直しました。

ミニブレッドボードはかわいい。場所を取らないし安い。出来る子なんです。というわけで、てんこ盛りにしてみました。

BME280、秋月さんがずっと品切れ状態なので、部品沼に沈んでいたものを使います。同ブレイクアウト基板はBME280の機能すべてを使える形のものが秋月さん、Sparkfun、スイッチサイエンスさんから出てますが、このメーカー不詳の基板はI2Cでの利用だけに特化しているので、場所を取らず配線がラクです。

空気質センサーは電源にUSBシリアルからの電源を直接つなぎ、センサーからのアナログ出力を半固定抵抗で分圧してTOUTに入力しています。

OLEDは例によって0.96インチSSD3306搭載のアレですが、今回は白を使ってみました。なお、ロットによってGNDとVCCの位置が逆だったりしますので、くれぐれもご注意ください。

肝心のESP-WROOM-02は自前のボードです。近日発売なので、その節はよろしくお願いします。 本日発売されました(2016年4月11日、追記)。

<追記 2016-03-18> 空気質センサーは90mAも消費するだけあって、動作させたままだと結構暖かくなります。放射温度計で測ったところ、一番暖かい場所で51度でした(室温24度)。使用する時にはこのことをお忘れなく。

■設計■

123Dとか使えば良いんですが、必要なモジュールがないと面倒だし、今回は回路ってほどのものではないので表計算を使いました(笑)。

あ、背景塗り忘れがある。けど面倒なので直さない

雑ですが、色は「硬いジャンパーワイヤ」の色です。」と「は曲がり角。まず最初に部品同士がぶつからないか実際に挿してみてレイアウトを決めます。それから、最初にGND、次に電源、それから信号線を置いていきます。置いたら長さを数えて、それに合った色を塗っておきます。

なお、配線図でBME280のVccとGndをESP-WROOM-02のIO13, IO12につないでいます。BME280はごくわずかな電流しか消費しないので、ESP-WROOM-02のGPIO出力から電源を取ってしまおうという寸法です。ピンによってはプルアップ済だったりリセット時に異常な電圧が出てくるのですが、IO4/IO5/IO12/IO13であれば問題ありません。ただ、ESPにかぎらずマイコンのGPIOはリセット時にハイインピーダンス状態になるので、起動したらなるべく早くHIGHとLOWを出力するようにします。間違ってもHIGHとLOWを間違えないようにしてください。

ちなみに私のジャンパーワイヤー入れはこんなぐあいに長さと色を表?にして張ってあります。長さより穴数の方が良かったなーと毎回思うので次のバージョンでは併記したいと思います。まぁたまにオレンジ色みたいな赤とか、青か緑か区別できない色のワイヤが混ざってたりして悩むのは改善されませんが。


なお、このパッケージに入って売っているジャンパーワイヤーは短いのがすぐになくなって、長いのだけが残ることで有名ですが、サンハヤトで短いやつだけ売ってます。直角になってなかったり平行でなかったりして閉口しますが、私はたくさん買ってストックしてあります。


■ソフトウェア■

今回先に貼っておきます。今まで使っていたBME280用ライブラリがこのモジュールでは動作しなかったので、例によって彷徨った結果、Sparkfunさんのライブラリが動作しました。I2cモードを選択し、I2Cアドレスは0x76ですのでご注意を。

余談ですが、以前から使っていたライブラリが動かなかった時には「あ、またebay.comにやられたか?」と思いました。Ebayはたまに部品番号はあっていてもタイトルが間違っていることがあります。以前9960を探している時に「RGB Gesture Sensor」って書いていてある9930というチップがヒットしました。やけに安かったのでたくさん買ってみたら単に明るさと近接センサーだけで安物買いのなんとやら。なので今回、もしや高価なBME280(温度湿度気圧)ではなくBME180(温度湿度)なのか?と思ったりしましたが、無事でした。

なお、9930はお風呂時計用デジタル時計で「部屋が明るくなったらLEDの表示をonにするための機能」として健気に働いております。

ebayのご利用は慎重に、くれぐれもat your own riskとpaypalで。

まぁ今回は、ライブラリ変えたら動きました。空気質センサーは半固定抵抗で分圧した値をTOUTに入力したので、アナログ値を読み取ってそのまま表示しています。

表示はOLED、以前と同じくこのライブラリを使っています。

各ライブラリの作者のみなさんに感謝致します。



■配線と動作確認■

設計通りにすべてのジャンパーワイヤーを刺していきます。直角に曲げるときにはラジオペンチやピンセットを使います。

刺し終わったものがこちら。


この状態でもう一度実物とあわせながら配線が間違っていないか確認します。


テスターがあれば、最低限GND-Vcc、Vcc-Vin、Vin-GNDがショートしていないかを確認しておきます。次に、ESP-WROOM-02だけを挿して、USBシリアルとの間の5vとGndだけを接続してみます。この状態で、もう一度テスターでGnd-Vin(5v)、Gnd-3v3の電圧を確認します。USBシリアルからの出力電圧やUSBからの電源電圧はわりといい加減ですが、どちらも誤差5%以内なら問題ないです。


さて、電源に問題がなければ、一度USBシリアルからUSBを抜いて、5v-Vin間の配線を外します。この状態で残りの部品を挿して行きます。

今までもわりと慎重に進めてきましたが、ここで間違うと元も子もないので、配線表と確認しながら実施します。なお、私は過去、そもそもの配線表が間違っていた、という過ちにより何度かチップを殺してしまったことがあります。くれぐれも各段階での確認は怠りなく。


そして、最後に電源を接続してUSBシリアルをUSBと接続、今回上記BME280ライブラリが動かなかった件を除けば、一発で動作しました。まぁ、今まで使ったものを組み合わせただけですからねぇ。

なお、まだGPIOピンが3本(電源に流用したものを含めれば5本)余ってますから、ダストカウンターを接続することもできますし、I2Cにはアドレスがぶつからなければ、まだ5-6個は搭載できます。TxとRxも空いているのでGPSも使えます。

…そんなのを何に使うんだ?という疑問をもってはいけません。

以上、ミニブレッドボードてんこ盛りでした。

■追記■

ダストセンサーPPD42も追加してみました。

…いかん、ミニブレッドボードからはみ出してしまった。



2016年2月29日月曜日

ESP8266のオートプログラム仕様

最近発売されるESPブレイクアウトボードには、「GPIO0をGNDに落とした状態でRESETを押す」なんて面倒なことをしなくても、Arduino IDEでcmd+Uを押すだけで勝手にコンパイル→アップロードが済むようになってます。Auto Program機能ってやつですね。フリップ&フロップやダイオードを使ったものなど何種類かあるようです。

DTRからの出力を時間差を作ってRESETとGPIO_0につなぐだけなので、組み込むのは造作もないことなのですが、私の設計している基板には搭載していません。

それは、ESP8266/ESP-WROOM-02にはリセット時に内部クロックがGPIO_0(ゼロ)から漏れてくる、というバグがあるからです。ただ漏れるだけなら大したことはないのですが、個体によっては -1 〜 5v まで変動するという計測結果もあり、これは回路によってはFTDIやUSB端子までも壊しかねない電圧です。

私の基板は、開発用ではなく「使い倒す基板」がコンセプトです。そのためにオーバークォリティ気味のレギュレータとOS-CONを搭載し、大きな面積を食うネジ穴を3つも開け、何より開発の時にしか使わないものに電流を食われることを排除しています。

ArduinoみたいにIDEでcmd+Uをタイプするだけでアップロードできるのは確かに便利ですが、ESP以外の基板を破損するようなリスクは極力小さくしたい、と思ってます。なので、GPIO_0にはスイッチとプルアップ抵抗しかつないでいません。

なお、あんまり作例ではみかけないのですが…GPIO_0に取り付けたスイッチは、プログラムをアップロードするときだけでなく普通にスイッチ入力として使えます。スイッチが1つ付いているだけですごく便利なんですよね。ただ、チャタリングを避けつつ長押しとちょい押しを判断するプログラムって以外と面倒くさいので、今度、作ります。

閑話。



写真がないと寂しいので、今日の昼飯(仕出し弁当430円)の写真を貼っておきますw 430円の割には野菜分が多いので愛してます。

なお、今日から「特茶」飲み始めました。

知人がこれで数キロ落とすことに成功したというので、箱買しました。その安易な姿勢が(ry

2016年2月24日水曜日

ESP-WROOM-02 + 空気質センサー


空気室なら知ってるけど、空気質ってあんまり聞かない / 使わない言葉ですね。意味わかるけど。


ずっと前にaitendoで衝動買いしてそのまま忘れていました(空気質センサモジュール [MQ135-4P])。それにしても空気質。指標はいろいろありますが、いったい何を測定してくれるのでしょうか。とりあえず、この手のものとしては秋月で売っているTGS2450が電子工作界ではおなじみだと思います。

秋月のサイトから

ただしTGS2450は結構気難しいというかヒーターの電圧や加圧時間を間違えるとすぐに焼損することで有名です。私も使ったことがあります(懐かしい記事はこちら)。

でも、こっちの空気質センサーは、モジュールになっていて電源5vをかければ0-4vで空気の質がわかる、というシロモノです。

ということで、使ってみました。

<追記 2016-03-18> 90mAも消費するだけあって、動作させたままだと結構暖かくなります。放射温度計で測ったところ、一番暖かい場所で51度でした(室温24度)。お使いになる時はこのことを覚えておいてください。

■構成■

毎度おなじみESP-WROOM-02のTOUTをアナログ入力として使います。TOUTは1v入力なので、空気質センサーの出力は分圧してから使います。

接続はこれだけです。空気質センサのDoutは使いません。なお、空気質センサーは100mA近い電流を消費するので、小さなUSBシリアルだと電流容量不足になります。

ESP-WROOM-02USBシリアル半固定抵抗空気質センサ
5vVcc
Vcc3.3v
GndGnd1Gnd
TxRx
RxTx
Tout2
3Aout

■調整方法など■

分圧には10kΩの半固定抵抗を使いました。

ぶっつけ本番でいきなりToutにつなぐとESP-WROOM-02をぶち壊す可能性が高いので、最初はブレッドボードの上で半固定抵抗の1を5v、3をGndに接続し、2とGndの間の電圧をテスターなどで測定しながら抵抗のツマミをまわし、約1.2vになるように調整します。

空気質センサーの出力が4vなのだから5vで調整するとしたらフルスケール1.25vなのですが、少し余裕を見ます。なお、半固定抵抗の1と3は対称なので、調整後に組み込む際に間違えないようにします。私の場合はツマミのついている側を1に決めています。

先日のSCL/SDA同様、こういう決め事を作っておくと事故を防ぐことができます。

…と、数多くの事故にまみれてきた私が言うのだから説得力があります。

…いや、無いのか。

■ソフトウェア■

毎度おなじみの秒単位簡易リングバッファで1分間の平均値を取ってThingSpeak.comへ送っています。


■計測結果■

計測結果ですが、ほぼ無臭のフロンガスのエアダスターに対しては1mぐらい離れたところで使っても反応があります。無水アルコールにもわりと敏感ですね。私が「ハーッ」て息を吐きかけると、てきめん、数字が上がるので心が傷つきます。

[19]で息を吹きかけました。

ThingSpeak.comでの計測値はこんな感じ。


さて。加齢臭にはどうなのか。知りたいような知りたくないような。明日、換気状態で出勤して値はどう変わるのか。追ってご報告申し上げたいと思います。

…私が寝ている間に62まで下がりました。04:15ごろ起床。