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();
}
}