Main Site Documentation

EMX UART strange behaviors


#1

Hi, I have a pair of EMXs, one is used as a data sender and the other is configured as a receiver for two way communications. I have been using EMX in the past a few years on different projects but today came across something I didn’t understand of the EMX serial port.

First, both EMXs have tinybooter version 4.1.6 and firmware version 4.1.8. I installed the MFNET 4.3 (but use the 4.1 for the project) and used the VS2012 for debugging.

Second, EMXs are using COM2 for communication, one sends data to the other, and then the receiver sends some data back to the sender, both of them will blink a LED so we know each of them got the data.

The two projects (one for sender, and one for receiver) work fine in the VS2012 debugging mode, and also works well when I stopped the debugging. The two LEDs blink so I know the data are sending back and forth.

But if I press the RESET button or repower the board, EMXs will not start sending or receiving data any more, no LED blinks. But they indeed booted up, I insert another LED blinking code inside to test the boot up. The EMX did boot up and could process something else but failed to receive data via serial port. Seems like the serial DataReceived event didn’t triggered. I tried the COM3 and it was the same thing.

Any help will be highly appreciated.


#2

Can you add some debug.print statement inside your code? maybe this can help to figure out what’s going wrong. There’s no need to attach the VS debugger, you can use FezConfig or mf deploy to see the output.


#3

I also wonder if it’s a “start Sync” type problem of timing that isn’t showing up when you deploy-and-debug to them both ?


#4

Here is deploy information:

Looking for a device on transport 'USB’
Starting device deployment…
Iteration 0
Opening port \?\USB#VID_1B9F&PID_0102#6&2b4781c9&0&4#{09343630-a794-10ef-334f-82ea332c49f3}\Operations
Attaching debugger engine…
… debugger engine attached!
Querying device assemblies…
Found Assembly mscorlib 4.1.2821.0
Found Assembly Microsoft.SPOT.Native 4.1.2821.0
Found Assembly Microsoft.SPOT.Graphics 4.1.2821.0
Found Assembly System 4.1.2821.0
Found Assembly Microsoft.SPOT.Hardware.SerialPort 4.1.2821.0
Found Assembly GHIElectronics.NETMF.Hardware 4.1.8.0
Found Assembly GHIElectronics.NETMF.System 4.1.8.0
Found Assembly Receiver 1.0.0.0
Found Assembly McuLib 1.0.0.0
Found Assembly Microsoft.SPOT.Net 4.1.2821.0
Found Assembly Microsoft.SPOT.Hardware 4.1.2821.0


Incrementally deploying assemblies to device
All assemblies on the device are up to date. No assembly deployment was necessary.
Assemblies successfully deployed to device.
Restarting interpreter…
Attaching to device…
Waiting for device to initialize…

The McuLib assembly is nothing but just a shell of my object, just a enumeration definition.

The program runs very well in VS2012 debugging environment, I go the LED blinks when serial data received, and I debug.print the data and confirmed that both sender and receiver got their data respectively. But just after I reset the EMXs or repower them, the code side the serial DataReceived event part will not be triggered. Quite confused…


#5

It seems like the serialport DataReceived event never got triggered after reset or repower. But they are triggered in VS2012 deploy and debug mode. What is the “start Sync” problem? Can you give me some more details? Thanks a lot :slight_smile:


#6

OK, I just confirmed that the serial port can send out the data after the EMX reset or repower. The sender’s serial port is able to send out the data. But on the receiver EMX side, the serial port failed to receive or trigger the DataReceived event after reset or repower. But it works fine when connected with VS2012 in deploy-debug manner. Any help?

Thanks


#7

a “start sync” is just where you have a coupled system that must be aware of a restart condition could occur, at either end, at any time, and you need to handle that condition. For a simple case, you might send a text ^ mark when you restart, and periodically until the other end has acknowledged that by returning a text * mark. Think of it as a string can phone - you keep saying “are you there” until someone says “yes I’m there” and then you can have your conversation.

If you have an uncoupled system, like a remote device that just sends data to the receiver without acknowledgement or control, you do not have to worry about this.

So can I ask how do you know the handler hasn’t worked ? Are you assuming that, just because the data is never handled and your LED never flashes? Do you have or can you create a simple test app that shows this ? (my belief is that this is not a hardware issue it’s a program logic issue and we’ll need to see code to assist - you could post the entire project if it isn’t proprietary?)


#8

Very good point, Brett. I changed the code a little bit to make the sender and receiver as non-coupled. But still, they works fine in VS2012 deploy-debugging mode, if either one of them is debugging by VS, they works fine. But if I repower the board, the LED stop blinking to indicate that no data has been received on either end. Here is the code:

For the Sender part:

