SerialDataReceivedEventHandler

Hi everyone

I’m trying to use the SerialDataReceivedEventHandler to receive data at 56700 Bps. Data are sent by a 9dof Razor IMU.

I instantiate the serial port, open it and then subscribe to the event. Data are received properly untill reaching the empty while(true) loop.

Here’s the code:

using System.Threading;
using System.IO.Ports;
using System.IO;
using System.Text;
using Microsoft.SPOT;

namespace EMX_Application1
{
    public class Program
    {
        static SerialPort UART = new SerialPort("COM2", 57600);
        static void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] buffer = new byte[UART.BytesToRead];
            UART.Read(buffer, 0, buffer.Length);
            UART.DiscardInBuffer();
            UART.Flush();
            string output_imu = bytesToString(buffer);
            Debug.Print("IMU:" + output_imu);
            output_imu = null;
            buffer = null;
        }
        public static string bytesToString(byte[] bytes)
        {
            string s = "";
            for (int i = 0; i < bytes.Length; ++i)
                s += (char)bytes[i];
            return s;
        }


        static void send_cmd(char byte_snd, int time_wait)
        {
            byte[] buffer = new byte[1];
            buffer[0] = (byte)byte_snd;
            UART.Write(buffer, 0, 1);
            buffer = null;
            Thread.Sleep(time_wait);
        }

        public static void Main()
        {
            
            UART.ReadTimeout = 10;    
            
            UART.Open();
            UART.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
            send_cmd('4', 200);
            while (true)
            {
                Debug.Print("sleep for 10ms");
                Thread.Sleep(10);
            }

        }
       
    }
}

And the debug screen shows:

[quote]‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managé) : ‘C:\Program Files\Microsoft .NET Micro Framework\v4.1\Assemblies\le\mscorlib.dll’ chargé, symboles chargés.
‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managé) : ‘C:\Program Files\Microsoft .NET Micro Framework\v4.1\Assemblies\le\Microsoft.SPOT.Native.dll’ chargé, symboles chargés.
‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managé) : ‘C:\Program Files\Microsoft .NET Micro Framework\v4.1\Assemblies\le\Microsoft.SPOT.Hardware.dll’ chargé, symboles chargés.
‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managé) : ‘C:\Program Files\Microsoft .NET Micro Framework\v4.1\Assemblies\le\Microsoft.SPOT.Hardware.SerialPort.dll’ chargé, symboles chargés.
‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managé) : ‘C:\Documents and Settings\Jeremie\Bureau\EMXIMU\EMX Application1\EMX Application1\bin\Debug\le\EMX Application1.exe’ chargé, symboles chargés.
‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managé) : ‘C:\Program Files\Microsoft .NET Micro Framework\v4.1\Assemblies\le\Microsoft.SPOT.Net.dll’ chargé, symboles chargés.
‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managé) : ‘C:\Program Files\Microsoft .NET Micro Framework\v4.1\Assemblies\le\System.dll’ chargé, symboles chargés.
‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managé) : ‘C:\Program Files\Microsoft .NET Micro Framework\v4.1\Assemblies\le\Microsoft.SPOT.IO.dll’ chargé, symboles chargés.
‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managé) : ‘C:\Program Files\Microsoft .NET Micro Framework\v4.1\Assemblies\le\System.IO.dll’ chargé, symboles chargés.
‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managé) : ‘C:\Program Files\GHI Electronics\GHI NETMF v4.1 SDK\Assemblies\le\GHIElectronics.NETMF.Hardware.EMX.dll’ chargé
Le thread ‘’ (0x2) s’est arrêté avec le code 0 (0x0).
IMU:

9DOF IMU Firmware v20

==========================

[1]Accelerometer: ADXL345

[2]Magnetometer: HMC5843

[3]Gyroscope: ITG-3200

[4]Raw Output

[5]Change Baud Rate: 57600bps

[Ctrl+z]Toggle Autorun

[?]Help

$23,4,240,-11,1,80,-85,-21,-24#

IMU:$24,5,239,-12,5,76,53,-161,11#

$22,3,241,-12,4,81,-272,-53,18#

$24,5,241,-14,2,77,-1,-25,162#

IMU:$24,4,237,-11,2,80,-138,130,-260#

sleep for 10ms
IMU:$
IMU:23,4,
IMU:240,-15,2,
IMU:77,-43,-224,71#

sleep for 10ms
sleep for 10ms
sleep for 10ms
IMU:$
IMU:24,3,239,
IMU:-11,0,77,-79,-6,348#

IMU:
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
sleep for 10ms
[/quote]

It seems that the loop does not allow the events to be managed properly… Am I wrong or misunderstand anything?

Why are you doing this loop ?

A simple

Thread.Sleep(Timeout.Infinite);

is enough at this point.

As you said this is enough but this does not solve the problem.

The loop allows us to be sure that the EMX is still alive. The fact is that with the loop and sleep of 10ms or sleep forever (TimeOut.Infinite), data are received and after a while, events are not throw anymore.

Are you sure that the IMU is still alive and sending data ?

Edit: I mean, for example, using Teraterm or any other serial communication program and see if you have the same behaviour without the EMX board.

Hello Bec a fuel

I have already checked that and I also have a version of my code without the subscription to the event that Read bytes of data on the UART in the loop and it works well so the problem does not come from IMU.

So first suggestion - that thread.sleep will just be too noisy, causing GCs galore. Flash a LED to prove this works.

Second thought, why do you do this:


            UART.DiscardInBuffer();
            UART.Flush();

Don’t !! The scenario where you get some data in, then more comes in before it’s “read”, you risk flushing the message. Handle the even by reading what you can, and getting out.

Also look for some other posts on the datarecievedevent to find efficient ways of handling this.

Hello Brett and thanks for your interest in this pb.

For your first suggestion, I have to say that this code does not reflect the final program, this is not what will be coded at the end. This is the result of the debuging process.

I have to say also that even if this code seems to be stupid, this does not involve the GC and this, according to me should work.

.netmf seems to handle properly the loop without the need of freeing memory. The code can run during an hour without seeing any GC call.

For the second suggestion: the following two lines are located before freeing the buffer.
byte[] buffer = new byte[UART.BytesToRead];
UART.Read(buffer, 0, buffer.Length);

As a result, I would expect that the data are dumped to the buffer before any deletion, Am I wrong?

Let me just say that I said noisy - in particular string operations that can lead to GC. Whether you’re seeing it or not doesn’t matter, but if you’re trying to get an accurate reflection of what your IMU is doing then you are just cluttering up the text output.

Onto your serial port issues: what exactly do you mean by “data are dumped to the buffer”?

The READ operation takes a character off the input buffer that you can’t see, and puts it in your variable. That is then not on the input buffer, but if the IMU has then sent another character to you and put it on the input buffer and you flush it, it’s gone.

Remember that the event handler will fire whenever there is data; that might be one character or 15, but you can’t guarantee that you will get a complete “message” in that one event. You need to come up with an approach to handle the situation gracefully.

If all you want to do right now is have something reliable read and debug.print your serial input then the discard and flush are definetely bad (and I would say I am not sure when you would want to use them anyway).

Thanks Brett, You got it, I remove the two lines (the discard and flush ones) and it works. I don’t know why I didn’t try that before.

Is there any reason that there is no example in the ebook dealing with SerialDataReceivedEventHandler?

awesome to hear that you got it working.

Why no sample? maybe because they’re evil. Well maybe not evil, but personally I think it’s a harder ask to figure out a successful “read and act-on” strategy using it, plus it also doesn’t work when you have a serial-over-usb connection; so polling works best :slight_smile: