12 Replies - 4496 Views - Last Post: 12 September 2011 - 05:00 PM Rate Topic: -----

#1 RandomlyKnighted  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 117
  • View blog
  • Posts: 1,370
  • Joined: 14-January 10

Opening 2 Serial Ports?

Posted 11 September 2011 - 07:54 PM

Hello everyone, I'm working on a program that requires opening multiple serial ports and reading from them at the same time. Currently, I am trying to open 2 ports and once I get that working I'll increase them one by one until I get the number I need. The problem I'm having at the moment is that the first serial port opens without any problems but the 2nd one throws an UnauthorizedAccessException error and tells me that "Access to the port 'COM13' is denied."

My code is below. Any ideas as to why it does this?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Threading;

namespace Relay_Controller
{
    public partial class Form1 : Form
    {
        // Declares all variables
        public SerialPort sp1;
        public SerialPort sp2;
        Form2 f2;

        // dataReceived will be the buffer used to read data from the serial port
        string dataReceived = string.Empty;

        public Form1()
        {
            InitializeComponent();

            // Opens Form2 first
            f2 = new Form2(this);
            f2.ShowDialog();
            sp1.Open();
            sp2.Open();
            try
            {
                sp1.Write("\r\n");
                sp2.Write("\r\n");
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error");
            }
            this.sp1.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
            this.sp2.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);

        }

        public void createPort1(string com1Name)
        {
            sp1 = new SerialPort(com1Name, 57600);
        }

        public void createPort2(string com2Name)
        {
            sp2 = new SerialPort(com2Name, 57600);
        }

        void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                // Read data from serial
                string data1 = sp1.ReadExisting();
                string data2 = sp2.ReadExisting();

                // Displays data received to the textbox
                this.Invoke(new MethodInvoker(() =>
                {
                    textBox1.Text += data1.Trim();
                    textBox1.Selectionstart = textBox1.Text.Length;
                    textBox1.ScrollToCaret();

                    textBox1.Text += data2.Trim();
                    textBox1.Selectionstart = textBox1.Text.Length;
                    textBox1.ScrollToCaret();
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show("Data could not be read from the serial port." + ex.Message, "Error");
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (sp1.IsOpen | sp2.IsOpen)
            {
                sp1.Close();
                sp2.Close();
            }
        }

        private void allRelaysToggleBtn_Click(object sender, EventArgs e)
        {
            sp1.Write("RELS.GET");
            sp1.Write("\r\n");

            sp2.Write("RELS.GET");
            sp2.Write("\r\n");
            
        }

        public void onSwitch()
        {
            sp1.Write("RELS.ON");
            sp1.Write("\r\n");

            sp2.Write("RELS.ON");
            sp2.Write("\r\n");
        }

        public void offSwitch()
        {
            sp1.Write("RELS.ON");
            sp1.Write("\r\n");
            textBox1.Text = "\n";

            sp2.Write("RELS.ON");
            sp2.Write("\r\n");
            textBox1.Text = "\n";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            sp1.Write("REL1.ON");
            sp1.Write("\r\n");
        }

        private void button13_Click(object sender, EventArgs e)
        {
            sp1.Write("REL1.OFF");
            sp1.Write("\r\n");
        }

        private void button9_Click(object sender, EventArgs e)
        {
            sp2.Write("REL1.ON");
            sp2.Write("\r\n");
        }

        private void button17_Click(object sender, EventArgs e)
        {
            sp2.Write("REL1.OFF");
            sp2.Write("\r\n");
        }
    }
}



Is This A Good Question/Topic? 0
  • +

Replies To: Opening 2 Serial Ports?

#2 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5578
  • View blog
  • Posts: 11,931
  • Joined: 02-June 10

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 01:53 AM

Let me also throw in a couple tips:
  • You have to program as if everything breaks, nothing works, the cyberworld is not perfect, the attached hardware is flakey, the network is slow and unreliable, the harddrive is about to fail, every method will return an error and every user will do their best to break your software. Confirm everything. Range check every value. Make no assumptions or presumptions.

  • Take the extra 3 seconds to rename your controls each time you drag them onto a form. The default names of button1, button2... button54 aren't very helpful. If you rename them right away to something like btnOk, btnCancel, btnSend etc. it helps tremendously when you make the methods for them because they are named after the button by the designer.btnSend_Click(object sender, eventargs e) is a lot easier to maintain than button1_click(object sender, eventargs e)

