Serial Data Communication Part I

At present I am quite busy developing the controller module (CM1) together with the supplement DC motor simulator (EM1), as introduced in my Embedded Prototypes for Control Engineering article. The main purpose of these low-cost embedded systems are to serve as educational tools for control engineering, though, if one wishes to do so, the universal controller board can be used in certain real applications with up to two feedback loops.

Basic serial port communication in ASCII format is implemented on the target board for a user to issue commands and receive response, as well as capture data for analysis. Any UART terminal program such as HyperTerminal or CoolTerm can be used for such purpose. For classroom use, however, integration with Scilab would significantly improve user-friendliness of the board. What we need are a couple of Scilab functions to access the serial port. The required operations are open, read, write, and close. No need to be fancy. I have found The Serial Communication Toolbox on the ATOMS packaging system that provides just these basic functions and is very easy to use.

So in this article I elaborate on using this serial toolbox to establish UART communication between Scilab and the CM1 board. Once you understand the basics, I believe you could easily apply to other hardware such as Arduino. In addition to serial communication, some tips on and GUI building and Scilab string commands are also discussed.

This article, unfortunately, is written for audience with Windows only. Even though the CM1 board could communicate with Mac OS X and Ubuntu with UART terminal programs, the serial toolbox does not seem to work on Mac. I have not yet developed any software on the Linux platform.

Serial Communication Toolbox Installation

Like others in the ATOMS package, The Serial Communication Toolbox does not come preinstalled. Assuming your computer is connected to the internet, simply type this on Scilab console

--> atomsInstall('serial')

and wait until installation finishes. Relaunch Scilab. You should see the message shown in Figure 1 at startup.


Figure 1 Serial toolbox startup message

This means the toolbox is ready for use. We will come back to this console later. At this time let’s shift our attention to the target board to determine how we would want to communicate with it.

How CM1 Works

The MCU on CM1 board executes a simple firmware called RED core, where RED stands for Responsive Embedded Development (Off the record, I admit being inspired a little by Raymond Reddington of The Blacklist. lol) It’s simply a variation of cyclic executive scheduler. Control algorithms (2 loops maximum) are implemented as timer interrupts, while the infinite main loop is responsible for waiting a valid user command and executing corresponding function.

For example, if a user issues command “red,” the CM1 responds with a string indicating version and creator. Figure 2 shows some communication examples via a terminal software CoolTerm. Note that the prompt “>” is sent by RED to distinguish commands from the responses.


Figure 2 serial communication via CoolTerm software

In order to establish a successful communication, we should note the following parameters

  • COM port number: when the CM1 is connected to a USB port, Windows assigns a number for the board. This could be COM3, COM9, COM15, or etc. Some terminal program poses some limit on the range of COM port numbers, say, 1 – 6. Fortunately, we can change the COM port number in control panel to any unused value. Search google for sites that give instructions.
  • Protocol: values such as baud rate, number of bits and stop bit, parity type etc., that must be agreed upon for both sides could communicate successfully. UART protocol for CM1 board is set to 115200 bps, 8 data bits, 1 stop bit, no parity.

Assume that a CM1 board is plugged into USB port. Go to Control Panel->Device Manager to check COM port number as shown in Figure 3. In this case the USB-to-serial chip is assigned COM3.


Figure 3 checking COM port number in Device Manager window

Type this command in Scilab to open the serial port.

-->redh=openserial(3,"115200,n,8,1")
redh  =
 
 filea01d7b0

No error message means the port is opened successfully. This function returns a handle to the COM port, which is named redh. We can now use this handle for subsequent read/write operations.

For example, suppose we want to send the “red” command to see if CM1 could respond. Type

-->writeserial(redh,"red"+ascii(13))
 ans  =
 
    0.

Note the ascii(13) to signify the command end. Without this character, the RED core on CM1 will assume the command has not yet terminated and not process it.

For this serial toolbox, a return of 0 means success. Any problem would result in error message.

Now use readserial command to read the response from buffer.

-->readserial(redh)
 ans  =
 
RED Core 1.0 by dew.ninja
>

Received message is identical to what we got using a terminal program (Figure 2).
In case we want to read the buffer after some delay time, xpause() function can be used, with argument in microseconds. For example, to request the current value of proportional gain,

-->writeserial(redh,"kp"+ascii(13));xpause(20000);readserial(redh)
 ans  =
 
 Loop 1: Kp =  10
 
>

We need to warn you that the period resulting from xpause() is not very precise. If accurate real-time data capture and plot is needed, CM1 can provide time information for that matter.

Don’t forget to close the serial port after finish.

-->closeserial(redh)
 ans  =
 
    0.

These essential 4 commands are all what the toolbox offers. The rest is up to our creativity.

Building a simple GUI

As an example, let’s create a Scilab GUI with minimal control, called RED Command Window like in Figure 4. COM port list box, [Connect], and [Disconnect] buttons are used to establish and terminate serial connection with the CM1 board. After successful connection, a user types commands in the Command edit box and click [Send]. If read after send is checked, the response message is displayed immediately on Scilab console. Alternatively, the user may prefer to click the [Read Buffer] button to retrieve message. A string is displayed at lower right corner of the window to indicate connection status. The static string at lower left corner gives information of the protocol being used.


