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:
- 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.
<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:
- It connects to the COM.
- 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.
- 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**