Employers - Post Free Jobs
Forum guidelines
AuthorQuestion
C# form rs232 COM-port application
Posted on: 20 Feb 2012
We would like to create a program that counts how many times a "high" signal is received from a RS232 (COM) port.

4 signals have been hooked up to a rs232 connector and a form application will be used to count how many of each signals have been received..

Because of the fact that I'm a bit of a C# newbie, this isn't as easy as I had hoped.
What the program has to do:

- The form has 4 textboxes to show a counter for each pin
- One start button
- One stop button
- When the start button is pushed, the program opens a COM-connection and starts to get data from the com port
- When a high signal is received on one of the ports
- An event trigger will start and update 1 of 4 textboxes
- In my example below, I first want to try to fill 1 textbox with a value, but I keep getting the following errors:

* An object reference is required for the non-static field, method, or property 'System.Windows.Forms.Control.Text.get'

* Next to that when I run a similar (same) program in a console application, when the event is triggered it outputs "Pin x" to the console. It gets triggered 100.000 times it seems.. It keeps outputting, but
the signal only changes once per 5 seconds.

I hope you guys understand my problem and hope you can help me. Thanks in advance!

This is what I have so far..

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;


namespace
WindowsFormsApplication1
{
public partial class Form1 :
Form
{
public Form1()
{
InitializeComponent();
}

private
void button1_Click(object sender, EventArgs e)
{
SerialPort port = new
SerialPort("COM3", 9600, Parity.None, 8, StopBits.One); // Instantiate the
communications // port with some basic settings
port.Open(); // Open the port
for communications

while (true)
{
if
(Buttonstop==1)
{
port.Close(); // Close the
port
break;
}
port.PinChanged += new
SerialPinChangedEventHandler(port_PinChanged); // Nieuwe event
trigger
}
}

public static void port_PinChanged(object sender,
SerialPinChangedEventArgs e) // This will be called whenever the port
changes.
{
string info = string.Empty;
switch
(e.EventType)
{
case SerialPinChange.CDChanged:
Form1.textBox3.Text =
"Pin 1";
break;
case SerialPinChange.CtsChanged:
Form1.Text = "Pin
8";
break;
case SerialPinChange.DsrChanged:
Form1.textBox3.Text = "Pin
6";
break;
case SerialPinChange.Ring:
Form1.textBox3.Text = "Pin
9";
break;
default:
break;
}
}
}
}

AuthorReply
Re: C# form rs232 COM-port application
Posted on: 20 Feb 2012  
Well you're getting the error because textBox3 is an instance member of Form1, not a static member of it.

You therefore either need to precede it with 'this' or with nothing at all.

Also you can't access an instance member from a static method so you'll need to change the PinChanged handler from static to instance. I'd also make it private rather than public which is the usual case for eventhandlers.

Another problem is that the PinChanged event is called on a secondary thread, not on the user interface thread. Consequently, if you need to change the state of a control such as a textbox you need to marshal the call back to the UI thread using the Invoke method.

I'd therefore rewrite your PinChanged eventhandler as follows to get past that particular error.

I've also rewritten your other code so that it's now more in keeping with a Windows Forms application than a console application :

public partial class Form1 : Form
{
   private SerialPort port; // use private field for SerialPort

   public Form1()
   {
      InitializeComponent();
      // Instantiate the communication port field with some basic settings
      port = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One); // now instantiates field
      port.PinChanged += new SerialPinChangedEventHandler(port_PinChanged); // Nieuwe event trigger for communications
      button2.Enabled = false; // disable close button
   }

   private void button1_Click(object sender, EventArgs e)
   {
      port.Open(); // Open the port
      button2.Enabled = true; // enable close button
      button1.Enabled = false; // disable open button 
   }

   private void button2_Click(object sender, EventArgs e)
   {
      port.Close(); // Close the port
      button1.Enabled = true; // enable open button
      button2.Enabled = false; // disable close button 
   }

   private void port_PinChanged(object sender, SerialPinChangedEventArgs e) // static removed, changed to private
   {
      string info = string.Empty; // cache pin number in this variable so you only have to use marshalling code once

      switch (e.EventType)
      {
        case SerialPinChange.CDChanged:
           info = "Pin 1";
           break;
        case SerialPinChange.CtsChanged:
           info = "Pin 8";
           break;
        case SerialPinChange.DsrChanged:
           info = "Pin 6";
           break;
        case SerialPinChange.Ring:
           info = "Pin 9";
           break;
        default:
           break;
     }

    this.Invoke(new MethodInvoker(delegate() 
    { 
        this.textBox3.Text = info;
    })); 
 }

}


