serialport responding to EventHandler, but not ReadExisting or ReadLine? - c#

i have a program that's reading from serial port in c#. i need to quickly write to a port, read from it, then close it. i cannot leave it open. i understand that serial ports read and write slowly, I've tried to set the ReadTimeout and WriteTimeout properties high, and added a thread.Sleep to try to drag the read and write times out for the devices. here's a little bit of code:
my method to write to port:
private void CheckPorts(string testMessage)
{
foreach (string s in SerialPort.GetPortNames())
{
portNumber = Int32.Parse(s.Remove(0, 3));
testSerial = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
if (testSerial.IsOpen)
{
testSerial.Close();
}
testSerial.ReadTimeout = 2000;
testSerial.WriteTimeout = 1000;
testSerial.Open();
if (testSerial.IsOpen)
{
string received;
testSerial.DiscardInBuffer();
try
{
//testSerial.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);
testSerial.Write(testMessage);
System.Threading.Thread.Sleep(2000);
received = testSerial.ReadExisting(); //EITHER I USE THIS OR EVENT HANDLER, NOT BOTH
}
catch (TimeoutException e)
{
testSerial.Close();
continue;
}
if (received.Length > 0)
{
MessageReceived(received);
}
testSerial.Close();
}
}
}
private void testSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string received = testSerial.ReadExisting();
int y = received.IndexOf("\r");
while (y == -1)
{
received = received + testSerial.ReadExisting();
y = received.IndexOf("\r");
}
if (testSerial.IsOpen)
{
testSerial.Close();
}
}
i'm wondering, if i absolutely have to use datahandler, how do i keep the serial port open long enough to read from it, but close the serialport before the next port needs to be opened?
see, the first method gets called a few times, and it iterates through a foreach loop, trying a message on a few ports, then trying to read a response. so, at some point i have to close the ports, or else the next time it goes through it, it doesn't work properly because the port is still open
HERE'S MY UPDATED CODE (still not working):
private void CheckPorts(string testMessage, int baudRate)
{
foreach (string s in SerialPort.GetPortNames())
{
var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;
if (testSerial.IsOpen)
testSerial.Close(); // may not be necessary with Dispose?
testSerial.Dispose();
timer.Dispose();
};
portNumber = Int32.Parse(s.Remove(0, 3));
testSerial = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
testSerial.ReadTimeout = 2000;
testSerial.WriteTimeout = 2000;
if (testSerial.IsOpen)
{
testSerial.Close();
}
testSerial.Open();
timer.Enabled = true;
if (testSerial.IsOpen)
{
string received;
//testSerial.DiscardInBuffer();
//autoEvent = new AutoResetEvent(false);
try
{
// testSerial.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);
// autoEvent.Reset();
lblPortNum.Content = s;
lblPortNum.Refresh();
testSerial.Write(testMessage);
//System.Threading.Thread.Sleep(2000);
//testSerial.NewLine = "\r\n";
byte[] rBuff = new byte[2];
int rCnt = testSerial.Read(rBuff, 0, 2);
System.Text.Encoding enc = System.Text.Encoding.ASCII;
received = enc.GetString(rBuff);
//received = testSerial.ReadLine();
}
catch (TimeoutException e)
{
testSerial.Close();
continue;
}
if (received.Length > 0)
{
MessageReceived(received, Int16.Parse(s.Remove(0, 3)));
}
/*
if (autoEvent.WaitOne(2000))
{
// the port responded
// testSerial.Close();
autoEvent.Dispose();
lblPortNum.Content = "HEY I RESPONDED";
}
else
{
testSerial.Close();
autoEvent.Dispose();
continue;
// port did not respond within 2 seconds
}*/
//testSerial.Close();
}
}
}
UPDATED AGAIN (still not working properly)
private void CheckPorts(string testMessage, int baudRate)
{
foreach (string s in SerialPort.GetPortNames())
{
portNumber = Int32.Parse(s.Remove(0, 3));
// MUST BE LOCAL
var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
serialOneOfMany.ReadTimeout = 2000;
serialOneOfMany.WriteTimeout = 2000;
if (serialOneOfMany.IsOpen)
{
serialOneOfMany.Close();
}
// timer must be defined _after_ serialOneOfMany
var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;
if (serialOneOfMany.IsOpen)
serialOneOfMany.Close(); // may not be necessary with Dispose?
serialOneOfMany.Dispose();
timer.Dispose();
};
if (serialOneOfMany.IsOpen)
{
string received;
try
{
lblPortNum.Content = s;
lblPortNum.Refresh();
serialOneOfMany.Write(testMessage);
byte[] rBuff = new byte[2];
int rCnt = serialOneOfMany.Read(rBuff, 0, 2);
System.Text.Encoding enc = System.Text.Encoding.ASCII;
received = enc.GetString(rBuff);
}
catch (TimeoutException e)
{
serialOneOfMany.Close();
continue;
}
if (received.Length > 0)
{
CheckIfTheMessageMatches(received, Int16.Parse(s.Remove(0, 3)));
}
}
}
}
so with this update, it just blows through the code, i can step through the code line by line, but it doesn't stop for 3 seconds at all. if i run it without any debugging breaks, it just goes through it i a fraction of a second
UPDATE 10-25-11
private void CheckPorts(string testMessage, int baudRate)
{
foreach (string s in SerialPort.GetPortNames())
{
string received = "";
testSerial = new SerialPort(s,baudRate, Parity.None, 8, StopBits.One);
lblStatus.Content = "Scanning...";
lblStatus.Refresh();
if (testSerial.IsOpen)
{
testSerial.Close();
}
else
{
testSerial.Open();
}
if (testSerial.IsOpen)
{
try
{
testSerial.NewLine = "\r";
lblPortNum.Content = s;
lblPortNum.Refresh();
testSerial.WriteTimeout= 500;
testSerial.ReadTimeout = 1000;
testSerial.WriteLine(testMessage);
System.Threading.Thread.Sleep(500);
/*THIS DOESN'T WORK
byte[] buffer = new byte[testSerial.BytesToRead];
int rCnt = testSerial.Read(buffer, 0, buffer.Length);
received = enc.GetString(buffer);*/
//received = Convert.ToString(testSerial.BaseStream.Read(buffer, 0, (int)buffer.Length));
received = testSerial.ReadLine();
int y = received.IndexOf("\r");
while (y == -1)
{
received = received + testSerial.ReadExisting();
y = received.Length;
}
if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
{
CheckIfTheMessageMatches(received, s);
received = received + lblInfo.Content;
lblInfo.Content = received;
}
else
{
lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
}
if (testSerial.IsOpen)
{
testSerial.Close();
}
/*I USE THIS WITH THE sPort.Read() METHOD
while (rCnt > 0)
{
if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
{
CheckIfTheMessageMatches(received, s);
rCnt = 0;
received = received + lblInfo.Content;
lblInfo.Content = received;
}
else
{
lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
}
}
*/
if (testSerial.IsOpen)
{
testSerial.Close();
}
}
catch (TimeoutException e)
{
testSerial.Close();
continue;
}
received = null;
}
}
lblStatus.Content = "Finished Scanning.";
lblPortNum.Content = "";
}
UPDATED CODE
here's some new code, still not working, dataeventhandler not even called once. i know it's getting messages because i have another program that works with the serial devices
private void CheckPorts(string testMessage, int baudRate)
{
foreach (string s in SerialPort.GetPortNames())
{
var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
serialOneOfMany.ReadTimeout = 700;
serialOneOfMany.WriteTimeout = 100;
var interval = 500; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;
if (serialOneOfMany.IsOpen)
serialOneOfMany.Close(); // may not be necessary with Dispose?
serialOneOfMany.Dispose();
timer.Dispose();
};
timer.Enabled = true;
lblStatus.Content = "Scanning...";
lblStatus.Refresh();
if (serialOneOfMany.IsOpen)
{
serialOneOfMany.Close();
}
else
{
serialOneOfMany.Open();
}
if (serialOneOfMany.IsOpen)
{
string received;
try
{
lblPortNum.Content = s;
lblPortNum.Refresh();
serialOneOfMany.WriteLine(testMessage);
System.Threading.Thread.Sleep(400);
serialOneOfMany.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);
}
catch (TimeoutException e)
{
serialOneOfMany.Close();
continue;
}
}
}
lblStatus.Content = "Finished Scanning.";
lblPortNum.Content = "";
}
private void testSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort receivingSerial = sender as SerialPort;
string received = receivingSerial.ReadExisting();
int y = received.IndexOf("\r");
while (y == -1)
{
received = received + receivingSerial.ReadExisting();
y = received.IndexOf("\r");
}
if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
{
string name = receivingSerial.PortName;
received = received + lblInfo.Content;
lblInfo.Content = received;
CheckIfTheMessageMatches(received, name);
}
else
{
lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
}
if (receivingSerial.IsOpen)
{
receivingSerial.Close();
}
}

You should be able to do these simultaneously (assuming that's ok). You would then close them as the DataReceived event is raised (extraneous code removed). Just don't close the port in CheckPorts.
private void testSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort localSerialPort = sender as SerialPort;
... // use localSerialPort instead of global/class variable
if (localSerialPort.IsOpen)
{
localSerialPort.Close();
}
}
EDIT: Responding to comment.
You can always add a timer on the fly. If you put this in the foreach loop, you'll get a timer for every serial port that will dispose its given serial port after 3 seconds. It's important here that the timer is declared within the foreach loop.
var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o,e) =>
{
timer.Enabled = false;
if (testSerial.IsOpen)
testSerial.Close(); // may not be necessary with Dispose?
testSerial.Dispose();
timer.Dispose();
}
timer.Enabled = true;
EDIT: Code updated so I'll update
Scope is very important with the code I provided. You should get rid of the non-local testSerial or use an entirely different name here.
portNumber = Int32.Parse(s.Remove(0, 3));
// MUST BE LOCAL
var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
serialOneOfMany.ReadTimeout = 2000;
serialOneOfMany.WriteTimeout = 2000;
if (serialOneOfMany.IsOpen)
{
serialOneOfMany.Close();
}
// timer must be defined _after_ serialOneOfMany
var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;
if (serialOneOfMany.IsOpen)
serialOneOfMany.Close(); // may not be necessary with Dispose?
serialOneOfMany.Dispose();
timer.Dispose();
};

