Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Serial communications timing mismatch?

serial

  • Please log in to reply
2 replies to this topic

#1 Verdris

Verdris

    Advanced Member

  • Members
  • PipPipPip
  • 128 posts
  • LocationReno, NV

Posted 23 April 2013 - 10:03 PM

Hi all,

 

On my PC side I have

gooby.Write(xmit, 0, 4);

 

where gooby is a SerialPort and xmit is a 4 byte array.

 

On the Netduino side, inside the event handler I have

gooby.Read(xmit, 0, 4);

 

where gooby and xmit are declared as on the PC side. The settings for the serial ports match identically.

 

What I'm trying to do is transmit an integer 0-5000 from the PC to the Netduino. Easy enough, I break the integer into its component bytes and transmit them. However, on the Netduino side, all 4 bytes don't always arrive. Sometimes the event handler thinks there are 3, sometimes 1, sometimes 0. Also, occasionally it will offset by a whole byte, making a number like 1250 come out to 320000. This is easy enough to fix with a while loop, but on the occasion where it receives 0 bytes, not only does it crash the PWM (by passing a frequency of 0) but it will result in creepy offsets for all subsequent serial communications.

 

Ideas?

 

using System;using System.Net;using System.Net.Sockets;using System.Threading;using Microsoft.SPOT;using Microsoft.SPOT.Hardware;using SecretLabs.NETMF.Hardware;using SecretLabs.NETMF.Hardware.Netduino;using System.IO.Ports;using System.Text;namespace Chatty{    public class Program    {        public static SerialPort gooby = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);        public static PWM rawr = new PWM(PWMChannels.PWM_PIN_D10, 1000, 0.5, false);        public static OutputPort light = new OutputPort(Pins.ONBOARD_LED, false);        public static void Main()        {            gooby.DataReceived += new SerialDataReceivedEventHandler(on_rec);            gooby.Open();            Thread.Sleep(Timeout.Infinite);        }        public static void on_rec(object sender, SerialDataReceivedEventArgs e)        {            light.Write(true);            Debug.Print("Bytes in buffer: " + gooby.BytesToRead.ToString());            rawr.Stop();            byte[] xmit = new byte[4];            gooby.Read(xmit, 0, 4);            int result = 0;            for (int i = 0; i < 4; i++)            {                Debug.Print("Byte " + (i + 1).ToString() + ": " + xmit[i].ToString());                result += ((Int32)(xmit[i]) << (24 - (i * 8)));            }            while (result > 5000)            {                result = result >> 8;            }            Debug.Print("Result: " + result.ToString());            rawr.Frequency = result;            rawr.Start();            light.Write(false);        }    }}

 

 



#2 Shadi

Shadi

    Member

  • Members
  • PipPip
  • 12 posts

Posted 23 April 2013 - 10:47 PM

You're ignoring an important return variable with [color=rgb(0,0,0);font-family:monospace;font-size:13px;]gooby[/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;].[/color][color=rgb(102,0,102);font-family:monospace;font-size:13px;]Read[/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;]([/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;]xmit[/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;],[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;] [/color][color=rgb(0,102,102);font-family:monospace;font-size:13px;]0[/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;],[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;] [/color][color=rgb(0,102,102);font-family:monospace;font-size:13px;]4[/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;]);[/color]

You're also ignoring [color=rgb(102,0,102);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]SerialDataReceivedEventArgs[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);] e's EventType, which should be checked.[/color]

 

[color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]Read doesn't guarantee the buffer will be filled by the Read method.[/color] So it is best to use the return value from Read to determine how much more you need to read.

 

So you would need a buffer that has larger scope than your event. You can either directly work with this buffer or create a buffer & copy bytes read into it. Also, you need to remember to call Read() until it returns 0, because the event may not trigger again and the bytes in the serial port buffer will get lonely.

 

[font="'courier new', courier, monospace;"]const int ProtocolLength = 4;[/font]

[font="'courier new', courier, monospace;"]static int bufferPos = 0;[/font]

[font="'courier new', courier, monospace;"]static byte[] buffer = new byte[[/font]ProtocolLength[color=rgb(0,0,0);font-size:small;]];[/color]

 

[font="'courier new', courier, monospace;"]int readLen = 0;[/font]

[font="'courier new', courier, monospace;"]do[/font]

[font="'courier new', courier, monospace;"]{[/font]

[font="'courier new', courier, monospace;"]readLen = gooby.Read(buffer, bufferPos, [/font]ProtocolLength - bufferPos[color=rgb(0,0,0);font-size:small;]);[/color]

[font="'courier new', courier, monospace;"]bufferPos += readLen;[/font]

[font="'courier new', courier, monospace;"]if (bufferPos == [/font]ProtocolLength[color=rgb(0,0,0);font-size:small;])[/color]

[font="'courier new', courier, monospace;"]{[/font]

[font="'courier new', courier, monospace;"]// call PWM method here[/font]

[font="'courier new', courier, monospace;"]bufferPos = 0; // restart protocol buffer[/font]

[font="'courier new', courier, monospace;"]}[/font]

[font="'courier new', courier, monospace;"]}[/font]

[font="'courier new', courier, monospace;"]while(readLen > 0);[/font]

 

 have no idea if the above code works 100%, but it looks like it should.



#3 ziggurat29

ziggurat29

    Advanced Member

  • Members
  • PipPipPip
  • 244 posts

Posted 24 April 2013 - 12:32 AM

I second shadi's points about needing to consume all readable data in your event handler, and that you also need a buffer that lives longer than one event, so you can accumulate partial data until you have a complete whatever-you-are-transferring.

 

I want to add from personal experience that I found the DataReceived event to be unreliably delivered -- it works for a while, then just stops firing events (on the NP2 as of this writing).  This same code was validated on the desktop so I'm fairly sure that the problem is netmf specific.  I worked around it by using a worker thread that monitors BytesToRead and then 'fires' (i.e. 'calls') a pseudo event method that has the same implementation as a conventional 'DataReceived' event handler.







Also tagged with one or more of these keywords: serial

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.