Main Site Documentation

FEZ Panda Serial Port Questions


#1

Ok So I’m new to this forum and FEZ in general, but am familiar with C# and .NET

So I had a couple of question I couldn’t seem to find in the forum or on the web site all regarding the serial port.

Question 1: What is the buffer size of the UARTs on the panda?

Question 2: So I’m writing some event driven software to parses MIDI data coming in on COM1. It seems to work fine except when a lot of data rushes into the port at once and also at other time sort of randomly.

using System;
using System.Threading;
using System.IO.Ports;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;

namespace FEZ_Panda_MIDI
{
    public class Program
    {
         
        public static void Main()
        {
            Program MyProgram = new Program();

            MyProgram.begin("COM1", 0);

            while (true)
            {
                Thread.Sleep(1000);
            }
           
        
        }
        
        public void begin(string port, byte Channel)
        {
            SerialPort UART;
            UART = new SerialPort(port, 31250);
            UART.DataReceived += new SerialDataReceivedEventHandler(DataReceviedHandler);
            UART.ReadTimeout = 0;
            UART.Open();


          



        }
        private static void DataReceviedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort UART = (SerialPort)sender;
            
            if (UART.BytesToRead > 128)
            {
                UART.Flush();
            }
            
            while (UART.BytesToRead > 0)
            {

                byte[] mData = new byte[UART.BytesToRead];
                byte highNibble = 0;
                byte lowNibble = 0;
                string type;
                int channel = 0;
                int data1 = 0;
                int data2 = 0;
                

                UART.Read(mData, 0, UART.BytesToRead); //Read all the data in the buffer 

                //loop through all data from serial buffer
                for (int i = 0; i < mData.Length; i++)
                {
                    //check if the current byte we are checking is a statis byte
                    if (mData[i] >= 128)
                    {
                        highNibble = (byte)(mData[i] >> 4); //get high nibble (message type)
                        lowNibble = (byte)(mData[i] & 15); //get low nibble (MIDI channel);
                        channel = lowNibble; 

                        switch (highNibble)
                        {
                            case 8: //Note off event
                                type = "NoteOff";
                                data1 = mData[i + 1];
                                data2 = mData[i + 2];
                                Debug.Print("Channel " + channel + " " + type + " Data1 = " + data1 + " Data2 = " + data2 + "\n");
                                break;
                            case 9: //Note on event
                                type = "NoteOn";
                                data1 = mData[i + 1];
                                data2 = mData[i + 2];
                                Debug.Print("Channel " + channel + " " + type + " Data1 = " + data1 + " Data2 = " + data2 + "\n");
                                break;
                            case 14: //pitch bend event
                                type = "PitchBend";
                                data1 = mData[i + 1];
                                data2 = mData[i + 2];
                                Debug.Print("Channel " + channel + " " + type + " Data1 = " + data1 + " Data2 = " + data2 + "\n");
                                break;

                        }

                    
                    
                    }



                }


            }
        }
    }
}

This is the error I get:
#### Exception System.ArgumentOutOfRangeException - CLR_E_OUT_OF_RANGE (3) ####
#### Message:
#### System.IO.Ports.SerialPort::Read [IP: 0000] ####
#### FEZ_Panda_MIDI.Program::DataReceviedHandler [IP: 0044] ####
#### System.IO.Ports.SerialPort::DataEventHandler [IP: 0012] ####
A first chance exception of type ‘System.ArgumentOutOfRangeException’ occurred in Microsoft.SPOT.Hardware.SerialPort.dll
An unhandled exception of type ‘System.ArgumentOutOfRangeException’ occurred in Microsoft.SPOT.Hardware.SerialPort.dll

It is coming from the line “UART.Read(mData, 0, UART.BytesToRead);”

Something went out of bonds and I’m not sure exactly what. It would help if I knew a bit more about what the error is implying.

