obnizのフォーラムは新しいシステムに移行しております。
新しいフォーラムはこちらになりますPeripherals SPIについて
-
こちらの LCDモジュール をobnizで制御するパーツライブラリを開発しています。そこで、obniz.js及びobniz内の動作を確認させてください。
-
spi.write()
は一度で最大1024Bとなっているため、例えば、40KBのデータを送信する場合は、1KBづつ40回繰り返して呼ぶことになりますが、個々のspi.write()
は同期ではなく、obniz.js内でバッファリングしているように見えます。そしてこのバッファがオーバーフローする場合があるため、1回づづ同期で呼び出すことはできないでしょうか?await
を付けてもダメでした。 -
spi.writeWait()
は送信したバイト数と同じだけ受信する仕様となっていますが、例えば、1バイトのコマンドを送信して、3バイトの結果を受信するような場合はどのようにすれば良いのでしょうか?
注) 上記のオーバーフローを起こす条件が定まりません。週末にいくつか実験して結果をアップデートするつもりです。
よろしくお願いします。
-
-
ご連絡ありがとうございます。面白そうなLCDモジュールですね。初めて知りました。
まず、spi.writeですがおっしゃる通り繰り返し送る必要があります。
その際にバッファオーバーフローが出るとのことですが、分割していることが原因というよりも送ろうとされているデータ量が実際にspiやwifiで送れる量よりも多い可能性があります。
次フレームの送信タイミングを前フレームの送信が完了したところで送ってみて頂けますでしょうか。
方法としては最後のspi.writeのみawaitをつける方法もありますが、await obniz.pingWait()
としていただくと、obnizからpong応答が帰ってくるまで待つことができます。
返ってくるということはやるべき処理がない状態なので、
その次から新しいフレームを送っていただければ詰まることはないかと思います。
こちらはまだ内部関数で、これからドキュメントに掲載する予定のものです。また、同期的な呼び方ですが、
await spi.writeWait()
で1回ずつ同期的に呼べるかと思います。ただ、そういった一連の処理をする関数をsetInterval()などで呼び出している場合は、同時に走ることになってしまいます。ちなみにobniz.js内のバッファリングですが、内部関数の
obniz._drainQueued()
を呼ぶことでその時に送ることも可能です。
spi.write([,,,,,]) obniz._drainQueued() spi.write([,,,,,]) obniz._drainQueued()
のような形です。
ただ、TCPが分割されますのでこれを呼ぶことで遅くなる場合が多いです。1バイト送って3バイト受信について
1バイトを送って3バイトを受信する方法ですが、SPIでは必ず送信と受信のバイト数が一致します。送受信が同時に行われるのでそうなります。
https://obniz.io/doc/lessons_obnizjs_spi_shiftout
送りたいデータのあとに不要なデータを入れるなどでできるかと思います。
result = await spi.writeWait([0xAA, 0, 0 ])
または、モジュールの仕様によりますが、送ったあとに別の通信として3バイト受信する事ができるものも多いと思います。
その場合はspi.write([0xAA]) result = await spi.writeWait([0, 0, 0 ])
のように、送りたい1バイトだけ送り、受信は無視して、
次に意味のないデータを3バイト送り、3バイト受信するというので必要なデータがとれることがあると思います。これはモジュールそれぞれの仕様によりますので一度ご確認ください。
以上よろしくお願い致します。
また、非常に面白そうなモジュールですので、無事写りましたらぜひこのフォーラムに作り方など載せていただければと思います。
-
@Yuki-Sato さん
ご教授ありがとうございます。
いくつか試していますが、なかなか納得できる動きをしていません。obniz._drainQueued()
を使ってもバッファオーバーフローする場合があります。Uncaught (in promise) Error: Warning: over 116078 bytes queued at Obniz.error (obniz.js:8598) at Obniz._sendRouted (obniz.js:8002) at Obniz._drainQueued (obniz.js:8032) at HTMLButtonElement.<anonymous> (private_128x160pixel.html:203) at HTMLButtonElement.dispatch (jquery-3.2.1.min.js:10) at HTMLButtonElement.g.handle (jquery-3.2.1.min.js:10)
await obniz.pingWait()
をspi.write()
と対で呼び出せば、何もエラーは出ずLCDに描画できますが、さすがに速度が遅すぎて・・・。どのくらいのタイミングで同期をとれば良いかチューニングというか試行錯誤していますが、その実験の過程で下記エラーが出たり、
Uncaught Error: Error: Error module=5 func=3 err0=0 returned=3 at Obniz.error (obniz.js:8598) at Obniz.notifyToModule (obniz.js:8564) at Obniz.wsOnMessage (obniz.js:7667) at WebSocket.ws.onmessage.event (obniz.js:7819)
obniz本体のエラー(?)で、ブラウザが再起動する現象おきます。
もう少し時間を要しそうですが、またアップデートします。
よろしくお願いします。
-
@nak435 様
obniz._drainQueued()
ですが、これはqueueに溜まったものを捨てるコマンドではなく、一時的にためたものを急いで”送信”するためのものとなります。
しかし、バッファが溜まっているところでこれを実行してもobniz側が受け付けられない場合は結局送信できないことになるので、オーバーフロー時にこれで解決することはできないです。内部エラーですが、こちらはspiに長さが0だったりと異常なデータが来てしまいエラーとなっているようです。obniz.jsに問題がある可能性があります。
もしよろしければエラーとなるソースコードを共有していただいてこちらでも検証を行いたいと思います。await obniz.pingWait()をspi.write()と対で呼び出せば、何もエラーは出ずLCDに描画できますが、さすがに速度が遅すぎて・・・。
1フレームの描画完了後に一度だけpingWait()していただき、
その後すぐに次フレームの描画を開始するようにしていただく場合がバッファに溜まらない最も速い描画になるかと思います。1秒間に30回フレームを描画するような方法ですとそれだけの転送能力がない場合に必ずオーバーフローしてしまいます。
なので、フレーム完了後に次フレームの描画を開始するようなコードにしていただければバッファに溜まったとしても最大1フレーム分となります。
-
@Yuki-Sato さん
ありがとうございます。このLCDは128x160pixelで16bit/pixelカラーモードの場合、画面全体を書き換えるために送信するデータは40KBで、
3つのコマンドとカラーデータの送信で合計45回のspi.write()
を発行します。
そして、最後にobnizと同期を取るためにawait obniz.pingWait()
を発行すると、一連の処理で合計480ms程かかります。
この描画方式ですと、バッファオーバーフローやobniz本体のエラーも発生しないことは確認できました。一方、図形の描画など、ある意味不連続なpixelを大量に描画する場合にエラーが起きます。
情報は別途連携いたします。よろしくお願いします。
-
-
-
@Yuki-Sato さん
数十回試しましたが、エラーは発生しませんでした。
また、若干性能も良くなったように感じます。このLCDパーツライブラリも後日アップしたいと思います。
よろしくお願いします。
-
-
@Yuki-Sato さん
LCDパーツライブラリの掲載ありがとうございました。
さらにサンプルのビデオまで撮影していただき嬉しい限りです。
LCDにObnizを描いて、そこのOLEDの所に何か描いたら楽しいだろうなーと考えました。(共感していただけた?)
よろしくお願いします。
-
@nak435 さん
サンプルを動かしたときは驚きました!obnizと時計が写ったときには「おぉ〜」となりました。
また、すばらしいライブラリですね。そこにも驚きました。新しいプルリクエストもありがとうございます。1.11.2としてリリースしました。
楽しんで頂けて我々も嬉しいです^^