Ruby Serial Port Read

Serial Port Communication In C# - C# Tutorials

Interfacing Arduino and Ruby. The SerialPort gem seems to do the job. simplest example. Here s a simple example of how to read from the arduino now efficiently.

ruby serial port read

I ve always wanted to play around with one of these. And using Ruby on top of that. Thanks for the write up.

A Ruby project that tells Icom radios what to do. IcomProgrammer figures out what to do based on internal and external sources of information.

RubySerial is a simple RubyGem for reading from and writing to serial ports.

Installation

gem install rubyserial

Usage

require rubyserial

serialport Serial.new /dev/ttyACM0, 57600

Methods

write data : String - Int

Returns the number of bytes written.

Emits a RubySerial::Exception on error.

read length : Int - String

Returns a string up to length long. It is not guaranteed to return the entire

length specified, and will return an empty string if no data is

available. Emits a RubySerial::Exception on error.

getbyte - Fixnum or nil

Returns an 8 bit byte or nil if no data is available.

RubySerial::Exception

A wrapper exception type, that returns the underlying system error code.

License

Apache 2.0. See LICENSE for more details.

Welcome to my tutorial on Serial Port Communication in VB.Net. Lately Ive seen a lot of questions on how to send and receive data through a serial port, so I thought.

Welcome to my tutorial on Serial Port Communication in C. Lately Ive seen a lot of questions on how to send and receive data through a serial port, so I thought it.

Welcome to my tutorial on Serial Port Communication in C. Lately Ive seen a lot of questions on how to send and receive data through a serial port, so I thought it was time to write on the topic. Back in the days of Visual Basic 6.0, you had to use the MSComm Control that was shipped with VB6, the only problem with this method was you needed to make sure you included that control in your installation package, not really that big of a deal. The control did exactly what was needed for the task.

We were then introduced to. Net 1.1, VB programmers loved the fact that Visual Basic had finally evolved to an OO language. It was soon discovered that, with all it s OO abilities, the ability to communicate via a serial port wasn t available, so once again VB developers were forced to rely on the MSComm Control from previous versions of Visual Basic, still not that big of a deal, but some were upset that an intrinsic way of serial port communication wasn t offered with the. net Framework. Worse yet, C developers had to rely on a Visual Basic control and Namespace if they wanted to communicate via serial port.

Then along comes. Net 2.0, and this time Microsoft added the System.IO.Ports Namespace, and within that was the SerialPort Class. DotNet developers finally had an intrinsic way of serial port communication, without having to deal with the complexities of interoping with an old legacy ActiveX OCX control. One of the most useful methods in the SerialPort class is the GetPortNames Method. This allows you to retrieve a list of available ports COM1,COM2,etc. available for the computer the application is running on.

Now that we have that out of the way, lets move on to programming our application. As with all application I create, I keep functionality separated from presentation, I do this by creating Manager classes that manage the functionality for a given process. What we will be looking at is the code in my CommunicationManager class. As with anything you write in. Net you need to add the references to the Namespace s you ll be using:

using System;

using System.Text;

using System.Drawing;

using System.IO.Ports;

In this application I wanted to give the user the option of what format they wanted to send the message in, either string or binary, so we have an enumeration for that, and an enumerations for the type of message i.e; Incoming, Outgoing, Error, etc. The main purpose of this enumeration is for changing the color of the text displayed to the user according to message type. Here are the enumerations:

region Manager Enums

///

/// enumeration to hold our transmission types

public enum TransmissionType Text, Hex

/// enumeration to hold our message types

public enum MessageType Incoming, Outgoing, Normal, Warning, Error ;

endregion

Next we have our variable list, 6 of them are for populating our class Properties, the other 2 are access throughout the class so they needed to be made global:

region Manager Variables

//property variables

private string _baudRate string.Empty;

private string _parity string.Empty;

private string _stopBits string.Empty;

private string _dataBits string.Empty;

private string _portName string.Empty;

private TransmissionType _transType;

private RichTextBox _displayWindow;

//global manager variables