Check this info from Microsoft:
This method returns the contents of the stream and internal buffer of the SerialPort object as a string. This method does not use a time-out. Note that this method can leave trailing lead bytes in the internal buffer, which makes the BytesToRead value greater than zero.
Why don't use the usual Read method SerialPort.Read (Byte[], Int32, Int32)

Please have a look at this (I also used in an answer to a serial port related question asked by darthwillard). All the ports are opened one after another, the DataReceived events are bound (all you need to do there is to test the incoming message), but no waiting is required. The timer event handler can close all the ports or keep the one you want to use etc. I hope it helps!
private List<SerialPort> openPorts = new List<SerialPort>();
private void button3_Click(object sender, EventArgs e)
{
int baudRate = 9600;
string testMessage = "test";
txtPortName.Text = "Testing all serial ports";
foreach (string s in SerialPort.GetPortNames())
{
SerialPort newPort = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
if (!newPort.IsOpen)
{
try
{
newPort.Open();
}
catch { }
}
if (newPort.IsOpen)
{
openPorts.Add(newPort);
newPort.DataReceived += new SerialDataReceivedEventHandler(serialOneOfMany_DataReceived);
newPort.Write(testMessage);
}
else
{
newPort.Dispose();
}
}
txtPortName.Text = "Waiting for response";
tmrPortTest.Enabled = true;
}
private void serialOneOfMany_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
txtPortName.Text = ((SerialPort)sender).PortName;
}
private void tmrPortTest_Tick(object sender, EventArgs e)
{
tmrPortTest.Enabled = false;
foreach (SerialPort port in openPorts)
{
if (port.PortName != txtPortName.Text)
{
port.Close();
port.Dispose();
}
}
}

Try setting your event handler before you write to the port, and then see if it doesn't catch your break point.

You can't use Thread.Sleep. It blocks the read from the device. You need to spawn a new thread.

