Get input from serial port (RS-232) - c#

im writing a program which reads the input from the serial port. It does recieve something but its breaking the line without reason.
The right input
This right inout should be
Sending...Sending...Sending...Sending...Sending...
Without changing line.
The actual input
Sending...
Se
ndin
g...
S
endi
ng..
.
Send
ing.
..
Se
ndin
g...
The code
public void Serial ()
{
try
{
SerialPort serial = new SerialPort(this.comboBox1.Text);
serial.BaudRate = 9600;
serial.Parity = Parity.None;
serial.StopBits = StopBits.One;
serial.DataBits = 8;
serial.Handshake = Handshake.None;
serial.DataReceived += new SerialDataReceivedEventHandler(SerialDataReceivedHandler);
serial.Open();
}
catch
{
}
}
public void SerialDataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string dataIn = sp.ReadExisting();
if (log_time == true)
{
this.richTextBox1.AppendText(time + dataIn);
}
else
{
this.richTextBox1.AppendText(dataIn + "\n");
}
}
The this.combobox1.Text is working fine, im using try because if not the program would crash if the serial port wasnt on!
Im initializing the serial on an other void with Serial();
How can i get the right input?

In your else clause, you should not append "\n" to this.richTextBox1. That is the special character for a new line. If you want the right input, need something like this.richTextBox1.AppendText(dataIn + "...");

Related

Why SerialPort only works after button pressed

