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)
{
}
}
Related
I am currently trying to build a windows forms app that gets sensor data from an arduino via the serial com.
when checking in the arduino IDE the data gets writen into the serial port correctly.
But i can't figure out how to read the data via c#.
class Program
{
static SerialPort SP;
static void Main(string[] args)
{
SP = new SerialPort();
SP.PortName = "COM7";
SP.BaudRate = 9600;
SP.Handshake = System.IO.Ports.Handshake.RequestToSend;
SP.Open();
while (true)
{
Console.WriteLine(DateTime.Now.ToString() + " : " + SP.ReadLine());
}
}
}
My guess is that the Port is not properly set up, but i have no idea what i am missing.
The Goal is just to receive strings from the arduino, i do not necessarily need to send any data to the arduino.
edit: i am working with an arduino micro
Did you close Arduino IDE?
You need to add a wait code before reading from the port
Below is a working example:
private SerialPort _currentPort = new SerialPort("COM7", 9600);
private readonly object _sync = new object();
public bool Open()
{
_currentPort.Encoding = Encoding.UTF8;
_currentPort.DtrEnable = true;
_currentPort.ReadTimeout = 2000;
try
{
if (!_currentPort.IsOpen)
lock (_sync)
{
if (_currentPort.IsOpen)
return true;
_currentPort.Open();
System.Threading.Thread.Sleep(1500);
}
}
catch (Exception e)
{
//_localLogger?.Error($"{_currentPort.PortName}, {e.Message}", e);
return false;
}
return _currentPort.IsOpen;
}
public bool Subscribe()
{
try
{
if (Open())
{
_currentPort.DataReceived += CurrentPortOnDataReceived;
return true;
}
return false;
}
catch (Exception e)
{
//_localLogger?.Error($"{_currentPort.PortName}, {e.Message}", e);
return false;
}
}
private void CurrentPortOnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (!_currentPort.IsOpen)
{
//_localLogger.Info($"{_currentPort} is closed");
Open();
}
Console.WriteLine(_currentPort.ReadExisting());
}
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;
}
}
}
}
Here the serial communication port shows error it cannot be accessed .....But the serial communication port works perfect in arduino, so it cant be the port problem, its not the driver problem either, the driver is updated and works well, so the problem can be in the code .....i am a newbie to C#.
public partial class Form1 : Form
{
private SerialPort myport;
private string in_data;
public Form1()
{
InitializeComponent();
}
private void Start_Click(object sender, EventArgs e)
{
myport = new SerialPort();
myport.BaudRate = 19200;
myport.PortName = pn.Text;
myport.Parity = Parity.None;
myport.DataBits = 8;
myport.StopBits = StopBits.One;
myport.DataReceived += myport_DataReceived;
try
{
myport.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error!!");
}
}
void myport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
*in_data = myport.ReadLine();***
this.Invoke(new EventHandler(displaydata_event));
}
private void displaydata_event(object sender, EventArgs e)
{
string[] newData = in_data.Split(',');
bv.Text = newData[0];
bi.Text = newData[1];
pv.Text = newData[2];
pi.Text = newData[3];
t.Text = newData[4];
}
}
it cannot be accessed
This may indicates that the port doesnt exists or is already in use.
Maybe another application is already listening on this port. (arduino?)
Comport.Open() Exceptions are descibed here:
MSDN SerialPort.Open Method
I saw that similar topics were posted on this forum, but I simply don't understand how to send AT commands and receive a response. (I started to program in C# several months ago. I'm still an n00b, but I'm working hard to learn it...).
I need to create application which would only receive SMS message through GSM USB dongle. So far I managed to create app that will recognize and connect modem through COM ports that is available. Now I need to push AT commands for receiving messages and displaying them into a textBox. I was wondering if anyone can spare few minutes to explain the process to me, and modify my code with comments so I can finally learn and understand how to use serialPort for communication. What I need to know, when SMS is sent, does this message is received and stored by GSM modem (and it is stored until I send some requests to read them or do I need to send some event that would trigger GSM modem to collect message from ISP)? how to push AT commands and receive their response (I only know that is done by using serialPort object, but doesn't have clue how to do it...)
This is my method for receiving (which I'm stuck BTW... :))
private void receiveMessage()
{
//commclass is only a class for getting COM port, baud rate and timeout
CommClass cc = new CommClass();
cc.setParameters();
serialPort1.PortName = cc.getPort();
serialPort1.BaudRate = cc.getBaud();
serialPort1.ReadTimeout = cc.getTimeout();
serialPort1.Open();
if (!serialPort1.IsOpen)
{
//MessageBox is written in Croatian language, it is only an alert to check the configuration because port is not opened...
MessageBox.Show("Modem nije spojen, molimo provjerite konfiguraciju...!");
//timer1.Stop();
}
else
{
//this.label2.Text = serialPort1.PortName;
//this.label2.Visible = true;
//this.label3.Visible = true;
//this is where I need to place a code for receiving all SMS messages
this.serialPort1.Write("AT+CMGL=\"REC UNREAD\"");
}
serialPort1.Close();
}
If anyone willing to help, I would appreciate that, if not I would have to deal with it by my self (probably spent few hours/days until I figure it out...)
In both cases, thank you anyway... Cheers.
Sorry for waiting for my reply, been busy lately.
In short this is my code for getting message from GSM USB dongle. I hope that it will be useful to someone...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace SMSget
{
public partial class SMSLogPanel : UserControl
{
SerialPort sp;
int datab = 0;
bool dtr = false;
bool encod;
Handshake h;
Parity p;
int wtimeout = 0;
StopBits s;
#region default constructor
public SMSLogPanel()
{
InitializeComponent();
this.sp = serialPort1 = new SerialPort();
this.datab = serialPort1.DataBits = 8;
this.dtr = serialPort1.DtrEnable = true;
this.encod = serialPort1.Encoding.Equals("iso-8859-1");
this.h = serialPort1.Handshake = Handshake.RequestToSend;
this.p = serialPort1.Parity = Parity.None;
this.wtimeout = serialPort1.WriteTimeout = 300;
this.s = serialPort1.StopBits = StopBits.One;
checkLink();
}
#endregion
#region checking communication and setting user controls...
private void checkLink()
{
GetValues value = new GetValues();
string com = value.getPort();
int baud = value.getBaud();
int timeot = value.getTimeout();
serialPort1.PortName = com;
serialPort1.BaudRate = baud;
serialPort1.ReadTimeout = timeot;
serialPort1.Open();
if (serialPort1.IsOpen)
{
label1.Visible = true;
}
else
{
MessageBox.Show("Komunikacija sa modemom se ne može uspostaviti, molimo postavite novu konfiguraciju...!");
this.Controls.Clear();
SMSConfigPanel cfg = new SMSConfigPanel();
cfg.Show();
this.Controls.Add(cfg);
}
serialPort1.Close();
}
#endregion
#region panel load method
private void SMSLogPanel_Load(object sender, EventArgs e)
{
setGSM();
}
#endregion
#region execute serialport handler
public void getMessage()
{
if (serialPort1.IsOpen)
{
serialPort1.DataReceived += new SerialDataReceivedEventHandler(getResponse);
}
else
{
MessageBox.Show("Nije moguće zaprimiti poruku, komunikacijski port nije otvoren...1");
return;
}
}
#endregion
#region get response from modem
public void getResponse(object sender, SerialDataReceivedEventArgs e)
{
SerialPort serPort = (SerialPort)sender;
string input = serPort.ReadExisting();
if (input.Contains("+CMT:"))
{
if (input.Contains("AT+CMGF=1"))
{
string[] message = input.Split(Environment.NewLine.ToCharArray()).Skip(7).ToArray();
textBox1.Text = string.Join(Environment.NewLine, message);
}
this.Invoke((MethodInvoker)delegate
{
textBox1.Text = input;
});
}
else
{
return;
}
}
#endregion
#region initialize GSM
private void setGSM()
{
serialPort1.Open();
if (!serialPort1.IsOpen)
{
MessageBox.Show("Problem u komunikaciji sa modemom, port nije otvoren...!");
}
serialPort1.Write("AT+CMGF=1" + (char)(13));
serialPort1.Write("AT+CNMI=1,2,0,0,0" + (char)(13));
}
#endregion
#region setiranje timer-a...
private void timer1_Tick_1(object sender, EventArgs e)
{
timer1.Stop();
getMessage();
timer1.Start();
}
#endregion
}
}
This was only code for testing so it works but there is lot to fix and improve. Basically it will be a nice start for all that are searching something like this...
cheers.
HI
im new in c# serial port. im writing a c# program running is winXP and win7 to keep received data from the serial port when the machine was sent data.
using System.IO;
using System.IO.Ports;
using System.Threading;
namespace RS232RVR
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
SettingRS232();
}
public void SettingRS232 ()
{
try
{
SerialPort mySerialPort = new SerialPort("COM6");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None; //send to hardware flow control.
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceviedHandler);
mySerialPort.Open();
richTextBox1.Text = "on";
mySerialPort.Close();
}
catch (Exception ex)
{
richTextBox1.Text = ex.Message;
}
}
private void DataReceviedHandler(
object sender,
SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
richTextBox1.Text = indata;
}
}
}
COM6 is active in my pc. but my problem was seem the datareceived event is not fire when it has data coming from the serial port. ( i had checked the sport by using some of the freeware application)
anyone can help?
thanks
mySerialPort.Open();
richTextBox1.Text = "on";
mySerialPort.Close();
That's not going to work, you'll close the serial port a couple of microseconds after opening it. Yes, the DataReceived event handler is not likely to fire. Only close the port when shutting down your program.
mySerialPort.Handshake = Handshake.None
That's a problem too, you'll need to control the handshake signals yourself now. The vast majority of serial port devices won't send anything until they see the machine powered up and ready to receive. Set the DtrEnabled and RtsEnabled properties to true.
Did you copy that code from your application? Is it perhaps just a case that the event handler name is misspelled? E.g. DataReceviedHandler should actually be spelt DataReceivedHandler.
The problem was solved and i would like to share it. i had fine dunning as below:
namespace RS232RVR
{
public partial class Form1 : Form
{
private delegate void SetTextDeleg(string data);
public Form1()
{
InitializeComponent();
SettingRS232();
}
public void SettingRS232 ()
{
try
{
SerialPort mySerialPort = new SerialPort("COM6");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.ReadTimeout = 2000;
mySerialPort.WriteTimeout = 500;
mySerialPort.DtrEnable = true;
mySerialPort.RtsEnable = true;
mySerialPort.Open();
//mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
mySerialPort.DataReceived += DataReceivedHandler;
textBox1.Text = "Serial Port is Ready.";
}
catch (Exception ex)
{
textBox1.Text = ex.Message;
}
}
public void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
System.Threading.Thread.Sleep(500);
string indata = sp.ReadExisting();
this.BeginInvoke(new SetTextDeleg(DisplayToUI), new object[] { indata });
//textBox1.Text += indata;
}
private void DisplayToUI(string displayData)
{
textBox1.Text += displayData.Trim();
// textBox1.Text += displayData;
}
}
}
If anyone have comment on the code you are welcome, is my pleasure and wish to code it better.