You may be best with BackgroundWorker. Eg:
BackgroundWorker worker=new BackgroundWorker();
worker.DoWork += (s, dwe) =>
{
// do your serial IO here
worker.RunWorkerCompleted += (s, rwe) =>
{
// check for rwe.Error and respond
};
worker.RunWorkerAsync();

open the port in public form1
just after/below the InitializeComponent(); myport.open
and close the after data is received.
worked!

Related

TCP-IP Connection Android App to C# Server

so what im actually trying to do is to comunicate with a DMX-Interface pluged to a PC/Host via an Xamarin Android App.
Allready got my Server running, works also with an console client i wrote first. So now I wrote the app,using the same Way as before, with a TCPClient and then writing the data via a stream.
Because I'm running the app in the emulator I use as IP 10.0.2.2 to connect, but I cannot establish a connection. The App crashes or I get a timeout exeption. Been trying and researching now for two days and now i'm desperate, so I attach my code here, hope anyone can help
Thanks, Johannes
App:
public class MainActivity : Activity
{
public Stream Stream;
TcpClient Client = null;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
//adding control elements from Resource.Layout.Main
Button at = FindViewById<Button>(Resource.Id.at);
Button enter = FindViewById<Button>(Resource.Id.enter);
Button thru = FindViewById<Button>(Resource.Id.thru);
Button all = FindViewById<Button>(Resource.Id.all);
Button one = FindViewById<Button>(Resource.Id.one);
Button two = FindViewById<Button>(Resource.Id.two);
Button three = FindViewById<Button>(Resource.Id.three);
Button four = FindViewById<Button>(Resource.Id.four);
Button five = FindViewById<Button>(Resource.Id.five);
Button six = FindViewById<Button>(Resource.Id.six);
Button seven = FindViewById<Button>(Resource.Id.seven);
Button eight = FindViewById<Button>(Resource.Id.eight);
Button nine = FindViewById<Button>(Resource.Id.nine);
Button zero = FindViewById<Button>(Resource.Id.zero);
Button comma = FindViewById<Button>(Resource.Id.comma);
Button connect = FindViewById<Button>(Resource.Id.connect);
Button clear = FindViewById<Button>(Resource.Id.clear);
at.Click += (o, e) =>
{
UpdateCmdLine("#");
};
clear.Click += (o, e) =>
{
FlushCmdLine();
};
enter.Click += (o, e) =>
{
TextView cmdLine = FindViewById<TextView>(Resource.Id.cmdLine);
ProcessData(cmdLine.Text);
FlushCmdLine();
};
thru.Click += (o, e) =>
{
UpdateCmdLine("/");
};
all.Click += (o, e) =>
{
UpdateCmdLine("#");
};
one.Click += (o, e) =>
{
UpdateCmdLine("1");
};
two.Click += (o, e) =>
{
UpdateCmdLine("2");
};
three.Click += (o, e) =>
{
UpdateCmdLine("3");
};
four.Click += (o, e) =>
{
UpdateCmdLine("4");
};
five.Click += (o, e) =>
{
UpdateCmdLine("5");
};
six.Click += (o, e) =>
{
UpdateCmdLine("6");
};
seven.Click += (o, e) =>
{
UpdateCmdLine("7");
};
eight.Click += (o, e) =>
{
UpdateCmdLine("8");
};
nine.Click += (o, e) =>
{
UpdateCmdLine("9");
};
zero.Click += (o, e) =>
{
UpdateCmdLine("0");
};
comma.Click += (o, e) =>
{
UpdateCmdLine(",");
};
connect.Click += (o, e) =>
{
try
{
TextView ip = FindViewById<TextView>(Resource.Id.ipField);
TextView port = FindViewById<TextView>(Resource.Id.portField);
TextView connectionStatus = FindViewById<TextView>(Resource.Id.connectedStatus);
Client = new TcpClient("10.0.2.2", 4711);
connectionStatus.Text = "Connected";
}
catch (System.Exception)
{
}
};
//implementing click functions
}
public void UpdateCmdLine(string update)
{
TextView cmdLine = FindViewById<TextView>(Resource.Id.cmdLine);
cmdLine.Text += update;
}
public void FlushCmdLine()
{
TextView cmdLine = FindViewById<TextView>(Resource.Id.cmdLine);
cmdLine.Text = "";
}
public int[] GetData(string channel, string value)
{
int[] data = new int[] {Int32.Parse(channel), Int32.Parse(value)};
return data;
}
public void SendData(int channel, int data)
{
if (Client.Connected)
{
Stream = Client.GetStream();
byte[] outgoingBytes = new byte[] {Convert.ToByte(channel),Convert.ToByte(data)};
Stream.Write(outgoingBytes,0,outgoingBytes.Length);
}
}
public void ProcessData(string cmdLine)
{
string[] divideStackedOps = cmdLine.Split(',');
foreach (string s in divideStackedOps)
{
if (s.Contains("/"))
{
string[] dividedThru = s.Split('/');
int channel1 = Int32.Parse(dividedThru[0]);
string[] dividedAt = dividedThru[1].Split('#');
int channel2 = Int32.Parse(dividedAt[0]);
int value = Int32.Parse(dividedAt[1]);
for (int e = channel2; e >= channel1; e--)
{
SendData(e, value);
}
}
else if (s.Contains("#"))
{
string[]dividedAll = s.Split('#');
int value = Int32.Parse(dividedAll[1]);
for (int e = 100; e > 0; e--)
{
SendData(e, value);
}
}
}
}
}
}
Server
public class DmxInterface
{
[DllImport("K8062D.dll")]
public static extern void StartDevice();
[DllImport("K8062D.dll")]
public static extern void SetData(int channel, int data);
[DllImport("K8062D.dll")]
public static extern void StopDevice();
[DllImport("K8062D.dll")]
public static extern void SetChannelCount(int count);
}
class Program
{
private static TcpListener Listener;
private static ArrayList Threads = new ArrayList();
public static Boolean ServerStopped;
public static void Main()
{
DmxInterface.StartDevice();
DmxInterface.SetChannelCount(10);
//Initialize Listener, start Listener
int port = 4711;
IPAddress ip = IPAddress.Parse("127.0.0.1");
Listener = new TcpListener(ip, port);
Listener.Start();
Console.WriteLine("Creating new listener on: "+ip+":"+port);
//Initialize MainServerThread, start MainServerThread
Console.WriteLine("Starting MainThread");
Thread mainThread = new Thread(Run);
mainThread.Start();
Console.WriteLine("Done");
while (!ServerStopped)
{
Console.WriteLine("Write 'stop' to stop Server...");
String cmd = "";
cmd = Console.ReadLine();
if (cmd.ToLower().Equals("stop"))
{
Console.WriteLine("stopping server");
ServerStopped = true;
}
else
{
Console.WriteLine("unknow command: " + cmd);
}
}
EndThreads(mainThread);
}
public static void EndThreads(Thread mainThread)
{
//stopping MainThread
mainThread.Abort();
Console.WriteLine("MainThread stopped");
//stopping all Threads
for (IEnumerator e = Threads.GetEnumerator(); e.MoveNext();)
{
//Getting next ServerThread
Console.WriteLine("Stopping the ServerThreads");
ServerThread serverThread = (ServerThread)e.Current;
//Stop it
serverThread.Stop = true;
while (serverThread.Running)
{
Thread.Sleep(1000);
}
}
//Stopping Listener
Listener.Stop();
Console.WriteLine("listener stopped");
Thread.Sleep(5000);
Console.Clear();
}
//opening a new ServerThread
public static void Run()
{
while (true)
{
Console.WriteLine("Listener waiting for connection wish");
//waiting for incoming connection wish
TcpClient client = Listener.AcceptTcpClient();
Threads.Add(new ServerThread(client));
}
}
}
class ServerThread
{
public bool Stop;
public bool Running;
private TcpClient client;
public ServerThread(TcpClient client)
{
this.client = client;
//starting new thread with run() function
Console.WriteLine("Starting new ServerThread");
new Thread(new ThreadStart(Run)).Start();
}
//threaded function
public void Run()
{
Stream stream = null;
Boolean gotstream = false;
Console.WriteLine("Reading incoming Data Stream");
Running = true;
while (!gotstream)
{
//making sure stream is not null to avoid exeption
if (client.GetStream() != null)
{
//getting stream, setting flag true
stream = client.GetStream();
gotstream = true;
}
}
Boolean loop = true;
byte[] incomingValues = new byte[] {255, 255};
Boolean gotData = false;
while (loop)
{
//checking if a remote host is still connected
if (client.Connected)
{
try
{
//reading Byte Array
stream.Read(incomingValues, 0, incomingValues.Length);
gotData = true;
}
catch (Exception e)
{
//catching exeptions
Console.WriteLine("Ooops, something wrent wrogn \n" + e);
loop = false;
}
if (gotData)
{
//converting bytes to int, sending DMX Values
int channel = Convert.ToInt32(incomingValues[0]);
int value = Convert.ToInt32(incomingValues[1]);
DmxInterface.SetData(channel, value);
Console.WriteLine("Received Data... \n Channel: " + channel + " Value: " + value);
}
}
else
{
//exiting loop if connection is lost
Console.WriteLine("connection lost");
Program.ServerStopped = true;
loop = false;
}
}
}
}
}

