Click here to Skip to main content
15,884,298 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hallo All.

I am currently teaching myself C# through making an app. It is slow progress with a lot of time spent on forums, but still fun none the less...

As for the problem. The code I have made sends an array of bytes out and should get a byte array back as a reply. I believe my problem is coming up when I try and save the received message.

The best outcome I have gotten so far was to save the 1st byte received and nothing more.

//this part is in my main code.
 myport.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);

 private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
   {
      if (!myport.IsOpen) return;  //If port is closed exit
      int bytes = myport.BytesToRead;  //find the size of the array needed
      byte[] buffer = new byte[bytes];  //create the array
      myport.Read(buffer, 0, bytes);  //read the message and save it into the buffer
      byte[] ReceivedMessage = new byte[bytes];  //create an array of the same size
      Array.Copy(buffer, ReceivedMessage, bytes);  //copy it across
   }


After this part of the code runs only the first byte is saved in "ReceivedMessage" and the rest is all null. The message received is suppose to be 25 bytes long.

What I have tried:

Testing the Received message to see if it all comes through (it does).
Tried different forms of the Read command (doesn't seem to really help).
Posted
Updated 25-Mar-17 2:26am
Comments
Richard MacCutchan 25-Mar-17 6:58am    
That is most likely because you only read the first byte. Serial ports are extremely slow and you need to keep checking whether there is any data ready to read, you cannot assume that you will get the complete message on your first attempt.
Terrence13 25-Mar-17 7:50am    
Thank you for the reply Richard.
That does make a lot of sense yes. Is there a way I can make my code wait until it receives all 25 bytes and fills the array before continuing?
I tried doing this with ReadLine, but that caused an infinite loop.
Richard MacCutchan 25-Mar-17 7:00am    
> After this part of the code runs only the first byte is saved in "ReceivedMessage" and the rest is all null.
> Testing the Received message to see if it all comes through (it does).

Both of those statements cannot be true.
PIEBALDconsult 25-Mar-17 9:38am    
I think you get the _last_ byte.

Array.Copy(buffer, ReceivedMessage, bytes);
"bytes" should be "0" here ?

Serial data is just that: serial - it does not all arrive at once, it arrives byte-by-byte, and pretty slowly compared to modern software. If your serial port is running at 9600 baud, then the fastest you can receive data is at about 100 bytes per second.
That means that each byte will most likely generate it's own separate DataReceived event rather than you getting one event for the whole set.
Instead of copying them to a class level buffer - which will discard any existing data and leave you with only the latest byte - try using Console.Write to print the data as you receive it to the Output pane in the debugger and see if you can see all the data then.
If you can, see if it has a terminator or a lead-in byte, so you can synchronise your data and assemble the complete message from a number of DataReceived events.
 
Share this answer
 
Comments
Terrence13 25-Mar-17 8:30am    
Thank you for the reply Griff and the great explanation.

I am going to try this and see if I can get it to work.
OriginalGriff 25-Mar-17 9:35am    
:thumbsup:
I had to deal with a very old printer some weeks ago, what seems to be similar to your requirements, here is what I did.
Collect the incoming results from the port in a stringbuilder, log what you get into a file. Once you identify the "the answer is complete" indicator (in my case a given length) you can invoke a callback.


public interface IHerma300
{
  void GetStatus(Action<string> callback);
}

public class Herma300 : IHerma300
{
  readonly System.IO.Ports.SerialPort _port;
  private Action<string> _callback;
  private readonly System.Text.StringBuilder _responseFromHerma;
  public const int statusResponseExpectedLength = 62;

  public Herma300(string portName
    , int baudRate
    , System.IO.Ports.Parity parity
    , int dataBits
    , System.IO.Ports.StopBits stopBits
    , int waitTimeMs)
  {
    _responseFromHerma = new StringBuilder(100);
    _port = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
    _port.DataReceived += OnPortDataReceived;
    _port.Open();
    _waitTimeMs = waitTimeMs;
  }

  private void OnPortDataReceived(object sender, SerialDataReceivedEventArgs e)
  {
    System.IO.Ports.SerialPort port = (System.IO.Ports.SerialPort)sender;
    int count = port.BytesToRead;
    byte[] data = new byte[count];
    port.Read(data, 0, data.Length);
    // use your logger here and write  BitConverter.ToString(data)
    var dataAsString = System.Text.Encoding.Default.GetString(data);
    _responseFromHerma.Append(dataAsString);
    if (_responseFromHerma.Length == statusResponseExpectedLength) CompleteAnswerReceived();
  }

  private void CompleteAnswerReceived()
  {
    _callback.Invoke(_responseFromHerma.ToString());
  }


  public void GetStatus(Action<string> callback)
  {
    _callback = callback;
    _responseFromHerma.Length = 0;
    string getStatusCommand = "send some command to the other side";
    _port.Write(getStatusCommand);
  }

}


// calling code
var labelPrinter = new Herma300(params...);
labelPrinter.GetStatus(OnStatusFromPrinter);

private void OnStatusFromPrinter(string result)
{
   // you are not in the ui thread here, so be careful when updateing ui controls
}
 
Share this answer
 
v2
Comments
Terrence13 25-Mar-17 8:31am    
Hey FranzBe. Thank you for the response and the code snippit.
I will try add this to my code and see if I can get it to work.
Looks promising.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900