private Color MessageColor Color.Blue, Color.Green, Color.Black, Color.Orange, Color.Red ;

private SerialPort comPort new SerialPort ;

NOTE:I always separate my code into sections using the region endregion to make it easier when scanning my code. It is a design choice so it s not necessary if you don t want to do it.

Now we need to create our class properties. All the properties in this class are public read/write properties. We have properties for the following items of the Serial Port: Baud Rate: A measure of the speed of serial communication, roughly equivalent to bits per second.

Parity: The even or odd quality of the number of 1 s or 0 s in a binary code, often used to determine the integrity of data especially after transmission.

Stop Bits: A bit that signals the end of a transmission unit

Data Bits: The number of bits used to represent one character of data.

Port Name: The port with which we re communicating through, i.e; COM1, COM2, etc.We also have 2 properties that aren t related to the port itself, but with where the data will be displayed, and what transmission type to use:

region Manager Properties

/// Property to hold the BaudRate

/// of our manager class

public string BaudRate

get return _baudRate;

set _baudRate value;

/// property to hold the Parity

public string Parity

get return _parity;

set _parity value;

/// property to hold the StopBits

public string StopBits

get return _stopBits;

set _stopBits value;

/// property to hold the DataBits

public string DataBits

get return _dataBits;

set _dataBits value;

/// property to hold the PortName

public string PortName

get return _portName;

set _portName value;

/// property to hold our TransmissionType

public TransmissionType CurrentTransmissionType

get return _transType;

set _transType value;

/// property to hold our display window

/// value

public RichTextBox DisplayWindow

get return _displayWindow;

set _displayWindow value;

To be able to instantiate any class object we create we need Constructors. Constructors are the entry point to your class, and is the first code executed when instantiating a class object. We have 2 constructors for our manager class, one that sets our properties to a specified value, and one that sets our properties to an empty value, thus initializing the variables preventing a NullReferenceException from occurring. We also add an EventHandler in the constructor, the event will be executed whenever there s data waiting in the buffer:

region Manager Constructors

/// Constructor to set the properties of our Manager Class

/// Desired BaudRate

/// Desired Parity

/// Desired StopBits

/// Desired DataBits

/// Desired PortName

public CommunicationManager string baud, string par, string sBits, string dBits, string name, RichTextBox rtb

_baudRate baud;

_parity par;

_stopBits sBits;

_dataBits dBits;

_portName name;

_displayWindow rtb;

//now add an event handler

comPort.DataReceived new SerialDataReceivedEventHandler comPort_DataReceived ;

///

/// Comstructor to set the properties of our

/// serial port communicator to nothing

public CommunicationManager

_baudRate string.Empty;

_parity string.Empty;

_stopBits string.Empty;

_dataBits string.Empty;

_portName COM1 ;

_displayWindow null;

//add event handler

The first think you need to know about serial port communication is writing data to the port. The first thing we do in our WriteData method is to check what transmission mode the user has selected, since binary data needs to be converted into binary, then back to string for displaying to the user. Next we need to make sure the port is open, for this we use the IsOpen Property of the SerialPort Class. If the port isn t open we open it by calling the Open Method of the SerialPort Class. For writing to the port we use the Write Method:

region WriteData

public void WriteData string msg

switch CurrentTransmissionType

case TransmissionType.Text:

//first make sure the port is open

//if its not open then open it

if . comPort.IsOpen true comPort.Open ;

//send the message to the port

comPort.Write msg ;

//display the message

DisplayData MessageType.Outgoing, msg n ;

break;

case TransmissionType.Hex:

try

//convert the message to byte array

byte newMsg HexToByte msg ;

comPort.Write newMsg,0,newMsg.Length ;

//convert back to hex and display

DisplayData MessageType.Outgoing, ByteToHex newMsg n ;

catch FormatException ex

//display error message

DisplayData MessageType.Error, ex.Message ;

finally

_displaywindow.SelectAll ;

default:

break;

You will notice in this method we call three methods: HexToByte

ByteToHex