Re: C# form rs232 COM-port application
Posted on: 12 Jul 2012  
I see now that I forgot to thank you for your answer. It was really helpfull. I had to create some hardware to make things work, but now I'm running into additional problems. Below is what I made of the code.

The counting goes well, but it has some strange bugs. When a trigger is received the "ring" it counts, as it is supposed to. When after that a trigger is received from the "cts", it also triggers the "ring" it seems. Resulting in a double textbox update. TxtGeen and TxtZwaar.

I had similar problems with other cells, but I solved them with a workaround. I check if a trigger has been received less than 1 ms ago. If so somehow this is a wrong trigger, therefore don't execute the code.

I know I only get 1 signal from the hardware. Cause when I trigger the same pin continiously, the counting is correct. I will double check this by measuring next week, just to be sure.

Can it somehow be that a trigger of the ring is "buffered" or stuck somewhere and gets triggered after triggering cts? It sounds and seems very weird to me. But that is what seems to happen.

I hope you guys somehow have an explanation for this and hoping for a mistake in my code.. Thanks in advance..

using System;
using System.IO;
using System.IO.Ports;
using System.Management;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Media;
using System.Data.SqlServerCe;
using System.Diagnostics;

namespace WindowsFormsApplication2
{
    public partial class Blauwteller : Form
    {
        private SerialPort port;

        // Deze tijd (milliseconden) is om onterechte dubbele tellingen te voorkomen. Ook kunnen er geen meer aardappelen per tijdsinterval worden geteld.
        int AllowedTimeBetweenTicks = 200;

        private int AantalGeen = 0;
        private int AantalLicht = 0;
        private int AantalMatig = 0;
        private int AantalZwaar = 0;

        private int TicksPreviousCD = Environment.TickCount;
        private int TicksPreviousCTS = Environment.TickCount;
        private int TicksPreviousDSR = Environment.TickCount;
        private int TicksPreviousRing = Environment.TickCount;

        public Blauwteller()
        {
            InitializeComponent();

            Reset();

            txtMatig.Enabled = false;
            txtLicht.Enabled = false;
            txtZwaar.Enabled = false;
            txtGeen.Enabled = false;
            txtBlauwIndex.Enabled = false;

            try
            {
                string[] theSerialPortNames = System.IO.Ports.SerialPort.GetPortNames();
                string RemovePort = "COM1";
                theSerialPortNames = theSerialPortNames.Where(val => val != RemovePort).ToArray();
                RemovePort = "COM2";
                theSerialPortNames = theSerialPortNames.Where(val => val != RemovePort).ToArray();
                string UsbToSerialPort = null;
                UsbToSerialPort = theSerialPortNames[0];

                // Nieuwe instantie van de communicatie poort
                port = new SerialPort(UsbToSerialPort, 9600, Parity.None, 8, StopBits.One);
                port.PinChanged += new SerialPinChangedEventHandler(port_PinChanged); // Nieuwe event trigger voor communicatie
            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("Kabel is niet aangesloten, sluit de kabel aan");
            }
        }

