correct way to parse serial port data? - c#

I'm testing out a program right now that is supposed to receive data from a serial port and parse it, and continually update certain variables tied to that parsed data. I'm having trouble with the actual parsing itself.
The data string output of the port I'm using is: 8 data bits, 1 start bit, 1 stop bit, and no parity. A message starts with the colon symbol : and ends with . An example - : 3.00 20.45 2355 1000 554
First question: Is there any method for setting the start bit? I know there's a .StopBits which I have equal to StopBits.One, but I haven't found anything for a start bit.
In regards to the parsing-
In the code method below:
serial.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(Receive);
private void Receive(object sender, SerialDataReceivedEventArgs e)
{
// Collecting the characters received to our 'buffer' (string).
received_Data = serial.ReadExisting();
}
Would the best way be to set up a string array = received_Data.Split, then use a for loop to go through each "split" and assign it to the correct variable? I've never worked with ports before so this is all new to me. After looking around there seems to be several ways to do this, not sure what the best way would be though.

Related

Visual Studio windows form application C# serial communication receive data?

I need a code that will receive serial data from arduino and display them in text boxes .
I am receiving int type data separated by commas .
Arduino serial data sample : 250,389,123,232,255,536,366,455,...
I need first six data to be displayed in six separate text boxes and then the consecutive data must replace the already existing values in those text boxes.
I tried several times but everything went in vain. Some one help me.
I assume you're using System.IO.Ports namespace and SerialPort class for communication. I also hope that BaudRate and other communication settings are as expected by the device.
If yes, then further if you receive the data repeatedly, you may capture it by using ReadTo method and giving it a comma as parameter. Such reading loop may look like this:
while(true) // replace it with some wiser condition
{
string textRead = serialPort.ReadTo(",");
// do the rest here
}
Now, you may also want to capture some larger amounts of data at once. Of course you can (say, capture 100 characters), but then you should:
- split the string with comma;
- leave the last item of string array (which will be the result of splitting method) and insert at 0 position of next received pack of characters;
- repeat those steps in loop like above.
Now, to the TextBox'es. If there are N of them and we take the first capturing method into account, you may do it like this:
TextBox[] tboxes = new TextBox[N]; // your number is 6, I know
int boxIndex = 0;
while(true) // again, use a reasonable condition
{
string textRead = serialPort.ReadTo(",");
tboxes[boxIndex].Text = textRead.Trim(',');
if(++boxIndex >= tboxes.Length)
boxIndex = 0;
}
This should do the job.

How to get the correct values from this Modbus address?

I have a MOXA Modbus TCP module (M-4210 in combination with the NA-4010 networking module that also has some other modules attached) that works as a 2-channel analog output, each with voltages from 0 to 10 Volts.
In my C# application I need to get the current values of these outputs, which is not as easy as I'm quite new to the whole Modbus thing.
In my code I already have a working modbus tcp client that does its job, I tested it by reading and writing single coils of another digital output module. The analog output module however seems to work with registers instead of coils.
To start from the beginning, these are the modbus settings for the two channels within this module (taken from the MOXA ioAdmin Tool):
and the addresses:
And here's another screenshot from the web interface:
So I tried to read the values like this:
ModbusClient c = new ModbusClient();
c.Connect("172.17.6.15", 502);
int[] r = c.ReadHoldingRegisters(2048, 1);
for (int i = 0; i < r.Length; i++)
{
textBox1.Text += r[i].ToString() + System.Environment.NewLine;
}
This code returns one value, it changed as follows:
When channel #0 is set to the (raw) value of 1139, the returned int value is 29440
When channel #0 is set to 1140, the returned value is 29696
I seem to be on the right track, but I don't quite understand the offsets and how to separate the channels when the value comes back. It would be great if someone could shed some light on this, thanks in advance!
Is your client handling Modbus endianess correctly? Modbus is big endian.
1140 is 0x474, 29696 is 0x7400. 1139 is 0x473, 29440 is 0x7300. I can see a pattern. It seems that your Modbus client is setting the LSB to 0 and taking the MSB by shifting the received LSB to the left.
Try changing the channel's value to 1141, you'll probably read 29952 in your client. That will confirm my suspicion.
Try reading Holding Register 2047 and see if you get the value you're looking for...
Although it seems like the value you're after is shifted by 1 byte, not 2, so you might need to read 2047 and ask for 2 registers and do the shift yourself. Very strange.