I Have created some code for communicating with a device over the serialport. By sending certain command with serialPort1.WriteLine I should receive answer with serialPort1.ReadExisting(). Well I'm able to detect the device but I need to read some other information but to get this information correct I only get it when I place the code in a button_Click function. The funny thing is that All is written in a function and I wish to get the information after the device is detected immediately. When I call the function after the device has been detected it doesn't work and when I call the function after the button is pressed I get the correct information. I do not understand why this is so.
The function for detecting the device is like this:
private void detectVM25ToolStripMenuItem_Click(object sender, EventArgs e)
{
// Detect VM25 and show connection is established
String device;
//Search all portnames
String[] ports = SerialPort.GetPortNames();
int totalPorts = ports.Length;
int count = 0 ;
//Test which enabled port is the VM25.
foreach (string port in ports)
{
count = count + 1;
serialPort1.PortName = port;
serialPort1.Open();
if (serialPort1.IsOpen)
{
serialPort1.WriteLine("#S" + Environment.NewLine);
answer = serialPort1.ReadExisting();
if (answer != "")
{
device = answer.Substring(0, 4);
if (device == "VM25")
{
getRecordings();
statusLblDevice.ForeColor = Color.LawnGreen;
statusLblDevice.Text = port + " - " + device + " - Connected";
VM25Port = port;
}
}
else if (answer == "")
{
serialPort1.Close();
if (count == totalPorts)
{
MessageBox.Show("No device found");
}
}
}
}
}
The function getRecordings() should give me data. If I place this function in my form and get called after a button is pressed I get the correct info but when it is inside the above function it doesn't do anything.
private void getRecordings()
{
if (serialPort1.IsOpen)
{
serialPort1.WriteLine("#H" + Environment.NewLine);
memoryInfo = serialPort1.ReadExisting();
label1.Text = memoryInfo;
}
}
Does anybody knows why this is the case? I would like not to have press a button and get this information after it has detected the device. I also tried to create a delay with `Task.Delay()' unfortunately this did not help
It's surely because you have no synchronization whatsoever. .ReadExisting() does not get an entire response, it gets only what's already been received. So calling it right after .WriteLine(...)... well your data hasn't even reached the device yet, so there definitely won't be an answer ready to read.
Since you know the length of your expected answer (or at least the prefix you're interested in), set the read timeout and then call .Read() (or better, .BaseStream.ReadAsync()) with that length.
Even that is only going to mostly work when the port is freshly opened... for subsequent commands you risk getting data in your buffer from the tail end of a reply to an earlier command. Correct use of a serial port really requires the two ends to agree on some sort of framing, whether that is "a message contains only ASCII and ends with CR+LF" or "a message starts with the length of its payload" or some less common scheme.
with the point out of #Ben Voigt I discovered I should tackle this issue different.
I have use the method serialPort1.ReadTo() because I know that each message end with "/a".
therefore I fixed the function as follows
private void detectVM25ToolStripMenuItem_Click(object sender, EventArgs e)
{
// Detect VM25 and show connection is established
String device;
//Search all portnames
String[] ports = SerialPort.GetPortNames();
int totalPorts = ports.Length;
int count = 0 ;
//Test which enabled port is the VM25.
foreach (string port in ports)
{
count = count + 1;
serialPort1.PortName = port;
serialPort1.Open();
if (serialPort1.IsOpen)
{
serialPort1.WriteLine("#S" + Environment.NewLine);
answer = serialPort1.ReadExisting();
if (answer != "")
{
device = answer.Substring(0, 4);
if (device == "VM25")
{
statusLblDevice.ForeColor = Color.LawnGreen;
statusLblDevice.Text = port + " - " + device + " - Connected";
VM25Port = port;
serialPort1.WriteLine("#H" + Environment.NewLine);
string input = serialPort1.ReadTo("/a");
label1.Text = input;
string totalMeasurements = input.Substring(0, 11);
string totalFFT = input.Substring(11, 11);
statusLblMeas.Text = totalMeasurements;
statusLblFFT.Text = totalFFT;
}
}
else if (answer == "")
{
serialPort1.Close();
if (count == totalPorts)
{
MessageBox.Show("No device found");
}
}
}
}
}
Note the changes of reading the serialport where I stated that it should read up to "/a"

SerialPort.DataReceived not firing

so I have a hardware connected to a COM port, but when I try to get its input it doesnt receive nothing. It just doesnt fires that receives something.
First I get all the COM ports and I know that its connected to COM5 so I do
public void StartCOM(string COMPort, ref SerialPort serialPort)
{
serialPort = new SerialPort(COMPort, 9600, Parity.None, 8, StopBits.One);
serialPort.Handshake = Handshake.None;
serialPort.RtsEnable = true;
Debug.Log("Serial port inicializado en: " + COMPort + " |Baudrate: " + baudRate);
}
then I call
serialPort.DataReceived += DebugReceivedData;
That does:
void DebugReceivedData(object sender, SerialDataReceivedEventArgs e)
{
Debug.Log("Data recibida");
SerialPort serialPortSender = (SerialPort)sender;
string dataReceived = serialPortSender.ReadExisting();
Debug.Log(dataReceived);
}
and finally I call:
public void OpenCOM(ref SerialPort serialPort)
{
//Comprobamos si el serial port existe
if (serialPort != null)
{
//Si ya está abierto no hacemos nada
if (serialPort.IsOpen)
{
Debug.Log("El puerto " + serialPort.PortName + " ya estaba abierto");
}
//Si está cerrado lo abrimos
else
{
Debug.Log("Abrimos puerto: " + serialPort.PortName);
serialPort.Open();
// Set the read/write timeouts
serialPort.ReadTimeout = 16;
//serialPort.ReadTimeout = 500;
//serialPort.WriteTimeout = 500;
}
}
}
It wont never Debug "Data recibida".
Im using Unity with API 4.0
UPDATE:
Checking every frame (That does Update method)
private void Update()
{
string dataReceived = serialPort.ReadExisting();
Debug.Log(dataReceived);
}
It prints the received data (ie: -17F)

Serial Port.Datareceived is not firing (.net 4.5)

I am using .net 4.5 and since i got aware about some internet discussion about .net having wrong code implementation to rad serial data, i went with the code below.
The problems is however even despite i can see i create a COM port connection (to the right com port number), its never firing on data received.
The data receiving is based upon a simple Arduino app, (Arduino monitor does show data gets send over serial), but .net never seams to fire upon serial events.
I've put breakpoints on eventread, it never gets hit
i've looked at other discussions here like .NET SerialPort DataReceived event not firing but so far they don't resolve the issue i have. I tried various combination of serial line setups, and believe the below ones are correct.
as for Arduino part the line is setup as:
Serial.begin(9600);
I call my class like : `InfraredSensor mySens = new InfraredSensor("COM4",9600);'
class InfraredSensor
{
private string Eventlogapp = "IRlogging";
private SerialPort Port;
public InfraredSensor(string COMport, int baudrate) //constructor
{
if (applicationlog != "") this.EventlogSapec = applicationlog;
WriteEventLog(EventlogSapec, EventSource, "Initializing-IR:" + COMport, info, EventIRStarted);
// I found that the .net standard implementation for com port reading is not OK (.net doesnt follow win32 api).
// There are numerous readings about it, but a good way to read seams to be to use Serial BaseStream.ReadAsync
// code below is based upon : http://www.c-sharpcorner.com/code/2880/serial-port-with-efficient-data-reading-in-c-sharp.aspx
this.comport = COMport;
SerialPort Port = new SerialPort(comport);
Port.BaudRate = baudrate;
Port.DataBits = 8;
Port.Parity = Parity.None;
Port.StopBits = StopBits.One;
Port.Handshake = Handshake.None;
Port.NewLine = Environment.NewLine;
Port.ReceivedBytesThreshold = 2; // + linefeed
Port.DataReceived += ReadEvent;
Port.Open();
Port.DtrEnable = true;
// i've tested from here i do have an open connection
// its just dat ReadEvent never fires...
}
private void ReadEvent(object sender, SerialDataReceivedEventArgs e)
{
byte[] buffer = new byte[2];//todo i only send "A" or "B", for the debug moment
Action kickoffRead = null;
kickoffRead = (Action)(() => Port.BaseStream.BeginRead(buffer, 0, buffer.Length, delegate (IAsyncResult ar)
{
try
{
int count = Port.BaseStream.EndRead(ar);
byte[] dst = new byte[count];
Buffer.BlockCopy(buffer, 0, dst, 0, count);
RaiseAppSerialDataEvent(dst);
}
catch (Exception ex)
{
WriteEventLog(Eventlogapp, "IR", "Failure-IR:" + ex.Message, info, 204);
}
kickoffRead();
}, null)); kickoffRead();
}
private void RaiseAppSerialDataEvent(byte[] Data)
{
// code never gets to here
string msg = Encoding.Default.GetString(Data);
int breakpointhere = 0;
if (msg.Contains('A')) WriteEventLog(Eventlogapp, "IR", "Sensor A", info, 213);
if (msg.Contains('B')) WriteEventLog(Eventlogapp, "IR", "Sensor B", info, 214);
}
}
I ran out of ideas (and hair as its driving me nuts) what could cause this behaviour ?
finally this took me 2 days ...
in arduino code i now use
serial.print("Mytext\n"); // using \n to be sure of escape character
for the serial line config i now use
this.comport = COMport;
this.Port = new SerialPort(comport);
this.Port.BaudRate = baudrate;
this.Port.DataBits = 8;
this.Port.Parity = Parity.None;
this.Port.StopBits = StopBits.One;
this.Port.Handshake = Handshake.None;
this.Port.RtsEnable = true;
// Port.NewLine = "\n";
// Port.ReceivedBytesThreshold = 2; // + linefeed
this.Port.DataReceived += new new SerialDataReceivedEventHandler(ReadEvent);
....
..
SerialDataReceivedEventHandler(ReadEvent);
//code didnt change inside but the method has changed see the +=
The DataReceived event fires when there is data coming through the serial port, but it can fire randomly. So you could get part of the message in one event and the other half of the message in another event. You should have some sort of key to know when you have the whole message. So build your string until you have the whole message then do something based on the message.
For example, my device's message is done when there is a Line Feed. So my code looks something like:
char ESC = (char)27;
char CR = (char)13;
char LF = (char)10;
StringBuilder sb = new StringBuilder();
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string Data = serialPort1.ReadExisting();
foreach (char c in Data)
{
if (c == LF)
{
sb.Append(c);
//we have our message, do something, maybe like
if (sb.ToString().Contains("A"))
{
//print A
}
else
{
//print B
}
}
else
{
sb.Append(c);
}
}
}