Figure 4 a basic GUI to communicate with CM1 board

The whole script for this GUI is written in redcmd.sce. Here we explain only certain parts related to this article.

The Connection Section

To establish a connection, first the COM port number has to be checked manually as in Figure 3, and changed, if necessary, to value between 1 – 6. (It would be great if the future version of toolbox could allow us to check COM port number within Scilab). Then the number in list box is selected accordingly. Below is the code for the COM port list box and its callback function *.

// COM port select
comnlist = uicontrol(redcmdwin,'style','listbox');
comnlist.Units="normalized";
comnlist.Position = [0.12 0.7 0.1 0.07];
 
comnlist.String = "1|2|3|4|5|6";
comnlist.Value = 1;
comnlist.Callback = "comselect";
 
function comselect(comnlist)  
    global comnum;
    //comnlist.Value = eval(comnlist.String);
    comnum = comnlist.Value;
 
endfunction

* Please refer to some other source on Scilab GUI basics, such as how to code uicontrol and callback function. Scilab Help Browser is a good starting point.

The port selection from the list box is saved to a global variable comnum, to be used in the callback function of [Connect] button. Note the explicit declaration “global” of comnum in function comselect. This is necessary.

The uicontrol and callback function of [Connect] is as follows

// -------------- send button ------------------
cmdsendbutton=uicontrol(redcmdwin,"style","pushbutton");
cmdsendbutton.Units = "normalized";
cmdsendbutton.Position = [0.7 0.5 0.2 0.08];
cmdsendbutton.String = "Send";
cmdsendbutton.BackgroundColor=[0.9 0.9 0.9];
cmdsendbutton.Callback = "sendredcmd";
cmdsendbutton.Relief="raised";
 
function connectred(connectbutton )
  global comnum connectflag redh;
  if connectflag== 0,
        redh = openserial(comnum,"115200,n,8,1");
        set(connectbutton,'relief','sunken');
        set(statustxt,'string','Connected');
        connectflag = 1;
  end
endfunction

When the window starts, a flag variable connectflag is assigned value 0. So when the user presses [Connect], the openserial command is executed with proper COM port number and protocal. Handle is assigned to a global variable redh. Next, the button relief is set to ‘sunken.’ This makes the button appearance remain pressed. Also, the status string is changed to ‘Connected.’ Before leaving, the connectflag is set to 1.

Without connectflag the user would get error message if he/she inadvertently presses [Connect] again when it’s already connected. One annoying behavior of Scilab GUI is once something goes wrong, everything tends to function erratically or even becomes unusable. If that happens, just close the window. Issue command closeserial(redh) on Scilab console and relaunch the Red Command window.

The uicontrol and callback function of [Disconnect] has very much the same logic, only with reverse functionality. When the user clicks the button, the serial connection is closed. Global variable connectflag is set to 0, the relief of [Connect] set to ‘raised,’ and status text changed to ‘Disconnected.’

The Serial Communication Section

The lower part of Red Command Window consists of an edit box to receive command, [Send] and [Read Buffer] buttons, and ‘read after send’ check box. In ‘read after send’ mode, the response is displayed on Scilab console after a command is sent. If this mode is not selected, the user has to click [Read Buffer] to read the response.

The command edit box does not have any interesting point to discuss. It simply captures the string typed by the user. Most work is done by [Send] button, whose uicontrol and callback function is shown below.

// -------------- send button ------------------
cmdsendbutton=uicontrol(redcmdwin,"style","pushbutton");
cmdsendbutton.Units = "normalized";
cmdsendbutton.Position = [0.7 0.5 0.2 0.08];
cmdsendbutton.String = "Send";
cmdsendbutton.BackgroundColor=[0.9 0.9 0.9];
cmdsendbutton.Callback = "sendredcmd";
cmdsendbutton.Relief="raised";
 
function sendredcmd(readbufbutton)
    global redh connectflag rcvstr;
    if connectflag==1
        disp(">"+cmdebox.String);
        writeserial(redh,cmdebox.String +ascii(13));
	 if rasflag==1,  // read after send
	    xpause(300000);
 
            rcvstr=readserial(redh);
            disp(rcvstr);
       end 
 
    end
 
endfunction

Note that the command string typed by user is captured in cmdebox.String, which is then terminated by ascii(13) and passed to writeserial(). A flag variable, ‘rasflag’ is set or reset by the ‘read after send’ check box. It this flag is set, the received message is read immediately to rcvstr variable after xpause time of 0.3 second expired. The message is then displayed on Scilab console.

With rasflag=0, the user has to click on [Read Buffer] to read the CM1 response. This mode is useful for commands that invokes a massive data transfer. We can wait for arbitrary time period to make sure data capture is finished before reading from the buffer.

Figure 5 shows the Red Command window in operation. A couple of commands are typed in the edit box. The corresponding responses shown on Scilab console indicates that the GUI is working properly.


Figure 5 testing the RED Command Window

On the second part of this article, some problem with the processing of received data is discussed. We will present a solution to fix that.

Reference

  1. E.Segre and A. Sengupta. Serial Communication Toolbox

Comments

comments

Comments are closed.