LusoRobótica - Robótica em Português

Software => C# => Tópico iniciado por: ivitro em 14 de Maio de 2015, 11:27

Título: Ajuda - Gráfico tempo real porta série
Enviado por: ivitro em 14 de Maio de 2015, 11:27
Olá a todos,

Estou a fazer um projeto pessoal que consiste em receber dados da porta serie para fazer um gráfico.

Os meus requisitos são:

A ideia é ter mais ou menos aquilo que está na imagem em anexo.

Neste momento já tenho os dados a serem impressos numa caixa de texto mas ainda não consegui desenhar no gráfico.

Deixo o que tá feito do projeto no seguinte link https://www.dropbox.com/sh/t39pctffom6b4z9/AADihedKxFOOcvUthHE94gAaa?dl=0 (https://www.dropbox.com/sh/t39pctffom6b4z9/AADihedKxFOOcvUthHE94gAaa?dl=0)

O código principal é este:

Código: [Seleccione]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Windows.Forms.DataVisualization.Charting;


namespace serial_rx_tx_opt_chart
{
    public partial class Form1 : Form
    {

        //delegate void SetTextCallback(string indata);
        //delegate void SetTextCallback( );

        double t = 0;
        public string indata;

        public Form1()
        {
            InitializeComponent();

            Control.CheckForIllegalCrossThreadCalls = false;//evita error de sobrecarga

            chart1.Titles.Add("Informação Gráfica");

            //preenchimento da combobox da velocidade
            cboBaudRate.Items.Add(300);
            cboBaudRate.Items.Add(600);
            cboBaudRate.Items.Add(1200);
            cboBaudRate.Items.Add(2400);
            cboBaudRate.Items.Add(9600);
            cboBaudRate.Items.Add(14400);
            cboBaudRate.Items.Add(19200);
            cboBaudRate.Items.Add(38400);
            cboBaudRate.Items.Add(57600);
            cboBaudRate.Items.Add(115200);

            //preenchimento da combobox da data bits
            cbDatabits.Items.Add(7);
            cbDatabits.Items.Add(8);

            //preenchimento da combobox paraidade
            foreach (string s in Enum.GetNames(typeof(Parity)))
            {
                cbParity.Items.Add(s);
            }

            //preenchimento da combobox de controlo
            foreach (string s in Enum.GetNames(typeof(Handshake)))
            {
                cbHandshake.Items.Add(s);
            }

            foreach (string s in Enum.GetNames(typeof(StopBits)))
            {
                cbStopbit.Items.Add(s);
            }

            string[] ArrayComPortsNames = SerialPort.GetPortNames();

            if (!(ArrayComPortsNames.Length == 0))
            {
                // Display each port name to the console.
                foreach (string port in ArrayComPortsNames)
                {
                    cboPorts.Items.Add(port);
                }
            }
       
        }

        private void bConnect_Click(object sender, EventArgs e)
        {
            if (bConnect.Text == "Ligar")
            {
                try
                {
                   
                    // Allow the user to set the appropriate properties.
                    ComPort.PortName = cboPorts.SelectedItem.ToString();
                    ComPort.BaudRate = int.Parse(cboBaudRate.SelectedItem.ToString());
                    ComPort.Parity = (Parity)Enum.Parse(typeof(Parity), cbParity.SelectedItem.ToString());
                    ComPort.DataBits = int.Parse(cbDatabits.SelectedItem.ToString());
                    ComPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cbStopbit.SelectedItem.ToString());
                    ComPort.Handshake = (Handshake)Enum.Parse(typeof(Handshake), cbHandshake.SelectedItem.ToString());

                    ComPort.ReadTimeout = 500;
                    ComPort.WriteTimeout = 500;

                    ComPort.Open();
                   
                    bConnect.Text = "Desligar";

                }
                catch{
                   
                }
               
            }
            else {
                try
                {
                    ComPort.Close();
                    bConnect.Text = "Ligar";
                }
                catch { }
               
            }
        }

        private void btRxClear_Click(object sender, EventArgs e)
        {
            tbRx.Text = "";
        }

        private void btTxSend_Click(object sender, EventArgs e)
        {
            if(ComPort.IsOpen){
                ComPort.WriteLine(tbTx.Text);
                tbTx.Text = "";
            }
           
        }

        Boolean i = false;
        private void ComPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {

            //inicia el timer1 para que sea cero cuando se recibe el primer dato
            if (i == false)
            {
                t = 0;
                i = true;
            }


            indata = ComPort.ReadExisting();
            chart1.Series[0].Points.AddXY(t, Math.Sin(t));
           
        }
        public void SetText(object sender, EventArgs e)
        {

            tbRx.AppendText(indata);       
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            t = t + 0.1;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (ComPort.IsOpen) ComPort.Close();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            timer1.Start();

        }

    }
}

Desde já obrigado pela ajuda.
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: metRo_ em 14 de Maio de 2015, 14:18
Eu diria que a seguir a adicionares os dados ao gráfico deve existir uma função para redesenhar o gráfico, começa por tentar desenhar um gráfico com dados estáticos.
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: ivitro em 14 de Maio de 2015, 14:38
Segundo outra aplicação em que me baseio ao adicionar dados à série ele faz a atualização do gráfico sozinho.

Agora na outra aplicação está a funcionar, na minha não mostra as linhas do gráfico.

