ESP8266 で 1MHz 50%duty を出力する
ESP8266 で 1MHz 50%duty を出力する 命題を聞いて試してみました。 2016.02.19
ESP8266 から 1MHzを出力するには 速度的に Direct Access Port 方式が必要です。
波形の確認は、Analog Discovery で測定しました。
結論:1MHz の目標に対し 1.000MHz を達成。
_ スペクトラムによるセンター周波数は 1.000MHz。
_ 精度は 25KHz。
_ Duty比は 50.0%。(小数点2桁目はジッターの為 省略)
スケッチ:
_ PIN_13(GPIO13)の出力の後に PIN_13 と NOP の遅延を入れ時間を調整しました。
_ 最小単位の命令は、 nop命令で「 __asm__ __volatile__ (“nop”); 」を使用。
_ 「 __asm__(“nop\n\t”); 」でも使用可能でした。:7of9 さんのアドバイスに感謝。
_ この NOP命令は、1マシンサイクルで 1/80000000 second = 12.5 nsec です。
_ 12.5nsec は 50% duty で 25KHz。25KHz単位で変化させる事ができる訳です。
_ つまり 最小時間の NOP 命令で精度が 25KHz と言うことですね。
_ スケッチの for文は ちょっとダサイ感じがしますがお許しください。
_ 課題:for(;;){}、while(1);{} の無限ループは 一瞬途絶えます。
_ この時 GPIO0とGPIO2が一瞬 “0” になり同時にGPIO13の信号が途絶えます。
_ 修正:2016.02.20 :void setup に noInterrups(); を追加:
_ これにより for( int ,,, による、信号が一瞬途絶える不具合はなくなりました。
_ この件は 再び 7of9 さんのアドバイスによるもので 大変感謝致します。
#define PIN_OUT *(volatile uint32_t *)0x60000300 #define PIN_DIR *(volatile uint32_t *)0x6000030C #define PIN_13 *(volatile uint32_t *)0x6000035C void setup() { noInterrupts(); PIN_OUT = (1<<13); PIN_DIR = (1<<13); } void loop() { for( int i=0; i<100000; i++){ PIN_13 = 0;PIN_13 = 0;PIN_13 = 0;PIN_13 = 0;PIN_13 = 0; __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); PIN_13 = 1;PIN_13 = 1;PIN_13 = 1;PIN_13 = 1;PIN_13 = 1; __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); __asm__ __volatile__ ("nop"); } }
参考:
ESP8266 Community Forum:DURATION NOP INSTRUCTION:NOPの記述方法。
collector {dt.:Sammler}:ESP8266 GPIO output performance:波形付きの詳細な内容
Arduino.CC:AVR Code:NOPの記述方法。__asm__(“nop\n\t”);
Let’s Make Robots:Arduino 101: Timers and Interrupts:noInterrupts();
sandeepmistry:esp8266_peri.h:Arduino環境の為のESP8266の中心部。Regの定義。
ESP8266 Community Forum:esp8266_peri.h:Registorの定義。追記:2016.07.11
alfredo / AgroSis:esp8266_peri.h:Registorの定義。追記:2016.07.11
感想:
_ アセンブラー:「__asm__ __volatile__ (“nop”); 」というアセンブラーがスケッチで
_ 使えるとは勉強になりました。
_ 課題:信号が途絶える問題:for(;;){処理}、while(1);{処理} で起きる。
_ この件は、奥が深そうなので宿題として残しておきましょう。
_ 他の信号:この時、何かの原因で GPIO0 と GPIO2 が一瞬 “0” になります。
_ これにより違うモードになり再度 スケッチが動作するように見受けられます。
_ 青はGPIO0。GPIO2は表示していませんが同じ波形がでます。
追記及び修正:7of9 さんから 素晴らしいアドバイスを頂きました。
_ noInterrupts(); の件は 驚きましたね。ありがとうございました。
信号発生器:今回は 1MHz の方形波を出力するものですが、超低周波から 3.3MHz
_ 位までの信号をスケッチだけで出来る事が解りました。
_ そうなると、凄い物が作れる可能性を秘めていますね。
Analog Discovery :本題ではありませんが、Analog Discoveryのお話。、、本題より長い
電子工作では オシロスコープがあると回路動作を詳細に確認する事が出来ます。
信号を見る事は ありがちな「動作しない」「不安定」「ハマる」が少なくなり
確実に早く作る道具になります。理論と現実が一致すると楽しくなりますね。
:
性能は100MHz位が理想ですが価格が高いですから早々には買えないのが実状。
希望の性能と価格からいくとRIGOLに落ち着いて行きます。
以下の記事は納得できる判断になる訳です。
Rabibit Note:コスパ抜群のオシロスコープ Rigol DS1054Z の薦め:5万円。
使用した事のある、200MHzのオシロよりは劣りますがね。
:
一方、Analog Discovery というマック(ウィンも)にUSB接続して画面で観測できる
アナログ回路万能測定ツールがあります。デジタルも可能です。
帯域は5MHz。これは希望の100MHzとかけ離れる数値でかなり躊躇します。そう、かなりです。
「現実は見るに限る」で、使用している友人のものを見せていただきました。
それも何回かです。結果、Analog Discovery にしました。価格は3万6千円です。
ここ価格帯でのオシロは性能的に買わない範疇になります。
:
購入した結果、Analog Discovery が良かったです。ネットの記事も参考にしてください。
:
使用感:
コンピュター上で使えるので場所を取らない。オシロだと置き場所が必要です。
波形等の記録が直ぐ取れ、画面の大きさはデイスプレーのサイズまで大きく出来る。
27インチを使用していますが横いっぱいにするとデーターロガーみたいになります。凄い!
この点はオシロではできない機能。オシロは寂しい画面になると思います。
マウスでいろいろな設定ができる。オシロは操作したりコンピュターを見たり煩雑です。
DigilentのWaveformというソフトを使用し、この機能が凄いです。
Scope,Waveform,Supplies,Meter,Logic,patterns,StaticsIO,NetWork,Spectrum,Scriptが出来るのです。
Spectrumができる。今回の記事でSpectrumを使用し周波数の安定度が把握できました。
重要な機能に信号発生器があります。これは何か信号を必要とする場面でとても役に立ちます。
今回の記事で信号を発生させプローブできちんと受かるかの準備をしてから始めました。
仮想の装置を作れる訳で、いろいろなSGとか買う必要がなくなります。デジタルもできます。
結果、RIGOL等のオシロより凄い事が解り便利にしています。
使いこなせば使いこなすほど高性能の機能が出てきますね。
:
購入のきっかけになった秋葉原にいる友人のブログが参考になればよいかと思います。
この方は、アプリを良く使いこなしている事と、この装置を作った DIGILENT より
凄い周辺装置を作られています。最近 接続に重要なUSB ISOLATOR を製作,販売をしています。
アナログ回路のおもちゃ箱
http://designideas.cocolog-nifty.com
秋月電子通商:ANALOG DISCOVERY:36000円。ANALOG DISCOVERY 2:36800円
ストロベリー・リナックス:ANALOG DISCOVERY:36000円
:
Analog Discovery は iMac 27 inch Mountain Lion+VMWare+Windows で使用。
Analog Discovery 2 :新しく購入する場合はこれですね。、、、欲しい。
WaveForms2015(digilent.waveforms_v3.1.5) のアプリの機能が向上しました。
このアプリで初期のAnalog Discoveryも動きます。条件としてマックの場合
Marverics,Yosemite,EI Captain 英語版OSでのみ動作します。
ウインの場合は以前と同じ環境で動くとネットでは報告があります。
:
アカデミー版だと安く買える、、米国に友人とか、、どなたかかいないでしょうか?
値段を聞いて秋月で買うのを躊躇しました。
お疲れ様です。やはり参考になります。
> 結論:1MHz の目標に対し 1.000MHz を達成。
さらっと書かれたこの1行がすごいです。
>_ 課題:for(;;){}、while(1);{} の無限ループは 一瞬途絶えます。forも同様です。
>_ この時 GPIO0とGPIO2が一瞬 “0” になり同時にGPIO13の信号が途絶えます。
このあたりGPIOの値が変わるというのが確かに注意点ですね。
ただ、この非常に短時間のGPIO値の変化が生じる具体的な不具合については自分は未経験で今のところ分かっていません。
とりあえず現在準備中のPiZero contest (2/25締め切り)が落ち着いてから、またAnalog Discovery 2が到着してからこの記事の通りに実施してみようと思っています。
7of9
2月 20, 2016 at 2:58 am
ESP8266に興味がある人が多いQiitaでリンクなどもまとめています。
以下のようにリンクを張りました。
http://qiita.com/7of9/items/da32e946ff8a6bee8a5c
不都合があれば記事を消しますのでご連絡ください。
7of9
2月 20, 2016 at 3:00 am
間違いがあるかもしれませんが、ご自由にのせてください。
私は Qiita での皆さんの記事を大変参考にさせていただいて助かっています。
皆さん素晴らしいですよね。感謝しています。
macsbug
2月 20, 2016 at 6:55 am
あら! 凄い。高いですが注文されたのですね。祝!
いいですね〜、今日、秋月に部品を買いに行きましたが、Analog Discovery 2 を横目で見ました。
到着しましたら、是非、使用感をお聞きしたいです。
GPIO0とGPIO2も変化していましたので波形を乗せておきました。
このGPIO0,2って動作モードに関係する端子ですね。後は難しいのでパスしようと思います。
macsbug
2月 20, 2016 at 6:51 am
> 課題:for(;;){}、while(1);{} の無限ループは 一瞬途絶えます。forも同様です。
Interrupt handlerが動いているのでしょうか。
http://letsmakerobots.com/node/28278
にある
noInterrupts();
で全ての割り込みを無効にしてどうなるかですね。
今度試してみます。
7of9
2月 20, 2016 at 3:14 am
7of9さん、驚きました。
なんと、noInterrupts(); で、for(int ,, 方式の物は、瞬間的に途絶える不具合が消えました。
同時に、GPIO0 と GPIO2 に発生していた妙なパルスも(その後波形を投稿しました)解消。
いや〜、唖然と驚いて嬉しい状態。
>nterrupt handlerが動いているのでしょうか。
私にはかなり難しくなってきましたが凄いヒントです。
Arduinoには貴重なノウハウがあるので助かります。
ただし、while(1),for(;;) は依然として不具合は消えません。
while には他の課題があって、スケッチの最後に delay(1)を入れないと動かないという
事もある報告が Qiita にあって私の方でも実際にそうでした。それでdelay(1)で解決。
ただし、この件の原因は不明なので職人芸のように使用している訳です。
ですのでこの件は宿題にしておこうかと思っています。
凄いアドバイスをありがとうございました。
macsbug
2月 20, 2016 at 7:12 am
Qiitaへのリンクの掲載許可についてありがとうございます。
Analog Discovery 2 ですが、確かに高いですが、たくさん使えば高いものという認識はなくなりそうです。
10年前に購入したmp3プレーヤー iriver T10は概算で1500時間累積駆動しており、時給15円程度の働きものです。
Analog Discovery 2 も今後どんどん使います。
—–
while(1), for(;;)についてdelay(1)の話ですが、以下のリンクですね。
http://qiita.com/azusa9/items/fe20794aa858a73fd97b
MCUが正常に起動しているかの確認をするウォッチドッグ(wdt)により、while(1), for(;;)でwdtへの連絡がなくなりセットがかけられるということなのでしょうね。
対応としては以下のいずれかなのでしょう。 (1) ウォッチドッグをOFF, (2)ウォッチドッグに逐次連絡 (ESP.wdtFeed()かdelay(1))
関連1 https://github.com/esp8266/Arduino/issues/34
– setup()処理で1秒超えたら wdtがリセットをかける
– ESP.wdtEnable(), ESP.wdtDisable(), ESP.wdtFeed()
関連2 http://www.fadvisor.net/blog/2015/08/arduino-resets-when-disabling-watchdog-timer/
– 8秒という記載あり
wdtを切った場合は別の問題があるかもしれません。その点は今後調べようと思います。
7of9
2月 21, 2016 at 2:55 am
記事中にAnalog Discoveryのことも追記されていたのですね。
さらに参考になります。
RIGOLのリンクですが、リンク切れのようでした。こちらのリンクが近いかもしれません。
http://rabbit-note.com/2015/06/27/rigol-ds1054z/
USB絶縁は興味がありますが、個人で買うのはまだまだ先のことになりそうです。
7of9
2月 21, 2016 at 3:40 am
macsbugさん
こんばんわ
コードを拝借して1MHz出力できました。感謝。
http://qiita.com/7of9/items/aaa5dcdf471f748f1206
リンギング対策はもう少し考えてみます。
7of9
3月 3, 2016 at 1:12 pm
超初心者で申し訳なく恐縮ですが、digitalwriteを高速化する方法は、理解したのですが、
digitalreadを早くする方法を教えて頂けないでしょうか?
又、割り込みを使いたいので、noInterrupts();は入れたくないのですが、
GPIO0,2,13以外のピン(例えば、13/15/16)などをプルアップしてdigitalreadしても大丈夫でしょうか?
shitouto_naka
7月 9, 2016 at 3:02 am
shitouto_nakaさん、サイトへの訪問をありがとうございます。
お返事が大変遅れ申し訳ありません。
本来はdigitalreadも行いたかったのですが、トライしましたが完成しませんでした。
それで、記事はdigitalwriteを高速化だけしか記載できませんでした。
digitalreadの高速化が手軽にできれば、オシロスコープや信号解析ができる事になります。
質問され再度数日試したのですが動くまでに至りませんでした。
同じ様にレジスターを設定してみましたが、どうやっても動作せず。
恐らく何か理解が出来ていないからだと思っています。
さらに事例を検索したのですが事例はありませんでした。
とても残念なのですが、課題として残しておきます。
>GPIO0,2,13以外のピン(例えば、13/15/16)などをプルアップしてdigitalreadしても大丈夫でしょうか?
はい、ピンはプルアップして大丈夫です。
プルアップした方が正しい使用方法です。
macsbug
7月 26, 2016 at 3:48 am