serial communication rs232 and eurotherm 2208e

i have a problem with rs232 and Eurotherme 2208e this is the code without problem.
public Window8()
{
InitializeComponent();
DispatcherTimer myDispatcherTimer = new DispatcherTimer();
myDispatcherTimer.Interval = new TimeSpan(0, 0, 1); // 100 Milliseconds
myDispatcherTimer.Tick += myDispatcherTimer_Tick;
myDispatcherTimer.Start();
}
void myDispatcherTimer_Tick(object sender, EventArgs e)
{
textBlock1.Text = DateTime.Now.ToString("HH:mm:ss");
}
public void port_DataReceived(object o, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
time_out.Stop();
msg_recu += port.ReadExisting();
Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Send, new recevoir_del(recevoir), oven_index);
}catch(UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message,"",MessageBoxButton.OK,MessageBoxImage.Error);
}
}
public delegate void ask_mesure_del(four oven);
public void ask_mesure(four new_etuve)
{
try{
msg_recu = "";
if (new_etuve.regulateur=="EUROTHERM") {
port.StopBits = StopBits.One;
demande_pv_E[1] = demande_pv_E[2] = (byte)new_etuve.gid.ToString().ElementAt(0);
demande_pv_E[3] = demande_pv_E[4] = (byte)new_etuve.uid.ToString().ElementAt(0);
port.Write(demande_pv_E, 0, demande_pv_E.Length);
}
time_out.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "askmesure", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
this is the call instruction :
Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Send, new ask_mesure_del(ask_mesure), Oven_Class.list_Oven.ElementAt(oven_index));
when i add this bloc to function ask_mesure :
public delegate void ask_mesure_del(four oven);
public void ask_mesure(four new_etuve)
{
try{
msg_recu = "";
if (new_etuve.regulateur=="EUROTHERM") {
port.StopBits = StopBits.One;
demande_pv_E[1] = demande_pv_E[2] = (byte)new_etuve.gid.ToString().ElementAt(0);
demande_pv_E[3] = demande_pv_E[4] = (byte)new_etuve.uid.ToString().ElementAt(0);
port.Write(demande_pv_E, 0, demande_pv_E.Length);
}
if(flago == 1){
port.StopBits = StopBits.One;
ecriture_sl_h_E[1] = ecriture_sl_h_E[2] = (byte)new_etuve.gid.ToString().ElementAt(0);
ecriture_sl_h_E[3] = ecriture_sl_h_E[4] = (byte)new_etuve.uid.ToString().ElementAt(0);
for (int i = 0; i < new_etuve.consigne.ToString().Length; i++)
{
ecriture_sl_h_E[10 - i] = (byte)new_etuve.consigne.ToString().ElementAt(new_etuve.consigne.ToString().Length - 1 - i);
}
ecriture_sl_h_E[ecriture_sl_h_E.Length - 1] = bcc(ecriture_sl_h_E);
port.Write(ecriture_sl_h_E, 0, ecriture_sl_h_E.Length);
}
time_out.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "askmesure", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
the port communicate 2 minute and after there is a connection failure 3 minute and connection returns
You may capture your communications to a file using any port monitoring software like Advanced Serial Port Monitor and see the last data packet. It is possible it will help you to diagnose the problem.
Then you may re-send the specific data packet to your program and debug it step-by-step.

passing arguments to ElapsedEventHandler C#

This program is designed to open two COM ports and send data from one to the other ever 1 second. The user inputs which port transmits and which port recieves. The problem I am having is with the ElapsedEventHandler() takes in the OnTimedEvent() function which has two default arguments. I want the OnTimedEvent() function to write something to the send port and read it in on the recieve port, then display it to the console. Obviously my code will not work the way I have it now because the ports and message are not in the scope of OnTimedEvent(). What can I do to make that function work the way I want? Thanks in advance.
using System;
using System.IO.Ports;
using System.Timers;
public class serial_test1
{
public static void Main(string[] args)
{
string sender;
string recver;
string buff_out;
string message;
SerialPort send_port;
SerialPort recv_port;
if (args.Length == 1)
{
sender = "UART";
recver = "USB";
message = args[0];
}
else if (args.Length == 2)
{
sender = args[0];
message = args[1];
if (sender == "USB")
{
recver = "UART";
}
else
{
recver = "USB";
}
}
else
{
sender = "UART";
recver = "USB";
message = "TEST MESSAGE";
}
int baud = 115200;
int data_bits = 8;
Parity parity = Parity.None;
StopBits stop_bits = StopBits.One;
buff_out = message;
SerialPort UARTport = new SerialPort("COM1", baud, parity, data_bits, stop_bits);
SerialPort USBport = new SerialPort("COM7", baud, parity, data_bits, stop_bits);
UARTport.Open();
USBport.Open();
if (sender == "USB")
{
send_port = USBport;
recv_port = UARTport;
}
if (sender == "UART")
{
send_port = UARTport;
recv_port = USBport;
}
string header = "from " + sender + " port to " + recver + " port";
Console.WriteLine(header);
Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 1 second.
aTimer.Interval = 1000;
aTimer.Enabled = true;
UARTport.Close();
USBport.Close();
Console.ReadLine();
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
string buff_in;
send_port.WriteLine(buff_out);
buff_in = recv_port.ReadLine();
Console.WriteLine(buff_in);
}
}
I suggest using System.Threading.Timer instead, you can pass in a state object into the constructor that is passed in to the TimerCallback.
You can use one of these options:
01 - Simply use an auxiliar object
static string _value;
static void MyElapsedMethod(object sender, ElapsedEventArgs e)
{
Console.WriteLine(_value);
}
02 - Or use a closed class
class CustomTimer : System.Timers.Timer
{
public string Data;
}
private void StartTimer()
{
var timer = new CustomTimer
{
Interval = 3000,
Data = "Foo Bar"
};
timer.Elapsed += timer_Elapsed;
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
string data = ((CustomTimer)sender).Data;
}

Not receiving data from Serial Port anymore?

I am using the SerialPort.ReadLine() method to display the data received from a Serial Port (code below).
Previously the code looked like that and received data but it did not send data. Now it is the other way around:
Since I placed the port.DataReceived event within the if(port==null) statement and added SerialPort port; as field, I don't receive data anymore. Can placing the event within an if statement change the way data is received and displayed? How can I fix that?
//Fields
List<string> myReceivedLines = new List<string>();
SerialPort port;
//subscriber method for the port.DataReceived Event
private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
while (sp.BytesToRead > 0)
{
try
{
myReceivedLines.Add(sp.ReadLine());
}
catch (TimeoutException)
{
break;
}
}
}
protected override void SolveInstance(IGH_DataAccess DA)
{
//Opening the port
if (port == null)
{
string selectedportname = default(string);
DA.GetData(1, ref selectedportname);
int selectedbaudrate = default(int);
DA.GetData(2, ref selectedbaudrate);
bool connecttodevice = default(bool);
DA.GetData(3, ref connecttodevice);
//Assigning an object to the field within the SolveInstance method()
port = new SerialPort(selectedportname, selectedbaudrate, Parity.None, 8, StopBits.One);
//Event Handling Method
if (connecttodevice == true)
{
port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
DA.SetDataList(0, myReceivedLines);
}
//Enables the data terminal ready (dtr) signal during serial communication (handshaking)
port.DtrEnable = true;
port.Open();
}
//Displays if port if opened
if (port.IsOpen)
{
DA.SetData(1, "Port Open");
}
//If the port is open do all the rest
if (port.IsOpen)
{
//Assigning the input to variables for the code.
List<string> gcode = new List<string>();
DA.GetDataList(0, gcode);
bool sendtoprint = default(bool);
DA.GetData(4, ref sendtoprint);
bool homeall = default(bool);
DA.GetData(5, ref homeall);
//What happens when input is set
if (sendtoprint == true)
{
if (homeall == true)
{
port.Write("G28" + "\n");
}
}
else
{
DA.SetData(1, "Port Closed");
}
}
Try something like this, removing the attaching of the eventhandler out of the port creation section
if (port == null)
{
string selectedportname = default(string);
DA.GetData(1, ref selectedportname);
int selectedbaudrate = default(int);
DA.GetData(2, ref selectedbaudrate);
bool connecttodevice = default(bool);
DA.GetData(3, ref connecttodevice);
//Assigning an object to the field within the SolveInstance method()
port = new SerialPort(selectedportname, selectedbaudrate, Parity.None, 8, StopBits.One);
//Enables the data terminal ready (dtr) signal during serial communication (handshaking)
port.DtrEnable = true;
}
if (connecttodevice == true)
{
if(!port.IsOpen)
{
port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
DA.SetDataList(0, myReceivedLines);
port.Open();
}
}
else
{
if(port.IsOpen)
{
port.DataReceived -= new SerialDataReceivedEventHandler(DataReceivedHandler);
// DA.SetDataList(0, myReceivedLines); // Not sure how you want to remove this
port.Close();
}
}

serialport and dispatchertimer, how to make my thread pause when com port is open?

i have a serial port that will iterate through the ports with this method:
foreach (string s in SerialPort.GetPortNames())
{
var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
if (serialOneOfMany.IsOpen)
{
serialOneOfMany.Close();
}
else
{
try
{
serialOneOfMany.Open();
}
catch
{
var openSerial = new System.Timers.Timer(3100);
openSerial.Elapsed += (o, e) =>
{
serialOneOfMany.Open();
openSerial.Enabled = false;
openSerial.Dispose();
};
openSerial.Enabled = true;
}
}
if (serialOneOfMany.IsOpen)
{
string received;
try
{
lblPortNum.Content = s;
lblPortNum.Refresh();
serialOneOfMany.Write(testMessage);
serialOneOfMany.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);
}
catch (TimeoutException e)
{
serialOneOfMany.Close();
continue;
}
}
}
so, i want to open the port, send it a message, listen for the response, then close it. as everyone knows, every comport found in GetPortNames isn't a valid serial port. so, what i've been doing is setting a timer with a dispatcher timer:
DispatcherTimer time = new DispatcherTimer();
time.Interval = TimeSpan.FromMilliseconds(3000);
time.Tick += new EventHandler(someEventHandler);
time.Start();
here's the other method handled here:
private void someEventHandler(Object sender, EventArgs args)
{
SerialPort serial = (SerialPort)sender;
if (serial.IsOpen)
serial.Close();
serial.Dispose();
//if you want this event handler executed for just once
DispatcherTimer thisTimer = (DispatcherTimer)sender;
thisTimer.Stop();
}
so, it'll open the com port, if it doesn't get a response within 3 seconds, it will close the port. the problem i'm having is that the foreach loop will just barrel through the code and open the comport several times, i'll get a message saying The COM Port is open already and can't be used. so basically it's not pausing in openSerial.
i want it to open a new serial port, and if it's not accessible, wait 3100 milliseconds and try again. how do i do that?
UPDATED CODE:
private void button1_Click(object sender, RoutedEventArgs e)
{
CheckPorts();
}
private void checkPorts()
{
SendMessage("messageToDevice1", 19200);
SendMessage("Message2", 9600);
}
private void SendMessage(string testMessage, int baudRate)
{
int baudRate = 9600;
string testMessage = "test";
txtPortName.Text = "Testing all serial ports";
foreach (string s in SerialPort.GetPortNames())
{
SerialPort newPort = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
if (!newPort.IsOpen)
{
try
{
newPort.Open();
}
catch { }
}
if (newPort.IsOpen)
{
openPorts.Add(newPort);
newPort.Write(testMessage);
newPort.DataReceived += new SerialDataReceivedEventHandler(serialOneOfMany_DataReceived);
}
else
{
newPort.Dispose();
}
}
txtPortName.Text = "Waiting for response";
tmrPortTest.Enabled = true;
}
my new problem is that it just blows through the com ports, i need it to stop for each one, take a second to listen, then close it. it just blows through the foreach loop.
now, the reason why i don't just open up the port and keep it open through all the messages is that my devices have different baud rates, and i can't adjust them to all match. so, i need to open the ports, then send messages, listen, if they don't respond to the first round of messages, then open them up at the new baudrate and send a new batch of messages. but the foreachloop doens't pause for me to listen.
I think this more or less agrees with rare's answer. The port where you receive a response (you would probably want to check the response as well) will remain open and all the others should close.
private List<SerialPort> openPorts = new List<SerialPort>();
private void button3_Click(object sender, EventArgs e)
{
int baudRate = 9600;
string testMessage = "test";
txtPortName.Text = "Testing all serial ports";
foreach (string s in SerialPort.GetPortNames())
{
SerialPort newPort = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
if (!newPort.IsOpen)
{
try
{
newPort.Open();
}
catch { }
}
if (newPort.IsOpen)
{
openPorts.Add(newPort);
newPort.Write(testMessage);
newPort.DataReceived += new SerialDataReceivedEventHandler(serialOneOfMany_DataReceived);
}
else
{
newPort.Dispose();
}
}
txtPortName.Text = "Waiting for response";
tmrPortTest.Enabled = true;
}
private void serialOneOfMany_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
txtPortName.Text = ((SerialPort)sender).PortName;
}
private void tmrPortTest_Tick(object sender, EventArgs e)
{
tmrPortTest.Enabled = false;
foreach (SerialPort port in openPorts)
{
if (port.PortName != txtPortName.Text)
{
port.Close();
port.Dispose();
}
}
}
Here's how I would do this --
First, try to open all the serial ports. The ones that actually do open are put in a list.
Assign all serial ports in the list to the same DataReceived event handler. The event handler is where you will save the port name (it's in the args) and kill the timer if you rx'd the response
Send your testMessage out all the open ports
Set just one timer for 3.1 seconds
Close the ports once the timer fires or the event handler rx's the response.

Categories

Resources