Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doing something while receiving data from serial port in WPF

I want to create program, that will color ellipse in any way depending on the received data in "real time". The data is like: x1-1, x2-1 etc.

I have strange problem, I can see while debugging that, color of filling ellipse should change, but it doesn't happen.

Part of my code with receiving data:

 private void ReceiveData()
            {
                SerialPort serialPort = new SerialPort("COM1", 9600);
                serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
                serialPort.Open();
            }

 private static void DataReceivedHandler(
                object sender,
                SerialDataReceivedEventArgs e)
            {
                SerialPort sp = (SerialPort)sender;
                string indata = sp.ReadExisting();
                if (indata.Contains(" "))
                {
                    testString = indata.Substring(0, 4);

                }
                Console.Write(indata);
            }

I can see received data in console, even after click on button, that starts receiving data. The testString is to extract single x1-1 from indata, that is still growing during receiving data. I know that it doesn't work like it should but it doesn't matter now.

Code of action on button:

 private void button1_Click(object sender, RoutedEventArgs e)
        {
            ReceiveData();
            while (true)
            {
                if (testString == "x1-1") x1.Fill = Brushes.Blue;
                else x1.Fill = Brushes.Red;
            }
        }

x1 is ellipse that I want to make red or blue. I can set the breakpoint in this function and I can see that it should change. I think the problem is, that program is waiting for close port and finish transmission, and then maybe it would change, but I need to have it in "real time". Anyone knows how to do it?

like image 963
Vades Avatar asked Apr 08 '26 00:04

Vades


1 Answers

I believe you are going about this the wrong way. Instead of constantly checking the value of teststring you need to just start the comm port listener and let it run in the background - as this will be on it's own thread. Then you need to create a Data Binding to the color. Whenever the comm port listener parses a string, it can automatically update the color.

First, in the CommPort class:

class MyCommPort : INotifyPropertyChanged
{
    SerialPort serialPort = null;
    public MyCommPort()
    {
        serialPort = new SerialPort("COM3", 9600);
        serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
        serialPort.Open();
    }
    ~MyCommPort()
    {
        serialPort.Close();
    }

    private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        string testString = null;
        string indata = sp.ReadLine();
        if (indata.Length >= 4)
        {
            testString = indata.Substring(0, 4);
            // Update the value
            if (testString == "x1-1") EllipseBrush = Brushes.Blue;
            else EllipseBrush = Brushes.Red;
        }
        Console.Write(testString);
    }

    // Create a property that will be bound
    private SolidColorBrush ellipseBrush = Brushes.Red;
    public SolidColorBrush EllipseBrush
    {
        get { return ellipseBrush; }
        set
        {
            ellipseBrush = value;
            OnPropertyChanged("EllipseBrush");
        }
    }

    // Extend the INotifyPropertyChanged interface
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            // Alert anyone bound to this that the value has changed
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Then, set the Ellipse's DataContext to the CommPort class and bind the Ellipse's Fill property to EllipseBrush. Now all you have to do is start the Commport listener (ReceiveData();) and the color updates should happen automatically.

For example: MainWindow.xaml

<Window x:Class="delete_me.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Ellipse x:Name="ellipse" Fill="{Binding Path=EllipseBrush}" />
    </Grid>
</Window>

And the code behind: MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        ellipse.DataContext = new MyCommPort();
    }
}
like image 159
Johnny Mopp Avatar answered Apr 09 '26 12:04

Johnny Mopp