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...