os dados estão a ser enviados de 1 em 1 ms.
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: metRo_ em 14 de Maio de 2015, 14:53
Segundo outra aplicação em que me baseio ao adicionar dados à série ele faz a atualização do gráfico sozinho.

Agora na outra aplicação está a funcionar, na minha não mostra as linhas do gráfico.

os dados estão a ser enviados de 1 em 1 ms.

Tenta criar uma aplicacao em que apenas mostras um grafico.
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: ivitro em 14 de Maio de 2015, 14:58
Olha vê esta aqui:

https://www.dropbox.com/sh/t1e3ng7tcps28zt/AACOKyI1_GdkheOFxaXwwuCwa?dl=0 (https://www.dropbox.com/sh/t1e3ng7tcps28zt/AACOKyI1_GdkheOFxaXwwuCwa?dl=0)

Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: metRo_ em 14 de Maio de 2015, 15:10
Queres que veja o que?
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: ivitro em 14 de Maio de 2015, 15:20
Esse é o código de só apresentar o gráfico.

Se quiseres testar. ;)
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: metRo_ em 14 de Maio de 2015, 15:28
Tu ja testaste?
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: ivitro em 14 de Maio de 2015, 15:37
Sim, claro...


E funciona... faz o gráfico que é o que interessa.

Mas na aplicação que eu quero que funcione não está a dar.
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: senso em 14 de Maio de 2015, 15:50
Pode ser tanta coisa....
Ou não lhe estão a chegar dados, estão a ser mal interpretados, tens um erro na parte do gráfico.
Dai o metro dizer, mete dados estáticos e vê se dá!
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: ivitro em 14 de Maio de 2015, 17:16
Já consegui resolver parte do problema.

Mas queria saber como faço o gráfico ter uma janela de tempo fixa.

Neste momento ao desenhar o gráfico ele vai acrescentando pontos infinitamente, queria que ele só tivesse o últimos 10 segundos de histórico.

 
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: senso em 14 de Maio de 2015, 17:17
Adicionas o "ultimo" ponto e apagas o primeiro.
Não faço ideia como funciona essa função do gráfico, mas basicamente podes usar um buffer circular e fazes só o plot desse gráfico.
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: ivitro em 14 de Maio de 2015, 17:41
Então crio o buffer e depois faço o update do gráfico de x em x tempo.
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: ivitro em 20 de Maio de 2015, 10:19
Boas,

O gráfico já funciona e desliza tal como eu queria.

Agora quanto à prestação da aplicação queria saber a vossa opinião sobre a periocidade de envio dos dados.

Ao enviar dados em intervalos de 1ms a aplicação chega a um ponto e deixa de funcionar bem (julgo que me falta qualquer coisa sobre libertação de memoria).

Mas o quero mesmo saber é que intervalo de tempo acham admissível para enviar dados?

PS: não vale dizer que depende da aplicação, preciso de um valor aceitável e que funcione bem em grande parte do casos.
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: Njay em 20 de Maio de 2015, 10:34
Lol... Como é óbvio, depende da aplicação :) . 1ms parece-me mesmo muito muito muito frequente, só que eu não sei qual é a tua aplicação, pode justificar-se.

Libertação de memória? O C# não tem garbage colector?
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: senso em 20 de Maio de 2015, 10:43
Se estiver sempre a alocar memória e mantiver tudo no plot provavelmente o C# não vai lá chegar e tirar pontos do gráfico.
Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: ivitro em 20 de Maio de 2015, 11:01
Lol... Como é óbvio, depende da aplicação :) . 1ms parece-me mesmo muito muito muito frequente, só que eu não sei qual é a tua aplicação, pode justificar-se.

Libertação de memória? O C# não tem garbage colector?

Então achas que se meter 1ms tá fixe? aplicação neste momento não há. A ideia é ter isto como um pequena ferramenta de trabalho... à pouco tempo fiz o controlo de um motor e senti a necessidade de ter algo que me fizesse um gráfico para optimizar o controlador.

Isso da libertação de memoria terei que ver não faço ideia só com mais testes.

Se estiver sempre a alocar memória e mantiver tudo no plot provavelmente o C# não vai lá chegar e tirar pontos do gráfico.

O gráfico tá a deslizar e não tem scroll bar horizontal por isso penso que não fique lá nada.

Título: Re: Ajuda - Gráfico tempo real porta série
Enviado por: Njay em 20 de Maio de 2015, 11:32
Então achas que se meter 1ms tá fixe? aplicação neste momento não há. A ideia é ter isto como um pequena ferramenta de trabalho... à pouco tempo fiz o controlo de um motor e senti a necessidade de ter algo que me fizesse um gráfico para optimizar o controlador.
Não sei se tá fixe, depende da aplicação. Para um gráfico com display em tempo real parece-me demasiado, 1ms são 1000 pixeis por segundo, um "ecran" inteiro por segundo, isso parece-me demasiado rápido para se ter tempo de tirar muita informação relevante visualmente. Se for para logar e ver depois (que é se calhar o que tu queres no caso do motor) não estranho o valor de 1ms. Também podes logar a 1ms e mostrar no gráfico apenas 1 em 100 amostras. Mas dizer que a aplicação é um gráfico para optimizar um controlador continua a ser muito vago. Tem que se usar a frequência de amostragem que capture aquilo que se quer ver; se for temperatura se calhar bastam 2Hz, se for corrente no motor se calhar 20Hz, se for as quedas de tensão nos condensadores se calhar 5MHz...