C# can't open serial port from application launch successfully

So I have this port that I'm opening and saving the name of the port in a setting of my application. When I load the form it tries to open the port however fails to do so. Only after clicking on my "open port" button that has the EXACT same code does the port open. And then If I click my "close port" button and reopen the form it works! It automatically opens the port for me. However it's only if I'm fast enough. If I leave the application closed (and thus port closed) for say 10-15 seconds and reopen the application, I'll get my error thrown at me. What's the reason for this??
The code used at launch and in my "open port" button:
mySerialPort.createPort(Properties.Settings.Default.portName);
if (!mySerialPort.isOpen)
{
try
{
mySerialPort.openSerialPort();
}
catch
{
MessageBox.Show("Error: Could not open Serial port " + Properties.Settings.Default.portName, "Port Opening Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
if (mySerialPort.isOpen)
{
portActiveStatusLbl.Text = Properties.Settings.Default.portName + " OPEN";
portActiveStatusLbl.ForeColor = Color.Green;
}
}
and here's mySerialPort Class:
public static class SerialPortConfig
{
public static SerialPort mySerialPort = new SerialPort();
public static string myString = "";
public static bool isOpen { get { return mySerialPort.IsOpen; } }
public static void createPort (string portName)
{
if (portName == "")
portName = "COM1";
mySerialPort.PortName = portName;
mySerialPort.BaudRate = 2400; //Depending on the hardware used this may change, mitutoyo input tool asks for 2400 baud
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.RequestToSend; //DO NOT SET TO NONE
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
}
public static void openSerialPort()
{
mySerialPort.Open();
}
public static void closeSerialPort()
{
mySerialPort.Close();
}
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting(); //stores the char that fired the event into 'indata'
myString += indata;
if (indata.Contains("\r")) //check to see if char received indicates end of measurement
{
if (myString == "911\r") //911 is the code given when the micrometer is off, so we have it do nothing
myString = "";
else
{
myString = myString.Substring(4, 8);
Form1.instance.pendingMeasurement = true;
}
}
}
}

Semaphore timing out while accessing a serial port?

I'm experiencing this problem while opening a serial port in C# (which should be dirt simple; or so I thought).
When I try to open a serial port, I am getting the following exception:
The semaphore time-out period has expired.‎
Here is the method that is doing this.
public static void Open_TheActivePortWeWillUse(String Drone_StringNameFromUser)
{
var TempSerialPort = new SerialPort (
Drone_StringNameFromUser,
(int) SerialPortParameter.TheSerialPortSpeed);
// Now we have a name that anybody can see and use
OurSpecificPorts.TheActivePortWeAreUsing = TempSerialPort;
// We'll do 8-N-1 since almost the whole planet does that
OurSpecificPorts.TheActivePortWeAreUsing.DataBits = 8;
// We'll do 8-N-1
OurSpecificPorts.TheActivePortWeAreUsing.Parity = Parity.None;
// We'll do 8-N-1
OurSpecificPorts.TheActivePortWeAreUsing.StopBits = StopBits.One;
OurSpecificPorts.TheActivePortWeAreUsing.DataReceived +=
OurBackGroundSerialPortReceiver;
// We can now open our active port, which is what this line does
OurSpecificPorts.TheActivePortWeAreUsing.Open();
}
The strangest thing for me is that I get this error inconsistently. Half the time it works okay, and the other half, it does not.
Does anybody see anything obviously wrong with my code? Am I missing something?
Declaring your SerialPort object inside the method will not allow access to it after the method closes. Here is a method that works to open the port:
private void OpenSerialPort(String portName)
{
try
{
serialPort1.Close();
serialPort1.PortName = portName;
serialPort1.BaudRate = 115200;
serialPort1.DataBits = 8;
serialPort1.Handshake = Handshake.None;
serialPort1.Parity = Parity.None;
serialPort1.RtsEnable = false;
serialPort1.StopBits = StopBits.One;
serialPort1.Open();
}
catch (Exception ex)
{
MessageBox.Show("Could not open serial port " + portName, "Error");
}
}
The SerialPort object is declared in the class:
namespace Arcadia
{
public partial class Form1 : Form
{
private SerialPort serialPort1;
And the callback is added in the constructor:
public Form1()
{
InitializeComponent();
serialPort1.DataReceived += new SerialDataReceivedEventHandler(this.SerialPortReadCallback);
Sending data is handled in a different method:
private void SerialPortWrite(String writeString)
{
if (serialPort1.IsOpen)
{
serialPort1.WriteLine(writeString);
}
}
And here is the received data callback:
private void SerialPortReadCallback(object sender, SerialDataReceivedEventArgs args)
{
try
{
while (serialPort1.BytesToRead > 0)
{
// Do something with the data
}
}
catch (Exception ex)
{
}
}

Categories

Resources