        private void port_PinChanged(object sender, SerialPinChangedEventArgs e)
        {
            switch (e.EventType)
            {
                case SerialPinChange.CtsChanged:
                    if ((Environment.TickCount - TicksPreviousDSR) > 1 && (Environment.TickCount - TicksPreviousRing) > 1 && (Environment.TickCount - TicksPreviousCD) > 1)
                    {
                        if ((Environment.TickCount - TicksPreviousCTS) > AllowedTimeBetweenTicks)
                        {
                            AantalMatig++;
                            this.Invoke(new MethodInvoker(delegate()
                            {
                                this.txtGeen.Text = Convert.ToString(AantalMatig);
                            }));
                            TicksPreviousCTS = Environment.TickCount;
                        }
                    }
                  
                    break;
                case SerialPinChange.DsrChanged:
                    if ((Environment.TickCount - TicksPreviousCTS) > 1 && (Environment.TickCount - TicksPreviousRing) > 1 && (Environment.TickCount -TicksPreviousCD) > 1)
                    {
                        if ((Environment.TickCount - TicksPreviousDSR) > AllowedTimeBetweenTicks)
                        {
                   
                        AantalLicht++;
                        this.Invoke(new MethodInvoker(delegate()
                        {
                            this.txtLicht.Text = Convert.ToString(AantalLicht);
                        }));
                        TicksPreviousDSR = Environment.TickCount;
                        }
                    }
                    break;
                case SerialPinChange.CDChanged:
                    if ((Environment.TickCount - TicksPreviousCTS) > 1 && (Environment.TickCount - TicksPreviousRing) > 1 && (Environment.TickCount -TicksPreviousDSR) > 1)
                    {
                        if ((Environment.TickCount - TicksPreviousCD) > AllowedTimeBetweenTicks)
                        {
                            AantalGeen++;
                            this.BeginInvoke(new MethodInvoker(delegate()
                            {
                                this.txtMatig.Text = Convert.ToString(AantalGeen);
                            }));
                            TicksPreviousCD = Environment.TickCount;
                        }
                    }
                   break;
                case SerialPinChange.Ring:
                       if ((Environment.TickCount - TicksPreviousDSR) > 1 && (Environment.TickCount - TicksPreviousCD) > 1 && (Environment.TickCount - TicksPreviousCTS) > 1)
                       {
                           if ((Environment.TickCount - TicksPreviousRing) > AllowedTimeBetweenTicks)
                           {
                               AantalZwaar++;
                               this.Invoke(new MethodInvoker(delegate()
                               {
                                   this.txtZwaar.Text = Convert.ToString(AantalZwaar);
                               }));
                               TicksPreviousRing = Environment.TickCount;
                           }
                       }
                break;
                default:
                break;
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                // Poort openen
                port.Open();   

                if (txtVeld.Text.ToString() == "")
                {
                    MessageBox.Show("Er is geen veld waarde ingevuld.");
                    port.Close();
                    return;
                }

                if (txtVeld.Text.ToString() == "")
                {
                    MessageBox.Show("Er is geen veld ingevuld.");
                    port.Close();
                    return;
                }

                // Knoppen (on)zichtbaar maken
                btnStop.Show();
                btnStart.Hide();
                btnReset.Hide();

                comboBestand.Enabled = false;
                txtVeld.Enabled = false;

            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("Kabel is niet aangesloten, sluit de kabel aan");
                Reset();
                return;
            }
        }
       
        private void btnStop_Click(object sender, EventArgs e)
        {
            try
            {
                // Knoppen (on)zichtbaar maken
                btnStart.Show();
                btnReset.Show();
                btnOpslaan.Show();
                btnOverzicht.Show();
                btnStop.Hide();

                // Poort sluiten
                port.Close();  
            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("Kabel is niet meer aangesloten, sluit de kabel aan");
            }
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            Reset();
        }

        private void btnOverzicht_Click(object sender, EventArgs e)
        {
            try
            {
                string Datum = String.Format("{0:yyyy-MM-dd}", DateTime.Now); 
                string textfile;
                textfile = ".\\" + Datum + " " + comboBestand.Text.ToString() + ".txt";
                System.Diagnostics.Process.Start(textfile);
            }
            catch (Exception)
            {
                System.Windows.Forms.MessageBox.Show("Er zijn nog geen metingen gedaan in dit bestand");
            }

        }

        private void btnOpslaan_Click(object sender, EventArgs e)
        {
            string Waarden;
            Waarden = " " + txtVeld.Text.PadRight(14) + txtGeen.Text.PadRight(14) + txtLicht.Text.PadRight(14) + txtMatig.Text.PadRight(14) + txtZwaar.Text.PadRight(14) + txtBlauwIndex.Text.PadRight(14);

            if ((Convert.ToDouble(txtMatig.Text) + Convert.ToDouble(txtLicht.Text) + Convert.ToDouble(txtZwaar.Text) + Convert.ToDouble(txtGeen.Text)) == 0)
            {
                MessageBox.Show("Er zijn geen aardappelen geteld");
            }
            else if (txtVeld.Text == "")
            {
                MessageBox.Show("Er is geen veldnummer ingevoerd");
            }
            else
            {
                WriteData(comboBestand.Text.ToString(), Waarden);
                MessageBox.Show("Gegevens opgeslagen");
                Reset();
            }
        }

        private void btnBeheren_Click(object sender, EventArgs e)
        {
            new frmBestanden().Show();
        }

