problem with multiple serial ports

Hi,

I am having problem with reading data from multiple serial ports on same form.

I have 1 form with 2 serial port objects on that. Both serial ports connected to diffrent printing devices and handles send and receive of data for devices. These printing device expects data to be print in such a way that once you send data you have to wait for response from device and then and only then you can send next data.

Here is summary of my code:

I am assigning port details to both ports in form initialization

On button click I am sending data to both ports one by one.

There are two functions SendDatatoVIN() (which sends data to first serial port and waits for response and once it receives response it will send next data.) and SendDatatoHeadstock() (which sends data to secound serial port and waits for response and once it receives response it will send next data)

public enum VINPortStatus { None, LaunchCode, VINNumber, Para1, Para2, Para3, Para4, Para5, VINDone };

private enum HeadstockPortStatus { None, LaunchCode, HeadstockNumber, Para1, Para2, Para3, Para4, Para5, HeadstockDone };

private SerialPort VINcomport = new SerialPort();

private SerialPort Headstockcomport = new SerialPort();

public VINPortStatus objVINPortStatus;

private HeadstockPortStatus objHeadstockPortStatus;

private byte[] m_IncomingRawData = new byte[280];

private byte[] m_IncomingData = new byte[280];

private int m_IncomingRawDataCount = 0;

public frmVINScan()

{

InitializeComponent();

setscreen();

checkPortAvailability();

}

private void checkPortAvailability()

{

if (VINcomport.IsOpen) VINcomport.Close();

//MarkerIO is a XML file which have parameter details of ports

MarkerIO objmarkerIO = new MarkerIO();

// Set the port's settings

VINcomport.NewLine = "\r";

VINcomport.BaudRate = int.Parse(objmarkerIO.iBaudVIN);

VINcomport.DataBits = int.Parse(objmarkerIO.iDataBitsVIN);

VINcomport.StopBits = (StopBits)Enum.Parse(typeof(StopBits), objmarkerIO.iStopBitsVIN);

VINcomport.Parity = (Parity)Enum.Parse(typeof(Parity), objmarkerIO.iParityVIN);

VINcomport.PortName = objmarkerIO.sComPortVIN;

if (Headstockcomport.IsOpen) Headstockcomport.Close();

Headstockcomport.NewLine = "\r";

Headstockcomport.BaudRate = int.Parse(objmarkerIO.iDataBitsChassis);

Headstockcomport.DataBits = int.Parse(objmarkerIO.iDataBitsChassis);

Headstockcomport.StopBits = (StopBits)Enum.Parse(typeof(StopBits), objmarkerIO.iStopBitsChassis);

Headstockcomport.Parity = (Parity)Enum.Parse(typeof(Parity), objmarkerIO.iParityChassis);

Headstockcomport.PortName = objmarkerIO.sComPortChassis;

}

private void btnAccept_Click(object sender, EventArgs e)

{

StampandPrint();

}

private void StampandPrint()

{

btnAccept.Enabled = false;

btnReject.Enabled = false;

Log(LogMsgType.Outgoing, "##############################################################" + "\n");

Log(LogMsgType.Outgoing, "Stamp and print function starting " + "\n");

Log(LogMsgType.Outgoing, "Time Stamp : " + DateTime.Now.ToString() + "\n");

Log(LogMsgType.Outgoing, "##############################################################" + "\n");

if (objMarkingType == MarkingType.VIN || objMarkingType == MarkingType.VINandLable)

{

try

{

VINcomport.Open();

Log(LogMsgType.Outgoing, "VIN port test successfully..." + "\n");

}

catch (Exception ex)

{

Log(LogMsgType.Outgoing, "VIN port test unsucessful... reason : " + ex.Message.ToString() + "\n");

}

SendDataToVIN();

lblStatusData.Text = m_ResourceMain.GetString("VINSTAMPCOMPLETED", LoginUserInfo.iCultureInfo);

//if (VINcomport.IsOpen) VINcomport.Close();

}

if (objMarkingType == MarkingType.Lable || objMarkingType == MarkingType.VINandLable)

{

SendDatToPrinter();

}

objMarkingType = MarkingType.Headstock;

try

{

Headstockcomport.Open();

Log(LogMsgType.Outgoing, "Headstock port test successfully..." + "\n");

}

catch (Exception ex)

{

Log(LogMsgType.Outgoing, "Headstock port test unsucessful... reason : " + ex.Message.ToString() + "\n");

}

SendDataToHeadstock();

if (Headstockcomport.IsOpen) Headstockcomport.Close();

Log(LogMsgType.Outgoing, "##############################################################" + "\n");

Log(LogMsgType.Outgoing, "Stamp and print function finished " + "\n");

Log(LogMsgType.Outgoing, "Time Stamp : " + DateTime.Now.ToString() + "\n");

Log(LogMsgType.Outgoing, "##############################################################" + "\n");

lblStatusData.Text = m_ResourceMain.GetString("HEADSTOCKCOMPLETED", LoginUserInfo.iCultureInfo);

setscreen();

}