DisplayDataThese methods are required for this manager. The HexToByte method converts the data provided to binary format, then the ByteToHex converts it back to hex format for displaying. The last one, DisplayData is where we marshal a call to the thread that created the control for displaying the data, since UI controls can only be accessed by the thread that created them. First we ll look at converting the string provided to binary format:

region HexToByte

/// method to convert hex string into a byte array

/// string to convert

/// a byte array

private byte HexToByte string msg

//remove any spaces from the string

msg msg.Replace , ;

//create a byte array the length of the

//string divided by 2

byte comBuffer new byte msg.Length / 2 ;

//loop through the length of the provided string

for int i 0; i msg.Length; i 2

//convert each set of 2 characters to a byte

//and add to the array

comBuffer i / 2 byte Convert.ToByte msg.Substring i, 2, 16 ;

//return the array

return comBuffer;

Here we convert the provided string to a byte array, then the WriteData method sends it out the port. For displaying we need to convert it back into string format, so we use the ByteToHex method we created:

region ByteToHex

/// method to convert a byte array into a hex string

/// byte array to convert

/// a hex string

private string ByteToHex byte comByte

//create a new StringBuilder object

StringBuilder builder new StringBuilder comByte.Length 3 ;

//loop through each byte in the array

foreach byte data in comByte

//convert the byte to a string and add to the stringbuilder

builder.Append Convert.ToString data, 16. PadLeft 2, 0. PadRight 3, ;

//return the converted value

return builder.ToString. ToUpper ;

The last method that WriteData depends on is the DisplayData method. Here we use the Invoke Method of our RichTextBox, the control used to display the data, to create a new EventHandler which creates a new Delegate for setting the properties we wish for our message, then appending it to the value already displayed:

region DisplayData

/// method to display the data to from the port

/// on the screen

/// MessageType of the message

/// Message to display

STAThread

private void DisplayData MessageType type, string msg

_displaywindow.Invoke new EventHandler delegate

_displaywindow.SelectedText string.Empty;

_displaywindow.SelectionFont new Font _displaywindow.SelectionFont, FontStyle.Bold ;

_displaywindow.SelectionColor MessageColor int type ;

_displaywindow.AppendText msg ;

_displaywindow.ScrollToCaret ;

;

NOTE: You will notice that we hyave added the STAThread Attribute to our method. This is used when a single thread apartment is required by a control, like the RichTextBox.

The next method we will look at it used when we need to open the port initially. Here we set the BaudRate, Parity, StopBits, DataBits and PortName Properties of the SerialPort Class:

region OpenPort

public bool OpenPort

//first check if the port is already open

//if its open then close it

if comPort.IsOpen true comPort.Close ;

//set the properties of our SerialPort Object

comPort.BaudRate int.Parse _baudRate ; //BaudRate

comPort.DataBits int.Parse _dataBits ; //DataBits

comPort.StopBits StopBits Enum.Parse typeof StopBits, _stopBits ; //StopBits

comPort.Parity Parity Enum.Parse typeof Parity, _parity ; //Parity

comPort.PortName _portName; //PortName

//now open the port

comPort.Open ;

//display message

DisplayData MessageType.Normal, Port opened at DateTime.Now n ;

//return true

return true;

catch Exception ex

return false;

Next lets take a look at our event handler. This event will be executed whenever there s data waiting in the buffer. This method looks identical to our WriteData method, because it has to do the same exact work:

region comPort_DataReceived

/// method that will be called when theres data waiting in the buffer

void comPort_DataReceived object sender, SerialDataReceivedEventArgs e

//determine the mode the user selected binary/string

//user chose string

//read data waiting in the buffer

string msg comPort.ReadExisting ;

//display the data to the user

DisplayData MessageType.Incoming, msg n ;

//user chose binary

//retrieve number of bytes in the buffer

int bytes comPort.BytesToRead;

//create a byte array to hold the awaiting data

byte comBuffer new byte bytes ;

//read the data and store it

comPort.Read comBuffer, 0, bytes ;

DisplayData MessageType.Incoming, ByteToHex comBuffer n ;

string str comPort.ReadExisting ;

DisplayData MessageType.Incoming, str n ;

