I am working on making GUI for a Smart Water flow meter whose communication protocol is RS485,
as per instructions from Communication Manual i am sending an inquiry packet and i am receiving proper response in serial port terminal. But when i am trying to do it on my C# app.
Things are happening oppositely.
string data = "[H201815000081]";
private void button1_Click(object sender, EventArgs e)
{
serialPort1.Write(data);
incoming_data = serialPort1.ReadExisting();
text_reciever.Text = incoming_data;
}
// text_reciver is the text box of my gui where i want to display the
// values from flow meter.Data Type of incoming_data is string
Here is the code, i am sending an inquiry code to the device and in return i am getting garbage values on my text box. Some times it is stream of Question mark symbol (?), some time it shows nothing.
But when i revert myself to serial port terminal (Real Term).
It is showing proper values as mentioned in communication manual.
Please assist in this regards.
After looking around i just found the answer to my question.
The point is previously i was communicating with serial port teminal, where everything was working fine, but when it comes to interacting with peripherals one need to make sure that Serialport.DTRProperty is enabled.
When opening the serial port one must enable the DTR property by:
serialPort1.DtrEnable = true;
Otherwise the windows form will read the garbage value.
the incoming data would be serial number of device (ASCII Format) and Water flow values
Related
What I try to do: Processing 3 is receiving a sort of QR code via my webcam --> it reads the value and sends it to my Arduino, Arduino successfully receives it and can now do stuff with it. Now I want to add another communication channel, Unity. I want the Arduino to send the value from the Processing to Unity.
It is easy to communicate between Arduino and Unity, but I need Processing for the webcam value.
The problem: Both Processing 3 and Unity make use of the same port (COM4, 9600). This will cause an IO exception in Unity saying "Access Denied" followed by errors of the Serial port isn't open.
Processing 3 code
...
//Open port
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
myPort.write(1);
...
Arduino code
void setup() {
// put your setup code here, to run once:
...
Serial.begin(9600); // Start serial communication at 9600 bps
...
}
void loop() {
if (Serial.available()) { // If data is available to read,
val = Serial.read(); // read it and store it in val
}
//val contains now the data that was sent from Processing 3
//Send this data to Unity:
Serial.flush();
Serial.println(val);
}
Unity code
...
SerialPort stream = new SerialPort ("COM4", 9600); //We obviously can't open this port since its already in use by Processing 3. How to fix this?
...
// Use this for initialization
void Start () {
stream.Open(); //Throws IO exception: Access Denied error
}
// Update is called once per frame
void Update () {
string value = stream.ReadLine();
val = int.Parse(value);
if (val == 1) {
//Links van arduino
goLeft();
}else if (val == 2) {
//Rechts van arduino
goRight();
}
}
We obviously can't open the port in Unity since its already in use by Processing 3. How to fix this?
Communication stream:
Processing 3 --> Arduino --> Unity
Eventually Unity needs to know whether you have to go Left or Right based on the QR code input on the webcam.
You can't use the same serial port in two concurrent applications (why do you want to use an Arduino at all?) A solution is to establish alink between applications. A network connection, using a 127.0.0.1 loopback connection, is a tried and tested way of creating that link.
As far as protocols go, you have endless options, my personal preference is to use OSC - both processing (via OSCP5) and Unity (various plugins, including my own I should really make public at some point) have decent support for messaging, but you can use many other types of links (ie. websockets)
For the people who would like to know how to solve this problem.
You can't. We have to think in another way.
Options were:
Close port while done processing and then open port in Unity (was not practical since we need a constant stream of instructions)
Leave out the Arduino and communicate between Processing and Unity (was not practical either since we need the Arduino in this case for blinkers)
Find another communication form between the Arduino/Processing and Unity without any ports. (Thanks to #kaj)
I've implemented the last option
Output Processing results to a "data.txt" file
Unity opens this file in C# with ReadAccess FileStream and reads the output and uses this
In this way we can still use the Arduino and Unity directly reads output from the Processing without a middleman.
Question Withdrawn. I found out that I was sending incorrect ASCII patterns and THIS was my problem versus any problems with the receiver. Receiving a single character was merely the echo back of my wrong command
Summary:
C# form app. Serial 38400:N81 no flow control. Talking to a custom device.
If I use Teraterm, everything's fine.
The device I attach to gives simple, immediate responses:
Type 'v' you get a version string "v1.34 02-18-16 17:22" where the v in that is the local echo of the typed command. There are other status commands which are similar, once a character is received by the device, it replies immediately.
In my C# application I have pretty much exactly what you see in this guide under the example:
https://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived%28v=vs.110%29.aspx
Differences are that I'm at 38400 versus 9600 and I also do not set up the Handshake or the RtsEnable.
I've done this before so feeling stupid as to some obvious problem here. And I did do a bit of searching/following similar question links too.
Instead of receiving the version string, I receive one character '6'.
For a different command I also receive one character '8'. The notable thing here is that while '6' is part of my version string, '8' is never in the response for that other command.
Any suggestions on how I'd debug the ReadExisting() call?
I fully understand that a received string may arrive in fragments. The issue is that I always only ever receive the one character and nothing else. The event handler never sees any additional data. When I re-issue my version command I get the same '6' back I get before.
My event handler where I'm trying to test the receiver:
private void ReceiveData(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Debug.WriteLine("Data Received: ");
Debug.Write(indata);
}
Under the debugger, indata.Length is 1.
Teraterm Port Settings:
I was suggested to look for errors and here's the code:
public event SerialErrorReceivedEventHandler ErrorReached;
protected virtual void OnReceiveError(SerialErrorReceivedEventArgs e)
{
SerialErrorReceivedEventHandler handler = ErrorReached;
if (handler != null)
{
handler(this, e);
}
Debug.WriteLine("Serial error");
}
I saw no errors.
Further comments were that the receiver needs to be run more than once. It is, when I issue a 'v' (just the v) I should see the version and 's' should give me status. Again, both work fine on Teraterm. I get 686868 if I issue vsvsvs or other matching patterns if I type like vvsss, I'll get 66888 in reply.
Other point is controlling this device if I issue r and s for run and stop, there is a LED on it which goes solid red (from intermittent flashing to indicate that it's running. I see it run and stop per my commands. So I know that I'm talking to the device in a proper/coherent fashion. Just still have troubles seeing valid receive data.
Some suggestions to try:
You're reading a string from the port, so if the data can't be readily interpreted as a string you may only get a fragment before it stops converting. Read into a byte array to be sure you are really seeing the data that you receive. Even if you think you should get a string, this lets you see what you are actually receiving.
Check your port settings. Symptoms of the wrong baud rate or encoding are frequently that you receive a reduced number of (possibly random, possibly repeatable) bytes of "garbage". This would be consistent with receiving characters that should not be in the response, and the string terminating early.
Remove all configuration options from your port, apart from setting the baud rate. Very few devices use anything other than 8n1 and attempting to set options can often screw the port up. If that doesn't work then start seeing additional options only if you have to.
Make sure you only open the port once and keep it open till you have finished talking to the device. (Repeatedly opening and closing the port I'd really five by accident, and would flush the data in it, interfering with your attempts to read)
For my project I need to communicate with an Cypress PSoC5. I can use a serial connection or a USB HID connection.
I created a C# project for sending and reading data to/from PSoC5. Right now I'm using the ReceivedData event of the serialport to get notified if there is new data. Basically my project can either receive a datastream that should be plotted in realtime or just some settings I want to update within the GUI.
Right now I face the problem that the ReceivedData event fires very often (every 32 bytes), which is of course not good when there is a datastream. Basically I receive 24000 bytes per second if I get data for the plot. I know I can adjust the ReceivedBytesThreshold, but then I will not get an event for data below the threshold.
Can anyone tell if there is an approach to handle this?
Would it be an advantage to use the PSoC5 as a HID device instead?
By default SerialPort.ReadBufferSize is set to 4096 bytes. Slighly more info here. But you can easily change it to accomodate necessary amount of data. Then in DataReceived event handler do something like this
static void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (Serial.BytesToRead < 24000) return;
... //Recieve and process your data here
}
24000 is given here for example.
I have a serial port app that read weighing machine.
public void Read()
{
while (Puerto.BytesToRead > 0)
{
try
{
string inputData = Puerto.ReadExisting();
dataReceived = inputData;
}
catch (TimeoutException) { }
}
}
the return string is like this
It has other extrange chars in it, how can i do to parse or get a clean data from it? all I need is 0.52lb
I have no idea what weighing machine is it and what the serial port specs on it but, if it is black box to you too then, check the following:
- check if you have a technical spec that explains what comes out of RS232 port
- do several (10?) samples with one sample weight and see if the number of bytes are delivered each time
- if you see the number of bytes being constant (barring discrepancy in the 0.52lb text changing to 0.5lb once in a while), it is likely that garbage following the weight is additional binary data.
- if not, and you see the weight (text) with exact offset each time, you just can scrape the output
this is complete reverse engineering, I suggest going after technical spec and doing more insightful data handling though.
This could be anything - a bug in the weighing machine, some sort of hardware issue, or a problem in how the serial port is configured. I would suspect a configuration problem. Make sure all the settings are correct (BaudRate, Handshake, Parity, StopBits). Also, try connecting to the same serial port device using another program (e.g. see http://helpdeskgeek.com/windows-7/windows-7-hyperterminal/ ) and see if you see the same garbage data.
I have one device which sends data on COM port say on COM13. Now i want to read that data and display it in the RichTextBox or in any text control.
I have written the application with the help of IO and IO.Ports but comport.DataRecived event does not fire, even though device is sending data on that port.
I have some software on which i define the port number and it successfully display data, which insure me that data is receiving on the Port but i am unable to receive.
Is there any way i can read data?
comm.Parity = cboParity.Text;//None
comm.StopBits = cboStop.Text;//One
comm.DataBits = cboData.Text;//8
comm.BaudRate = cboBaud.Text;//9600
comm.DisplayWindow = rtbDisplay;//Null
comm.PortName = "COM13";
comm.OpenPort();
cmdOpen.Enabled = false;
cmdClose.Enabled = true;
cmdSend.Enabled = true;
public bool OpenPort()
{
if (comPort.IsOpen)
{
comPort.Close();
}
comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
comPort.PortName = _portName;
comPort.Open();return true;
}
This normally comes from a wrong configuration of a serial port. It is not enough to simple open a serial port and waiting for some data to come in. You have also to set all the SerialPort.Properties to a correct value for your wanted connection.
Some of the common ones are BaudRate, DataBits or Parity, but to be really sure you have to set all of them. Even such things as RtsEnable or ReadTimeout.
You have to set the all, cause the configuration state will be saved from the port itself. So if one application opens such a port, makes some changes to the configuration and closes it, the next application that opens the port starts with this configuration, till it change it.
Update
Seems to be a problem i can't see from here. ;-))
The only advice i can give you is to use a Monitor tool, to better understand what your other application really does and what comes on the wire. Additionally you can set up two virtual com ports to test reading and writing on one machine (even within the same application), to have a better control about when will which data be send.
Have you read the documentation for the DataReceived event?
From MSDN:
The DataReceived event is not guaranteed to be raised for every byte received. Use the BytesToRead property to determine how much data is left to be read in the buffer.
The DataReceived event is raised on a secondary thread when data is received from the SerialPort object. Because this event is raised on a secondary thread, and not the main thread, attempting to modify some elements in the main thread, such as UI elements, could raise a threading exception. If it is necessary to modify elements in the main Form or Control, post change requests back using Invoke, which will do the work on the proper thread.
The snippet you've posted is quite rough, but I'd set the ReceivedBytesThreshold property to one. This ensures the event firing when at least one byte is present in the incoming buffer.
Cheers
Use PortMon to capture the working software, and then capture your software; then compare the traces. Pay particularly close attention to all the configuration parameters, making sure they are the same (as Oliver mentioned).