tspshikari
tspshikari

Reputation: 101

CPU High Usage with time for serial port

Iam currently working on a project where i have to read serial port continuously. The data is coming continuously for a max of 45 min. I have to validate the data via checksum and create a packet of 79 bytes. After this i have to plot the data(Trajectory) on a real time basis. The problem with the code is that at start it uses 20% of the CPU usage(Pentium 4, 3.0 GHz, Hyper threading)(which i think is still high) but with time the CPU usage increases and at end it reaches to 60%.

The data is coming in with a baud rate of 115200 and is sent continuously at the rate 100 msec.

My code for reading, validating and plotting is as follows: The following function receive the data and validate it...

    private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        try
        {
            header1 = serialPort1.ReadByte();
            if (header1 == 0)
                header2 = serialPort1.ReadByte();
            if ((header1 == 0) && (header2 == 1))//Store the data in an array.
            {
                for (int i = 0; i < 77; i++)
                    abudata[i] = serialPort1.ReadByte();
                tail = abudata[76];
            }
            else
            {
                serialPort1.DiscardInBuffer();
            }
            checksum = 1;// Calculate the checksum.
            for (i = 0; i < 74; i++)
                checksum = checksum + (abudata[i]);
            checksum1 = (abudata[75] << 8);
            checksum1 = checksum1 + (abudata[74]);

            if ((checksum == checksum1) && (tail == 4))
                this.Invoke(new EventHandler(Display_Results));// Function to display
        }
        catch (Exception ode)
        {
            l4[4].BackColor = Color.Red;
        }
    }

The following function display the data on labels and draw the trajectory on a picture box

    private void Display_Results(object s, EventArgs e)
    {
        head1[0] = header1;
        head1[1] = header2;
        for (k = 0; k < 77; ++k)
            head1[k + 2] = (((int)abudata[k]) & 0x000000ff);
        jk = 0;
        for (k = 0; k < 36; ++k) //Data packing into 36 bytes
        {
            num_1[k] = (ulong)((head1[jk + 1]) + (head1[jk] << 8)) & 0x0000ffff;
            num_1[k] = (double)num_1[k];
            num_2[k] = (double)num_1[k];
            jk = jk + 2;
            signbit = (int)num_1[k] >> 15;

            if (signbit == 1)
            {
                sgnval = -1;
                num_1[k] = num_1[k] - 65535;
                num_1[k] = num_1[k] * (-1.0);
            }
            else
                sgnval = 1;

            //Converting the data into engineering values

            engval[k] = Math.Round(num_1[k] * parammaxval[k] * sgnval / 32767.0, 3);

            if (k == 14)
            {
                try
                {

                    curr_x = (pictureBox2.Width / 2) + (int)((engval[13] * (pictureBox2.Width)) / map_width);
                    curr_y = (pictureBox2.Height / 2) - (int)((engval[14] * (pictureBox2.Height)) / map_height);
                    PointF p1 = new Point(curr_x, curr_y);
                    if (_gPath != null && _gPath.PointCount > 0)
                        p1 = _gPath.PathPoints[_gPath.PathPoints.Length - 1];
                    PointF p2 = new Point(curr_x, curr_y);
                    _gPath.AddLine(p1, p2);
                    pictureBox2.Invalidate();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

        }           
    }    

Upvotes: 2

Views: 3111

Answers (2)

tspshikari
tspshikari

Reputation: 101

i got what was the problem with the above code..

I am using Graph path for plotting the trajectory

if (k == 14)
{
    try
    {

        curr_x = (pictureBox2.Width / 2) + (int)((engval[13] * (pictureBox2.Width)) / map_width);
        curr_y = (pictureBox2.Height / 2) - (int)((engval[14] * (pictureBox2.Height)) / map_height);
        PointF p1 = new Point(curr_x, curr_y);
        if (_gPath != null && _gPath.PointCount > 0)
            p1 = _gPath.PathPoints[_gPath.PathPoints.Length - 1];
        PointF p2 = new Point(curr_x, curr_y);
        _gPath.AddLine(p1, p2);
        pictureBox2.Invalidate();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Now as the application continues to run, it gathers lots of graph points and hence plotting this huge number of point is consuming the resources.

Can anybody suggest me solution to this problem that how to plot the trajectory without slowing the system...

Upvotes: 1

Dmitry Romanov
Dmitry Romanov

Reputation: 14090

I extensively work with serial port connected devices and may assure you, that regular using of SerialPort class by itself doesn't produce high CPU load.

FIRST I would suggest you to PROFILE your application. There are a bunch of profilers for .NET

Only after profiling I would suggest to decouple SerialPort reading and data processing. Use Producer Consumer pattern. Put data from SerialPort to queue and consume it from other thread.

That what I have in SerialPortDataReceived function in one of my projects

    private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        lock (SyncObject)
        {
            if (!_serialPort.IsOpen) return;

            try
            {                    
                int toread = _serialPort.BytesToRead;
                byte[] bytes = new byte[toread];
                _serialPort.Read(bytes, 0, toread);

               ProducerAddBytes(bytes);
            }
            catch (TimeOutException)
            {
                //logic
            }
        }
    }

P.S. But PROFILE FIRST!

Upvotes: 4

Related Questions