We have 3 small methods left, and these are actually optional, for the lack of a better word. These methods are used to populate my ComboBox s on my UI with the port names available on the computer, Parity values and Stop Bit values. The Parity and Stop Bits are available in enumerations included with the. Net Framework 2.0: Parity Enumeration

StopBits Enumeration

region SetParityValues

public void SetParityValues object obj

foreach string str in Enum.GetNames typeof Parity

ComboBox obj. Items.Add str ;

region SetStopBitValues

public void SetStopBitValues object obj

foreach string str in Enum.GetNames typeof StopBits

region SetPortNameValues

public void SetPortNameValues object obj

foreach string str in SerialPort.GetPortNames

That is how you do Serial Port Communication in C. Microsoft finally gave us intrinsic tools to perform this task, no more relying on legacy objects. I am providing this class and a sample application to show how to implement what we just learned. What I am providing is under the GNU General Public License meaning you can modify and distribute how you see fit, but the license header must stay in tact. I hope you found this tutorial useful and informative, thank you for reading.

Happy Coding

 SerialPortCommunication.zip 101.85K

Number of downloads: 124091

This post has been edited by PsychoCoder: 12 November 2007 - PM

atomskaze, on 10 Jul, 2009 - AM, said:

Hello.

I just wanted to know how should be the output of the communication.

Also, I am using this with an FPGA but when I open the port, and send data. the FPGA light goes lit but doesn t turn off. Also, when I want to close the port, it looks like the program is frozen. Is it that the code needs something else, or does it not support FPGA, or there could be fault in the programming of the FPGA.

I also want to know if part of the output of the program displays a message regarding that the object received data, or displays the data that was received.

I am bad at understanding things at first time, so please don t get mad if it was explained in the first post.

I just downloaded the code from the alternate link in a previous post. It seems that the click event was never created to close the port. It s an easy fix, here s what I added to make it work

in CommunicationsManager.cs:

region ClosePort

public bool ClosePort

DisplayData MessageType.Normal, Port closed at DateTime.Now n ;

//return true if port is closed

if comPort.IsOpen false return true;

DisplayData MessageType.Normal, Issue closing port n ;

NOTE: I added some basic error checking code to make sure the port closed before returning true, but I don t do anything with the false value at this point if there was a problem

in frmMain.cs:

private void cmdClose_Click object sender, EventArgs e

comm.ClosePort ;

cmdOpen.Enabled true;

cmdClose.Enabled false;

cmdSend.Enabled false;

Hope that helps.

Tom

th4k1dd, on 20 March 2008 - AM, said:

Hello, I was so excited to find this post and can t wait to play. I did run into one problem I am having with the code. I went ahead and threw it into C and compiled. The program detects my one and only COM port, COM12 and adds it to the port drop down box like it should.

However, when I hit the Open Port button, it throws up an error in the Rich Text Box which says that COM1 does not exist. Of course that was not a mistype. I select COM12 and yet it tries to connect to COM1.

I took a look at the code and followed the _portName variable but was unable to see why it would cut off the 2 in 12. It would seem it should not as the variable is setup as a string.

Quick Info:

Windows Vista Business

Microsoft. Net Visual Studio 2008 Express

Arduino USB Microcontroller Card

Port Settings should be : COM12, 9600, None, 1, 8

Programs Receiving COM12: Arduino Software, Putty, Realterm

Am I missing something. You help is greatly appreciated.

One thing I noticedI went into Device Manager and changed the USB Virtual COM port to use COM1 and for some reason the program works fine. Also works great if changed to COM2 in Device Manager.

Any ideas.

Needs to read up on variable tracing

I noticed the same thing, it looks like the form does not set the port name so the default COM1 is always used.

Try adding comm.PortName cboPort.Text; to the cmdOpen_Click method in frmMain.cs.

Excellent tutorial, very very helpful.

Tom.

hybridgroup/rubyserial

The Eibar/Ruby pistols most distinctive identifying features are: Shrouded hammer; Lumpy-looking safety lever above trigger; Longitudinal grooves around the muzzle.