Read serial data with timer function

Hello,

i have a problem with serial input. Here is my plan once:

I use the FEZ Spider and i want to process incoming data via the UART interface in a time window of 100 ms. The data will be sent every 10ms by ZigBit transmitters (3 channels). The master is connected to the port 8th My problem is that RX is to be retrieved from the serial interface exactly 3x within the 100ms. How can I achieve this without closing the interface? Any idea? Without the timer, the data will be read only one time.

Here ist the Code:


        GT.Interfaces.Serial _mySerial;
        const int BaudRate = 115200;
        const int DataBits_Input = 8;

        int counter = 0;
        GT.Timer timer;

void ProgramStarted()
        {
            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");

            timer = new GT.Timer(100);
            timer.Tick += new GT.Timer.TickEventHandler(timer_Tick);

            _mySerial = new GT.Interfaces.Serial(GT.Socket.GetSocket(8, false, null, null),
                                                BaudRate,
                                                GT.Interfaces.Serial.SerialParity.None,
                                                GT.Interfaces.Serial.SerialStopBits.One,
                                                DataBits_Input,
                                                GT.Interfaces.Serial.HardwareFlowControl.NotRequired,
                                                null);

            _mySerial.DataReceived += new GT.Interfaces.Serial.DataReceivedEventHandler(_mySerial_DataReceived);
            //_mySerial.ReadTimeout = 100;
            _mySerial.Open();
            
            timer.Start();
        }

void timer_Tick(GT.Timer timer)
        {
            readData = true;
        }
void _mySerial_DataReceived(GT.Interfaces.Serial sender, System.IO.Ports.SerialData data)
        {
            Debug.Print("DataReceived");

                if ((counter < 3))
                {
                    Testfunktion(sender);
                    counter++;
                }
                else
                {
                    readData = false;
                    counter = 0;
                    ShowValueDevices();
                    Debug.Print("----------------------");
                }
        }

private void Testfunktion(GT.Interfaces.Serial mySerial)
        {
            Debug.Print("Testfunktion aufgerufen");
            int NumberOfBytesToRead = mySerial.BytesToRead;
            byte[] buffer = new byte[NumberOfBytesToRead];
            char[] recData = new char[NumberOfBytesToRead];

            mySerial.Read(buffer, 0, buffer.Length);
            mySerial.DiscardInBuffer();
            mySerial.Flush();

            recData = System.Text.Encoding.UTF8.GetChars(buffer);

            //Testausgabe START
            string s = new string(recData);
            Debug.Print(recData[0].ToString() + NumberOfBytesToRead.ToString() + " | " + s);
            //Testausgabe ENDE

            if ((recData[0] == 'E') && (recData[NumberOfBytesToRead - 1] == '\n') && (NumberOfBytesToRead < 20))
            {
                Debug.Print("read");
                buffer = null;
            }
        }


You should just start a new thread that reads data when it’s available. It stuffs it into a buffer that you can then look at in your timer.

Your current structure of the program is anything but simple Why do you bother doing things in the datarecieved event except read data?
.

Sorry, I’ve never worked with threads because my programs have always been small so far.

You mean something like this?


void ProgramStarted()
        {
            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");

            _mySerial = new GT.Interfaces.Serial(GT.Socket.GetSocket(8, false, null, null),
                        BaudRate,
                        GT.Interfaces.Serial.SerialParity.None,
                        GT.Interfaces.Serial.SerialStopBits.One,
                        DataBits_Input,
                        GT.Interfaces.Serial.HardwareFlowControl.NotRequired,
                        null);

            Thread t = new Thread(new ThreadStart(() =>
            {
                _mySerial.DataReceived += new GT.Interfaces.Serial.DataReceivedEventHandler(_mySerial_DataReceived);
            }));

            _mySerial.Open();
            t.Start();
        }

In the DataReceived event stands more, because I need to build a routine that queries only 3 times in the 100ms RX.

Sorry i am a newbee in this area and especially to work with gadgeteer.

I am not sure of the current status, but in the past you could have a problem if you registered for the data received event before you opened a serial port.

Ok, i tried it with timer. I believe that I have the right approach, but i dont understand, why the timer give me a NullReferenceException.
It looks as if the timer reacts faster than data received, its strange, because my ZigBit modul sends every 10ms and the timer tick is 100ms.