[EDIT]
Also I occupationally seem to be getting this in the debug window as well:
GC: 2msec 13428 bytes used, 50952 bytes available
Type 0F (STRING ): 240 bytes
Type 11 (CLASS ): 960 bytes
Type 12 (VALUETYPE ): 108 bytes
Type 13 (SZARRAY ): 408 bytes
Type 15 (FREEBLOCK ): 50952 bytes
Type 16 (CACHEDBLOCK ): 120 bytes
Type 17 (ASSEMBLY ): 8040 bytes
Type 18 (WEAKCLASS ): 48 bytes
Type 19 (REFLECTION ): 24 bytes
Type 1B (DELEGATE_HEAD ): 144 bytes
Type 1D (OBJECT_TO_EVENT ): 72 bytes
Type 1E (BINARY_BLOB_HEAD ): 252 bytes
Type 1F (THREAD ): 768 bytes
Type 20 (SUBTHREAD ): 96 bytes
Type 21 (STACK_FRAME ): 1332 bytes
Type 27 (FINALIZER_HEAD ): 96 bytes
Type 31 (IO_PORT ): 108 bytes
Type 34 (APPDOMAIN_HEAD ): 72 bytes
Type 36 (APPDOMAIN_ASSEMBLY ): 540 bytes

I’m not sure if it’s an error or not some explanation of this would be great.

Any help would be great!
Eric


#2

for your second question, that is simply the output from the Garbage Collection process. You can ignore it (or use it to check if any of those items leak memory as you work with serial data :slight_smile: )

Someone else will also point out thread.sleep(timeout.infinite) is a better way to have your main routine not affect the system.

And on the serial data - seems a classic problem of using bytestoread “incorrectly”. There are many threads discussing this, it’s probably best to go searching for those. It also seems that you’re doing lots of work in what can effectively be thought of as an “interrupt service routine” and you should possibly look to just put the data in a queue to be used outside the event handler. Because you can’t guarantee that the last byte you’ve buffered in is a data byte, not a command byte, I suspect that the i+1 in your case statements (data1 = mData[i + 1]:wink: is breaking.


#3

Yes you are correct the mData[i + 1] did trip up a couple of times, I will move the processing of the data to another thread. But still the line that is reading the data still seems to be breaking.

Exception System.ArgumentOutOfRangeException - CLR_E_OUT_OF_RANGE (3)

Message:

System.IO.Ports.SerialPort::Read [IP: 0000]

FEZ_Panda_MIDI.Program::DataReceviedHandler [IP: 0044]

System.IO.Ports.SerialPort::DataEventHandler [IP: 0012]

A first chance exception of type ‘System.ArgumentOutOfRangeException’ occurred in Microsoft.SPOT.Hardware.SerialPort.dll
An unhandled exception of type ‘System.ArgumentOutOfRangeException’ occurred in Microsoft.SPOT.Hardware.SerialPort.dll

It is coming from the line “UART.Read(mData, 0, UART.BytesToRead);”

Not sure what to make of this error.


#4

I think the problem is that between this line:

byte[] mData = new byte[UART.BytesToRead];

and this one

UART.Read(mData, 0, UART.BytesToRead); //Read all the data in the buffer

additional data is placed in the buffer. That means that UART.BytesToRead is now larger than the array you just allocated for it. Try replacing UART.Read(…, UART.BytesToRead) with mData.Length.


#5

Eric6,

I find the code http://code.tinyclr.com/project/191/telnet-type-class-for-netmf/ to be very reliable.
Just replace the USB part with Serial. I have it running for 4 day and 23h and didn’t missed a bit.

Give it a try

And welcome to the forum

Greetings.


#6

[quote]I think the problem is that between this line:

byte[] mData = new byte[UART.BytesToRead];

and this one

UART.Read(mData, 0, UART.BytesToRead); //Read all the data in the buffer

additional data is placed in the buffer. That means that UART.BytesToRead is now larger than the array you just allocated for it. Try replacing UART.Read(…, UART.BytesToRead) with mData.Length.[/quote]

That makes total sense and is probably what is happening, that would explain why the error is an “Out of rang” type error. What tripped me up is that the error was direct at the serial code and not the array.

[quote]Eric6,

I find the code http://code.tinyclr.com/project/191/telnet-type-class-for-netmf/ to be very reliable.
Just replace the USB part with Serial. I have it running for 4 day and 23h and didn’t missed a bit.

Give it a try

And welcome to the forum

Greetings.[/quote]

This looks interesting and I will check it out.

Thanks for the help ill do some reworking and if it doesn’t work ill be back!

Thanks again,
Eric