Ir para conteúdo
Fórum Script Brasil
  • 0

AJUDA PYTHON LOG E gráficos URGENTE


Alexandre Stoiev

Pergunta

import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
from datetime import datetime
import serial
import time

style.use('ggplot')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)

porta = 'com7'
baud_rate = 9600

opçao = input("Iniciar verificação de temperatura ? S ou N ")

if opçao == "S":

    tempo = int(input("Informe o intervalo entre cada leitura: "))

    objeto_porta = serial.Serial(porta, baud_rate)
    objeto_porta.flushInput()

    arquivo = open("LOG.txt", "a+")

    while True:
        # Cria o objeto_hoje, pega os valores de
        # dia, mes, ano e horario, converte para string
        objeto_hoje = datetime.today()
        dia = str(objeto_hoje.day)
        mes = str(objeto_hoje.month)
        ano = str(objeto_hoje.year)
        horario = str(objeto_hoje.strftime("%X"))

        # Le os valores passados pelo arduino
        temperatura = str(objeto_porta.readline())

        arquivo.write(horario)
        arquivo.write("  ")
        arquivo.write(temperatura)
        arquivo.write("\n")

        def animate(i):
            arquivo = open("LOG.txt", "r").readline()
            lines = arquivo.split("\r\n")
            x = []
            y = []
            for line in lines:
                X, Y = line.split("  ")
                x.append(X)
                y.append(Y)

                ax1.clear()
                ax1.plot(x, y)


        ani= animation.FuncAnimation(fig,  animate, interval=tempo*1000)

        plt.show()

else:

    print("Saindo...")

Olá,  sou iniciante e estou desenvolvendo um sistema de controle de temperatura visual para um trabalho escolar, porem me deparei com o seguinte inconveniente

Para gerar os gráficos estou usando a blibioteca matplotlib e para os dados lidos pelo sensor de temperatura eu utilizo um simples arquivo txt, como um log. Ou seja o conceito do projeto é 

Ler dados do sesor -> armazenar -> plottar o grafico. devido ao meu log funcionar dentro de um WHILE ao chegar no comando que chama o pyplot, plt.show(), ele não retorna ao inicio do loop dessa forma só a primeira leitura do sensor é armazenada e plottada 

 

Gostaria muito de ajuda pois sou um estudante por conta propria e não consigo visualizar a solucao para este problema

Editado por Alexandre Stoiev
Link para o comentário
Compartilhar em outros sites

21 respostass a esta questão

Posts Recomendados

  • 0
13 horas atrás, ArteEN disse:


    while True:
        # Cria o objeto_hoje, pega os valores de
        # dia, mes, ano e horario, converte para string
        arquivo = open("LOG.txt", "a+")
        
        objeto_hoje = datetime.today()
        dia = str(objeto_hoje.day)
        mes = str(objeto_hoje.month)
        ano = str(objeto_hoje.year)
        horario = str(objeto_hoje.strftime("%X"))

        # Le os valores passados pelo arduino
        temperatura = str(objeto_porta.readline())

        arquivo.write(horario)
        arquivo.write("  ")
        arquivo.write(temperatura)
        arquivo.write("\n")

        def animate(i):
            arquivo = open("LOG.txt", "r").readline()
            lines = arquivo.split("\r\n")
            x = []
            y = []
            for line in lines:
                X, Y = line.split("  ")
                x.append(X)
                y.append(Y)

                ax1.clear()
                ax1.plot(x, y)


        ani= animation.FuncAnimation(fig,  animate, interval=tempo*1000)

        plt.show()

experimente isolar partes do codigo

pode começar fazendo um sensor fake e conferir se o restante do codigo esta agindo de acordo

depois testar a leitura do sensor em uns script separado

Olá, eu fiz como voce recomendou e separei o meu codigo em 2 scripts, um para cada função, e os dois funcionam corretamente.

No meu codigo de programa "completo" eu penso que identifiquei o problema mas não sei como resolve-lo.

Devido ao meu programa funcionar em um loop infinito para atulizar a leitura do log ao chegar no parte do codigo que chama o grafico         plt.show()        ele não recomeca o loop pois essa seria uma "funçao" que não tem fim, ou seja é o programa esta realizando a tarefa porem ela não acaba e o loop não recomeça 

Como eu posso resolver esse problema ? Talvez passar o loop que registra o log para dentro do mesmo evento que atualiza o grafico ? 

 

Editado por Alexandre Stoiev
Link para o comentário
Compartilhar em outros sites

  • 0

Dei uma olhada na documentação, a meu ver o problema esta como você esta usando a função FuncAnimation

Se você olha na documentação vera o parâmetro intervalo, ele faz parecer que a própria função já é um loop infinito, e o resultado do seu código é um loop infinito dentro de outro loop infinito

Então vem a primeira interação do primeiro loop infinito, e começa o segundo loop, e como o segundo loop nunca termina, o primeiro loop não prossegue

Link para o comentário
Compartilhar em outros sites

  • 0

 

 

 

13 minutos atrás, Alexandre Stoiev disse:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
from datetime import datetime
import serial
import matplotlib.dates as mdates
import time

style.use('ggplot')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)

porta = 'com7'
baud_rate = 9600
x = []
y = []

opçao = input("Iniciar verificação de temperatura ? S ou N ")

if opçao == "S":

    tempo = int(input("Informe o intervalo entre cada leitura: "))

    objeto_porta = serial.Serial(porta, baud_rate)
    objeto_porta.flushInput()



    while True:


        def animate(i):

            arquivo = open("LOG.txt", "a+")

            objeto_hoje = datetime.today()
            horario = str(objeto_hoje.strftime("%H"))
            minuto = str(objeto_hoje.strftime("%M"))
            segundos = str(objeto_hoje.strftime("%S"))

            temperatura = str(objeto_porta.readline())

            arquivo.write(horario)
            arquivo.write(".")
            arquivo.write(minuto)
            arquivo.write(".")
            arquivo.write(segundos)
            arquivo.write(",")
            arquivo.write(temperatura)
            arquivo.write("\n")

            arquivo.close()

            arquivo = open("LOG.txt", "r")

            for line in arquivo:
                line = line.strip("\r\n'")
                X, Y = line.split(",b'")
                x.append(X)
                y.append(Y)

                ax1.clear()
                ax1.plot(x, y)



            arquivo.close()




        ani= animation.FuncAnimation(fig,  animate, interval=tempo*1000)

        plt.show()
26 minutos atrás, ArteEN disse:

Dei uma olhada na documentação, a meu ver o problema esta como você esta usando a função FuncAnimation

Se você olha na documentação vera o parâmetro intervalo, ele faz parecer que a própria função já é um loop infinito, e o resultado do seu código é um loop infinito dentro de outro loop infinito

Então vem a primeira interação do primeiro loop infinito, e começa o segundo loop, e como o segundo loop nunca termina, o primeiro loop não prossegue

após muitos testes nesse script eu cheguei a essa mesma conclusão então eu alterei o código para que todo o loop do programa estivesse contido dentro desse evento dessa forma o programa executa o loop sempre que o evento de animação é chamado. o  programa em si funcionou de maneira aceitável porem agora eu estou tendo problemas técnicos com o matplotlib

 

como minhas leituras são realizadas a cada um segundo, o gráfico fica saturado no eixo x de informações(que seriam o horário) porem como elas são strings ( exemplo 15:13:00)  ele tenta mostrar todos os horários de leitura ao invés de "criar uma média" e adaptar a visualização

 

ate agora não consegui achar uma solução para esse problema talvez você possa me ajudar

existe alguma maneira de transformar o horário em um float (pois até onde sei é o único modo de numeros em que o gráfico ajusta os valores de exibição)  ou então uma função que interprete o horário corretamente ?

 

 

 

Editado por Alexandre Stoiev
Link para o comentário
Compartilhar em outros sites

  • 0

Eu já havia tentado algo parecido porem apesar de funcionar não é oque eu preciso. Mas obrigado por ajudar

Eu preciso manter o formato HH:MM:SS pois é necessario para o trabalho que vai ser feito, porem dessa maneira o gráfico não se ajusta sozinho 

Até agora não achei uma soluçao para essa problema. Talvez uma outra biblioteca de plot ? Ou então um grafico que se extenda no eixo x e uma barra de rolagem para viajar por ele completo ?

So achei na internet alguns poucos exemplos assim e não consegui formar nenhum script dessa maneira

Meu problema não é adquirir os dados nesse  formato de hora/minuto/segundo mas sim fazer o matplotlib se ajustar a eles

Editado por Alexandre Stoiev
Link para o comentário
Compartilhar em outros sites

  • 0

uma solução facil é criar um objeto ou lista onde ele tenha os dois valores

 

l = ['00:01:00', 60]
l = ['00:02:00', 120]

#ou

class Horario:
  def __init__(self, e, n):
    self.extenso = e
    self.numeral = n
    
h = Horario('00:01:00', 60)

com isso você pode usar o valor dos segundos para entrar como paramentro de posição no grafigo, e o formato de hora para exibição, porem é apenas suposição minha, não tenho o matplot istalado para conferir se é possivel, vou ficar devendo

Link para o comentário
Compartilhar em outros sites

  • 0

eu estou ficando doido com isso mas agradeço de verdade a ajuda. eu vou procurar saber se isso é possível.

eu não estou conseguindo extrair as informações mesmo dos exemplos do site do matplot que eu preciso. Essa biblioteca é muito extensa portanto acho que deve ter algo sobre oque eu preciso mas não sei ainda como aplicar 

caso você queira dar uma olhada nos exemplos ou na documentação dessa biblioteca para me ajudar vou deixar o link https://matplotlib.org/index.html, mas já agradeço pela ajuda com o primeiro problemas do loop foi uma baita de uma ajuda amigo. 

Link para o comentário
Compartilhar em outros sites

  • 0

eu estava dando uma olhada, bem me ocorreu uma ideia, você esta fazendo um grafico de linha?

vi que tem uma função onde redesenha o grafico, imagino que você pode criar uma lista com um range de 10 ou 20 posições, e ir atualizando essa lista como o ultimo valor, e atualizar o grafico em seguida

 

l = [0 for x in range(10)]

for i in range(20):
  print(l)
  l.pop(0)
  l.append(int(input('leitura')))
  

veja o exemplo de como a lista vai se atualizando, claro que funcionando você devera tirar do loop for

Link para o comentário
Compartilhar em outros sites

  • 0

Sim, a ideia é ótima mas o projeto que me foi passado exige que a temperatura seja lida em tempo real mas que armazene os dados do período todo em que foi acionado(sendo exibidos para o operador) no dia para garantir a conformidade do equipamento para futuras vistorias.

o gráfico começa, tem que se atualizar ao vivo, mas sem parar de mostrar as informações anteriores, e então ser salvo ao final do dia. é um projeto bem complicadinho estou nisso a semanas já.

eu acebei de olhar algumas documentações e achei uma falando sobre um modo de plot chamado xdate, que reconhece como datas do matplot e não como strings poderia funcionar e também nessa mesma biblioteca uma função chamada date2num que transforma objetos de datetime em objetos para o matplot dates date2numxdate

apesar de ter encontrado ainda não entendi como usa-los corretamente no meu código, dê uma olhada nos links desses se puder são funcionalidades que me parecem bem interessantes. 

 

ta vendo oque acontece no eixo x ? é isso que eu quero evitar 

 

Captura de Tela (11).png

Editado por Alexandre Stoiev
Link para o comentário
Compartilhar em outros sites

  • 0

nesse segundo link diz que funciona igual ao matplotlib.pyplot.plot, só que usando datas

 

acho que é para ficar no lugar do fig = plt.figure()

como fig = plt.plot_date()

ou

ax1.plot(x, y) para ax1.plot_date(x, y)

é o que penso vendo a documentação e seu codigo antigo

Link para o comentário
Compartilhar em outros sites

  • 0
 for line in arquivo:
                line = line.strip("\r\n'")
                X, Y = line.split(",b'")
                x.append(X)
                y.append(Y)

                plt.clear()
                plt.plot_date(x, y, xdate=True, ydate=False)

a única mudança que funcionou foi essa parte do final para o xdate, mas ai  o meu código da erro de Split  ele diz que esperava por 2 valores em X, Y e só recebeu um agora eu fiquei confuso

se eu mudo no fig ou no ax1 ele diz que subplots não tem esses tributos

será que agora ele esta esperando um modelo de data no x e o que eu estou enviando não é aceito ? por isso o erro ?

 

 

Editado por Alexandre Stoiev
Link para o comentário
Compartilhar em outros sites

  • 0

acho que achei sua solução, de uma olhada

https://jakevdp.github.io/PythonDataScienceHandbook/04.10-customizing-ticks.html

3 minutos atrás, Alexandre Stoiev disse:

 X, Y = line.split(",b'")
ValueError: not enough values to unpack (expected 2, got 1)

ele esta apontando um erro antes do Split ?

 

erro meu, não olhei o append(X) ou (Y)

na mensagem de erro não aponta a linha?

Link para o comentário
Compartilhar em outros sites

  • 0
12 minutos atrás, ArteEN disse:

acho que achei sua solução, de uma olhada

https://jakevdp.github.io/PythonDataScienceHandbook/04.10-customizing-ticks.html

erro meu, não olhei o append(X) ou (Y)

na mensagem de erro não aponta a linha?

desculpe foi um erro meu eu coloquei sem querer um caractere errado no log 

12 minutos atrás, ArteEN disse:

acho que achei sua solução, de uma olhada

https://jakevdp.github.io/PythonDataScienceHandbook/04.10-customizing-ticks.html

erro meu, não olhei o append(X) ou (Y)

na mensagem de erro não aponta a linha?

quanto a este, qual você acha que resolvera meu problema ? oque elimina as legendas não serve pois eu preciso delas

vou salvar esse link pode ser muito útil essas informações de formatação mais a frente

 

estou achando que não existe uma função nesse biblioteca que ajuste as datas assim como faz com os números em float

 

Editado por Alexandre Stoiev
Link para o comentário
Compartilhar em outros sites

  • 0
13 minutos atrás, ArteEN disse:

pelo o que eu vi, tem um comando que limita a informação no eixo

veja os exemplos 7 e 8

finalmente acho que isso finalmente resolve meu problema, vou testar AGORA se funcionar você vai ser meu herói KKKK

13 minutos atrás, ArteEN disse:

pelo o que eu vi, tem um comando que limita a informação no eixo

veja os exemplos 7 e 8

Cara você é fenomenal isso realmente resolveu meus problemas ( vejamos se não vão aparecer mais KKKK) obrigado pela ajuda

Ah, faltou só uma coisa, devido a minha temperatura vir por serial ela fica salva com esse /r/n sabe como resolver isso ?

Editado por Alexandre Stoiev
Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152k
    • Posts
      651,8k
×
×
  • Criar Novo...