private void SendDataToVIN()

{

// Send the user's program selection command to device

string s1 = "\x1B" + "\x05" + "\x30" + "\x31" + "\x0D";

if (objItemmast.Count > 0)

{

try

{

Log(LogMsgType.Outgoing, "------------------------------------------" + "\n");

Log(LogMsgType.Outgoing, "Starting VIN Stamping " + "\n");

Log(LogMsgType.Outgoing, "Port Name : " + VINcomport.PortName.ToString() + "\n");

Log(LogMsgType.Outgoing, "Port Status : " + VINcomport.IsOpen.ToString() + "\n");

Log(LogMsgType.Outgoing, "------------------------------------------" + "\n");

VINcomport.Write(s1);

Log(LogMsgType.Outgoing, "Program selection command sent to comport: " + s1 + "\n");

objVINPortStatus = VINPortStatus.LaunchCode;

while (objVINPortStatus != VINPortStatus.None)

{

System.Threading.Thread.Sleep(500);

System.Windows.Forms.Application.DoEvents();

if (VINcomport.IsOpen && VINcomport.BytesToRead > 0)

{

m_IncomingRawDataCount = VINcomport.BytesToRead;

VINcomport.Read(m_IncomingRawData, 0, m_IncomingRawDataCount);

// show the hex bytes received

string s = "";

for (int i = 0; i < m_IncomingRawDataCount; i++)

s += m_IncomingRawDataIdea.ToString("X2") + " ";

string t = "";

for (int i = 0; i < m_IncomingRawDataCount; i++)

t += (char)int.Parse(m_IncomingRawDataIdea.ToString()) + " ";

Log(LogMsgType.Outgoing, "Data received from port: " + s + " " + t + "\n");

if (objVINPortStatus == VINPortStatus.LaunchCode)

{

string s2 = "\x1B" + "\x07" + "\x0D";

VINcomport.Write(s2);

Log(LogMsgType.Outgoing, "Launch code sent to comport: \n");

objVINPortStatus = VINPortStatus.VINNumber;

}

else if (objVINPortStatus == VINPortStatus.VINNumber)

{

VINcomport.WriteLine(lblVIN.Text);

Log(LogMsgType.Outgoing, "VIN Number sent to comport: " + lblVIN.Text + "\n");

objVINPortStatus = VINPortStatus.Para1;

}

else if (objVINPortStatus == VINPortStatus.Para1)

{

VINcomport.WriteLine(objItemmast[0].PARA_1);

Log(LogMsgType.Outgoing, "Para - 1 sent to comport: " + objItemmast[0].PARA_1 + "\n");

objVINPortStatus = VINPortStatus.Para2;

}

else if (objVINPortStatus == VINPortStatus.Para2)

{

VINcomport.WriteLine(objItemmast[0].PARA_2);

Log(LogMsgType.Outgoing, "Para - 2 sent to comport: " + objItemmast[0].PARA_2 + "\n");

objVINPortStatus = VINPortStatus.Para3;

}

else if (objVINPortStatus == VINPortStatus.Para3)

{

VINcomport.WriteLine(objItemmast[0].PARA_3);

Log(LogMsgType.Outgoing, "Para - 3 sent to comport: " + objItemmast[0].PARA_3 + "\n");

objVINPortStatus = VINPortStatus.Para4;

}

else if (objVINPortStatus == VINPortStatus.Para4)

{

VINcomport.WriteLine(objItemmast[0].PARA_4);

Log(LogMsgType.Outgoing, "Para - 4 sent to comport: " + objItemmast[0].PARA_4 + "\n");

objVINPortStatus = VINPortStatus.Para5;

}

else if (objVINPortStatus == VINPortStatus.Para5)

{

VINcomport.WriteLine(objItemmast[0].PARA_5);

Log(LogMsgType.Outgoing, "Para - 5 sent to comport: " + objItemmast[0].PARA_5 + "\n");

objVINPortStatus = VINPortStatus.VINDone;

}

else if (objVINPortStatus == VINPortStatus.VINDone)

{

Log(LogMsgType.Outgoing, "------------------------------------------" + "\n");

Log(LogMsgType.Outgoing, "VIN Stamping finish" + "\n");

Log(LogMsgType.Outgoing, "------------------------------------------" + "\n");

objVINPortStatus = VINPortStatus.None;

}

}

}

}

catch (Exception ex)

{

Log(LogMsgType.Outgoing, "VIN stamp exception : " + ex.Message.ToString() + "\n");

}

}

}

