1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Python] Problema com gráfico animado em tempo real

Discussão em 'Python' iniciado por Stack, Outubro 3, 2024 às 15:12.

  1. Stack

    Stack Membro Participativo

    Olá, comunidade!

    Estou desenvolvendo uma classe em Python responsável por capturar dados em tempo real do Arduino e gerar dois gráficos. Para melhorar o desempenho, estou utilizando a técnica de blitting. No entanto, estou enfrentando alguns problemas:

    Atualização do Eixo X: O eixo X, que representa o tempo, não está se atualizando corretamente conforme novos dados são recebidos. Ele permanece estático, o que impede a visualização dinâmica dos dados em tempo real.

    Independência dos Gráficos: Preciso que os gráficos funcionem de maneira independente um do outro, cada um refletindo os dados em tempo real sem interferência.

    Animação em Tempo Real: O gráfico não parece ser animado em tempo real, o que é essencial para a minha aplicação.


    Alguém tem sugestões sobre como resolver esses problemas? Agradeço antecipadamente pela ajuda!

    class Graficos:
    def __init__(self, arduino, master):
    self.arduino = arduino # Recebe o objeto arduíno
    self.master = master # Recebe o objeto master

    self.dados_lvdt = {'lvdt1': [], 'lvdt2': [], 'lvdt3': [], 'media': []} # Cria um dicionário para armazenar os dados do lvdt 1, 2, 3 e da média
    self.dados_lvdt_axial = {'lvdt_axial': []} # Cria um dicionário para armazenar os dados do lvdt axial
    self.tempos = [] # Adicionado para armazenar os tempos

    self.fig, self.axs = plt.subplots(1, 2, layout="constrained", figsize=(25.3, 5))# figura e um conjunto de subplots,largura de 15 polegadas e uma altura de 3 polegadas, e há 45 subplots na figura.
    self.fig.suptitle('Gráficos LVDT', fontsize=16)#adiciona um título à figura.
    self.canvas = FigureCanvasTkAgg(self.fig, master=self.master)#exibir a figura na interface gráfica do usuário.
    self.canvas_widget = self.canvas.get_tk_widget() # Cria o widget Tkinter
    self.canvas_widget.grid(row=0, column=0) # Posicionamento
    self.limite_pontos = 50 # Limite de pontos

    self.ax1, self.ax2 = self.axs[0], self.axs[1] # Cria os 2 gráficos
    self.line_lvdt1, = self.axs[0].plot([], [], lw=2) # Cria a linha do lvdt 1
    self.line_lvdt2, = self.axs[0].plot([], [], lw=2) # Cria a linha do lvdt 2
    self.line_lvdt3, = self.axs[0].plot([], [], lw=2) # Cria a linha do lvdt 3
    self.line_media, = self.axs[0].plot([], [], lw=2) # Cria a linha da média
    self.line_lvdt_axial, = self.axs[1].plot([], [], lw=2) # Cria a linha do lvdt axial

    self.configurar_graficos() # Configura os gráficos

    # Mudança em 03/10/2024

    # Exibe a figura e prepara o fundo para o blit
    plt.show(block=False)
    self.fig.canvas.draw() # Necessário para capturar o fundo corretamente
    self.bg = self.fig.canvas.copy_from_bbox(self.fig.bbox) # Salva o fundo da figura



    """
    02/10/2024
    # Exibe a figura e prepara o fundo para o blit
    plt.show(block=False)
    plt.pause(0.1) # Garante que a figura seja exibida
    self.bg = self.fig.canvas.copy_from_bbox(self.fig.bbox) # Salva o fundo da figura
    """
    self.iniciar_animacao() # Inicia a animação

    # Inicializando as linhas nos subplots
    self.lines = [ax.plot([], [])[0] for ax in self.axs]#inicializa uma lista de linhas vazias para cada subplot.


    # Metódo para configurar os gráficos.
    def configurar_graficos(self):
    self.ax1.set_xlabel('Tempo (ms)') # Título do eixo x
    self.ax1.set_ylabel('Deslocamento (mm)') # Título do eixo y
    #self.ax1.set_xlim(0, 1000) # Intervalo do eixo X (ms)
    self.ax1.set_ylim(-1.4, 1.6) # Intervalo do eixo Y (mm)
    #self.ax1.set_yticks(np.arange(-1.4, 1.6, 0.2)) # Escala do eixo y, passo de 0,25
    self.ax1.set_yticks(ticker.MultipleLocator(0.2).tick_values(-1.4,1.4))
    self.ax1.set_title('LVDT 1, 2, 3 e Média') # Titulo do subplot
    self.ax1.legend(['LVDT 1', 'LVDT 2', 'LVDT 3', 'Média'], loc='lower left') # Legenda
    #self.ax1.set_facecolor('gray')
    self.ax1.grid(True) # Mostra a grade

    self.ax2.set_xlabel('Tempo (ms)') # Nomemclatura do eixo x
    self.ax2.set_ylabel('Deslocamento (mm)') # Título do eixo y
    #self.ax2.set_xlim(0, 500) # Intervalo do eixo X (ms)
    self.ax2.set_ylim(-1.4, 1.6) # Intervalo do eixo Y (mm)
    #self.ax2.set_yticks(np.arange(-1.4, 1.6, 0.2)) # Escala do eixo y, passo de 0,2
    #self.ax2.set_yticks(list(self.float_range(-1.4, 1.6, 0.2)))
    self.ax2.set_yticks(ticker.MultipleLocator(0.2).tick_values(-1.4,1.4))
    self.ax2.set_title('LVDT Axial') # Titulo do subplot
    #self.ax2.set_facecolor('gray')
    self.ax2.grid(True) # Mostra a grade

    def gerar_dados(self, frame): # Método para gerar os dados. Recebe o frame e o objeto arduíno
    novo_dado_lvdt = self.arduino.dados_lvdt() # Recebe novos dados do objeto arduíno

    if novo_dado_lvdt: # Se houver novos dados
    # Atualiza os gráficos lvdt
    lvdt1, lvdt2, lvdt3, lvdtaxial = novo_dado_lvdt # Recebe os novos dados
    self.dados_lvdt['lvdt1'].append(lvdt1) # Adiciona os novos dados ao dicionário lvdt1

    self.dados_lvdt['lvdt2'].append(lvdt2) # Adiciona os novos dados ao dicionário lvdt2

    self.dados_lvdt['lvdt3'].append(lvdt3) # Adiciona os novos dados ao dicionário lvdt3

    self.dados_lvdt['media'].append((lvdt1 + lvdt2 + lvdt3) / 3) # Faz o cálculo da média dos 3 lvdts e os adiciona no dicionário
    self.dados_lvdt_axial['lvdt_axial'].append(lvdtaxial) # Adiciona novos dados ao dicionário lvdt axial

    self.tempos.append(frame) # Adiciona o novo tempo

    self.atualizar_dados() # Atualiza os dados

    # Retornar as linhas atualizadas (objetos Artist)
    return self.line_lvdt1, self.line_lvdt2, self.line_lvdt3, self.line_media, self.line_lvdt_axial

    #self.atualizar_dados()



    #Certifique-se de que as linhas têm dados suficientes
    #if len(self.tempos) > 0:


    def atualizar_dados(self): # Atualiza os dados

    # Re-captura o fundo da figura antes de redesenhar as linhas
    self.bg = self.fig.canvas.copy_from_bbox(self.fig.bbox)

    # Restaura o fundo (background)
    self.fig.canvas.restore_region(self.bg)

    # Atualiza os dados
    self.line_lvdt1.set_data(self.tempos, self.dados_lvdt['lvdt1'])
    self.line_lvdt2.set_data(self.tempos, self.dados_lvdt['lvdt2'])
    self.line_lvdt3.set_data(self.tempos, self.dados_lvdt['lvdt3'])
    self.line_media.set_data(self.tempos, self.dados_lvdt['media'])
    self.line_lvdt_axial.set_data(self.tempos, self.dados_lvdt_axial['lvdt_axial'])

    # Redefinir os limites do eixo X
    if len(self.tempos) > 0:
    # Definir o limite do eixo X de 0 até o valor máximo de tempo registrado
    max_tempo = max(self.tempos)
    if max_tempo > 0:
    self.ax1.set_xlim(0, max_tempo)
    self.ax2.set_xlim(0, max_tempo)

    # Redesenha as linhas
    self.ax1.draw_artist(self.line_lvdt1)
    self.ax1.draw_artist(self.line_lvdt2)
    self.ax1.draw_artist(self.line_lvdt3)
    self.ax1.draw_artist(self.line_media)
    self.ax2.draw_artist(self.line_lvdt_axial)



    """
    Excluído em 03/10/2024
    self.line_lvdt1.set_xdata(self.tempos) # Define os novos dados no eixo x , o qual será o tempo
    self.line_lvdt1.set_ydata(self.dados_lvdt['lvdt1']) # Define os novos dados no eixo y , o qual é o lvdt1


    self.line_lvdt2.set_xdata(self.tempos) # Define os novos dados no eixo x , o qual é o tempo
    self.line_lvdt2.set_ydata(self.dados_lvdt['lvdt2']) # Define os novos dados no eixo y , o qual é o lvdt2

    self.line_lvdt3.set_xdata(self.tempos) # Define os novos dados no eixo x , o qual é o tempo
    self.line_lvdt3.set_ydata(self.dados_lvdt['lvdt3']) # Define os novos dados no eixo y , o qual é o lvdt3

    self.line_media.set_xdata(self.tempos) # Define os novos dados no eixo x , o qual é o tempo
    self.line_media.set_ydata(self.dados_lvdt['media']) # Define os novos dados no eixo y , o qual é a média

    self.axs[0].relim() # Atualiza os limites dos eixos
    self.axs[0].autoscale_view() # Atualiza os limites dos eixos

    self.line_lvdt_axial.set_xdata(self.tempos) # Define os novos dados no eixo x , o qual é o tempo
    self.line_lvdt_axial.set_ydata(self.dados_lvdt_axial['lvdt_axial']) # Define os novos dados no eixo y , o qual é o lvdtaxial

    self.axs[1].relim() # Atualiza os limites dos eixos
    self.axs[1].autoscale_view() # Atualiza os limites dos eixos


    02/10/2024
    # Atualiza a tela com o novo gráfico
    self.fig.canvas.blit(self.fig.bbox)
    """

    # Atualiza a tela com as partes redesenhadas
    self.fig.canvas.blit(self.fig.bbox)

    # Opcional: flush events para garantir que o canvas seja atualizado
    self.fig.canvas.flush_events()

    """
    # Excluído em 03/10/2024 self.canvas.draw() # Atualiza o widget Tkinter com a imagem atualizada.
    self.canvas.flush_events() # Método para limpar figuras em cada iteração, para que figuras sucessivas não se sobreponham.
    """



    def iniciar_animacao(self): # Inicia a animação
    self.anim = FuncAnimation(self.fig, self.gerar_dados, blit=True, interval=10, cache_frame_data=False) # Cria a animação, que gera novos dados a cada 10 ms, e armazena os dados gerados.Blit só só redesenha partes #do gráfico que mudaram .
    #self.anim.save('Minha animação.gif')

    Continue reading...

Compartilhe esta Página