Limit Event Handler

Apologies if my 'lingo' doesn't make sense... I'm fairly new to this and coding!
I am working on a project which involves a RFID reader and a Bluetooth module communicating with a C# windows form.
The com port event handler sends the RFID tag's unique ID continuously. Is there a way for it to be sent just once?
Is there a way for the program to just receive the ID once, so it can be processed; as opposed to receiving the ID numerous times.
Thanks in advance! :)
My code so far is as follows.
I have the serial port open from somewhere else
private void port_DataRecieved(object sender, System.IO.Ports.SerialDataRecievedEventArgs e)
{
string data = serialPort.ReadExisting(); // read what came from the RFID reader
if (data.Length > 9) // check if the string if bigger than 9 characters
{
CODE = data.Substring(0, 9); // if string is bigger than 9 characters trim the ending characters until it is only 9 long
}
else
{
CODE = data; // if less that 9 characters use however many it gets
}
}
Don't use ReadExisting. Instead check whether there are 9 bytes yet.
If not, return immediately.
If yes, read only 9 and leave the others for the next event.
You probably should have some resynchronization logic also.
Also, received data needs to be in a byte[], not a string. The Microsoft-provided serial port class always leads people to use the wrong approach.

Get a numeric value or string from an address of an attached process

I am building a small tool which allows me to edit in real time the memory of an attached process.
so the tool has 1 numericUpDown and 2 buttons, a get and a set.
my set code is as followed
private void sendButton_Click(object sender, EventArgs e)
{
byte[] stat = BitConverter.GetBytes(Convert.ToInt32(statNumericUpDown.Value.ToString()));
SetMemory(0x0175914a, stat);
}
where I am stuck is reversing that process so I can get numbers from my attached process and send them to my numericUpDown.
I hope I explained well enough and any help would be much appreciated.
EDIT: Better Explanation
What I am trying to do is real time edit memory in order to set and get values from my attached process' memory. So lets say in that process there is a value we'll call it Wins. I know the memory address of Wins is 00000001. in my attached process I have say 32 Wins
Now manually I would use a debbuger point to 00000001 copy the bytes at that address, go to a hex to decimal converter, paste those copied bytes (20) and get a return value of 32
what I am trying to achieve is at the press of a button this is all done by system and have the returned value show in my numericUpDown Control
Surely the reverse of the process would simply be the reverse of what you have, i.e.:
byte[] statBytes = GetMemory(0x0175914a);
int stat = BitConverter.ToInt32(statBytes);
statNumericUpDown.Value = stat;
The key is BitConverter.ToInt32 for converting from a byte[] to an Int32.

Improper format reading the serial port in C#

I am reading data from an Arduino board using C#.
In C#, I have the following:
// Write a string
port.Write("x");
Thread.Sleep(50);
SerialPortRead();
... and in SerialPortRead() I have:
private static void SerialPortRead()
{
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
private static void port_DataReceived(object sender,SerialDataReceivedEventArgs e)
{
Console.WriteLine(port.ReadExisting());
}
and, the output would look something like:
329327
32
7
327
3
26
327
3
26
32
7
What did I do wrong? The output should be a around 326-329, where this value is coming from a compass which is hooked up to one of the pins that I am reading from Arduino.
Note that:
In Arduino, I have a Serial read method that watch for the input character x and return the value of the compass.
I'd guess that you are reading faster that the compass is writing. So that way your program believes that it is receiving two direction, while if it has delayed reading a little bit it would have received only one.
This hypothesis is supported by that if you group the read data into numbers of three, we get directions in the range you expect.
Try adding a delay before reading after sending the trigger character, or even better - add a control character to signal that the compass has written the entire direction and then read until you receive that char.
Edit: I now noticed that you already have a sleep - so the option remaining would be a separation/termination char.

Categories