Reading from serial port
-
I am trying to make a serial port terminal and i have succesfully made it except for some problems that i am facing. i have a button pressing which the terminal starts and the data from the serial port start to get displayed on the textbox. when i press the button again the serial port closes. Also i have put the code to read from the serial port in a timer with a time of 1 millisecond. So it automatically works like a loop and the data can be displayed continuously. Case 1. when i try reading from the serial port using
_SerialPort.ReadLine ()
what happens is that the data is getting displayed perfectly, but i am not able to press the button again to close the serial port, also i cant even close the application. I would have to use the task manager to kill the process. Case 2. when i try reading from the serial port using
_SerialPort.ReadExisting ()
what happens is that the earlier issue is resolved, but the data that is received is not continuous, that is some values are not recieved.
-
I am trying to make a serial port terminal and i have succesfully made it except for some problems that i am facing. i have a button pressing which the terminal starts and the data from the serial port start to get displayed on the textbox. when i press the button again the serial port closes. Also i have put the code to read from the serial port in a timer with a time of 1 millisecond. So it automatically works like a loop and the data can be displayed continuously. Case 1. when i try reading from the serial port using
_SerialPort.ReadLine ()
what happens is that the data is getting displayed perfectly, but i am not able to press the button again to close the serial port, also i cant even close the application. I would have to use the task manager to kill the process. Case 2. when i try reading from the serial port using
_SerialPort.ReadExisting ()
what happens is that the earlier issue is resolved, but the data that is received is not continuous, that is some values are not recieved.
ReadLine() blocks until a new line character occurs so you can't expect it to do anything immediately based on a key press unless the key causes a end of line. If your source for the characters are human input is human than it seems unlikely that ReadExisting() would lose anything. What would be more likely in that case is that your output code is not correctly handling what ReadExisting is returning.
-
I am trying to make a serial port terminal and i have succesfully made it except for some problems that i am facing. i have a button pressing which the terminal starts and the data from the serial port start to get displayed on the textbox. when i press the button again the serial port closes. Also i have put the code to read from the serial port in a timer with a time of 1 millisecond. So it automatically works like a loop and the data can be displayed continuously. Case 1. when i try reading from the serial port using
_SerialPort.ReadLine ()
what happens is that the data is getting displayed perfectly, but i am not able to press the button again to close the serial port, also i cant even close the application. I would have to use the task manager to kill the process. Case 2. when i try reading from the serial port using
_SerialPort.ReadExisting ()
what happens is that the earlier issue is resolved, but the data that is received is not continuous, that is some values are not recieved.
Don't use either of them like that. Instead, handle the SerialPort.DataReceived[^] event, and get the data in that using ReadExisting - you can then add the data to the textbox in the event handler and you should never lose any data, nor should your UI freeze up. Remember, Serial ports are very slow devices - data transfer is not instantaneous, nor is it packet based. if you are running your serial port as 9600 baud for example, it will receive one character about every millisecond (7 data bits, 1 parity, 1 start and one stop bit == 10 bits, 9600/10 = 960 characters per second.) So if you just read once, you will get whatever characters are in teh buffer at that moment, and nevr get any more.
The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
-
ReadLine() blocks until a new line character occurs so you can't expect it to do anything immediately based on a key press unless the key causes a end of line. If your source for the characters are human input is human than it seems unlikely that ReadExisting() would lose anything. What would be more likely in that case is that your output code is not correctly handling what ReadExisting is returning.
jschell wrote:
If your source for the characters are human input is human than it seems unlikely that ReadExisting() would lose anything.
the characters are not human input. its source is a micro controller ADC output. So it continuously sends data to the serial port. Parity - Even Databits - 8 Stopbits - 2 Baudrate - 4800
jschell wrote:
ReadLine() blocks until a new line character occurs so you can't expect it to do anything immediately based on a key press unless the key causes a end of line.
The button press calls the
serialport.Close();
so then it shouldn't matter what the
ReadLine()
function gets.
-
Don't use either of them like that. Instead, handle the SerialPort.DataReceived[^] event, and get the data in that using ReadExisting - you can then add the data to the textbox in the event handler and you should never lose any data, nor should your UI freeze up. Remember, Serial ports are very slow devices - data transfer is not instantaneous, nor is it packet based. if you are running your serial port as 9600 baud for example, it will receive one character about every millisecond (7 data bits, 1 parity, 1 start and one stop bit == 10 bits, 9600/10 = 960 characters per second.) So if you just read once, you will get whatever characters are in teh buffer at that moment, and nevr get any more.
The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
OriginalGriff wrote:
Instead, handle the SerialPort.DataReceived[^] event, and get the data in that using ReadExisting - you can then add the data to the textbox in the event handler
Sorry forgot to mention, i had tried that too... Same problem. losing data....
-
OriginalGriff wrote:
Instead, handle the SerialPort.DataReceived[^] event, and get the data in that using ReadExisting - you can then add the data to the textbox in the event handler
Sorry forgot to mention, i had tried that too... Same problem. losing data....
How did you use it? Do you still have the code?
The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
-
How did you use it? Do you still have the code?
The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
private void Start_Click (object sender, EventArgs e)
{
if(Start.Text == "Start")
{
Start.Text = "Stop";
_SerialPort.DataReceived += new SerialDataReceivedEventHandler (Port_DataReceived);
}
else
{
Start.Text = "Start";
}
}private void Port\_DataReceived (object sender, SerialDataReceivedEventArgs e) { string data = \_SerialPort.ReadExisting (); rtbTerminal.AppendText (data); rtbTerminal.ScrollToCaret (); }
private void Start_Click (object sender, EventArgs e)
{
if(Start.Text == "Start")
{
Start.Text = "Stop";
_SerialPort.DataReceived += new SerialDataReceivedEventHandler (Port_DataReceived);
}
else
{
Start.Text = "Start";
}
}private void Port\_DataReceived (object sender, SerialDataReceivedEventArgs e) { string data = \_SerialPort.ReadExisting (); rtbTerminal.Invoke (new EventHandler (delegate { rtbTerminal.SelectedText = string.Empty; rtbTerminal.AppendText (data); rtbTerminal.ScrollToCaret (); })); }
I have tried both ways above.
-
private void Start_Click (object sender, EventArgs e)
{
if(Start.Text == "Start")
{
Start.Text = "Stop";
_SerialPort.DataReceived += new SerialDataReceivedEventHandler (Port_DataReceived);
}
else
{
Start.Text = "Start";
}
}private void Port\_DataReceived (object sender, SerialDataReceivedEventArgs e) { string data = \_SerialPort.ReadExisting (); rtbTerminal.AppendText (data); rtbTerminal.ScrollToCaret (); }
private void Start_Click (object sender, EventArgs e)
{
if(Start.Text == "Start")
{
Start.Text = "Stop";
_SerialPort.DataReceived += new SerialDataReceivedEventHandler (Port_DataReceived);
}
else
{
Start.Text = "Start";
}
}private void Port\_DataReceived (object sender, SerialDataReceivedEventArgs e) { string data = \_SerialPort.ReadExisting (); rtbTerminal.Invoke (new EventHandler (delegate { rtbTerminal.SelectedText = string.Empty; rtbTerminal.AppendText (data); rtbTerminal.ScrollToCaret (); })); }
I have tried both ways above.
Um. You do realize that each time you click the "Start" button, you add another handler to the existing list? So when a character arrives, the same handler method will be called twice, then three times, then four, etc... And that DataReceived is likely to be called each time a character arrives, since your PC runs rather faster than the serial port does, most of the time? How I would start: Add the handler once, when you first construct the SerialPort instance. Add a bool to enable / disable receive. When you press the Start button, clear the text from the RTB, then set the bool to enabled. When you press the Stop button, set the bool to disabled. In the DataReceived Handler, read the data available. Then, check the bool. If it is enabled, Append the data to the RTB and scroll to the caret. (You shouldn't need an invoke, I don't think). Do not clear the RTB. If it is disabled, throw the data away! Try that...
The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
-
I am trying to make a serial port terminal and i have succesfully made it except for some problems that i am facing. i have a button pressing which the terminal starts and the data from the serial port start to get displayed on the textbox. when i press the button again the serial port closes. Also i have put the code to read from the serial port in a timer with a time of 1 millisecond. So it automatically works like a loop and the data can be displayed continuously. Case 1. when i try reading from the serial port using
_SerialPort.ReadLine ()
what happens is that the data is getting displayed perfectly, but i am not able to press the button again to close the serial port, also i cant even close the application. I would have to use the task manager to kill the process. Case 2. when i try reading from the serial port using
_SerialPort.ReadExisting ()
what happens is that the earlier issue is resolved, but the data that is received is not continuous, that is some values are not recieved.
I use:
stream = port.BaseStream ;
...
byte[] buffer = new byte [ port.ReadBufferSize ] ;
...
stream.Read ( buffer , 0 , buffer.Length ) ;And I run the reader in a thread that raises events.
-
Um. You do realize that each time you click the "Start" button, you add another handler to the existing list? So when a character arrives, the same handler method will be called twice, then three times, then four, etc... And that DataReceived is likely to be called each time a character arrives, since your PC runs rather faster than the serial port does, most of the time? How I would start: Add the handler once, when you first construct the SerialPort instance. Add a bool to enable / disable receive. When you press the Start button, clear the text from the RTB, then set the bool to enabled. When you press the Stop button, set the bool to disabled. In the DataReceived Handler, read the data available. Then, check the bool. If it is enabled, Append the data to the RTB and scroll to the caret. (You shouldn't need an invoke, I don't think). Do not clear the RTB. If it is disabled, throw the data away! Try that...
The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
I have two forms, the first one is the main form and creates the serial port instance and then i pass the serial port object into the second form which is the terminal form. The following code is the contents of the namespace of the second form
bool Receive_Enable = false;
public Terminal (SerialPort Serial_Port)
{
InitializeComponent ();
_SerialPort = Serial_Port;
_SerialPort.Close ();
_SerialPort.DataReceived += new SerialDataReceivedEventHandler (Port_DataReceived);
}private void Start_Click (object sender, EventArgs e)
{
if(Start.Text == "Start")
{
Start.Text = "Stop";
_SerialPort.Open ();
Receive_Enable = true;
}
else
{
Receive_Enable = false;
_SerialPort.Close ();
Start.Text = "Start";
}
}private void Port_DataReceived (object sender, SerialDataReceivedEventArgs e)
{
if(Receive_Enable)
{
rtbTerminal.AppendText (Convert.ToString (_SerialPort.ReadLine ()));
rtbTerminal.ScrollToCaret ();
}
}Tried this.... Also tried with
_SerialPort.ReadExisting ()
The application freezes after few seconds.... :wtf: What to do???? :confused: Am i doing this right???
-
I have two forms, the first one is the main form and creates the serial port instance and then i pass the serial port object into the second form which is the terminal form. The following code is the contents of the namespace of the second form
bool Receive_Enable = false;
public Terminal (SerialPort Serial_Port)
{
InitializeComponent ();
_SerialPort = Serial_Port;
_SerialPort.Close ();
_SerialPort.DataReceived += new SerialDataReceivedEventHandler (Port_DataReceived);
}private void Start_Click (object sender, EventArgs e)
{
if(Start.Text == "Start")
{
Start.Text = "Stop";
_SerialPort.Open ();
Receive_Enable = true;
}
else
{
Receive_Enable = false;
_SerialPort.Close ();
Start.Text = "Start";
}
}private void Port_DataReceived (object sender, SerialDataReceivedEventArgs e)
{
if(Receive_Enable)
{
rtbTerminal.AppendText (Convert.ToString (_SerialPort.ReadLine ()));
rtbTerminal.ScrollToCaret ();
}
}Tried this.... Also tried with
_SerialPort.ReadExisting ()
The application freezes after few seconds.... :wtf: What to do???? :confused: Am i doing this right???
First off, stop opening and closing it - just leave it open. That ensures that nothing else can get at the port, since serial ports need exclusive locks. ReadLine is also unhelpful - it will always block until a newline is received, so if whatever device is on the other end of the connection doesn't use the same newline as your PC, it will never return. So, try this:
bool Receive_Enable = false;
public Terminal (SerialPort Serial_Port)
{
InitializeComponent ();
_SerialPort = Serial_Port;
_SerialPort.Open (); // **** IF IT ISN'T ALREADY OPENED BY THE CALLING CODE.
_SerialPort.DataReceived += new SerialDataReceivedEventHandler (Port_DataReceived);
}private void Start_Click (object sender, EventArgs e)
{
if(Start.Text == "Start")
{
Start.Text = "Stop";
Receive_Enable = true;
}
else
{
Receive_Enable = false;
Start.Text = "Start";
}
}private void Port_DataReceived (object sender, SerialDataReceivedEventArgs e)
{
if(Receive_Enable)
{
int bytes = _SerialPort.BytesToRead;
byte[] data = new byte[bytes];
_SerialPort.Read(data, 0, bytes);
string s = System.Text.Encoding.ASCII.GetString(data);
Console.WriteLine(s);
rtbTerminal.AppendText(s);
rtbTerminal.ScrollToCaret();
}
}You may want to play with the Encoding later, but that should be pretty safe. The Console output is just for debugging - it shows you what is received, in what chunks.
The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
-
First off, stop opening and closing it - just leave it open. That ensures that nothing else can get at the port, since serial ports need exclusive locks. ReadLine is also unhelpful - it will always block until a newline is received, so if whatever device is on the other end of the connection doesn't use the same newline as your PC, it will never return. So, try this:
bool Receive_Enable = false;
public Terminal (SerialPort Serial_Port)
{
InitializeComponent ();
_SerialPort = Serial_Port;
_SerialPort.Open (); // **** IF IT ISN'T ALREADY OPENED BY THE CALLING CODE.
_SerialPort.DataReceived += new SerialDataReceivedEventHandler (Port_DataReceived);
}private void Start_Click (object sender, EventArgs e)
{
if(Start.Text == "Start")
{
Start.Text = "Stop";
Receive_Enable = true;
}
else
{
Receive_Enable = false;
Start.Text = "Start";
}
}private void Port_DataReceived (object sender, SerialDataReceivedEventArgs e)
{
if(Receive_Enable)
{
int bytes = _SerialPort.BytesToRead;
byte[] data = new byte[bytes];
_SerialPort.Read(data, 0, bytes);
string s = System.Text.Encoding.ASCII.GetString(data);
Console.WriteLine(s);
rtbTerminal.AppendText(s);
rtbTerminal.ScrollToCaret();
}
}You may want to play with the Encoding later, but that should be pretty safe. The Console output is just for debugging - it shows you what is received, in what chunks.
The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
Did just that as you said now, Removed all the
SerialPort.Close()
No change, output is good, but the application freezes after a while. When i try to make the terminal as earlier without event handler i am getting a perfect output with
ReadExisting()
But using the eventhandler, it just doesn't work as expected