電源周波数観測のサーバプログラム更新(リアルタイム表示化)

1日に1回くらい起きる「突然51Hzくらいの瞬間がある」という現象に悩んで進まなかったサーバプログラム更新ですが、やっと更新しました。(51Hzくらいの異常データは単にフォトカプラのLEDのスレッショルド付近を跨ぐノイズだろうと思います。冷静に考えれば、本来1周期に1回のインプットキャプチャ発動が稀にノイズで1周期に2回起きてしまう=1秒間に50回のものが51回になる=51Hz付近に見えるというだけでしょう)

新バージョンでは毎回ページを全リロードするのではなく、増えたデータだけ受け取ってデータが増えたらchart.jsで描画しているグラフの部分だけを再描画しています。なので、転送量も減っているはず・・・だと思います。

下のグラフはまだサーバ内に12時間分のデータがないので疎なグラフになっています。

その他の変化点は以下の通りです。

  • 短時間と長時間のグラフが別ページでしたが、同じページに表示するようにしました。
  • 表示の更新はほぼ1秒単位。NTPで時刻合わせしてある端末があれば見比べるとわかりますが、ほぼリアルタイム表示です。
  • Firefoxでは再描画部分に表示範囲が引っ張られてしまうので、長時間の部分を見るのが難しい状況でした。ですので、描画の一時停止と再開ボタンをつけました。スクリーンショットを撮る際に停止させるのにも使えると思います。
  • データ(表示を一時停止しても内部的には更新されています)をCSV形式でエクスポートする機能をつけました。LibreOffice Calcで開いてグラフを表示させることが簡単にできます。Excelでも簡単にできると思います。

動作確認はLinux Mint上のGoogle ChromeとFirefoxでしか行ってません。Windows版のChromeとFirefoxは大丈夫だと思いますが、他はどうなるか予想もつきません。

なお、お遊びサーバなので、突然やめたり、突然再起動したり、突然停止したり、突然仕様が変わったり、突然バグったりするかもしれません(笑)。サーバ(Raspberry Pi Model B+)の周りも整理しないといけないので、気が向いたらしばらく停止したりするかもしれません。