        private void txtZwaar_TextChanged(object sender, EventArgs e)
        {
            double BlauwIndex = CalculateBlueIndex();
            txtBlauwIndex.Text = BlauwIndex.ToString();
        }

        private void txtMatig_TextChanged(object sender, EventArgs e)
        {
            double BlauwIndex = CalculateBlueIndex();
            txtBlauwIndex.Text = BlauwIndex.ToString();
        }

        private void txtLicht_TextChanged(object sender, EventArgs e)
        {
            double BlauwIndex = CalculateBlueIndex();
            txtBlauwIndex.Text = BlauwIndex.ToString();
        }

        private void txtGeen_TextChanged(object sender, EventArgs e)
        {
            double BlauwIndex = CalculateBlueIndex();
            txtBlauwIndex.Text = BlauwIndex.ToString();
        }

        private void Blauwteller_Activated(object sender, EventArgs e)
        {
            string DbConn = "Data Source=" + Convert.ToString(Environment.CurrentDirectory) + "\\Database1.sdf";
            // Open connection
            using (SqlCeConnection c = new SqlCeConnection(DbConn))
            {
                c.Open();
                // Create new DataAdapter
                using (SqlCeDataAdapter a = new SqlCeDataAdapter(
                    "SELECT ProefveldNaam FROM tblProefvelden order by ProefveldNaam", c))
                {
                    SqlCeCommandBuilder commandBuilder = new SqlCeCommandBuilder(a);

                    DataTable t = new DataTable();
                    a.Fill(t);
                    comboBestand.DataSource = t;
                    comboBestand.DisplayMember = "ProefveldNaam";
                }
            }

            string textfile;
            textfile = "c:\\" + comboBestand.Text.ToString() + ".txt";
            Process[] processes;
            string procName = "Notepad";
            processes = Process.GetProcessesByName(procName);
            try
            {
                foreach (Process proc in processes)
                {
                    proc.CloseMainWindow();
                    proc.WaitForExit();
                }
            }
            catch (System.NullReferenceException)
            {
                MessageBox.Show("No instances of Notepad running.");
            }
        }

        private double CalculateBlueIndex()
        {
            double AantalMatig = 0;
            double AantalLicht = 0;
            double AantalZwaar = 0;
            double AantalGeen = 0;
            double TotaalAantal = 0;
            double BlauwIndex = 0;

            if (txtMatig.Text != "") { AantalMatig = Convert.ToDouble(txtMatig.Text); }
            if (txtLicht.Text != "") { AantalLicht = Convert.ToDouble(txtLicht.Text); }
            if (txtZwaar.Text != "") { AantalZwaar = Convert.ToDouble(txtZwaar.Text); }
            if (txtGeen.Text != "") { AantalGeen = Convert.ToDouble(txtGeen.Text); }

            TotaalAantal = AantalLicht + AantalMatig + AantalZwaar + AantalGeen;
            BlauwIndex = 0;
            if (TotaalAantal != 0)
            {
                BlauwIndex = (((AantalLicht / TotaalAantal) + (2 * (AantalMatig / TotaalAantal)) + (3 * (AantalZwaar / TotaalAantal))) / 6) * 100;
            }
            else
            {
                BlauwIndex = 0;
            }
            return Math.Round(BlauwIndex, 0);
        }

        private void Reset()
        {
            txtMatig.Text = Convert.ToString(0);
            txtLicht.Text = Convert.ToString(0);
            txtZwaar.Text = Convert.ToString(0);
            txtGeen.Text = Convert.ToString(0);
            txtVeld.Text = "";
            txtBlauwIndex.Text = Convert.ToString(0);

            AantalGeen = 0;
            AantalLicht = 0;
            AantalMatig = 0;
            AantalZwaar = 0;

            // Deze variabelen worden gebruikt om te voorkomen dat er 2 x wordt getriggered bij 1 x detectie van de sensor
            TicksPreviousCD = Environment.TickCount;
            TicksPreviousCTS = Environment.TickCount;
            TicksPreviousDSR = Environment.TickCount;
            TicksPreviousRing = Environment.TickCount;

            btnStop.Hide();
            btnReset.Hide();
            btnOpslaan.Hide();
            btnOverzicht.Hide();

            comboBestand.Enabled = true;
            txtVeld.Enabled = true;
        }