using System;
using System.IO.Ports;
using System.Text;
using System.Threading;
using McuLib.Utility;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace Sender
{
    public class Sender
    {
        private static MultiColorLed LED;
        private static SerialPort serialPort;
        private static byte[] serialBuffer;
        private static string serialData = null;

        public static void Main ()
        {
            // set LED to green on start
            LED = new MultiColorLed ((Cpu.Pin)Config.Output.LedRed, (Cpu.Pin)Config.Output.LedGreen, (Cpu.Pin)Config.Output.LedBlue, LedColor.Green);

            serialPort = new SerialPort ("COM2", 115200);
            serialPort.DataReceived += serialPort_DataReceived;
            serialPort.ErrorReceived += serialPort_ErrorReceived;
            serialPort.WriteTimeout = 100;
            serialBuffer = new byte[256];
            serialPort.Open ();

            Debug.Print ("\nSender starts sending and receiving data via COM2 at 115200 baud rate...");

            while (true)
            {
                string data = "<com>Inquiry data from Sender</com>";
                byte[] dataToSend = Encoding.UTF8.GetBytes (data);
                serialPort.Write (dataToSend, 0, dataToSend.Length);

                // set LED to yellow to indicate data send out
                LED.SetColor (LedColor.Yellow);
                Thread.Sleep (500);
            }
        }

        private static void serialPort_DataReceived (object sender, SerialDataReceivedEventArgs e)
        {
            // clamp the reading size to prevent buffer overflow
            int byteSize = serialPort.BytesToRead;
            int count = byteSize > serialBuffer.Length ? serialBuffer.Length : byteSize;

            Array.Clear (serialBuffer, 0, serialBuffer.Length);
            serialPort.Read (serialBuffer, 0, count);

            // convert bytes to string and append the received segment
            string dataSegment = DataParser.GetString (serialBuffer);
            serialData += dataSegment;

            // parse the start and end tag and retrieve the data content
            string response = DataParser.Parse (ref serialData, "com", true);
            if (response != null)
            {
                Debug.Print ("Got response from receiver : " + response);

                // set LED to blink to indicator data received from sender
                LED.SetColor (LedColor.None);
            }
        }

        private static void serialPort_ErrorReceived (object sender, SerialErrorReceivedEventArgs e)
        {
            Debug.Print ("Sender serial port " + serialPort.PortName + " error : " + e.EventType.ToString ());
            LED.SetColor (LedColor.Red);
        }
    }
}

And for the Receiver:

using System;
using System.IO.Ports;
using System.Text;
using System.Threading;
using McuLib.Utility;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace Receiver
{
    public class Receiver
    {
        private static MultiColorLed LED;
        private static SerialPort serialPort;
        private static byte[] serialBuffer;
        private static string serialData = null;

        public static void Main ()
        {
            // set LED to green
            LED = new MultiColorLed ((Cpu.Pin)Config.Output.LedRed, (Cpu.Pin)Config.Output.LedGreen, (Cpu.Pin)Config.Output.LedBlue, LedColor.Green);

            // use COM2 at 115200 rate
            serialPort = new SerialPort ("COM2", 115200);
            serialPort.DataReceived += serialPort_DataReceived;
            serialPort.ErrorReceived += serialPort_ErrorReceived;
            serialPort.WriteTimeout = 100;
            serialBuffer = new byte[256];
            serialPort.Open ();

            Debug.Print ("\nReceiver starts sending and receiving data via COM2 at 115200 baud rate...");

            while (true)
            {
                // receiver also sends out data periodically
                string data = "<com>ACK data from Receiver</com>";
                byte[] dataBytes = Encoding.UTF8.GetBytes (data);
                serialPort.Write (dataBytes, 0, dataBytes.Length);

                // set LED to blue to indicate data send out
                LED.SetColor (LedColor.Blue);
                Thread.Sleep (500);
            }
        }

        private static void serialPort_DataReceived (object sender, SerialDataReceivedEventArgs e)
        {
            // clamp the reading size to prevent buffer overflow
            int byteSize = serialPort.BytesToRead;
            int count = byteSize > serialBuffer.Length ? serialBuffer.Length : byteSize;

            Array.Clear (serialBuffer, 0, serialBuffer.Length);
            serialPort.Read (serialBuffer, 0, count);

            // convert bytes to string and append the received segment
            string dataSegment = DataParser.GetString (serialBuffer);
            serialData += dataSegment;

            // parse the start and end tag and retrieve the data content
            string data = DataParser.Parse (ref serialData, "com", true);

            // got a complete data
            if (data != null)
            {
                Debug.Print ("Got data from sender : " + data);

                // set LED to blink to indicator data received from sender
                LED.SetColor (LedColor.None);
            }
        }

        private static void serialPort_ErrorReceived (object sender, SerialErrorReceivedEventArgs e)
        {
            Debug.Print ("Receiver serial port " + serialPort.PortName + " error : " + e.EventType.ToString ());
            LED.SetColor (LedColor.Red);
        }
    }
}

Really frustrated…Thanks


#9

A few things to consider…

I have never used the write timeout parameter. I am not sure what it is supposed to do. Try not using it.

On your reads, you are reading the data available or the size of the receive buffer whichever is smaller. If the amount of data available is greater than the size of the buffer, you do not clear out the remaining data. I use the following snippet in DataReceived event handlers:

while (serial.BytesToRead > 0)
{
    // do reading here...

}

#10

Good points, Mike.
I removed the serial port WriteTimeout and put the LED.SetColor (LedColor.None) on the first line inside the DataReceived event handler. So if there is any serial data received, the LED will blinks no matter whether the data gets processed or not. But again, it works fine as long as either program is connected with VS2012 debugging. After I repower them, the LEDs stare at me with no mercy…

:open_mouth:


#11

the speed of the first characters is faster without debugging. Could be missing first few characters at receiver, and parser gets confused.

bypass the parser to see if any data is arriving.


#12

Thanks for the advice. I changed the serial port DataReceived handler to:

private static void serialPort_DataReceived (object sender, SerialDataReceivedEventArgs e)
        {
            LED.SetColor (LedColor.None);

            // read all data
            int byteSize = serialPort.BytesToRead;
            if (byteSize > serialBuffer.Length)
                serialBuffer = new byte[byteSize];

            Array.Clear (serialBuffer, 0, serialBuffer.Length);
            serialPort.Read (serialBuffer, 0, byteSize);
            Debug.Print ("Got response from receiver : " + DataParser.GetString(serialBuffer));

            // no any additional data processing 
        }

Basically, when data came, the program will blink the LED and read in all data. No any tricky data parsing. Again, it failed to work when the EMXs got reset or repower. Really frustrated… :wall:


#13

@ bbcat - Can you try to update to 4.3 and see if the issue persists? We have not done any work on 4.1 for quite some time.