WPF - Refreshing UI Problems with Serial.Datareceived

Enrique Flores Fontau 1 Reputation point
2020-10-22T12:46:57.95+00:00

Hello,

I am working on an HMI with WPF and arduino through Serial Port.

Objectives (by now) are:

  • Receive data of the sensors continuously.
  • Send data to enable and disable pumps.
  • Send data with the PH limits.
  • UI must update the values of received data.
  • I made the following arduino code to test it without sensor reading.

ARDUINO SENDING:

  1. It should send every 3 seconds a value of PH, and every 5 another value of PH.

ARDUINO RECEIVING:

  • If it receives #PBA1 LED1 is ON. If it receives #PBA0 LED1 is off.
  • If it receives #PHLS, LED2 should be on. phls stores the value behind #PHLS.
  • If it receives #PHLI, LED2 should be off. phli stores the value behind #PHLI.

The arduino code is the following:

 unsigned long int TiempoAhora = 0;  
 unsigned long int TiempoDespues = 0;  
void setup() {  
  
    
 pinMode(3,OUTPUT);  
 pinMode(4,OUTPUT);  
 pinMode(5,OUTPUT);  
 Serial.begin(115200);  
   
   
}  
void loop() {  
  // put your main code here, to run repeatedly:  
  
    
  while (Serial.available()>0)  
  {  
  
     if (millis()>TiempoAhora+3000){  
      TiempoAhora= millis();  
      Serial.println("#PHTB1.8");  
      }  
     if (millis()>TiempoDespues+5000){  
      TiempoDespues= millis();  
      Serial.println("#PHTB1.6");  
     }  
  
      
    String c =Serial.readString();  
      
     
     
    if (c.indexOf("#PBA1")>=0){  
      digitalWrite(5,HIGH);  
    }  
  
    if (c.indexOf("#PBA0")>=0){  
      digitalWrite(5,LOW);  
    }  
      
    if (c.indexOf("#PHLS")>=0){  
      digitalWrite(4,HIGH);  
      String phSuperior=c.substring(5,3);  
      float phls = phSuperior.toFloat();  
        
    }  
    if(c.indexOf("#PHLI")>=0){  
      String phInferior=c.substring(5,3);  
      digitalWrite(4,LOW);  
      float phli = phInferior.toFloat();  
    }  
  
     
     
  }  
  delay(10);  
  }  

The XAML code and the UI is the following.

34305-ui-test.png

<Window x:Class="WpfSCADA.connect"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
        xmlns:local="clr-namespace:WpfSCADA"  
        mc:Ignorable="d"  
        Title="connect" Height="450" Width="800" Closing="Window_Closing">  
    <Grid>  
  
  
        <Button x:Name="connectbutton" Content="Connect" HorizontalAlignment="Left" Margin="148,146,0,0" VerticalAlignment="Top" Width="60" Height="34" Click="Connectbutton_Click" Background="#FF323232" BorderBrush="#FF4F4F4F" Foreground="#FFEAEAEA"/>  
        <ListBox x:Name="serialports" HorizontalAlignment="Left" Margin="84,182,0,100" Width="124" Background="#FF1E1E1E" BorderBrush="#FF4F4F4F" Foreground="#FFEAEAEA" FontSize="14"/>  
  
  
  
        <TextBox x:Name="txtPh" Margin="655,191,47,88" Background="#FF1E1E1E" BorderBrush="#FF4F4F4F" Foreground="#FFEAEAEA" FontSize="14"/>  
        <Label Content="PH:" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="620,195,0,0" Foreground="#FF4F4F4F"/>  
  
        <Button x:Name="btnSendPHLS" Content="Aplicar" HorizontalAlignment="Left" Margin="372,0,0,158" VerticalAlignment="Bottom" Width="126" Height="34" Click="btnPHLSSent_Click" Background="#FF323232" BorderBrush="#FF4F4F4F" Foreground="#FFEAEAEA"/>  
        <Button x:Name="btnUpdate" Content="Update" HorizontalAlignment="Left" Margin="84,146,0,0" VerticalAlignment="Top" Width="60" Height="34" Click="btnUpdate_Click" Background="#FF323232" BorderBrush="#FF4F4F4F" Foreground="#FFEAEAEA"/>  
        <TextBox x:Name="txtPhSuperior" Margin="266,231,436,157" Background="#FF1E1E1E" BorderBrush="#FF4F4F4F" Foreground="#FFEAEAEA" FontSize="14"/>  
        <Label Content="PHLS:" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="222,237,0,0" Foreground="#FF4F4F4F"/>  
        <TextBox x:Name="txtPhInferior" Margin="266,273,436,115" Background="#FF1E1E1E" BorderBrush="#FF4F4F4F" Foreground="#FFEAEAEA" FontSize="14"/>  
        <Label Content="PHLI: " HorizontalAlignment="Left" VerticalAlignment="Top" Margin="222,279,0,0" Foreground="#FF4F4F4F"/>  
        <Button x:Name="btnPBA" Content="Activar Bomba" HorizontalAlignment="Left" Margin="292,0,0,313" VerticalAlignment="Bottom" Width="126" Height="34" Click="btnPBAonoff_Click" Background="#FF323232" BorderBrush="#FF4F4F4F" Foreground="#FFEAEAEA"/>  
        <Button x:Name="btnSendPHLI" Content="Aplicar" HorizontalAlignment="Left" Margin="372,0,0,115" VerticalAlignment="Bottom" Width="126" Height="34" Click="btnPHLISent_Click" Background="#FF323232" BorderBrush="#FF4F4F4F" Foreground="#FFEAEAEA"/>  
  
    </Grid>  
</Window>  

And the c# code:

namespace WpfSCADA  
{  
     
  
    public partial class connect : Window  
    {  
        private static System.Timers.Timer aTimer;  
  
        bool pbaOn = false;  
        SerialPort mainport = new SerialPort();  
        string ReceivedData;  
        public connect()  
        {  
  
            InitializeComponent();  
            GetSerialDevices();  
            disableControls();  
  
             
        }  
  
         
  
        private void disableControls()  
        {  
            btnSendPHLS.IsEnabled = false;  
            btnSendPHLI.IsEnabled = false;  
        }  
  
        private void enableControls()  
        {  
            btnSendPHLS.IsEnabled = true;  
            btnSendPHLI.IsEnabled = true;  
        }  
  
        //this method will get all the serial devices on the computer (your computer, probably...)  
        private void GetSerialDevices()  
        {  
            foreach (string deviceport in SerialPort.GetPortNames())  
            {  
                serialports.Items.Add(deviceport);  
            }  
        }  
  
        private void ClearSerialDevices()  
        {  
            foreach (string deviceport in SerialPort.GetPortNames())  
            {  
                serialports.Items.Remove(deviceport);  
            }  
        }  
  
          
  
        private void Connectbutton_Click(object sender, RoutedEventArgs e)  
        {  
            if (!mainport.IsOpen)  
            {  
                try  
                {  
                    mainport.BaudRate = 115200;  
                    mainport.DataBits = 8;  
                    mainport.Parity = Parity.None;  
                    mainport.StopBits = StopBits.One;  
                    mainport.NewLine = "\n";  
  
                }  
                catch (Exception aaa)  
                {  
                    MessageBox.Show(aaa.Message, "Error defining variables for serial port");  
  
                }  
                try  
                {  
                    if (serialports.SelectedItem != null)  
                    {  
                        mainport.PortName = serialports.SelectedItem.ToString();  
                        mainport.Open();  
                        connectbutton.Content = "Disconnect";  
                        enableControls();  
                        mainport.DataReceived += new SerialDataReceivedEventHandler(receivePH);  
                    }  
                }  
                catch (Exception bbb)  
                {  
                    MessageBox.Show(bbb.Message, "Error defining the portname for serial port");  
  
                }  
            }  
            else if (mainport.IsOpen)  
            {  
                try  
                {  
                    mainport.Close();  
                    connectbutton.Content = "Connect";  
                }  
                catch (Exception ccc)  
                {  
                    MessageBox.Show(ccc.Message);  
                }  
            }  
        }  
  
        private void receivePH(object sender, SerialDataReceivedEventArgs e)  
        {  
            ReceivedData = mainport.ReadTo("\n");  
            if (ReceivedData.Contains("?"))  
            {  
  
            }  
            else if (ReceivedData.Contains("#PHTB"))  
            {  
                string PHTB = ReceivedData.Substring(5, 3);  
                Dispatcher.Invoke(() => txtPh.Text += PHTB);  
            }  
        }  
  
   
  
        private void btnPHLSSent_Click(object sender, RoutedEventArgs e)  
        {  
  
            try  
            {  
                string c = "#PHLS" + txtPhSuperior.Text;  
                Console.WriteLine(c);  
                mainport.Write(c);  
                  
                  
  
  
            }  
            catch (Exception sss)  
            {  
                MessageBox.Show(sss.Message, "El puerto está cerrado");  
            }  
  
        }  
        private void btnPHLISent_Click(object sender, RoutedEventArgs e)  
        {  
  
            try  
            {  
                string s = "#PHLI" + txtPhInferior.Text;  
                Console.WriteLine(s);  
                mainport.Write(s);  
  
  
            }  
            catch (Exception sss)  
            {  
                MessageBox.Show(sss.Message, "El puerto está cerrado");  
            }  
  
        }  
  
  
        private void main_Loaded(object sender, RoutedEventArgs e)  
        {  
  
  
        }  
  
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)  
        {  
            try  
            {  
                mainport.Close();  
            }  
            catch (Exception ddd)  
            {  
                MessageBox.Show(ddd.Message, "Error al cerrar el puerto serie");  
            }  
        }  
  
        private void btnUpdate_Click(object sender, RoutedEventArgs e)  
        {  
            ClearSerialDevices();  
            GetSerialDevices();  
        }  
  
        private void btnPBAonoff_Click(object sender, RoutedEventArgs e)  
        {  
            if (mainport.IsOpen)  
            {  
                if (!pbaOn)  
                {  
                    pbaOn = true;  
                    mainport.Write("#PBA1");  
                    btnPBA.Content = "Desactivar Bomba";  
                }  
                else  
                {  
                    pbaOn = false;  
                    mainport.Write("#PBA0");  
                    btnPBA.Content = "Activar Bomba";  
                }  
            }  
              
  
  
        }  
  
    }  
  
}  

Things working:

  1. It connects to the COM.
  2. It controls the LED1. When I press on the btn, it sends PBA1 and the Led is ON. If i Press again, it sends PBA0 and the Led is off.
  3. When I send the String on PHLS or PHLI txtblock the arduino switches on or off the LED2.

PROBLEM IS:

**1- I do not get the receivedData shown in the textblock unless I press a button on the UI. When I press the buttons to send the data. I get the txtPH updated with the PH received. But if i do not make any action, the data is not updated.

I will send this data every minute, and I would like to refresh the textblock, every time is received**

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,783 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. DaisyTian-1203 11,626 Reputation points
    2020-10-29T01:50:47.197+00:00

    According to the below link, Arduino need to set DtrEnable to True, to enable the DataTransmitReady flag. Otherwise the datareceived event will not firing.
    https://stackoverflow.com/questions/2281618/net-serialport-datareceived-event-not-firing
    Turns out the Adafruit SAMD51 Arduino USB driver needs DtrEnable set in order to work.
    35862-1.png


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.