tags:

views:

8495

answers:

4

Hi All,

I am attempting to create a small application to collect data received from an external sensor attached to COM10. I have successfully created a small C# console object and application that opens the port and streams data to a file for a fixed period of time using a for-loop.

I would like to convert this application to use the dataReceived event to stream instead. After reading the Top 5 SerialPort Tips, I still can't seem to it to work and don't know what I am missing. I rewrote the console application so that all the code is in Main and is pasted below. Can someone please help enlighten me as to why the event handler port_OnReceiveDatazz is not being called even though I know that there is data being sent to the port by the hardware?

Thanks

Azim

PS: Thanks to @Gabe, @Jason Down, and @abatishchev for all the suggestions. I am stumped and can't seem to get the event handler to work. Perhaps it has something to do with the device. I can live with just reading the port in a thread and streaming the data straight to file.


Code


namespace serialPortCollection
{   class Program
    {
        static void Main(string[] args)
        {

            const int bufSize = 2048;
            Byte[] buf = new Byte[bufSize]; //To store the received data.

            SerialPort sp = new SerialPort("COM10", 115200);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler

            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream

            // Wait for data or user input to continue.
            Console.ReadLine();

            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
        }

       // My Event Handler Method
        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
        {
            SerialPort spL = (SerialPort) sender;
            const int bufSize = 12;
            Byte[] buf = new Byte[bufSize];
            Console.WriteLine("DATA RECEIVED!");
            Console.WriteLine(spL.Read(buf, 0, bufSize));
        }
    }
}
+3  A: 

I think your issue is the line:

sp.DataReceived += port_OnReceiveDatazz;

Shouldn't it be:

sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz);

I've also seen suggestions that you should turn the following options on for your serial port:

sp.DtrEnable = true;    // Data-terminal-ready
sp.RtsEnable = true;    // Request-to-send

You may also have to set the handshake to RequestToSend (via the handshake enumeration).


UPDATE:

Found a suggestion that says you should open your port first, then assign the event handler. Maybe it's a bug?

So instead of this:

sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz);
sp.Open();

Do this:

sp.Open();
sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz);

Let me know how that goes.

Jason Down
+= new SerialDataReceivedEventHandler
abatishchev
Yup, fixed er up. Thanks.
Jason Down
yes I tried that as well. port_OnReceivedDatazz still doesn't get called even though I know for sure that data is being received.
Azim
Use this code in any case. Else you're wrong
abatishchev
setting DtrEnable and RtsEnable to true seems to break communication and when I close the port the device fails its internal self-test :(
Azim
You may also need to play with CtsHolding and DsrHolding as well. I haven't used this stuff in a little while, so I can't exactly how they work. If you're enabling the rts and dtr stuff, you'll need to check the cts/dsr holding before doing writes.
Jason Down
ok. I will look at the CtsHolding and DsrHolding Properties. I also noticed you suggest I should add the event handler after opeing the port. thanks
Azim
@Jason Down: Reversed the order of opening the port and adding the event handler. the receive data event still doesn't seem to get fired.
Azim
I don't Azim. I'm stumped =(
Jason Down
ok. Jason thanks for your effort. I am stumped too! Perhaps it has something to do with the device.
Azim
That's the only explanation I can think of. It SHOULD work...
Jason Down
Maybe try one last thing, though I wouldn't get your hopes up... Try sending a couple "\r\n" to the serial port before you send the "$" character.
Jason Down
tried sending the four "\r\n" before the "$" character. Still doesn't fire the receive event.
Azim
Blargh! Maybe threaten the device ;)
Jason Down
About to throw it out the window. anyway, thanks for the help!
Azim
A: 

By the way, you can use next code in you event handler:

switch(e.EventType)
{
  case SerialData.Chars:
  {
    // means you receives something
    break;
  }
  case SerialData.Eof:
  {
    // means receiving ended
    break;
  }
}
abatishchev
+2  A: 

First off I recommend you use the following constructor instead of the one you currently use:

new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One);

Next, you really should remove this code:

// Wait 10 Seconds for data...
for (int i = 0; i < 1000; i++)
{
    Thread.Sleep(10);
    Console.WriteLine(sp.Read(buf,0,bufSize)); //prints data directly to the Console
}

And instead just loop until the user presses a key or something, like so:

namespace serialPortCollection
{   class Program
    {
        static void Main(string[] args)
        {
            SerialPort sp = new SerialPort("COM10", 115200);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler

            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream

            Console.ReadLine();

            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
        }

       // My Event Handler Method
        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
        {
            SerialPort spL = (SerialPort) sender;
            byte[] buf = new byte[spL.BytesToRead];
            Console.WriteLine("DATA RECEIVED!");
            spL.Read(buf, 0, buf.Length);
            foreach (Byte b in buf)
            {
                Console.Write(b.ToString());
            }
            Console.WriteLine();
        }
    }
}

Also, note the revisions to the data received event handler, it should actually print the buffer now.

UPDATE 1


I just ran the following code successfully on my machine (using a null modem cable between COM33 and COM34)

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread writeThread = new Thread(new ThreadStart(WriteThread));
            SerialPort sp = new SerialPort("COM33", 115200, Parity.None, 8, StopBits.One);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler

            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream

            writeThread.Start();

            Console.ReadLine();

            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
        }

        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
        {
            SerialPort spL = (SerialPort) sender;
            byte[] buf = new byte[spL.BytesToRead];
            Console.WriteLine("DATA RECEIVED!");
            spL.Read(buf, 0, buf.Length);
            foreach (Byte b in buf)
            {
                Console.Write(b.ToString() + " ");
            }
            Console.WriteLine();
        }

        private static void WriteThread()
        {
            SerialPort sp2 = new SerialPort("COM34", 115200, Parity.None, 8, StopBits.One);
            sp2.Open();
            byte[] buf = new byte[100];
            for (byte i = 0; i < 100; i++)
            {
                buf[i] = i;
            }
            sp2.Write(buf, 0, buf.Length);
            sp2.Close();
        }
    }
}

UPDATE 2


Given all of the traffic on this question recently. I'm beginning to suspect that either your serial port is not configured properly, or that the device is not responding.

I highly recommend you attempt to communicate with the device using some other means (I use hyperterminal frequently). You can then play around with all of these settings (bitrate, parity, data bits, stop bits, flow control) until you find the set that works. The documentation for the device should also specify these settings. Once I figured those out, I would make sure my .NET SerialPort is configured properly to use those settings.

Some tips on configuring the serial port:

Note that when I said you should use the following constructor, I meant that use that function, not necessarily those parameters! You should fill in the parameters for your device, the settings below are common, but may be different for your device.

new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One);

It is also important that you setup the .NET SerialPort to use the same flow control as your device (as other people have stated earlier). You can find more info here:

http://www.lammertbies.nl/comm/info/RS-232_flow_control.html

Gabe
Hi Thanks. I have modified my code as you suggested but the event handler still doesn't get called.
Azim
Are you sure the handshaking is setup properly? What serial port settings have you used in the past (in hyperterminal or whatever) to be able to communicate with it?
Gabe
In your last edit you get the event to fire by sending data in the write thread. The write thread just simulates my device sending data.
Azim
That's correct. I don't actually have your device, so I had to simulate it somehow. It sounds like either the device is not sending data, or your serial port is not configured properly.How have you communicated with the device in the past?
Gabe
With the default settings when I create the serialport object. So in fact the Console.WriteLine in my for-loop does print out data being received. But the event handler never gets called.
Azim
You have to remove that "for" loop for the event handler to get called. See my code above.
Gabe
Yes, I know. I removed the for-loop. I can be confident that the device is sending data because there is data to be read in the port buffer before I close the port. Thanks for the updates to your question.
Azim
+1  A: 

I was having the very same problem with a modem that had previously worked and then one day just stopped raising the DataReceived event.

The solution in my case, very randomly, was to enable RTS e.g.

sp.RtsEnable = true;

No idea why that worked on this particular bit of kit (not a comms man at all really), nor why it had worked and then stopped but it may help somebody else one day so just posting it just in case...

Justin Wignall