I have application with several windows (actually its two almost same windows with some functions). One of that function is reading data from COM port (read weight from weighting machine). Problem is that, it works perfect on first window, but when im closing it and opening another window, then clicking same function (lets call it calculate weight), im getting this error message:
Access to the port 'COM1' is denied.
Code:
private void calculateWeight_Click(object sender, RoutedEventArgs e)
{
sp = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
tekst = string.Empty;
sp.Open();
sp.WriteLine(((char)5).ToString());
sp.WriteLine(((char)17).ToString());
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
}
private delegate void UpdateUi(string s);
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
tekst += sp.ReadExisting();
if (tekst.Contains('S') && tekst.Length > 14)
Dispatcher.Invoke(DispatcherPriority.Send, new UpdateUi(czytajWage), tekst);
}
string tekst = string.Empty;
void czytajWage(string s)
{
string w = "";
for (int i = 5; i < 14; i++)
{
w += s[i];
}
MessageBox.Show(w);
w = "";
tekst = "";
sp.DataReceived -= sp_DataReceived;
}
Anyone can help? ;)
Method calculateWeight_Click opens serial port. So I assume that you get your exception on Open call as documentation states UnauthorizedAccessException can be thrown when:
The current process, or another process on the system, already has the specified COM port open either by a SerialPort instance or in unmanaged code.
So solution for you is to Close and Dispose sp after you are done or use IsOpen if you want to reuse existing instance.
Related
I have a small window form application (C#): Read data from barcode by COM UART RS232 and display to textbox
If I connect barcode with COM extension ( PCI express serial), after scan barcode => data only have /0/0/0/0/0/0/0/0
If I connect barcode with default COM ( communication COM) of computer => It's OK.
How can I fix that with extension COM ?
the below is my Code :
string path = ".\\Setting\\Config.ini";
IniFile inisys = new IniFile(path);
string PortName = inisys.GetString("FORMULA", "BarcodeCOM", "COM5");
int BaudRate = inisys.GetInt32("FORMULA", "baudrate", 9600);
port = new SerialPort(PortName, BaudRate, Parity.None, 8, StopBits.One);
port.Open();
if (port.IsOpen)
{
// set the 'invoke' delegate and attach the 'receive-data' function
// to the serial port 'receive' event.
accessControlFromCentralThread = displayTextReadIn;
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs rcvdData)
{
while (port.BytesToRead > 0)
{
lineReadIn += port.ReadExisting();
Thread.Sleep(100);
}
// display what we've acquired.
displayTextReadIn(lineReadIn);
}
private void displayTextReadIn(string ToBeDisplayed)
{
if (Txt_itemNo.InvokeRequired)
Txt_itemNo.Invoke(accessControlFromCentralThread, ToBeDisplayed);
else
Txt_itemNo.Text = ToBeDisplayed;
}
When using C# I can only read the last 4 characters of the value in COM2.
Putty reads it correctly
I have no control or information over the source that is putting the value on COM2.
My C# settings resemble the basic settings on Putty configuration screen, but C# offers more settings, so Putty must have some underlying settings not being shown.
I checked the documentation on Putty, I can't find the default settings on serial port.
My code:
using System.IO.Ports;
...
SerialPort mySerialPort = null;
mySerialPort = new SerialPort("COM2");
mySerialPort.BaudRate = 19200;
mySerialPort.Parity = System.IO.Ports.Parity.None;
mySerialPort.StopBits = System.IO.Ports.StopBits.One
mySerialPort.DataBits = 8;
mySerialPort.Handshake = System.IO.Ports.Handshake.None;
mySerialPort.DiscardNull = true;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
mySerialPort.ReadBufferSize = 2147483647;
...
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string value= sp.ReadExisting(); //I onle get the last four characters
}
So I should be obtaining the value "17159160118A" but I onle get "118A", Putty reads the whole string correctly
So given that I have no information about the signal source, my best bet is to use similar configuration as Putty in my code, do you know what configuration this could be? or what am I doing wrong?
So, I deleted all the code and started again with a clean console application, the source was sending the data in two parts, , I was just only reading the second, I just needed to know what was the string terminator, I found out that it was the null terminator character ('\0') so I used that to concatenate my strings, here's my code:
class Program
{
static void Main(string[] args)
{
using (SerialPort sp = new SerialPort("COM2", 19200, Parity.None, 8, StopBits.One))
{
//sp.DiscardNull = true;
sp.Handshake = Handshake.XOnXOff;
sp.ReadBufferSize = 16384;
sp.Open();
sp.DataReceived += sp_DataReceived;
AppDomain.CurrentDomain.ProcessExit += new EventHandler((x, y) =>
{
sp.Close();
});
Console.ReadKey();
}
}
static string myString = string.Empty;
static void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (sender as SerialPort);
if (sp.BytesToRead > 0)
{
myString += sp.ReadExisting().Trim();
if (myString.Last() == '\0')
{
myString = myString.Trim('\0').Trim();
if (!string.IsNullOrWhiteSpace(myString))
{
Console.WriteLine(myString);
}
sp.DiscardInBuffer();
myString = string.Empty;
}
}
}
}
I commented out //sp.DiscardNull = true; as it was removing all the null characters and it worked, so any way thanks for the downvote.
I'm doing a keypad project for 10-digit ID input. For each key press, it will send '1' or '2' or '3' and so on to the serial port. However, after trying to display the content of my id buffer with Console.WriteLine(id[i]), it only display the first keypad value from serial port. I need to display all 10-digit input from the buffer. I cant find where is the error in the code. I'm using System.IO.Ports
static void Main(string[] args)
{
char[] id = new char[10] ;
SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
port.Open();
if (port.IsOpen)
{
Console.WriteLine("port is now open");
}
else
{
Console.WriteLine("port not opened correctly");
}
port.Read(id, 0, 10);
for (int i = 0; i < 10; i++)
{
Console.WriteLine(id[i]);
}
Console.ReadLine();
}
First check whether your device is sending any data.
You can use a RS232 terminal for this.
Termite is a free terminal software.
If your hardware is sending data correctly,
Add DataReceive event,
port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
Then use ReadExisting() method for capture received data.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
Console.WriteLine(port.ReadExisting());
}
I am trying to communicate with ECUsim 2000 which is OBD-ll ECU simulator (link). Yet, responses I always receive from device are something like "??" or "?" (when I run programs like TouchScan or OBD Auto Doctor, they successfully reads data so device is working properly). I am sending comand in C# via
serialPort1.Write("010D\r")
and I am receiving signal in SerialPort's DataReceived event as
message = "Data Received: " + serialPort1.ReadExisting();
this.Invoke(new EventHandler(displayText));
I do not now what I am missing. Here is the full source code
private void Form1_Load(object sender, EventArgs e)
{
serialPort1.PortName = "COM3";
serialPort1.BaudRate = 115200;
serialPort1.Parity = System.IO.Ports.Parity.None;
serialPort1.StopBits = System.IO.Ports.StopBits.One;
serialPort1.DataBits = 8;
serialPort1.Handshake = System.IO.Ports.Handshake.None;
serialPort1.Open();
}
private void button1_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.Write("010D\r");
}
}
private void displayText(object sender, EventArgs e)
{
textBox1.AppendText(message + "\n");
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
message = "Data Received: " + serialPort1.ReadExisting();
this.Invoke(new EventHandler(displayText));
}
Default communication settings of ECUsim 2000 are
Baud Rate: 115200
Data bits: 8
Parity: none
Stop bits:1
protocol is ISO 15765-4 and there are two switches on the device which are protocol attribute CAN ID 29/11 bit and CAN Baud Rate 500 kbps/250kbps. Maybe, the problem are related with these such that there is no proper communication set.
Another question -> Is there a way to set protocol (like ISO 15765-4) in serial communication?
There are two problems related with the code given.
1) There are two connector on the ECUsim 2000. One of them is type B USB port, other one is Diagnostic Link Connector (DLC). If one wants to get connected to device via type B USB port, baud rate is: 115200. If DLC is used, Baud Rate is most probably either 9600 or 38400. Here, connection is made through scan tool, therefore (for my case) baud rate 38400 worked for me.
2) As mentioned in the comment, In order to get data, Read() method of SerialPort must be used. It can be used as the following code:
int buffSize = 1024;
bool cont = true;
int count = 0;
byte[] bff = new byte[buffSize];
string returnVal = string.Empty;
count = serialPort1.Read(bff, 0, buffSize);
returnVal += System.Text.Encoding.Default.GetString(bff, 0, count);
I'm working on a project that involves my client software sending data to a Arduino microcontroller, AtMega32U4, through serial communication. I've looked through many answered questions so far yet none of them were specific to my problem. However, I believe my problem may be limited to threading issues or Arduino autoreset problems.
Code 1:
public MainForm()
{
InitializeComponent();
serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
serialPort1.DtrEnable = true;
//serialPort1.RtsEnable = true;
}
private void button3_Click(object sender, EventArgs e)
{
// Disables button while processing
button3.Enabled = false;
GetDir dir = new App.GetDir();
dir.getCoords(Origin.Text, Destination.Text, Application.StartupPath + #"\temp2.html", "temp2.xml");
dataBrowser.Navigate(Application.StartupPath + #"\temp2.html");
dataBrowser.Update();
waypoints = dir.coordsLat.Length;
counter = dir.coordsLat.Length;
coords = new double[dir.coordsLat.Length, 2];
for (int i = 0; i < counter; i++)
{
coords[i, 0] = (Convert.ToDouble(dir.coordsLat[i]));
coords[i, 1] = (Convert.ToDouble(dir.coordsLon[i]));
}
//serialPort1.Close();
//System.Threading.Thread.Sleep(1000);
if (serialPort1.IsOpen && !doubleClick)
{
serialPort1.Close();
System.Threading.Thread.Sleep(2000);
try
{
serialPort1.Open();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, "Cannot open serial port");
}
System.Threading.Thread.Sleep(2000);
}
else
{
if (!serialPort1.IsOpen)
{
try
{
serialPort1.Open();
doubleClick = true;
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, "Cannot open serial port");
}
System.Threading.Thread.Sleep(2000);
serialPort1.Write("^");
System.Threading.Thread.Sleep(1000);
Console.WriteLine('^');
//button3.Enabled = true;
}
}
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//System.Threading.Thread.Sleep(1000);
readData = serialPort1.ReadLine();
Console.WriteLine(readData);
// If microcontroller sends "&", it is ready to receive next piece of data
if (readData == "&")
{
sendRequest = true;
}
else
{
sendRequest = false;
}
// Write next piece of data to microcontroller if it is ready
if (sendRequest)
{
this.BeginInvoke( new EventHandler (write_serialPort1));
}
}
In during the debugging of code 1, the event handler (serialPort1_DataReceived) never gets called. In this process, somehow button3_click gets called twice as the console outputs '^' twice. Afterwards, the client stalls since there is nothing beind received. Keep in mind that the Arduino will respond with an ampersand ('&') once it has received the circumflex ('^'). The Arduino code has been tested on the Arduino IDE and appears to be working fine. I believe the problem with button3_click being called twice comes from the button3_down and button3_up.
However, I was able to bypass this issue with Code 2. But also hit another brick wall.
Code 2 :
private void button3_Click(object sender, EventArgs e)
{
// Disables button while processing
button3.Enabled = false;
GetDir dir = new App.GetDir();
dir.getCoords(Origin.Text, Destination.Text, Application.StartupPath + #"\temp2.html", "temp2.xml");
dataBrowser.Navigate(Application.StartupPath + #"\temp2.html");
dataBrowser.Update();
waypoints = dir.coordsLat.Length;
counter = dir.coordsLat.Length;
coords = new double[dir.coordsLat.Length, 2];
for (int i = 0; i < counter; i++)
{
coords[i, 0] = (Convert.ToDouble(dir.coordsLat[i]));
coords[i, 1] = (Convert.ToDouble(dir.coordsLon[i]));
}
serialPort1.Close();
try
{
serialPort1.Open();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, "Cannot open serial port");
}
if (serialPort1.IsOpen)
{
System.Threading.Thread.Sleep(2000);
using (serialPort1)
{
serialPort1.Write("^");
System.Threading.Thread.Sleep(1000);
Console.WriteLine("^");
serialPort1.Close();
System.Threading.Thread.Sleep(5000);
}
}
else
{
button3.Enabled = true;
}
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//SerialPort sp = (SerialPort)sender;
System.Threading.Thread.Sleep(10000);
/*if (!serialPort1.IsOpen)
{
serialPort1.Close();
System.Threading.Thread.Sleep(10000);
serialPort1.Open();
System.Threading.Thread.Sleep(10000);
}*/
//serialPort1.Open();
//using (sp)
using (serialPort1)
{
serialPort1.Open();
System.Threading.Thread.Sleep(5000);
readData = serialPort1.ReadExisting();
Console.WriteLine(readData);
// If microcontroller sends "&", it is ready to receive next piece of data
if (readData == "&")
{
sendRequest = true;
}
else
{
sendRequest = false;
}
// Write next piece of data to microcontroller if it is ready
if (sendRequest)
{
this.BeginInvoke(new EventHandler(write_serialPort1));
}
}
}
In Code 2, the event handler does get called and the button3_click only runs once. But when it tries to open the port, it returns the error 'Access to Port X denied'. Furthermore, I wish I didn't have to close and open the ports like this, but when the event handler is called (in an earlier code) it returned the error that the COM Port was not opened. In order to satisfy that error, I had to close it and reopen it during button3_click and event handling.
I've added a lot of delay in the code after I read about many problems dealing with the threading issues with serial communication. I had even tried a minute delay in hopes of a thread ending to solve the problem. However, no luck there.
I also specified my serial port in the MainForm designer instead of declaring it in the code (At first I did both and realized it was redundant). I'm not sure if this contributes to the problem, but I've seen examples of both being used.
Lastly, it could definitely deal with the Arduino auto resetting everytime a serial connection has been made (eg. opening and closing a port). In summary, it seems be sending data through serial, but unable to read the incoming data from serial.
Thank you for reading this and if someone could point me in the right direction, it would be very much appreciated.
Edit #1: Even after using BeginInvoke in Code 1, it still deadlocks because the event handler was never called.
Edit #2: Edits to Code 1 as per newbie's suggestions.
Edit #3: Added mainform initialization and updated Code 1 to current state.
Edit #4: Deleted (Commented out) the sleep at the event handler. I was sleeping during the event handler, thus I couldn't receive anything that the microcontroller would send to me. Code works fine as expected now.
Make sure you are using COM1, if you do not COM1 serial port,
change through Computer -> Device Manager -> Ports (COM & LPT) ->
Select the COM to be changed -> Port Settings -> Advanced -> ComPort Number -> select COM1.
Make sure that you have installed jumper / connect with a screwdriver
between pin2 and pin3 of COM1.
Add button1 and textBox1 to Form and run this program
using System;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
using System.Text;
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
const int MAX_BUFFER = 100;
int i = 0;
byte[] DataReceived = new byte[MAX_BUFFER];
SerialPort serialPort = new SerialPort();
public Form1() {
InitializeComponent();
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
}
void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) {
// wait data ready
Thread.Sleep(500);
// while data ready in buffer
while (serialPort.IsOpen && serialPort.BytesToRead > 0) {
// read data serial
DataReceived[i] = Convert.ToByte(serialPort.ReadByte());
// counter data
i++;
// reset conter if more then maxvalue
if (i >= MAX_BUFFER) {
i = 0;
}
}
if (i == 1 && DataReceived[0] == ASCIIEncoding.ASCII.GetBytes("^")[0]) {
this.textBox1.Invoke(new Action(() => {
this.textBox1.Text = ASCIIEncoding.ASCII.GetString(DataReceived, 0, 1);
}));
}
}
public void InitSerialPort() {
serialPort.PortName = "COM1";
serialPort.BaudRate = 9600;
serialPort.Parity = Parity.None;
serialPort.DataBits = 8;
serialPort.StopBits = StopBits.One;
serialPort.ReceivedBytesThreshold = 1;
}
private void Form1_Load(object sender, EventArgs e) {
// initialize serial port
InitSerialPort();
// assure port is closed before open it
if (serialPort != null && serialPort.IsOpen) {
serialPort.Close();
}
serialPort.Open();
}
private void button1_Click(object sender, EventArgs e) {
if (serialPort.IsOpen) {
serialPort.Write("^");
// wait data sent
Thread.Sleep(500);
}
}
}
}
In accordance to my 4th edit, deleted (Commented out) the sleep at the event handler. I was sleeping during the event handler, thus I couldn't receive anything that the microcontroller would send to me. Code works fine as expected now. Nothing was wrong with the serial ports on either components.