Reputation: 33
I am very new to interacting with hardware. I am currently building a GUI in C# using the Windows Forms. I am using a serial port/usb to interact with a hardware device. What I am trying to achieve is to have multiple threads poll the device at different times. Some data such as temperature, current, power, etc. should be retrieved regularly (at least every second) and be updated on the GUI for the user to see. While other data will only be retrieved when the user presses a button on the form. Would multi-threading be the right approach to tackle this problem? If not, what would be a better solution? Examples would be greatly appreciated. Thank you for your time guys!
Update: I am trying to use the SerialPort.DataReceived Event as many of you have suggested and a terminator character '\r' to parse out individual replies from the serial port. Then I am invoking a method called DisplayText to handle that string. My problem now is I have no idea how to figure out what the string represents. Does it represent a temperature, a current, etc.
private char terminator = '\r';
private void SerialPorts_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
output += serialPort1.ReadExisting();
if (output.IndexOf((char)this.terminator) > -1)
{
string workingString = output.Substring(0, output.IndexOf(terminator));
output = output.Substring(output.IndexOf(terminator) + 1);
this.Invoke(new EventHandler((s, a)=>DisplayText(s, a, workingString)));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void DisplayText(object sender, EventArgs e, string s)
{
Console.WriteLine(s); // for testing only
richTextBox1.AppendText(s); // for testing only
}
Upvotes: 2
Views: 3082
Reputation: 1760
My problem now is I have no idea how to figure out what the string represents. Does it represent a temperature, a current, etc.
Use simple protocol to send temperature, a current, ect.
SOH + DATA + ETX + BCC
SOH = 0x02;
ETX = 0x03;
BCC = 0x00-0xFF, XOR value of of all DATA + ETX.
DATA = use ';' as delimiter between Temperature(Temp) and Current(Curr)
Example:
TempCmd = 0x01
TempValue = 32 celcius = 0x20
CurrCmd = 0x02
CurrValue = 1,4 ampere = 0x0E -> result must be divide with 10 on receiver.
SOH + DATA + ETX + BCC
SOH + TempCmd:TempValue; CurrCmd:CurrValue + ETX + BCC
02 + 01:20;02:0E + 03 + BCC
BCC = 01 xor ':' xor 20 xor ';' xor 02 xor ':' xor 0E xor 03
Send data from microcontroller "0201:20;02:0E03;XX" (send as string)
Receive data in computer:
Upvotes: 0
Reputation: 568
You can guard all serial port access functionality using a mutex and design your application in such a way that the serial port is closed after each discrete operation (e.g. reading the temperature). One possible way to do this would be to write a wrapper API of-sorts which would:
Check if the mutex is unlocked (and return with an error code if it is locked),
Open the serial port
Read the required value
Close the serial port and clear the mutex
Return the read value
However, you are opening yourself up to all sorts of deadlocks with this solution and you will have to implement additional application level checks to prevent this.
As suggested above, a better solution would be to have a single thread periodically poll the serial port and continuously update all values in a data structure of your choice.
For the values which only need to be read after user input, you will have to implement a MessageQueue to request this data.
Update in response to the OPs edit
I would recommend either of the following 2 ways to approach the communication in your device:
In case you don't have the option of changing the code in the device, there must be some sort of order in which the values are reported by the device so maintaining a sequence number of the received data would be the way to go. But without knowing more details about what your device is doing, it would be difficult to suggest a solution.
Upvotes: 0
Reputation: 11
I think it is not a good idea to have multiple threads to poll single port and try to synchronize.
Better have one thread which does the polling and which stores all the values in some "middle" object (singleton, static fields, what you like) and than synchronize access to this storage.
So one threads polls the port, collects the values and stores them somewhere, than the other threads gets the values from there.
Upvotes: 1