private void SendDataToHeadstock()

{

try

{

// Program selection command for device

string s1 = "\x1B" + "\x05" + "\x30" + "\x34" + "\x0D";

if (objTemplateIO.ProgramSelection == "")

Log(LogMsgType.Outgoing, "unable to read selection program from template.ini\n");

else

{

Log(LogMsgType.Outgoing, "------------------------------------------" + "\n");

Log(LogMsgType.Outgoing, "Starting Headstock stamping " + "\n");

Log(LogMsgType.Outgoing, "Port Name : " + Headstockcomport.PortName.ToString() + "\n");

Log(LogMsgType.Outgoing, "Port Status : " + Headstockcomport.IsOpen.ToString() + "\n");

Log(LogMsgType.Outgoing, "------------------------------------------" + "\n");

Headstockcomport.Write(s1);

Log(LogMsgType.Outgoing, "Program selection command sent to comport: " + s1 + "\n");

objHeadstockPortStatus = HeadstockPortStatus.LaunchCode;

while (objHeadstockPortStatus != HeadstockPortStatus.None)

{

System.Threading.Thread.Sleep(500);

Log(LogMsgType.Outgoing, "waiting for device response" + "\n");

Log(LogMsgType.Outgoing, "Port Status : " + Headstockcomport.IsOpen.ToString() + "\n");

Log(LogMsgType.Outgoing, "Bytes in Buffer : " + Headstockcomport.BytesToRead.ToString() + "\n");

if (Headstockcomport.IsOpen && Headstockcomport.BytesToRead > 0)

{

m_IncomingRawDataCount = Headstockcomport.BytesToRead;

Headstockcomport.Read(m_IncomingRawData, 0, m_IncomingRawDataCount);

// show the hex bytes received

string s = "";

for (int i = 0; i < m_IncomingRawDataCount; i++)

s += m_IncomingRawDataIdea.ToString("X2") + " ";

string t = "";

for (int i = 0; i < m_IncomingRawDataCount; i++)

t += (char)int.Parse(m_IncomingRawDataIdea.ToString()) + " ";

Log(LogMsgType.Outgoing, "Data received from port: " + s + " " + t + "\n");

if (objHeadstockPortStatus == HeadstockPortStatus.LaunchCode)

{

string s2 = "\x1B" + "\x07" + "\x0D";

Headstockcomport.Write(s2);

Log(LogMsgType.Outgoing, "Launch code sent to comport: " + "1B " + "07 " + "0D" + " " + s2 + "\n");

objHeadstockPortStatus = HeadstockPortStatus.HeadstockNumber;

}

else if (objHeadstockPortStatus == HeadstockPortStatus.HeadstockNumber)

{

Headstockcomport.WriteLine(lblVIN.Text);

Log(LogMsgType.Outgoing, "(Headstock)VIN Number sent to comport: " + lblVIN.Text + "\n");

objHeadstockPortStatus = HeadstockPortStatus.HeadstockDone;

}

else if (objHeadstockPortStatus == HeadstockPortStatus.HeadstockDone)

{

Log(LogMsgType.Outgoing, "------------------------------------------" + "\n");

Log(LogMsgType.Outgoing, "Headstock Stamping finish" + "\n");

Log(LogMsgType.Outgoing, "------------------------------------------" + "\n");

objHeadstockPortStatus = HeadstockPortStatus.None;

}

}

}

}

}

catch (Exception ex)

{

Log(LogMsgType.Outgoing, "Headstock stamp exception : " + ex.Message.ToString() + "\n");

}

}

private void frmVINScan_FormClosing(object sender, FormClosingEventArgs e)

