Main Site Documentation

How use two serial ports on Fez Panda at same time


#1

Hello, I’m new to this forum. I’m working with a FEZ Panda, my application must receive data from xbee modules through a COM port and then must send data to a PC through another COM port.

I tried separately communication and working properly, the problem is when I want to use the two COM ports, using a first the other does not respond and vice versa. someone could provide a code example to use both ports at the same time?

Or have any suggestions of what could be the problem?

Thanks.


#2

Welcome to the forum!

Can you please show your code?


#3
using System;
using Microsoft.SPOT;
using FEZAPIXBee;
using System.Threading;
using Microsoft.SPOT.Hardware;
using System.Text;
using System.IO.Ports;
using GHIElectronics.NETMF.FEZ;


namespace FEZ_GATE_WAY
{
    public class Program
    {
        public static SerialPort Puerto = new SerialPort("COM1");
        public static SerialPort FTDI = new SerialPort("COM4");

        public static InputPort boton_desc = new InputPort((Cpu.Pin)FEZ_Pin.Digital.IO69, false,
            Port.ResistorMode.PullUp);

        private static DigiMesh mixbee = new DigiMesh();

        private static string enter;

        private static int nodos = 0;

        public static int codigo = 0;
        private static bool desc_red = false;
        private static bool sol_is = false;
        private static bool sol_ir = false;
        private static string[] temp = new string[30];
       
        
        private static string recepcion = "ATID,CH,NI,DH,DL,AP,SH,SL,CN";
        private static string[] vlectura = new string[10];
        public static void Main()
        {
            
            Puerto.BaudRate = 9600;
            Puerto.Parity = Parity.None;
            Puerto.StopBits = StopBits.One;
            Puerto.DataBits = 8;
            Puerto.Handshake = Handshake.None;
            Puerto.Open();
            Puerto.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
          
            FTDI.BaudRate = 9600;
            FTDI.Parity = Parity.None;
            FTDI.StopBits = StopBits.One;
            FTDI.DataBits = 8;
            FTDI.Handshake = Handshake.None;
            FTDI.Open();
            FTDI.DataReceived+=new SerialDataReceivedEventHandler(FTDI_DataReceivedHandler);
            

            while (true)
            {
                if (codigo == 1)
                {
                    descubrir_red();
                    codigo = 0;
                }
                if (!boton_desc.Read())
                {
                    codigo = 1;
                    while (!boton_desc.Read()) { }
                }
                Thread.Sleep(1000);
            }
           
        }

       

