perform real-time processing of data from a microcomputer board using python pygame

Asked 2 years ago, Updated 2 years ago, 454 views

I would like to communicate with arduino using this site https://algorithm.joho.info/arduino/python-serial-temperature-graph/ to display the graph in real time.
The text is displayed without any problems, but the graph cannot be displayed.
Are there any problems?

#-*-coding:utf-8-*-
import numpy as np
import matplotlib.pyplot asplt
import pygame
from pygame.locals import*
import serial
import sys

defmain():
    ser=serial.Serial("COM6")#COM port (Arduino connection)
    temp=[0]*100#Temperature Storage
    t = np.range(0,100,1)
    plt.ion()
    pygame.init()#Initialize Pygame
    screen=pygame.display.set_mode(200,200))#Create Screen (100x100)
    pygame.display.set_caption("voltage")#Title Bar
    font=pygame.font.Font(None,50)# Character Settings

    while True:
        screen.fill(0,0,0))# Clearing the Screen
        US>temp=ser.readline().rstrip()#\nRemove\n
        temp=temp.decode()
        text=font.render(temp+"[V]", False, (255, 255, 255))# Character Settings to Display
        screen.blit(text,(10,10))# render, display location
        pygame.display.flip()# Refresh the screen to reflect changes
        # Update list of temperature data
        temp.pop(99)
        temp.insert(0, float(temp))
        # Graph Display Settings
        line,=plt.plot(t,temps,'r-', label="Temperature[C]")#Y-axis update
        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():
            # Exit action when the exit button is pressed
            if event.type==QUIT:
                pygame.quit()
                ser.close()
                plt.close()
                sys.exit()


if__name__=='__main__':
    main()

python pygame

2022-09-30 21:54

3 Answers

How about using matplotlib.figure.canvas.flush_events?Now it will be displayed in real time.

*Regarding the display position of legend, I think it would be better to fix the display position as plt.legend(loc='upper right') etc.


defmain():
          :

    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()
          :


2022-09-30 21:54

If you are in the same environment as the previous question, you may be doing it on Windows, but the following article will apply.
The reason why it doesn't work in the introduction article is plt.show(), but plt.draw() seems to be the same.

Therefore, changing plt.draw() to plt.pause(interval) would be a countermeasure.

Draw real-time with matplotlib

I looked into articles like draw() instead of show() and articles like draw()...abbreviated...In Windows environment, the GUI hardened when I touched the graph even once, so I couldn't use it.

The bottom line is to use plt.pause(interval) instead of plt.show().

#First point
# -plt.show() Blocked and unable to describe in real time
# -plt.ion()+plt.draw() The graph window hardens and the program stops working.
# ---->plt.pause (interval) Use this !!! argument is sleep time
plt.pause(.01)

Related:How do I pot in real-time in a while loop using matplotlib?

However, jupyter notebook may have some other effect, so try only the element Python first.


2022-09-30 21:54

In addition to @kunif's response, plt.ylim([0,5]) is also a problem.
This only shows 0°C to 5°C.

The source linked to your question seems to have changed plt.xlim([0,100]) to plt.xlim([0,20]), and the interval between the scales has also been rewritten.
Below is a sample code that contains random dummy data from 10°C to 20°C so that it works without a sensor.

import numpy as np
import matplotlib.pyplot asplt
import pygame
from pygame.locals import*
import serial
import sys
import random
import time

defmain():
    # ◆□ Modified for testing□◆
    # ser = serial.Serial ("COM6") # COM port (Arduino connection)
    temp=[0]*100#Temperature Storage
    t = np.range(0,100,1)
    plt.ion()
    pygame.init()#Initialize Pygame
    screen=pygame.display.set_mode(200,200))#Create Screen (100x100)
    pygame.display.set_caption("voltage")#Title Bar
    font=pygame.font.Font(None,50)# Character Settings

    while True:
        screen.fill(0,0,0))# Clearing the Screen
        # ◆□ Modified for testing□◆
        temp=str(random.randint(10,20))
        #temp=ser.readline().rstrip()#\n (remove\n
        # temp = temp.decode()
        text=font.render(temp+"[V]", False, (255, 255, 255))# Character Settings to Display
        screen.blit(text,(10,10))# render, display location
        pygame.display.flip()# Refresh the screen to reflect changes
        # Update list of temperature data
        temp.pop(99)
        temp.insert(0, float(temp))
        # Graph Display Settings
        line,=plt.plot(t,temps,'r-', label="Temperature[C]")#Y-axis update
        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 Rewrite □◆
        #plt.ylim ([0,5])
        plt.ylim ([0,40])
        plt.draw()
        # ◆□Add TODO□◆
        #plt.pause(0.01) #Almost real-time drawing
        plt.pause(0.5)# Wait 0.5 seconds for test
        plt.clf()
        for event in pygame.event.get():
            # Exit action when the exit button is pressed
            if event.type==QUIT:
                pygame.quit()
                plt.close()
                sys.exit()

if__name__=='__main__':
    main()


2022-09-30 21:54

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.