  • You aren't paying for variable names by the byte. So instead of variables names of a, b, c go ahead and use meaningful names like Index, TimeOut, Row, Column and so on. You should avoid 'T' for the timer. Amongst other things 'T' is commonly used throughout C# for Type and this will lead to problems. There are naming guidelines you should follow so your code confirms to industry standards. It makes life much easier on everyone around you, including those of us here to help. If you start using the standards from the beginning you don't have to retrain yourself later.


  • Try to avoid having work actually take place in GUI control event handlers. It is usually better to have the GUI handler call other methods so those methods can be reused and make the code more readible.
    Spoiler

Was This Post Helpful? 0
  • +
  • -

#3 ragingben  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 170
  • View blog
  • Posts: 637
  • Joined: 07-October 08

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 01:57 AM

What happens if you try changin the serial port names so port 1 is COM1, and port 2 is COM3 for example. Even if you are not using these ports does this get rid of the error? Are you sure nothing else is using COM13, or you aren't already uisng it on accident? Using the following code I can connect to 2 serial ports, but if I change the port names so they are both COM1 I get an UnauthorizedAccessException "Access to the port 'COM1' is denied.".
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;

namespace Serial
{
    class Program
    {
        static void Main(string[] args)
        {
            SerialPort port1 = new SerialPort("COM1", 115200, Parity.None, 8, StopBits.One);
            SerialPort port2 = new SerialPort("COM3", 115200, Parity.None, 8, StopBits.One);

            port1.Open();
            port2.Open();

            port1.Close();
            port2.Close();

            Console.ReadLine();
        }
    }
}


If I try and connect to COM13 I always get an exception. Maybe this port is reserved, or is being used by some other peice of hardware. Do you need to use COM13? On my computer the bluetooth uses COM13 as it's port. Check on device manager and see what it says for location.

This post has been edited by ragingben: 12 September 2011 - 02:00 AM

Was This Post Helpful? 1
  • +
  • -

#4 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5578
  • View blog
  • Posts: 11,931
  • Joined: 02-June 10

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 02:05 AM

I don't see how you are even initializing your port definitions.
You create two SerialPort objects without ever assigning the port names. So at this point they are both the same.
Then in your constructor you try to open both of them.
So it seems to me sp1 and sp2 are both targeting the same serial port. So it makes sense sp2 can't open the port that sp1 has already opened.


namespace Relay_Controller
{
    public partial class Form1 : Form
    {
        // Declares all variables
        public SerialPort sp1;
        public SerialPort sp2;
        Form2 f2;

        // dataReceived will be the buffer used to read data from the serial port
        string dataReceived = string.Empty;

