Click here to Skip to main content
15,881,685 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
C#
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;


namespace Arduino
{
    public partial class Form1 : Form
    {
        bool arduinoConnected;
        bool hazardMode;
        string[] msgSplit;
        string msg;
        public Form1()
        {
            InitializeComponent();
        }
       
        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (arduinoConnected == false)
            {
                serialPort.Open();
                btnConnect.BackColor = Color.Green; 
                btnConnect.Text = "Disconnect";
                arduinoConnected = true;
                timer.Start();
            }
            else
            {
                serialPort.Close();
                btnConnect.Text = "Connect";
                btnConnect.BackColor = Color.Red;
                arduinoConnected = false;
                hazardMode = false;
                lbUpdates.Items.Add("Alarm Off");
                btnAlarm.BackColor = Color.Green;
                timer.Stop();
            }
        }

        private void btnAlarm_Click(object sender, EventArgs e)
        {
            if (serialPort.IsOpen)
            {
                if (hazardMode == false)
                {
                    hazardMode = true;
                    
                    serialPort.Write("HazardOn\n");
                    lbUpdates.Items.Add("Alarm On");
                    btnAlarm.BackColor = Color.Red;
                }
                else
                {
                    serialPort.Write("HazardOff\n");
                    hazardMode = false;
                    lbUpdates.Items.Add("Alarm Off");
                    btnAlarm.BackColor = Color.Green;
                }
            }
            else
            {
                MessageBox.Show("Please turn on the car first", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void timer_Tick(object sender, EventArgs e)
        {
            if (arduinoConnected)
            {
                lbUpdates.SelectedIndex = lbUpdates.Items.Count - 1;
                lbUpdates.SelectedIndex = -1;
                msg = serialPort.ReadLine().Trim();
                if (msg.StartsWith("Temp"))
                {
                    msgSplit = msg.Split(':');
                    tbTemp.Text = msgSplit[1];
                }
                else if (msg.StartsWith("Light"))
                {
                    msgSplit = msg.Split(':');
                    tbLights.Text = msgSplit[1];
                    if (msgSplit[1] == "ON")
                        tbLights.Text = "Headlights on";
                    else if (msgSplit[1] == "OFF")
                        tbLights.Text = "Headlights off";
                }
                else if (msg.StartsWith("LeftBlink"))
                {
                    msgSplit = msg.Split(':');
                    if (msgSplit[1] == "ON")
                        lbUpdates.Items.Add("Left Blink On");
                    else if (msgSplit[1] == "OFF")
                        lbUpdates.Items.Add("Left Blink Off");
                }
                else if (msg.StartsWith("RightBlink"))
                {
                    msgSplit = msg.Split(':');
                    if (msgSplit[1] == "ON")
                        lbUpdates.Items.Add("Right Blink On");
                    else if (msgSplit[1] == "OFF")
                        lbUpdates.Items.Add("Right Blink Off");
                }
            }
        }
    }
}


What I have tried:

I played around with the intervals of the timer and got it to work once the interval was >5000, but the issue is that I get a delayed feedback and I need it to be instant...
Posted
Updated 12-Nov-20 6:44am
v2
Comments
CHill60 12-Nov-20 12:36pm    
Probably because you are waiting on input from the port on your UI thread. That should be happening in the background. Here's a series of articles to get you started Beginners Guide to Threading in .NET: Part 1 of n[^]
TheJoKr Channel 12-Nov-20 12:41pm    
But why does the problem go away once I set the interval to 5000?
Thank you for the comment btw
CHill60 12-Nov-20 12:51pm    
Probably because by then the buffer is full so ReadLine no longer blocks - see @OriginalGriff's solution

1 solution

ReadLine is a blocking call - unless there is a complete line in the serial port input buffer, it will not return until there is. Since your Timer is active on the UI thread, that means that your whole UI cannot do anything else until that call returns.

You should not be processing input from a "slow device" (and serial ports are generally spectacularly slow) on the UI thread at all - which is one of the reasons that the "receive data available" event automatically runs on a different thread.

I would suggest spinning up a BackgroundWorker thread to handle your SerialPort data, and feed completed messages back to your UI thread via it progress reporting mechanism.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900