4

I am new in C# and trying to develop windows form project of RS-485 water pressure sensor. From my code when I Write only one command of sensor and read, it works properly. But when I write all command and try to execute it is not working properly. In my code DatafromCOM is global variable with string value and in Timer I wrote a code for write sensor command. Can you please give me some solution for this I am trying to do this for one week and I can not found solution for this. My code is below

 private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
 {
     while (serialPort1.BytesToRead != 0)
     {
         DatafromCOM = serialPort1.ReadLine();
     } 
}

private void timer1_Tick(object sender, EventArgs e)
{ 
     string cmdCurrent = "D0107012A0C";
     string cmdCrntTW = "D0107022B4C";
     string cmdVer = "D010703EB8D";
     string cmdConf = "D01070429CC";
     string cmdAdd = "D010705E90D";
     string cmdCorr = "D020B10";
     string cmdAvg = "D011011";
     string cmdLvlCor = "D010B12";
     string cmdGrvty = "D010B14";

     serialPort1.Write(cmdCrntTW + NewLine);
     serialPort1.Write(cmdVer + NewLine);
     serialPort1.Write(cmdConf + NewLine);
     serialPort1.Write(cmdAdd + NewLine);
     serialPort1.Write(cmdCorr + NewLine);
     serialPort1.Write(cmdCorr + NewLine);
     serialPort1.Write(cmdAvg + NewLine);
     serialPort1.Write(cmdAvg + NewLine);
     serialPort1.Write(cmdLvlCor + NewLine);
     serialPort1.Write(cmdGrvty + NewLine);

     txtKQ.Text += DatafromCOM + Environment.NewLine;
 }
Héctor M.
  • 2,302
  • 4
  • 17
  • 35
niksan karkee
  • 157
  • 1
  • 17
  • 1
    It would help if you posted more detail. Do you have a link to an API? Is this running on windows? Etc... – P.Brian.Mackey Apr 03 '18 at 02:59
  • 1
    @P.Brian.Mackey thank you for your comment. I don't have a link to an API. This program is for windows and not completed. like D0107012A0C.. are sensor's defined command. How can I Write and read using event for different sensor command. can you help me for this – niksan karkee Apr 03 '18 at 03:54
  • Take a look at https://stackoverflow.com/questions/2281618/net-serialport-datareceived-event-not-firing it has some solutions for the received event not firing (if that is indeed the issue) – Ian Mercer Apr 03 '18 at 04:36

1 Answers1

1

In general I find it's much easier to have two separate threads for handling serial port communications. One is a writer loop reading from a BlockingCollection, the other is a reader loop using ReadByte() to synchronously read the data one byte at a time and immediately loop back to get the next one. The reader thread communicates with other threads, including a UI thread using a Subject<T>, i.e. an observable sequence.

Your main UI (or other controlling threads or timers) can put bytes to send in the outgoing BlockingCollection and when input is received asynchronously on the observable it can be handled.

The SerialDataReceivedEvent never seemed reliable enough when I tried it which is why I have a dedicated reader thread. ReadAsync was also unreliable.

I have 10+ serial devices including many RS485 devices in my home automation system and this is the approach I use. My reader thread also checks for TimeoutException and IOException and InvalidOperationException, all of which can occur when you call ReadByte when there are transient or fatal errors on the serial port. Implementing an exponential back-off and then reopening the serial port, cancelling the sender thread, and restarting a new sender thread can handle all of these situations reliably.

But anyway, first step, try implementing a separate thread for reading from the serial port one byte at a time and make sure that works. Buffer up a line and then send that line to your UI using an IObservable, a Subject would be a good start there.

Ian Mercer
  • 38,490
  • 8
  • 97
  • 133