Another question: Is it possible to query an interrupt on pin RX manually?

Here the Code:


        GT.Interfaces.Serial _mySerial;
        const int BaudRate = 115200;
        const int DataBits_Input = 8;

        byte[] buffer;
        char[] recData;

        GT.Timer timer;

        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {


            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");
            Microsoft.SPOT.Hardware.Utility.SetLocalTime(DateTime.Now.Add(new TimeSpan(10, 06, 0)));

            _mySerial = new GT.Interfaces.Serial(GT.Socket.GetSocket(8, false, null, null),
              BaudRate,
              GT.Interfaces.Serial.SerialParity.None,
              GT.Interfaces.Serial.SerialStopBits.One,
              DataBits_Input,
              GT.Interfaces.Serial.HardwareFlowControl.NotRequired,
              null);
            _mySerial.DataReceived += new GT.Interfaces.Serial.DataReceivedEventHandler(_mySerial_DataReceived);
            _mySerial.Open();

            timer = new GT.Timer(100);
            timer.Tick += new GT.Timer.TickEventHandler(timer_Tick);
            timer.Start();
        }

        void timer_Tick(GT.Timer timer)
        {
            
                recData = new char[buffer.Length];
                recData = System.Text.Encoding.UTF8.GetChars(buffer);
                Interpret();
                buffer = null;
        }

        void _mySerial_DataReceived(GT.Interfaces.Serial sender, System.IO.Ports.SerialData data)
        {
            int NumberOfBytesToRead = _mySerial.BytesToRead;
            buffer = new byte[NumberOfBytesToRead];

            _mySerial.Read(buffer, 0, buffer.Length);
            _mySerial.DiscardInBuffer();
            _mySerial.Flush();
        }

        private string bytesToString(byte[] bytes)
        {
            string s = "";
            for (int i = 0; i < bytes.Length; ++i)
                s += (char)bytes[i];
            return s;
        }

        private void Interpret()
        {
             //for later
            string output_imu = bytesToString(buffer);
            Debug.Print(output_imu);
        }


Ok, now i see for every tick an empty line in system console, but no data.

Maybe i should explain, what my Enddevices send.

Every enddevice (ZigBit Slave) send a string like this: E09 I00 V3498
The number behind “E” stand for the enddevice who send actually.
The number behind “V” stand for the digits, they can be from 0 to no limit

Thats the new output which repeats. Thats right, the last character of the string is ‘\n’.

Only \n.

Now i have an output with your first solution ( only with \n as delimiter).
There are 2 devices which send actually. The last digits are higher if i change the poti, which is connected with the slave.

My problem is that I can only call 100ms each device once.
So if I have 3 devices, then I can in the time of each device only once get an input. I do not know how it is to be realized.

My device send exactly: Exx Ixx Vxxxxx\n

After the V the value is variable. This means that the length of a transmitted strings is never equal.

On the one side I have one Zigbit Modul (Master) which connected to the gadgeteer over UART.
On the other side, i have one or more Zigbit Moduls (max. 8) (Slaves) which send data on radio every 10ms.

The condition is that all slaves every 100ms be queried ONE time write the collected results to a text file.

I hope I have explained clearly.

So let me get this straight.

You need to send something to each remote device saying “send me your data”, then you’ll get a response from them and store off their data, then move to the next remote device, “send me your data”, store received data, “send me your data”, store data. And you might have up to 8 devices to do this to? And you have to do that every 100ms?

I personally would be surprised if you can deal with up to 8 in the timeframe. Parsing strings is your problem.

But you also talk about your devices sending data all the time. Unless you can stop listening, you’ll always get much more data than you can parse.

I must query only the RX port, without saying the device “send me your data”. The data are continuously sent to speak directly without the device.

And yes, it can be up to 8 devices. It now works in the way that I have the data in each storable tick an array, and the next ticking again on writing. Only the store only works no longer in 100ms.

Otherwise, my problem is solved. Thank you.

So if the devices are sending you data every 10ms, that means up to 8 data points in strings every 10ms, and you say you’re handling that now? Great.

So next, let me understand what you need to do? Every 100ms, you need to take the currently recorded values from those sensors and do something with them, write them somewhere. What part of that isn’t working? Isn’t it as simple as in the timer, take the current value in the variable and perform your action? If you can’t poll the device then that’s the logical approach, in my view.