“電源周波数観測のサーバプログラム更新(リアルタイム表示化)” への16件の返信

  1. こんにちは。
    Twitterを漁ってたらこちらのサイトにたどり着きました。 今回のプログラムの解説記事を是非書いていただけないでしょうか..?? 独学で勉強をしてるのですが、参考にさせて頂きたいです。

    1. 紗来さん、こんにちは。
      自分もJavascriptは独学で始めたばかりで、今回初めてJavascriptでコードを書いています。ですので、大部分はサンプルコードを参考にしたりググったりしています。
      で、どの部分を知りたいのかわからないのですが、今回のコードにまとめる前にテストをいくつかしていて、そちらを記事にしてあります。
      まず波形表示の更新については3/29の「Chart.jsによる波形描画テスト」です。これはテストなのでデータの生成と表示更新をデータ受信のタイミングではなくインターバル動作で行っていますが、やっていることは同じです。
      測定データの受信については、3/28の「aiohttpを使ってWebsocket通信してみる」です。これもテストでデータ受信したら表示している要素を書き換えるだけになっていますが、これを今回のコードでは測定データの受信に書き換えています。具体的には、新規接続時はサーバのデータをまとめてもらい(正確には送りつけられてくるようにしてあるので受け取り)chart.jsでのデータ形式に変換、その後は更新データをもらったらデータを書き足して表示を更新する、という処理です。
      ですので、これらをご覧いただければと思います。
      なお、ボタン押下はサーバとは何も関係なく、データ受信後の表示更新処理をするか否かのフラグ変数をON/OFFしたり、内部で持っているデータを形式を変換して吐き出したりしているだけです。

      1. 返信ありがとうございます!
        サーバー上のプログラムが分からなくて質問しました。

        過去記事を読んでみます!

  2. お久しぶりです。
    お忙しい中申し訳ないのですが、
    今回も周波数観測サイトのWEB側のプログラムの解説記事を作っていただけないでしょうか??

    1. 上の方の紗来さんのコメントへの返信で概ね記載していますので、そちらを見てみてください。書ける部分については個々の技術要素に分けて記載しています。ただ、pythonのasyncioについては自分も理解できていないので、現状書いている以上の解説はできないです。

  3. ありがとうございます。
    ある程度記事は見たのですが、測定データの送信の方法がわかりませんでした。。
    どのようにしていますでしょうか??

  4. すみません。
    先ほどのコメントでは言葉足らずでしたので補足いたします。

    「”測定データの受信については、3/28の「aiohttpを使ってWebsocket通信してみる」です。これもテストでデータ受信したら表示している要素を書き換えるだけになっていますが、これを今回のコードでは測定データの受信に書き換えています。具体的には、新規接続時はサーバのデータをまとめてもらい(正確には送りつけられてくるようにしてあるので受け取り)chart.jsでのデータ形式に変換、その後は更新データをもらったらデータを書き足して表示を更新する、という処理”」 

    この部分のプログラムがうまくいきませんでしたので質問いたしました。

    1. 3/28のpythonソースで説明します。

      クライアントが新規に接続に来ると、websocket_handler()というasync関数が呼ばれて、その中でresister()という関数が呼ばれます。resiter()ではクライアント接続のリストUSERSに接続してきたクライアントを追加して、notify_users()を呼んで全ユーザーに接続しているクライアント数の更新の通知(users_event()でメッセージの種別 type:users)を送っています。

      実際のプログラムでは、このregister()の中のUSERS.add(websocket)の直後で、await notify_data1(websocket)などとして新規のクライアントがまだ持っていないデータをまとめて新規のクライアントだけに送っています。メッセージの種別は適当に追加すればいいのですが、サーバのPython側とクライアントのJavascript側で合わせる必要があります。たとえば、json.dumps({“type”: “data1”, “value”: hist1 })をサーバ側から送りつけて、クライアント側で type:data1 が来たら、valueには一括でデータが入って来たものとして受け取って chart.js で描画できる形式に整形してやります。
      追加データはサーバ側でarduinoなどからシリアルデータを1行受信したら数値に変換して、json.dumps({“type”: “update1”, “value”: newdata }) などと増えたデータだけ送りつけて、クライアント側は type:update1 が来たら、valueには追加データが来たものとして先のデータに追加しています。

      なおシリアルの受信はserialではなく、こちらもasyncio対応のaioserialというモジュールに変更しています。(serialではreadline()のところでブロックしてしまうので)

      正直なところaiohttp、aioserial、asyncioの使い方が適切なのかはよくわかっていません。この辺はもっとasync/awaitの使い方を調べないといけないところです。(いまは時間がかかりそうな処理を呼ぶ際にとりあえずawaitをつけてみてる感じです)

  5. こんばんは。
    現在学校の課題研究で周波数計測などを研究しています。 研究の参考にさせて頂きたいのでプログラムのコードを公開していただけないでしょうか…??

    1. こんばんは。
      電源周波数を計測するソースコードは1月11日の「電源周波数の変動を測ってみた」という記事で掲載しています。サイト内検索で「電源周波数」で検索するか、タグで「電源周波数」で探してみてください。なお、実際に計測しているのは周波数ではなく周期です。

      1. 返信ありがとうございます。
        測定データをPythonで受け取ってると思うのですが、1[s]ごとにグラフが自動更新されるプログラム(WEB側)を見てみたいです。 そちらも公開していただけないでしょうか??(上の方々の返信を見てもイメージがつかなかった為)

        1. 申し訳ありませんが、Pythonのasync/awaitが理解できておらず、動いてはいるものの、全体の構成の考え方に問題がないのかよくわからない(それなりにも納得できてない)状態ではソースコードを公開するつもりはありません。グラフ更新そのものなど、個々の要素技術については概ね記載していますので、そちらを見てみてください。

  6. こんにちは。
    気になることがありコメントいたしました。

    Pythonで測定データの蓄積方法がググってもよくわかりませんでした。とものさんはどのようにしておりますでしょうか..??

    また、websocketで多数同時接続時、データの遅延が発生してしまうのですが、どのように対処しておりますでしょうか???

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

    1. 天空の白さん、こんにちは。

      測定データの蓄積は手抜きをしていて、データを受信するたびに時刻と値の組み合わせのタプルをhistという配列にappendしていって、その要素数がhlenという変数の値を越えたら先頭の要素を削除しています。
      ちょうど、3/8の記事の中のソースコードでいうと recieve() という関数内の hist.append((time.time(),data)) という行のあたりです。
      なので、Pythonのプログラムを再起動すると過去データが失われます。本当はデータベースにするとかいろいろ考えられるのですが、運用の楽さの方をとった感じです。(InfluxDBは試してみたいなぁ、とは思っていますが)

      websocketでの遅延は、どの現象を言っているのかわかりませんし、「多数」がどのくらいなのかわかりませんが、10とか20くらいの範囲だとそのような現象は見えていないです。
      はっきりは言えませんが、3/28の記事でいうとasync/await絡みのような気がします。基本的にはpythonはシングルスレッドで動いているので、相手からの応答があるまで動作がブロックされます(適切な表現かわかりませんが)。
      しかし、async/awaitを使うことで、待ち時間の多い処理を非同期処理にできる=応答を待たずに次の処理ができるので、見かけ上の遅延が大幅に減るように見えます。(ただ、自分もよくわかってないところなのですが・・・)
      いただいたコメントから思いつくのはこのあたりなのですが、どうでしょうか。

      1. ご回答ありがとうございます。
        データ蓄積の件はわかりました。
        websocketでの遅延の件は、1台接続時は1sごとにデータが飛んで来るのですが、2台になると2sでデータが飛んできます。3台接続では4sほど
        遅れて飛んできます。接続ユーザーが増えれば増えるだけ遅延が増加するような感じになっております。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)