{

if (VINcomport.IsOpen)

VINcomport.Close();

if (Headstockcomport.IsOpen)

Headstockcomport.Close();

}

Now My problem is that first serial port communication (SendDatatoVIN) is done fine and device successfully doing the printing. But secound serial port communicaiton (SendDatatoHeadstock) is not working. No data is received from device at all.

Please can anybody tell me what is the problem here(is anything to deal with threading or any problem with multiple port communication)

Looking forward for response.




Answer this question

problem with multiple serial ports

  • U_T_A

    I'm pretty sure you will need events and form from the code supplied it is difficult to see what iyou were doing before..

    Personally I would create a class for each port you want to communicate that encapsulates the port itself. I would also use events to communicate info back to your form. Create the ports and attach to the events you decare for each on the form and then connect and start sending and hopefully reciving.


    So each class would have a structure something like this


    public delegate void OnMessageRecieved(object sender, some data you want to pass.....);
    public event OnMessageRecieved MessageRecieved;

    public void Connect()
    {
    try
    {
    // Create new serial port on selected comm
    mPort = new SerialPort(mPortName, mBaudRate, mParity, mDataBits,mStopBits);

    // Add the event Handler
    mPort.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived);

    // Open the port
    mMPS2000Port.Open();
    }
    catch (Exception exception)
    {
    // re - throw with more info
    throw new Exception("Cannot connect to " + mPortName, exception);
    }
    }

    private void OnDataReceived(object sender, SerialDataReceivedEventArgs received)
    {
    // Read all the data from the port
    string messageData = mPort.ReadExisting();

    // Concatenate with any existsing data --
    mMessage += messageData;

    // Check you have a complete message - you can't guarentee all info has been recieved.
    if (check for end of message)
    {

    // Do what you want to do with the message data......

    // Raise events back to the form
    if (this.MessageRecieved != null)
    {
    MessageRecieved(this, the message data);
    }

    // Clean the message buffer
    mMessage = "";
    }
    }

    public bool Send(string message)
    {
    // Create the return
    bool sent = false;

    Byte[] messageBytes = System.Text.Encoding.ASCII.GetBytes(message.ToCharArray());

    // Write the message onto the port
    mPort.Write(messageBytes, 0, messageBytes.Length);

    // set the sent flag
    sent = true;

    // return
    return sent;
    }


  • RemcoJVG

    Having a quick scan I notice that your code does not make use of events and waits assuming one port is going to respond straight after the message which may not be the case. I always prefer to use events to manage communications and the lack of these, or alternatively threads, may mean the code can't flow as written.

    These may sound like silly questions, but...
    Have you tried without sending anything to VIN
    Have you tried running 2 copies with 1 talking to VIN the other to Headstock
    Have you definitiately got someting connected to the port you are talking on Opening the port does not require anything to be connected to it like other protocols (On numerous occasions I have started debugging only to realise that the port I connected to was not the one I though it was :) )

    You have a lot of debug info in there which could provide more detail as to what is going on, unless someone else can spot an obvious error.

  • tizza2k

    Thanks for response. I have already tried VINcomport_DataReceived and Headstockcomport_DataReceived events but I had big problem with event not getting fired everytime.

    For you reference see this code which I have implemented before doing this.

    private void VINcomport_DataReceived(object sender, SerialDataReceivedEventArgs e)

    {

    this.Invoke(new EventHandler(Handle_VINcomport_DataReceived));

    }

    private void Handle_VINcomport_DataReceived(object sender, EventArgs e)

    {

    string VINPortResponse = VINcomport.ReadExisting();

    Log(LogMsgType.Incoming, "Data received from port: " + VINPortResponse);

    if (objVINPortStatus == VINPortStatus.LaunchCode)

    {

    string s1 = "\x1B" + "\x07" + "\x0D";

    VINcomport.Write(s1);

    Log(LogMsgType.Outgoing, "Launch code sent to comport: \n");

    objVINPortStatus = VINPortStatus.VINNumber;

    objWait.DisplayMessage = "Sending launch code to VIN controller...";

    objWait.Status = PortStatus.VINNumber;

    }

    else if (objVINPortStatus == VINPortStatus.VINNumber)

    {

    VINcomport.WriteLine(lblVIN.Text);

    Log(LogMsgType.Outgoing, "VIN Number sent to comport: " + lblVIN.Text + "\n");

    objVINPortStatus = VINPortStatus.Para1;

    objWait.DisplayMessage = "Sending VIN number to VIN controller...";

    objWait.Status = PortStatus.VINPara1;

    }

    else if (objVINPortStatus == VINPortStatus.Para1)

    {

    VINcomport.WriteLine(objItemmast[0].PARA_1);

    Log(LogMsgType.Outgoing, "Para - 1 sent to comport: " + objItemmast[0].PARA_1 + "\n");

    objVINPortStatus = VINPortStatus.Para2;

    objWait.DisplayMessage = "Sending parameter-1 to VIN controller...";

    objWait.Status = PortStatus.VINPara2;

    }

    else if (objVINPortStatus == VINPortStatus.Para2)

    {

    VINcomport.WriteLine(objItemmast[0].PARA_2);

    Log(LogMsgType.Outgoing, "Para - 2 sent to comport: " + objItemmast[0].PARA_2 + "\n");

    objVINPortStatus = VINPortStatus.Para3;

    objWait.DisplayMessage = "Sending parameter-2 to VIN controller...";

    objWait.Status = PortStatus.VINPara3;

    }

    else if (objVINPortStatus == VINPortStatus.Para3)

    {

    VINcomport.WriteLine(objItemmast[0].PARA_3);

    Log(LogMsgType.Outgoing, "Para - 3 sent to comport: " + objItemmast[0].PARA_3 + "\n");

    objVINPortStatus = VINPortStatus.Para4;

    objWait.DisplayMessage = "Sending parameter-3 to VIN controller...";

    objWait.Status = PortStatus.VINPara4;

    }

    else if (objVINPortStatus == VINPortStatus.Para4)

    {

    VINcomport.WriteLine(objItemmast[0].PARA_4);

    Log(LogMsgType.Outgoing, "Para - 4 sent to comport: " + objItemmast[0].PARA_4 + "\n");

    objVINPortStatus = VINPortStatus.Para5;

    objWait.DisplayMessage = "Sending parameter-4 to VIN controller...";

    objWait.Status = PortStatus.VINPara5;

    }

    else if (objVINPortStatus == VINPortStatus.Para5)

    {

    VINcomport.WriteLine(objItemmast[0].PARA_5);

    Log(LogMsgType.Outgoing, "Para - 5 sent to comport: " + objItemmast[0].PARA_5 + "\n");

    Log(LogMsgType.Outgoing, "------------------------------------------" + "\n");

    Log(LogMsgType.Outgoing, "VIN Stamping finish" + "\n");

    Log(LogMsgType.Outgoing, "------------------------------------------" + "\n");

    objVINPortStatus = VINPortStatus.None;

    objWait.DisplayMessage = "Sending parameter-5 to VIN controller...";

    objWait.Status = PortStatus.VINDone;

    }

    }

    In this case problem I got is that event gets fired for Program selection and then for VINNumber but after that event is not getting fired and my program didn't work any more.

    I have noticed that at a time only 1 device is able to respond to my current implementation. As I am able to communicate with VIN or Headstock but not both

    Tell me if you need more information...



  • William Lowers

    Yes I can send data to 2nd port and receive from it if I connect one port to application and another to hyper terminal.

    I got some success and now I am able to send and receive data from both ports but not simultaneously. I have to Open first port and complete the cycle ot it first and close ot. Then I can open 2nd port and complete cycle for that.

    Important thing is I can not open both ports together....and process data together as I have told you that DataReceived event are not getting fired.



  • c_shah

    Thanks for response. As I said in last message that I have tried attaching events to both serial ports. But as I said datareceived events are not getting fired everytime and that is why I have done code without datareceived events.

    I agree with you that I must create a separate class but this is test applicaiton which must run successfully, after that I will create separate class for each port as you suggested.

    FOCUS: Problem is that when I open both ports and send data to first port it is working fine and for 2nd port I am not receiving data. BytesToRead always show 0 ....

    If I open just 1 port and test single device everything working fine.... but when I try to open 2 ports and want to send data to then one by one ... first port response perfectly but 2nd port is not responsing.....

    Looking forward for your response



  • osamaT


    I'm at a bit of a loss I'm afraid, so more questions...

    Are the message you send on the 2nd port deing recieved by the device
    Does this work fine if you have one port attached via your code and send/recieve to the other over hyper terminal

    Hopefully someone else might chip in with some other ideas.

  • problem with multiple serial ports