        private void WriteData(string textfile, string str)
            {
                string Datum = String.Format("{0:yyyy-MM-dd}", DateTime.Now); 
                string text = ".\\" + Datum + " " + textfile + ".txt";
                FileStream fs = new FileStream(text, FileMode.Append, FileAccess.Write);
                StreamWriter sw = new StreamWriter(fs);
                sw.WriteLine(str);
                sw.Flush();
                sw.Close();
                fs.Close();
            }

        private void txtVeld_Leave(object sender, EventArgs e)
        {
            string textfile = comboBestand.Text.ToString();
            string Datum = String.Format("{0:yyyy-MM-dd}", DateTime.Now);
            string text = ".\\" + Datum + " " + textfile + ".txt";

            if (File.Exists(text))
            {
                Boolean b1 = false;

                StreamReader reader = File.OpenText(text);

                while (!reader.EndOfStream)
                {
                    string currentLine = reader.ReadLine();
                    string[] split = currentLine.Split();
                    string waarde = split[1];

                    if (waarde == txtVeld.Text.ToString())
                    {
                        b1 = true;
                    }
                }

                if (b1 == true)
                {
                    MessageBox.Show("Veldnummer bestaat al in huidig bestand");
                    txtVeld.Focus();
                }
            }
        }
    }
}







Re: C# form rs232 COM-port application
Posted on: 12 Jul 2012  
Well, I can't see any obvious problems with the code so it does seem that (for whatever reason) the PinChanged event is firing twice in quick succession when a trigger is received from the "cts".

However, there is an easy way to block the unwanted "ring" call to the eventhandler:

  private bool alreadyEntered = false; // add this private field

  private void port_PinChanged(object sender, SerialPinChangedEventArgs e)
  {
      if (alreadyEntered)
      {
         alreadyEntered = false;
         return;
      }

      switch (e.EventType)
      {
          case SerialPinChange.CtsChanged:
   
             alreadyEntered = true; // if it gets this far alreadyEntered must be false

         // rest of method


However, this assumes that the event will always be fired twice when a "cts" trigger is received.

If that's not the case, then you need to impose a time limit after which a subsequent firing is regarded as a new trigger which is in effect what you're doing already.

Re: C# form rs232 COM-port application
Posted on: 12 Jul 2012  
Hi, Speaking as a Hardware guy it might be due to the signal itself, if the CTS and RI cables are parallel and not in a cable form (twisted) it might be that the sudden change in the Ring line (ringing!) could cause a parasitic rise in the CTS. You can get around this with some low value decoupling cap on the Ring Ind line. (had a similar problem myself a little while ago!) Glenn
Re: C# form rs232 COM-port application
Posted on: 12 Jul 2012  
That could be a possibility, but wouldn't it happen everytime the ring triggers then? It only happens when I've had a ring trigger and afterwards a cts trigger. My counter then counts a cts, as it it supposed to, but also counts a ring. So there also seems to be a trigger.
Re: C# form rs232 COM-port application
Posted on: 13 Jul 2012  
Hi,
It really is only a problem with rapidly changing signals, I was thinking the Ring line might be oscillating ringing if you will, the problem I had was to do with a 555 chip triggering the RI line when tripped, a decoupling cap cured it!
Best of luck Glenn
 

Re: C# form rs232 COM-port application
Posted on: 13 Jul 2012  
Thx for thinking with me. But in my case it it not a rapid changing signal, even after half a minute it still happens. I found that a com port also has some kind of buffer. I don't know if it is relevant in my case, but I will try to clear that everytime I've had a trigger. Maybe that does the trick. Also I'll test if my hardware makes some kind of mistake. Next to that I use a usb to rs232 cable, so it is also possible that it goes wrong there somehow. Next week I'll know more. I will keep you guys updated. Too bad I can't test it till next wednesday.. :)
Re: C# form rs232 COM-port application
Posted on: 13 Jul 2012  
Hi,
No problem, always annoying when you have to wait for hardware to test your software.  I am in that situation myself at the moment! USB to Serial don't expect a major change but the RI pin tends to handled differently, it can cause confusion at first but you can code around most problems once you are aware there their.
Glenn

Employers - Post Free Jobs

SPONSORED BY

Offshore Software and Database Development
MCN is your source for developing solutions involving websites, mobile apps, cloud-computing, databases, BI, back-end services and processes and client-server applications.