        private static void FTDI_DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                Thread.Sleep(100);
                bool Entrada = true;
                string comando;
                Byte[] Arreglo = new Byte[10];
                byte[] Temporal = new byte[5];
                FTDI.Read(Arreglo, 0, 1);
                Temporal[0] = Arreglo[0];
                while (Entrada)
                {
                    if (Arreglo[0] == 126)
                    {
                        string reading = FTDI.BytesToRead.ToString();
                        Debug.Print(reading);
                        FTDI.Read(Arreglo, 0, FTDI.BytesToRead);

                        comando = Convert.ToChar(Arreglo[0]).ToString() + Convert.ToChar(Arreglo[1]).ToString();
                        switch (comando)
                        {
                            case "ND": Debug.Print(comando);
                                codigo = 1;
                                break;
                            default: 
                                break;
                        }

                    }
                    Entrada = false;

                }
               

            }
            catch
            {

            }

        }

       
        private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
           
            try
            {
                if (desc_red || sol_is || sol_ir)
                {                    
                    Thread.Sleep(100);
                    bool Entrada = true;
                    int tamaño;
                    Byte[] Arreglo = new Byte[40];
                    byte[] temporal = new byte[5];
                    Puerto.Read(Arreglo, 0, 1);
                    temporal[0] = Arreglo[0];
                    while (Entrada)
                    {                        
                        if (Arreglo[0] == 126)
                        {                            
                            Puerto.Read(Arreglo, 0, 2);
                            tamaño = Arreglo[0] * 256 + Arreglo[1];
                            temporal[1] = Arreglo[0];
                            temporal[2] = Arreglo[1];
                            Puerto.Read(Arreglo, 0, tamaño + 1);
                            
                            if (Entrada)
                            {                                
                                if (Arreglo[0] == 0x88)
                                {
                                    //Comando ND
                                    respuesta_local(Arreglo);
                                }
                               
                                else if (Arreglo[0] == 0x92)
                                {
                                    mixbee.MakeVariables_remotas_ir(Arreglo);
                                }
                            }
                        }
                        Entrada = false;
                    }
                }
               
            }
            catch 
            {
                
              Debug.Print("Error");
            
            }
            Thread.Sleep(40);
           
        }
       
        static void timertick_desc(object o)
        {
            if (desc_red)
            {
                Debug.Print("Descubrimiento Completo");
                Debug.Print("Número de Nodos: " + nodos.ToString());
                mixbee.nodo = 0;
                desc_red = false;               
            }
        }
        
   
        private static void enviar_dato(byte[] paquete, SerialPort puerto)
        {
            puerto.Write(paquete, 0, paquete.Length);
        }
       
        private static byte[] leer_puerto(SerialPort puerto)
        {
            byte[] entrada = new byte[puerto.BytesToRead];
            puerto.Read(entrada, 0, entrada.Length);
            return entrada;
        }
        
        private static void descubrir_red()
        {
            desc_red = true;
            nodos = 0;
            mixbee.Make_API_Parametro("nd", "", 1);
            mixbee.Escribir_Puerto(Puerto);
            Debug.Print("Descubrimiento solicitado");
            Timer TemporizadorDescubrimiento = new Timer(new TimerCallback(timertick_desc), 0, 15000, 0);
        }

        private static void respuesta_local(byte[] Arreglo)
        {
            Debug.Print("Respuesta a comando local");
            string comando = Convert.ToChar(Arreglo[2]).ToString() + Convert.ToChar(Arreglo[3]).ToString();
            Debug.Print("Comando enviado: " + comando);
            Debug.Print("ID: " + Arreglo[1]);
            Debug.Print("Estado: ");
            if (Arreglo[4] == 0x00)
                Debug.Print("OK");
            if (Arreglo[4] == 0x01)
                Debug.Print("ERROR");
            if (Arreglo[4] == 0x02)
                Debug.Print("COMANDO INVALIDO");
            if (Arreglo[4] == 0x03)
                Debug.Print("PARAMETRO INVALIDO");
            if (comando == "ND")
            {
                mixbee.MakeEstructura(Arreglo);
                nodos++;
            }
        }
    }
}

I’m sorry, I`m new to forum.


#4

Can you please edit your previous post (pencil button) and enclose the source code part with code tags.

Thanks.


#5

I’m sorry, I’m new to this foru, I edited it.


#6

First thing to try is to Open the port first and only after that subscribe to the events. There was a known issue on some of the ports - the order is important.


#7

I changed the code as you told me, but I have the same problem.

Thanks.


#8

Your main thread while(true) loop is very tight as well. You don’t have enough time for thread switching and event processing.

Try adding Thread.Sleep inside that main loop.


#9

I tried with Thread.Sleep(1000) and tested it with several smaller values ​​like 500, 300, 100 and did not work.

Thanks.


#10

Also remember that there is only one tread doing the DataReceived event handling. For example if FTDI_DataReceivedHandler gets called, DataReceivedHandler is not going to get called until FTDI_DataReceivedHandler exits. Specifically, the Thread.Sleep(100) in one method essentially blocks processing of both serial ports for 100ms. If you are going to use the DataReceived event handler, quickly and efficiently get the data from the port and then get out. Process it on the main thread or different thread.

For multiple serial ports on a Panda II (and Cobra II) I had the best luck having a dedicated thread getting the data from each. Looping on a port.Read method:

while (true)
{
    int read = port.Read(byteBuffer, 0, byteBuffer.Length);
    if (read > 0)
    { 
       // process byteBuffer
       Debug.Print(Encoding.UTF8.GetChars(byteBuffer,0,read));
    }
}

#11

The best way to use the data received event handlers is just to de-queue data, not to process it. I would suggest you spend time to move the handling of the data to a separate action that you trigger.

You haven’t really articulated what doesn’t work. Is it just that you can’t keep up at the data rates you’re seeing? What is the data rate you’re trying to push from both ends?

Edit: And eolson also replied similarly… :slight_smile: