Home » C# ProgrammingRSS

SerialPort.Write & DataReceived issues

I'm having some issues with what I think may be caused by serial packet collision or packets getting clipped. 

I have an ATMEL 168 based microcontroller that I am communicating with through the SerialPort object in a C# Windows Form Application. The board has 5 IO pins, 3 Analog and 2 PWM. I have two TrackBar Controls on the form to control the PWM value (0-255), one checkbox to toggle the polling for the inputs and another TrackBar to control the Interval (30 - 2000 ms) of the Timer. What happens is that as soon as I enable the Timer to start the polling, the servos (PWM) start "twitching" as I scroll the TrackBars. 

 

I trimmed down the code below for clarity's sake but I've tried checking if BytesToRead is equal to 0 prior to issuing another SerialPort.Read, in addition to doing the same for SerialPort.Write.

 

 

 

  public partial class Form2 : Form
  {
    System.IO.Ports.SerialPort port = new System.IO.Ports.SerialPort();
    System.Timers.Timer tmrPolling = new System.Timers.Timer(200);
    static byte[] inputPacket = new byte[2] { (byte)255, (byte)0 }; // Byte to send to SerialPort when input polling timer is activated.

    public Form2()
    {
      InitializeComponent();
      port.PortName = "COM9";
      port.BaudRate = 38400;
      port.DataBits = 8;
      port.StopBits = System.IO.Ports.StopBits.One;
      port.Parity = System.IO.Ports.Parity.None;
      port.ReadTimeout = 1;
      port.ReceivedBytesThreshold = 5;
      port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived);
      port.Open();      
      tmrPolling.Elapsed += new System.Timers.ElapsedEventHandler(tmrPolling_Elapsed);     
    }

    void tmrPolling_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {  
      port.Write(inputPacket, 0, 2); // writes the input packet to the SerialPort - needed to read the IO values
    }
    
    void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
      // Reads the data coming in from the serial port and calls the thread safe delegate to update the values on the form.
      byte[] received = new byte[port.BytesToRead];
      port.Read(received, 0, received.Length);          
    }

    private void UpdateValues()
    {
      byte[] b = new byte[] { (byte)255, (byte)6, (byte)hsbPan.Value, (byte)vsbTilt.Value, (byte)0,       
        (byte)0, (byte)0, (byte)0, (byte)13, (byte)10 };
      port.Write(b, 0, 9);
    }

    private void chkEnablePolling_CheckedChanged(object sender, EventArgs e)
    {     
      tmrPolling.Enabled = chkEnablePolling.Checked;     
      vsbInputInterval.Enabled = chkEnablePolling.Checked;
      vsbInputInterval.Value = Convert.ToInt32(tmrPolling.Interval);
      txtInputInterval.Enabled = chkEnablePolling.Checked;
      txtInputInterval.Text = ((float)tmrPolling.Interval / (float)1000).ToString() + " sec";
    }

    private void vsbInputInterval_Scroll(object sender, ScrollEventArgs e)
    {
      // adjusts the tick frequency of the Timer for input polling. 
      txtInputInterval.Text = ((float)tmrPolling.Interval / (float)1000).ToString() + " sec";
      tmrPolling.Interval = vsbInputInterval.Value;
    }    

    private void vsbTilt_Scroll(object sender, ScrollEventArgs e)
    {
      UpdateValues();
    }

    private void hsbPan_Scroll(object sender, ScrollEventArgs e)
    {
      UpdateValues();
    }
  }

 

 

 

3 Answers Found

 

Answer 1

One thing which you could do is to only call UpdateValues when the scrollbar values change.

So, something like...

private void hsbPan_Scroll(object sender, ScrollEventArgs e)
{
  if (e.NewValue != e.OldValue)
    UpdateValues();
}

This will prevent any uneccessary transmission of data. You may want to have some kind of global flag which you set and clear during your write  routine, you can then check this to prevent or stall any future writes although I don't think a packet clash is your problem.

Also, do you have a clean GND rail? Do you have access to an oscilloscope?

Kev

 

Answer 2

GND was checked - The board has already gone through our hardware engineer's hands (eg. most potential hardware & firmware issues  have been cleared although there's always a chance that they missed something).

 

Adding the new/old value check had no effect. 

 

Answer 3

I found out that this is related to hardware in that the buffer of the microcontroller is getting overloaded. I'm currently looking into using the SerialPort.BaseStream for some Async operations to let the application know when it's cool to send/receive more data.

Any tips? 

 
 
 

<< Previous      Next >>


Microsoft   |   Windows   |   Visual Studio   |   Follow us on Twitter