        public Form1()
        {
            InitializeComponent();

            // Opens Form2 first
            f2 = new Form2(this);
            f2.ShowDialog();
            sp1.Open();
            sp2.Open();
            try
            {
                sp1.Write("\r\n");
                sp2.Write("\r\n");
            }



The only way this can be working is if the form2 you are opening as a modal dialog is letting the user pick the names for com ports 1 and 2.

If that is the case, then your communication between forms 1 and 2 is really not being done well/right. They would have to be tightly bound for this to be working because nowhere in your form1 is there a handler for any event in form2. Form2 would have to be directly accessing variables from form1 - which I am guess was the purpose of sending (this) to form2 upon opening. Am I correct? If so, please stop right here. This fugly form1<->form2 communication needs to be cleaned up before you go further.

See FAQ #2 for form to form communication.


FAQ (Frequently Asked Questions - Updated Aug 2011

Spoiler

This post has been edited by tlhIn`toq: 12 September 2011 - 02:06 AM

Was This Post Helpful? 0
  • +
  • -

#5 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5578
  • View blog
  • Posts: 11,931
  • Joined: 02-June 10

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 02:13 AM

Not a lot of us have in excess of 10 COM ports. I think I have 8. If I dug out every USB adapter I have I could make 13. Since this is a relay controller, I'm going to guess it is really a USB<->serial adapter of some kind, maybe built onto the relay control board. Is COM13 showing up as "In Use" in the Device Manager? Perhaps in all your programming and installing and testing to get this working the OS has it tied up erroneously.


Moving on to possible causes for the failure:
  • SP1 and SP2 are trying to open the same port.
  • Some other application is already holding "COM13" open.
  • Is it possible you opened up the OEM test software and still have it open when you are running your application?
  • Perhaps if you opened it during development and had a crash then the OS didn't clean up for you. The board might be holding the port open. Try rebooting.

Was This Post Helpful? 1
  • +
  • -

#6 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5578
  • View blog
  • Posts: 11,931
  • Joined: 02-June 10

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 02:50 AM

Ben's right - and has a come up with a really direct test. Take form2 out of the testing for a moment and just hard-code the selected ports to see if that works. And test different combinations of ports to see if it is always your second port or always COM13.

Also, in your form closing you are using a logical or instead of a conditional or
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
085
        {
086
            if (sp1.IsOpen | sp2.IsOpen)



To do that comparison you want to have this:
if (sp1.IsOpen || sp2.IsOpen)


Though there is no need do the check. You can safely close a port that is already closed.

You might consider cleaning up the code to have a ClosePorts() method that just does that one function. Then a Quit() method that goes through the list of methods for closing.

void Quit()
{
   ClosePorts();
   SaveSettings();
   CloseLogFile();
}

This post has been edited by tlhIn`toq: 12 September 2011 - 05:16 AM

Was This Post Helpful? 1
  • +
  • -

#7 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5578
  • View blog
  • Posts: 11,931
  • Joined: 02-June 10

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 02:56 AM

In most coding we try to not duplicate code, and you have it in every button handler that sends a message to the relay controller. It would be cleaner to have just one method that talks to the board. That way if you realize you have to add an extra step you only have to add it in one place, not a dozen.

Look how much cleaner this is.
Spoiler

If you didn't know, you can collapse all the code with a simple: Cntrl-M, Cntrl-O
Using the navigation drop down then takes you right to the method you need without having to look at 5,000 lines of expanded code.

Attached Image

This post has been edited by tlhIn`toq: 12 September 2011 - 02:58 AM
Reason for edit:: Fix logical or

Was This Post Helpful? 1
  • +
  • -

#8 RandomlyKnighted  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 117
  • View blog
  • Posts: 1,370
  • Joined: 14-January 10

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 05:51 AM

I got class real soon so I don't have time to implement all before that. For starters, I didn't use good button names because I was trying to get this whole project done in under 6 hours so I could move on to something else.

Basically, I'm working with a 4 port USB Relay Controller and I'm going from those to USB using a cable. Basically the COM port doesn't even show up until I plug it into the computer and then the only program that I'm telling to use it is my program.

My Form2 code is below so you can see what I was doing with it.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace Relay_Controller
{
    public partial class Form2 : Form
    {

        Form1 main;
        bool appClose = false;

        public Form2(Form1 f1)
        {
            InitializeComponent();
            main = f1;
            comChoiceBox.Items.AddRange(SerialPort.GetPortNames());
        }

        private void selectBtn_Click(object sender, EventArgs e)
        {
            appClose = true;
            this.Hide();
            main.createPort1(comChoiceBox.SelectedItem.ToString());
            main.createPort2(comChoiceBox.SelectedItem.ToString());
            this.Close();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (appClose == false)
            {
                Application.Exit();
            }
        }


    }
}


Was This Post Helpful? 0
  • +
  • -

#9 Curtis Rutland  Icon User is online

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4531
  • View blog
  • Posts: 7,903
  • Joined: 08-June 10

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 06:49 AM

Quote

For starters, I didn't use good button names because I was trying to get this whole project done in under 6 hours so I could move on to something else.


Ok, I do want to interject here. It takes all of three extra seconds to rename a UI control in VS. Even variables take almost no time to rename (Ctrl-R, R). So that's not going to make or break your project.

What might, is coming back in six hours and realizing you have no idea what button15 does.
Was This Post Helpful? 4
  • +
  • -

#10 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5578
  • View blog
  • Posts: 11,931
  • Joined: 02-June 10

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 07:08 AM

View PostRandomlyKnighted, on 12 September 2011 - 06:51 AM, said:

I got class real soon so I don't have time to implement all before that. For starters, I didn't use good button names because I was trying to get this whole project done in under 6 hours so I could move on to something else.

Slow is smooth... Smooth is fast.
It takes only a couple seconds to rename a control that you dragged onto a form.
That couple seconds then saves you many seconds, many time over and over.
What you saved in not doing this 3 second process you will waste in code maintainability every time you open this project and wonder... "What was button6 supposed to do again?"


View PostRandomlyKnighted, on 12 September 2011 - 06:51 AM, said:

I'm working with a 4 port USB Relay Controller [...]the COM port doesn't even show up until I plug it into the computer ...

As I suspected/suggested: The controller has a USB<->Serial converter built-in. Probably an FTDI chipset.

As I suspected, the instance of form2 is being used to set parameters for form1.
This is the ugliest way of coding this I can think of. All because you rushed to the keyboard rather than think it through a bit. If you are going to bind the two forms this tight, why not put a TabControl on your form and have one tab for Operation and one for Configuration? That way you can go back and forth between the two tabs as much as you need to. You could change which ports you want to work with, then re-open. You would save tons of time by not have to close and re-launch this application just to change ports.

[SOAPBOX SURMON]
Nothing relevant for problem solving. Just tlhIn`toq ranting. RandomlyKnighted probably doesn't want to open this.
Spoiler

[/SOAPBOX SURMON]

All of the advice on how to find the cause of the problem still stands. This code for form2 doesn't have any problems that would cause the failure. Its still a matter of some other thread/form/application holding the port open. You're going to have to debug that.

Honestly the code for form1 and form2 and the prinicpals underlying them is so bad that a lot of the seasoned coders here would and could re-write it all in ten different vastly better ways. But this is homework. I urge the rest of the DIC community to NOT rewrite this students homework. They need to turn in and be graded on THEIR work and knowledge, not YOURS/OURS.

This post has been edited by tlhIn`toq: 12 September 2011 - 07:08 AM

Was This Post Helpful? 1
  • +
  • -

#11 ragingben  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 170
  • View blog
  • Posts: 637
  • Joined: 07-October 08

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 08:18 AM

I don't need to go into naming as the guys above have covered that, but might I add it will not only benefit you but also those trying to help you in this case, and in a broader sense anyone who may use your code in the future. Just a great habit to be into. "Slow is smooth... Smooth is fast" is actualy a great way of putting, and applies to many things aswell as programming... ahem :)

Anyway, thlIn`toq is right, that does appear to be what is happening. Maybe there is something else usiong it even if your not telling it to. Maybe something starts up when the cable is plugged into the computer. Open task manager and watch the processes. Does anything start when you plug it in? If so whathappens if you kill it then try connecting. Have you got an SDK?
Was This Post Helpful? 1
  • +
  • -

#12 RandomlyKnighted  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 117
  • View blog
  • Posts: 1,370
  • Joined: 14-January 10

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 09:39 AM

I just want to start by saying that I generally don't leave variable names like that. I always try to name them something meaningful.

Second, this is not homework. This is an outside of class project that I'm working on for a club. They asked me to interact with the relay so that they can turn the HAM radios on and off when they are tracking satellites and or balloon payloads.

I am about to start working on the project again soon. I'll post later an update of my code later when I find time.
Was This Post Helpful? 0
  • +
  • -

#13 RandomlyKnighted  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 117
  • View blog
  • Posts: 1,370
  • Joined: 14-January 10

Re: Opening 2 Serial Ports?

Posted 12 September 2011 - 05:00 PM

View PosttlhIn`toq, on 12 September 2011 - 09:08 AM, said:

As I suspected, the instance of form2 is being used to set parameters for form1.
This is the ugliest way of coding this I can think of. All because you rushed to the keyboard rather than think it through a bit. If you are going to bind the two forms this tight, why not put a TabControl on your form and have one tab for Operation and one for Configuration? That way you can go back and forth between the two tabs as much as you need to. You could change which ports you want to work with, then re-open. You would save tons of time by not have to close and re-launch this application just to change ports.


I never thought of using a TabControl for this program. That would definitely make things easier to maintain as well as make it easier for the user to configure it as needed. The club president asked me if I could implement some features that were in another one of my programs so TabControl might be the best way for me to do this.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1