

このサイト<https://algorithm.joho.info/arduino/python-serial-temperature-
graph/>を用いてarduinoとの通信を行って、グラフをリアルタイム表示させたいです。  
textの方は問題なく表示されているのですが、グラフの方が表示することができないです。  
なにか問題点などあるのでしょうか？

[code]

    # -*- coding: utf-8 -*-
    import numpy as np
    import matplotlib.pyplot as plt
    import pygame
    from pygame.locals import *
    import serial
    import sys
    
    def main():
        ser = serial.Serial("COM6")  # COMポート(Arduino接続)
        temps = [0]*100              # 温度格納
        t = np.arange(0,100,1)
        plt.ion()
        pygame.init()                # Pygameを初期化
        screen = pygame.display.set_mode((200, 200))   # 画面作成(100×100)
        pygame.display.set_caption("voltage")         # タイトルバー
        font = pygame.font.Font(None, 50)              # 文字の設定
    
        while True:
            screen.fill((0,0,0))            # 画面のクリア
            temp = ser.readline().rstrip()   # \nまで読み込む(\nは削除)
            temp = temp.decode()
            text = font.render(temp + "[V]", False, (255,255,255))    # 表示する文字の設定
            screen.blit(text, (10, 10))     # レンダ，表示位置
            pygame.display.flip()           # 画面を更新して、変更を反映
            # 温度データのリスト更新
            temps.pop(99)
            temps.insert(0,float(temp))
            # グラフ表示設定
            line, = plt.plot(t, temps, 'r-',label="Temperature[C]") # Y軸更新
            line.set_ydata(temps)
            plt.title("Real-time temperature")
            plt.xlabel("Time [s]")
            plt.ylabel("Temperature [Celsius]")
            plt.legend()
            plt.grid()
            plt.xlim([1,100])
            plt.ylim([0,5])
            plt.draw()
            plt.clf()
            for event in pygame.event.get():
                # 終了ボタンが押されたら終了処理
                if event.type == QUIT:
                    pygame.quit()
                    ser.close()
                    plt.close()
                    sys.exit()
    
    
    if __name__ == '__main__':
        main()
    
[/code]


CC BY-SA 4.0
2020-11-12T15:35:27.537
71903
2020-11-13T03:35:23.923
37633
question
python pygame
python pygameを用いてマイコンボードからのデータをリアルタイム処理を行う


直前の質問と同様の環境だと、Windowsでやっていると思われますが、その場合は以下の記事が当てはまるでしょう。  
紹介記事では動作しない原因は`plt.show()`としていますが、`plt.draw()`も同様のようです。

なので、 **`plt.draw()`を`plt.pause(interval)`に変える** ことが対策になるでしょう。

[matplotlibでリアルタイム描画](https://qiita.com/hausen6/items/b1b54f7325745ae43e47)

> 調べてみると`show()`ではなくて`draw()`を使おう!みたいな記事とか，..途中省略..
> Windows環境だとグラフに一度でも触るとGUIが固まったりしてとてもじゃないけど使えなかったりした．
>
> 結論は`plt.show()`の代わりに`plt.pause(interval)`を使うということ．
[code]

>     # 一番のポイント
>     # - plt.show() ブロッキングされてリアルタイムに描写できない
>     # - plt.ion() + plt.draw() グラフウインドウが固まってプログラムが止まるから使えない
>     # ----> plt.pause(interval) これを使う!!! 引数はsleep時間
>     plt.pause(.01)
>  
[/code]

関連：[How do I plot in real-time in a while loop using
matplotlib?](https://stackoverflow.com/q/11874767/9014308)

ただし、jupyter notebook だと何か別の影響があるかもしれないので、まずは **素のPython だけで試してみてください。**


CC BY-SA 4.0
2020-11-13T00:54:01.467
71906
2020-11-13T00:54:01.467
26370
71903
answer


@kunifさんのご回答内容に加えて、`plt.ylim([0,5])`も問題です。  
これでは0℃～5℃までしか表示されません。

ご質問のリンク先にあるソースでは`plt.xlim([0,100])`を`plt.xlim([0,20])`に変更し、目盛線の間隔も書き換えられているようです。  
下記はセンサー無しで動くように10℃～20℃のランダムなダミーデータを入れるサンプルコードです。

[code]

    import numpy as np
    import matplotlib.pyplot as plt
    import pygame
    from pygame.locals import *
    import serial
    import sys
    import random
    import time
    
    def main():
        # ◆□ テストのため改修 □◆
        #ser = serial.Serial("COM6")  # COMポート(Arduino接続)
        temps = [0]*100              # 温度格納
        t = np.arange(0,100,1)
        plt.ion()
        pygame.init()                # Pygameを初期化
        screen = pygame.display.set_mode((200, 200))   # 画面作成(100×100)
        pygame.display.set_caption("voltage")         # タイトルバー
        font = pygame.font.Font(None, 50)              # 文字の設定
    
        while True:
            screen.fill((0,0,0))            # 画面のクリア
            # ◆□ テストのため改修 □◆
            temp = str(random.randint(10, 20))
            #temp = ser.readline().rstrip()   # \nまで読み込む(\nは削除)
            #temp = temp.decode()
            text = font.render(temp + "[V]", False, (255,255,255))    # 表示する文字の設定
            screen.blit(text, (10, 10))     # レンダ，表示位置
            pygame.display.flip()           # 画面を更新して、変更を反映
            # 温度データのリスト更新
            temps.pop(99)
            temps.insert(0,float(temp))
            # グラフ表示設定
            line, = plt.plot(t, temps, 'r-',label="Temperature[C]") # Y軸更新
            line.set_ydata(temps)
            plt.title("Real-time temperature")
            plt.xlabel("Time [s]")
            plt.ylabel("Temperature [Celsius]")
            plt.legend()
            plt.grid()
            plt.xlim([1,100])
            # ◆□ TODO 書き換え □◆
            #plt.ylim([0,5])
            plt.ylim([0,40])
            plt.draw()
            # ◆□ TODO 追記 □◆
            #plt.pause(0.01)  # ほぼリアルタイム描画
            plt.pause(0.5)    # テストのため0.5秒待機
            plt.clf()
            for event in pygame.event.get():
                # 終了ボタンが押されたら終了処理
                if event.type == QUIT:
                    pygame.quit()
                    plt.close()
                    sys.exit()
    
    if __name__ == '__main__':
        main()
    
[/code]


CC BY-SA 4.0
2020-11-13T01:13:54.173
71907
2020-11-13T01:13:54.173
9820
71903
answer


[matplotlib.figure.canvas.flush_events](https://matplotlib.org/3.3.2/api/backend_bases_api.html#matplotlib.backend_bases.FigureCanvasBase.flush_events)
を使う方法はどうでしょうか。これで一応はリアルタイムに表示される様になります。

※ legend の表示位置ですが `plt.legend(loc='upper right')` などとして表示位置を固定すると良いかと思います

[code]

    def main():
              :
    
        while True:
              :
            ## don't need to call plt.draw() if clearing the figure with plt.clf()
            #plt.draw()
            ## flush the GUI events for the figure
            plt.figure(1).canvas.flush_events()
            plt.clf()
              :
    
    
[/code]


CC BY-SA 4.0
2020-11-13T03:18:36.380
71911
2020-11-13T03:35:23.923
2020-11-13T03:35:23.923
71903
answer