Peripherals SPIについて



  • こちらの LCDモジュール をobnizで制御するパーツライブラリを開発しています。そこで、obniz.js及びobniz内の動作を確認させてください。

    • spi.write() は一度で最大1024Bとなっているため、例えば、40KBのデータを送信する場合は、1KBづつ40回繰り返して呼ぶことになりますが、個々のspi.write()は同期ではなく、obniz.js内でバッファリングしているように見えます。そしてこのバッファがオーバーフローする場合があるため、1回づづ同期で呼び出すことはできないでしょうか? awaitを付けてもダメでした。

    • spi.writeWait() は送信したバイト数と同じだけ受信する仕様となっていますが、例えば、1バイトのコマンドを送信して、3バイトの結果を受信するような場合はどのようにすれば良いのでしょうか?


    注) 上記のオーバーフローを起こす条件が定まりません。週末にいくつか実験して結果をアップデートするつもりです。

    よろしくお願いします。


  • administrators

    ご連絡ありがとうございます。面白そうな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本体のエラー(?)で、ブラウザが再起動する現象おきます。

    もう少し時間を要しそうですが、またアップデートします。
    よろしくお願いします。


  • administrators

    @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を大量に描画する場合にエラーが起きます。
    情報は別途連携いたします。

    よろしくお願いします。


  • administrators

    @nak435

    かしこまりました。不連続データに関するメール受け取りましたのでメールの方確認させていただきます。

    引き続きよろしくお願いいたします。


  • administrators

    @nak435 さん

    obnizの新しいファームウェア 1.0.9でSPIに関する問題を解決しました。
    エラーは出ないかと思いますので、Updateの後お試しください。

    よろしくお願い致します。



  • @Yuki-Sato さん

    数十回試しましたが、エラーは発生しませんでした。
    また、若干性能も良くなったように感じます。

    このLCDパーツライブラリも後日アップしたいと思います。
    よろしくお願いします。


  • administrators

    @nak435 さん

    良かったです!性能については意図的には上げてないのですが、偶然改善されたかもしれません。

    パーツライブラリについても了解です。
    よろしくお願い致します。



  • @Yuki-Sato さん

    LCDパーツライブラリの掲載ありがとうございました。
    さらにサンプルのビデオまで撮影していただき嬉しい限りです。
    LCDにObnizを描いて、そこのOLEDの所に何か描いたら楽しいだろうなーと考えました。(共感していただけた?)
    よろしくお願いします。


  • administrators

    @nak435 さん

    サンプルを動かしたときは驚きました!obnizと時計が写ったときには「おぉ〜」となりました。
    また、すばらしいライブラリですね。そこにも驚きました。

    新しいプルリクエストもありがとうございます。1.11.2としてリリースしました。

    楽しんで頂けて我々も嬉しいです^^


 

Recent Projects

  • @nak435 かしこまりました。よろしくお願いします。

    read more
  • @Yuki-Sato さん、

    外部の3.3vを使うとはいえ普通にvccやgndを供給して問題なくうごくのであれば、弊社での動作確認後Flick Hatのライブラリとして公開できればと思っているのですがいかがでしょう。

    今週末に確認しますので、お待ちください。

    read more
  • @nak435 時間がかかってすいません、

    なんとか3.3vをgndにつないでFlick Largeを動かしたかったのですが、うまく動かすことができなかったです。
    3.3vをgndを繋がずに接続するというのはライブラリで推奨して伝えることは難しいと思ってます。

    Flick LargeでなくFlick Hatの方で、外部の3.3vを使うとはいえ普通にvccやgndを供給して問題なくうごくのであれば、弊社での動作確認後Flick Hatのライブラリとして公開できればと思っているのですがいかがでしょう。

    よろしくお願い致します。

    read more
  • @nak435 ありがとうございます。
    接続は3.3vのgnd以外同じでした。
    エラーはそのせいかもしれませんが、しかし電気的にはgndを繋がない場合3.3vとしてうまく供給できないはずなのでそこが不思議です。

    教えていただいたプログラムの部分を修正して試してみたいと思います。
    また少し時間がかかりそうなのですが、早めに試したいと思います。

    引き続きよろしくお願い致します。

    read more