CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Jan 2014
    Posts
    29

    Recieve Data From Serial Com Port C# In One Line And Convert To integer problem

    Receive Data From Serial Com Port C# In One Line And Convert To int
    Posted A minute ago

    Hi guys i have problem i make code that take data from serial com port for weighting machine
    it is ok working but it receive data in more lines.I try to make it receive data in one line
    In code below i need to take weight fro weight bridge machine automatically by timer in visual studio 2005.it works but receive weight values in more lines.
    I need to receive weight in one line and automatically updated then convert t to integer

    using System;
    using System.IO.Ports;
    using System.Windows.Forms;
    namespace CommSample
    {
    public partial class Form1 : Form
    {
    /// <summary>
    /// Initializes a new instance of the <see cref="Form1"/> class.
    /// </summary>
    public Form1()
    {
    InitializeComponent();
    }
    /// <summary>
    /// Handles the Idle event of the Application control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    void Application_Idle(object sender, EventArgs e)
    {
    label3.Text = serialPort1.IsOpen ? "[Open]" : "[Closed]";
    }
    /// <summary>
    /// Handles the Click event of the button1 control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void button1_Click(object sender, EventArgs e)
    {
    if (pollingCheckbox.Checked)
    {
    timer1.Enabled = true;
    }
    else
    {
    timer1.Enabled = false;
    TransmitCommand();
    }
    }
    /// <summary>
    ///
    /// </summary>
    private void TransmitCommand()
    {
    if (textBox1.Text.Length > 0)
    {
    if (serialPort1.IsOpen)
    {
    serialPort1.Write(textBox1.Text + "\r");
    }
    }
    }
    /// <summary>
    /// Closes the port.
    /// </summary>
    private void ClosePort()
    {
    if (serialPort1.IsOpen)
    {
    serialPort1.DataReceived -= new SerialDataReceivedEventHandler(serialPort1_DataReceived);
    serialPort1.Close();
    }
    }
    /// <summary>
    /// Handles the Click event of the closePortToolStripMenuItem control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void closePortToolStripMenuItem_Click(object sender, EventArgs e)
    {
    ClosePort();
    }
    /// <summary>
    /// Handles the Click event of the exitToolStripMenuItem control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
    Close();
    }
    /// <summary>
    /// Handles the Load event of the Form1 control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void Form1_Load(object sender, EventArgs e)
    {
    serialPort1.PortName = Properties.Settings.Default.Port;
    serialPort1.BaudRate = Properties.Settings.Default.Baud;
    serialPort1.DataBits = Properties.Settings.Default.DataBits;
    serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), Properties.Settings.Default.Parity);
    serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), Properties.Settings.Default.StopBits);
    Application.Idle += new EventHandler(Application_Idle);
    }
    /// <summary>
    /// Opens the port.
    /// </summary>
    private void OpenPort()
    {
    serialPort1.Open();
    serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
    }
    /// <summary>
    /// Handles the Click event of the openPortToolStripMenuItem control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void openPortToolStripMenuItem_Click(object sender, EventArgs e)
    {
    OpenPort();
    }
    /// <summary>
    /// Handles the Click event of the optionsToolStripMenuItem control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
    {
    ClosePort();
    using (Form2 form = new Form2())
    {
    if (form.ShowDialog(this) == DialogResult.OK)
    {
    serialPort1.PortName = Properties.Settings.Default.Port;
    serialPort1.BaudRate = Properties.Settings.Default.Baud;
    serialPort1.DataBits = Properties.Settings.Default.DataBits;
    serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), Properties.Settings.Default.Parity);
    serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), Properties.Settings.Default.StopBits);
    }
    }
    }
    /// <summary>
    /// Handles the DataReceived event of the serialPort1 control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.IO.Ports.SerialDataReceivedEventArgs"/> instance containing the event data.</param>
    void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
    if (!InvokeRequired)
    {
    if (e.EventType == SerialData.Chars)
    {
    string portData = serialPort1.ReadExisting();
    textBox2.AppendText(portData);
    }
    }
    else
    {
    SerialDataReceivedEventHandler invoker = new SerialDataReceivedEventHandler(serialPort1_DataReceived);
    BeginInvoke(invoker, new object[] { sender, e });
    }
    }
    /// <summary>
    ///
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void pollingCheckbox_CheckedChanged(object sender, EventArgs e)
    {
    if (timer1.Enabled && !pollingCheckbox.Checked)
    {
    timer1.Enabled = false;
    }
    }
    /// <summary>
    ///
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void timer1_Tick(object sender, EventArgs e)
    {
    if (pollingCheckbox.Checked)
    {
    TransmitCommand();
    }
    }
    }
    }

  2. #2
    Join Date
    Mar 2014
    Posts
    3

    Talking Re: Recieve Data From Serial Com Port C# In One Line And Convert To integer problem

    It seems to me that it is lot of unnecessary coding. Only that you need is serial port on Form and than you automatically have datareceived handler (look at propertes. It`s less known: serial port opens his own thread) and than only thing that you are doing is to wait for the character to be received. You don`t need timer, pooling etc.
    Another thing to remember: serial port exchanges data on byte basis and if you want to receive ex. 16-bit integer you will receive two 8-bit bytes one after another. So, first, you must determine the format of the incoming data and how sender prepare them for sending and, at last, the way the sender sends them over the serial port.
    Let`s suppose that sender sends one 16-bit integer. It can send it only by two bytes, one by one. Depending of which byte is first, MSB or LSB, you can do two things:
    - if sender sends MSB first and than LSB you will do this:
    Code:
    uint16 MyData=0; // Some 16-bit number
         MyData=MSB; // Save first byte arrived. MSB is now at the place of 0 byte
         MyData<<=8; // Shift bits eight times to the left. Now the MSB byte is at the correct place. Byte 0 is filled with 0-es.
         MyData+=LSB; // Add the LSB byte. Now you have MSB and LSB on right places.
        //You can use or present the data, ex. txtBox.Items.Add(MyData.ToString());
    - if sender sends LSB first and than MSB you will do this:
    Code:
    uint16 MyData=0, MyMSB=0; // MyMSB is temporary storage
         MyData=LSB; // Save first byte arrived. LSB is now at the place of 0 byte
         MyMSB=MSB; // Save the second byte. MSB is now at the place of 0 byte
         MyMSB<<=8; Shift bits eight times to the left. Now the MSB byte is at the correct place
         MyData^=MyMSB; XOR MyData with temporary MyMSB. Now you have MSB and LSB on right places.
         //Now you can present the data, ex. txtBox.Items.Add(MyData.ToString());
    The previous text is the explanation of the principle. Details about data types, casting etc. are up to you.
    Next piece of code works fine for me – when I push a button on my microcontroller board I send one string asynchronously to PC by FTDI UM232H module (USB to RS232 converter - so is baudrate=116279 and on my machine UM232H is connected to COM20). On the Form for serialPort1 properties I set ReceivedByteThresold to 50. On that way the event will occurs on every 50 received bytes. But, of course, you set the thresold to 2(two) and after each two received byte the evnt will rise. Rest is obvious.
    For this to work make new project, add three buttons "Start", "Stop" and "Exit" and one TextBox. Also, add serial port component from Toolbx->Components->SerialPort (serialPort1). The code works in MS Visual Studio 2012 and .NET 4.5.


    Code:
    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 SimpleSerial
    {
        public partial class Form1 : Form
        {
            // Add this variable 
            string RxString;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void buttonStart_Click(object sender, EventArgs e)
            {
                serialPort1.PortName = "COM20";
    	    serialPort1.BaudRate = 116279;
    
                serialPort1.Open();
                if (serialPort1.IsOpen)
                {
    		textBox1.AppendText("Port is open!");
                    buttonStart.Enabled = false;
                    buttonStop.Enabled = true;
                    textBox1.ReadOnly = false;
                }
            }
    
            private void buttonStop_Click(object sender, EventArgs e)
            {
                if (serialPort1.IsOpen)
                {
                    serialPort1.Close();
                    buttonStart.Enabled = true;
                    buttonStop.Enabled = false;
                    textBox1.ReadOnly = true;
                }
    
            }
    
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (serialPort1.IsOpen)
                    serialPort1.Close();
            }
    
            private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
            {
                // If the port is closed, don't try to send a character.
                if (!serialPort1.IsOpen) return;
    
                // If the port is Open, declare a char[] array with one element.
                char[] buff = new char[1];
    
                // Load element 0 with the key character.
                buff[0] = e.KeyChar;
    
                // Send the one character buffer.
                serialPort1.Write(buff, 0, 1);
    
                // Set the KeyPress event as handled so the character won't
                // display locally. If you want it to display, omit the next line.
                e.Handled = true;
            }
    
            //******************** THIS IS THE KEY ********************************************
            private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                RxString = serialPort1.ReadExisting(); // Save arrived sstring.
                // You use here: serialPort1.ReadByte() and put bytes to ex. temporary buffer...
                this.Invoke(new EventHandler(DisplayText)); // Call "DisplayText".
            }
    
            private void DisplayText(object sender, EventArgs e)
            {
                textBox1.AppendText(RxString);
            }
    
            //******************************************************************************
    	private void button1_Click(object sender, EventArgs e)
    	{
                 this.Close();
    	}
        }
    }
    Maybe it will help
    Last edited by Pecilije; March 13th, 2014 at 05:58 AM. Reason: Some typing errors and to better explain what I mean.

  3. #3
    Join Date
    Jan 2014
    Posts
    29

    Re: Recieve Data From Serial Com Port C# In One Line And Convert To integer problem

    Thank you for reply
    1-Are this code above will work automatically there is no timer and thread
    you using text box key press event meaning you need to press button but i need it come automatically
    2- how i will convert code above to integer
    3-are this code will ignore new line because my problem in code above that value come in new line
    but i need value come updated example
    500 will become 600 will become 800(what i need)
    but not 500 600 800(what i don't need)
    thanks

  4. #4
    Join Date
    Mar 2014
    Posts
    3

    Re: Recieve Data From Serial Com Port C# In One Line And Convert To integer problem

    Quote Originally Posted by ahmedsa View Post
    Thank you for reply
    1-Are this code above will work automatically there is no timer and thread
    you using text box key press event meaning you need to press button but i need it come automatically
    Welcome!
    As I said - there is no need for pooling, timers, button presses etc. in relation with sending or receiving characters.

    The displayed code uses buttons only to open and set the serial port and than to close it. It is not code for your application. It is the example what is going on when you use event raised by serial port.

    Characters are sent by typing them in the text box - because of that there is the "textBox1_KeyPress()" method.
    This very last code is working example how to catch event when the receive buffer has data. I changed the code so maybe I confused you - sorry. It is better to read carefully the article from which I had learned at http://csharp.simpleserial.com/. As I sad earlier, main application has it own thread and serial port create his own, new thread. This is crucially: the serial port thread is acting independently and parallel with the main thread! When the stream of data comes to serial port, the serial port is the one who raised the event AUTOMATICALLY and asynchronously after the set number of bytes and main thread catch it and do the rest of the job. So, the process is independent and there is no need for the user to do anything. Bytes are arriving when device sends them, serial port puts them in receive buffer and after the set number of bytes raises the event, application (main thread) catches the event, the required method (called by Invoke()) converts the bytes to integer and deals with it (ex. shows number in text box or uses it for further calculations etc.) Application can then do the other work until new data comes.
    So, to conclude: in this example when the transmission completes, data are in the receive buffer and the event is raised. But, serial port CAN NOT WRITE DIRECTLY to text box on the main Form (main thread) from his own thread. So, look carefully: in the main Form we create a method "private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)" that waits for the event to happen FROM the serial port thread. When it happens the Invoke() method calls the delegate which calls the method "private void DisplayText(object sender, EventArgs e)" in the main thread who does the job.
    Again, SerialPort opens its own thread when you put it on the Form. In the properties panel you must adjust the baud rate, data format ( 7 or 8 bit), parity (none, even, odd) and stop bit (none, one, two or OnePointFive) and most important: ReceivedBytesTreshold and DataReceived method. They are the KEY. What does it mean? It means that the serial port will rise an event every time he receive the number of bytes that are set. But, before you set this you must remember my sentence:
    So, first, you must determine the format of the incoming data and how sender prepare them for sending and, at last, the way the sender sends them over the serial port.
    What does this mean? I will explain it by the example.
    My PC communicates with microcontrollers attached to it over the USB<->RS232 (serial port). How they understand each other? Easy. By protocol that I made. Up to now I have two of them: for the text and for the commands. The protocol for text is composed in this way:

    - byte for the beginning of transmission - ASCII STX - "Start Of Text",
    - followed by the ASCII number for the row of character LCD in which the text is to be written,
    - followed by ASCII character of the first byte of text, then second byte of text ... last byte of text for that line,
    - ASCII ETX - "End Of Text" byte for the end of text and
    - the next byte can be either new number of line of text or, if there is no further text
    - the last byte is ASCII EOT - "End Of Transmission".

    If it is command the format is like this:

    - DC1,
    - command code,
    - EOT.

    Let`s assume that PC want to send command. In that case it prepares three bytes in the out buffer and transmits it over the line. Firmware in microcontroller is then interrupted and start receiving those bytes in the receive buffer, decodes them and executes the desired command.
    The opposite is exactly the same: microcontroller prepares the necessary bytes in transmit buffer (according to the "agreement" format) and sends them to PC over the serial port. When bytes arrived in the receive buffer, serial port raises the event, main application is interrupted and catches the event, puts the arriving bytes to receive buffer, reads bytes from receive buffer, clears the buffer, decodes bytes and do the job. Than application continues to work another things until it is interrupted again from some new event.
    From the point of view of PC and microcontroller those bytes are meaningless without the "agreement" what every byte in the frame of data means. In my case they both know what every byte means by the agreement that I made.
    So, if you know the structure of the incoming data (let me to say "the format" or "the frame" - ask the manual or the manufacturer of the device) that your device sends to you, you will set the number of bytes for the ReceivedBytesTreshold. In that protocol some bytes are the bytes of your integer data and they have their places. Serial port himself does not add "new line", "carriage return", "line feed" or similar characters at the end of transmission: it only transmits byte after byte until the send buffer is empty.
    If there are some of those characters ("new line", "line feed" etc.) probably this (those) character(s) is (are) added by the device and you must know for their presence and to avoid them. Maybe this is the reason why your number go below the previous one.

    2- how i will convert code above to integer
    Again, this is not the code for your application. This is not the solution. And, well, I avoid to write finished code to somebody and let mi say, rather trying to explain how things work. When you understand the principle you than can control the process - the code than becomes the easiest part.
    So, read carefully my text in the part starting with
    Let`s suppose that sender sends one 16-bit integer. It can send ...
    There I had explained the principle with code how to make one 16-bit integer from the two received bytes that represents it depending of the order at they came. Again, you must know where are they in the arrived stream of bytes. The same principle is for 24-bit or 32-bit or 64-bit integer - only the number of bytes that represents the number may wary: 3 bytes, 4 bytes and 8 bytes.
    And, you must do the same.
    I am waiting for your response what you will do.
    Last edited by Pecilije; March 16th, 2014 at 06:44 AM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured