This text is documented in AsciiDoc format
Suggested viewer FireFox plugin Asciidoctor.js Live Preview
Scilab Serial Communication Toolbox (SSCT)
Abstract:
Scilab Serial Communication Toolbox (SSCT) is inspired by
a toolbox with a similar name
originally developed by
Aditya Sengupta and
Enrico Segre. However,
this new development line is an
attempt to comply / resemble MATLAB serial communication functionalities
and syntax as much as possible. The toolbox adds serial port
(e.g., RS-232) protocol communication to Scilab / Scicoslab platforms,
which are Free, Libre, and Open Source Software (FLOSS) alternatives of MATLAB.
The toolbox can be used "for sending commands to control robots, motors,
or reading sensors such as GPS, laser scanners, compasses, etc." [Esposito2009].
For the moment, the toolbox only works on Windows OS,
but development for Linux and macOS are under progress and hopefully will be added in the future.
This toolbox is still in the early-stage prototyping phase, and functions are not compiled.
To use it, just download this Gist and run the ssctmain.sci
in Scilab.
For ScicosLab, due to the fact that multiline commenting /* … */
is yet to be implemented,
the AsciiDoc documentations in those tags need to be removed in advance.
A serial object structure with similar
properties
/ attributes and
functions
of the one in MATLAB has been developed. There are of course, some syntax
differences due to Scilab intrinsic limitations, not-implemented
features, as well as extra features considered to improve upon what
MathWorks has already done. Considering that Scilab doesn’t have
built-in Serial Port communication, external languages, including Tcl,
PowerShell, CMD / batch, bash, C, C++, have been used. Moreover, due to the
lack of object-oriented programing (OOP) capability in Scilab there are major
differences between this toolbox and MATLAB. Mainly the serial object
has no routine
/ subroutine
/ procedure
accessible through the dot .
operator, as seen in the OOP languages. Furthermore, all the MATLAB
functions starting with an f
are changed to s
to avoid confusion and
conflicts with other Scilab functions, as well as possible copyright issues.
For example, MATLAB’s fopen
is sopen
in this toolbox. The syntax has been changed in a way to be more consistent and concise.
Although there are other FOSS options like Python, Octave, Julia, Sage, Maxima, R and FreeMat, …, Scilab stands out among these options for having the great xcos / scicos environment, which is a replica of SIMULINK visual programing. xcos / scicos can also include code blocks from other languages such as C/C++, Fortran, Scilab, and Modelica language. In addition, Scilab / ScicosLab also have a nice GUI building functionality that resembles MATLAB syntax. In general for users coming from a MATLAB background, it is one of the best alternatives.
The codes / texts copied from other sources have the original licensing if not specified. The text of this author is under Creative Commons License BY-NC-SA, and the codes are GPLv3. The beautiful logo is designed by Alex Potterson. If you are a FLOSS developer and need a logo, you may contact him.
Introduction:
A typical serial port communication session has five steps:
-
Find the valid, available, open, defined serial ports using the
slist
function -
Create a serial port object using the
sdefine
function, specifying the required properties. -
Opening the port using the
sopen
function and adjusting the properties usingsconfig
andsinfo
function -
Sending or receiving data using
-
sput
andsputl
for putting data to the serial port buffer andsflush
for sending them out, or alternativelyssend
/ssendl
-
sget
andsgetl
function for taking data out of the serial port buffer
-
-
Closing the port using the
sclose
function and cleaning up theDefinedPorts
list using thesdelete
function.
Alternatively one can use the sprint
/sprintl
and sread
/sreadl
functions to send and
read data in one step.
Example:
s1 = sdefine(Port = "COM1", BaudRate = 4800);
sopen(s1);
sput(s1, "*IDN?");
out = sget(s1);
sclose(s1);
sdelete(s1);
clear s1;
or alternatively using the simpler syntax:
sprint(Port = "COM1", Message = "*IDN?", BaudRate = 4800);
sread("COM1"); // to be implemented
Serial Object Properties:
This code is documented in AsciiDoc format
Suggested viewer FireFox plugin Asciidoctor.js Live Preview
SSCT serial object has been developed to be mostly compatible with MATLAB’s serial object properties, but when possible/needed go beyond that. and their accepted and default values. Default values have been specified with bold font.
BaudRate
Accepted values are 110
, 300
, 600
, 1200
, 2400
, 4800
,
9600
, 14400
, 19200
, 38400
, 57600
, 115200
, 128000
and
256000
bits per second. This property is also limited by the
MaximumBaudRate
(PowerShell syntax) provided by the operating system
and the underlying hardware.
*/
StandardBaudRates = [110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 128000, 256000]; //bits per second. 9600 is the default
/*
DataBits
Accepted values are 5, 6, 7 and 8
*/
StandardDataBits = [5, 6, 7, 8]; // 8 is the default
/*
Parity
"none"
, "odd"
, "even"
, "mark"
and "space"
*/
StandardParities = ["none", "odd", "even", "mark" "space"]; // none is the default
/*
StopBits
1
and 2
. Please consider that MATLAB also accepts 1.5
which is
not compatible with Tcl and this toolbox.
*/
StandardStopBits = [1, 2]; //1 is the default. MATLAB also accepts 1.5
/*
Terminator
Accepted values are "auto"
, "binary"
, "cr"
, "crlf"
, "lf"
.
Please consider that this is Tcl syntax not MATLAB’s.
*/
Terminators = ["auto", "binary", "cr", "crlf", "lf", "platform"]; // this is Tcl syntax. binary is the default. MATLAB accepts 0 to 127 ASCII or CR (carriage return), LF (linefeed), CR/LF or LF/CR
/*
FlowControl
*/
FlowControls = ["none", "hardware", "software"]; // default is none. Tcl syntax: rtscts (dtrdsr for Windows) for hardware and xonxoff for software
/*
Buffering
*/
Bufferings = ["full", "line", "none"]; // this is Tcl syntax. full is default
/*
ReadAsyncMode
*/
ReadAsyncModes = ["manual", "continuous"]; //MATLAB syntax, probably the blocking option in Tcl
/*
ByteOrder
*/
ByteOrders = ["bigEndian", "littleEndian"];
/*
Functions:
This code is documented in AsciiDoc format
Suggested viewer FireFox plugin Asciidoctor.js Live Preview
slist()
Lists the valid, available, open or defined serial ports / objects (similar to the seriallist of MATLAB)
Parameters:
-
Verbose: Boolean
-
PortList: One of the values (default
"available"
)
*/
PortLists = ["all", "available", "open", "defined"];
/*
Syntax:
*/
function SerialList = slist(Verbose, PortList)
/*
Description:
The Verbose
input is set to %f
by default returning a vector of
strings. If set to %t
it will export a matrix including more elaborate
details about the specified PortList
. The PortList
option can be
"all"
for showing the valid ports available or open, "available"
for
showing the ports are free to be opened, "open"
for all the already
opened ports and "defined"
for showing all the ports which are already
defined.
Example:
--> slist ans = !COM6 COM7 !
Source Code:
Click to see the source code
*/
WindowsPSProperties = ["DeviceID", "Description", "MaxBaudRate", "ProviderType"];
WindowsComExp = "/(COM[1-9]\d*)[^.]+?Baud.+?([1-9]\d*)[^.]+?Parity.+?(\w+)[^.]+?Data Bits.+?(\d)[^.]+?Stop Bits.+?(1|1\.5|2)[^.]+?Timeout.+?(ON|OFF)[^.]+?XON\/XOFF.+?(ON|OFF)[^.]+?CTS handshaking.+?(ON|OFF)[^.]+?DSR handshaking.+?(ON|OFF)[^.]+?DSR sensitivity.+?(ON|OFF)[^.]+?DTR circuit.+?(ON|OFF)[^.]+?RTS circuit.+?(ON|OFF)/"; // this is to extract information from cmd mode command
global DefinedPorts;
global OpenPorts;
global AvailablePorts;
if ~exists("Verbose","local") then
Verbose = %f;
end
if type(Verbose) ~= 4 then
error("The Verbose must be Boolean type %t or %f");
end
if ~exists("PortList","local") then
PortList = "available";
end
if isempty(find(PortLists == PortList)) then
error("Supported options for PortList are: " + strcat(PortLists, ", "));
end
if PortList == "defined" then
SerialList = return(DefinedPorts(2:$)');
end
if PortList == "open" then
SerialList = return(OpenPorts(2:$, 1)');
end
[OS, Version] = getos();
if OS == "Windows" then
if PortList == "all" then
if Verbose == %f then
// SerialList = powershell("[System.IO.Ports.SerialPort]::getportnames()")'; //--> This solution considers the ports opned by powershell as available while there are in fact opened internally as explained [here](https://superuser.com/questions/1412117/list-all-the-serial-ports-available-and-busy-on-any-of-windows-terminals)
if getinterpreter() == "scilab" then
[output, bOK] = powershell("Get-WMIObject Win32_SerialPort | Select-Object DeviceID");
[start, final, match, foundString] = regexp(strcat(output), '/(COM\d+)/');
SerialList = foundString';
else
outputString = unix_g("cmd /V:ON /C '"set '"var='" & (For /F '"tokens=1 Delims= '" %s In (''WMIC Path Win32_SerialPort Get DeviceID^|FindStr '"COM[0-9]*'"'') do @IF DEFINED var (@set '"var=!var!,%s'") else (set '"var=%s'")) & @echo !var!'""); //"
SerialList = tokens(outputString, [",", " "])';
return;
end
else
if getinterpreter() == "scilab" then
SerialList = powershell(" Get-WMIObject Win32_SerialPort | Select-Object DeviceID, Description, MaxBaudRate, ProviderType")(2:$-2);
else
SerialList = unix_g("WMIC Path Win32_SerialPort Get DeviceID, Description, MaxBaudRate, ProviderType"); // cmd / batch alternative
return;
end
end
elseif PortList == "available" then
if Verbose == %f then
if getinterpreter() == "scilab" then
[rep, stat] = dos("mode");
//[rep, stat] = unix_g("mode"); //unix_g, unix, host are scicoslab compatible
[start, final, match, foundString] = regexp(strcat(rep), '/(COM\d+)/'); // using strindex instead of regexp to make it ScosLab compatible
SerialList = foundString';
else
outputString = unix_g("cmd /V:ON /C '"set '"var='" & (For /F '"tokens=4 Delims=: '" %s In (''Mode^|FindStr '"COM[0-9]*'"'') do @IF DEFINED var (@set '"var=!var!,%s'") else (set '"var=%s'")) & @echo !var!'""); //"
SerialList = tokens(outputString, [",", " "])';
return;
end
else
if getinterpreter() == "scilab" then
[rep, stat] = dos("mode");
[start, final, match, foundString] = regexp(strcat(rep), WindowsComExp);
SerialList = cat(1, WindowsComProperties, foundString);
return;
else
[rep, stat] = unix_g("mode");
[start, final, match, foundString] = regexp(strcat(rep), WindowsComExp);
SerialList = cat(1, WindowsComProperties, foundString);
return;
end
end
end
elseif OS == "Darwin" then
if PortList == "all" then
if Verbose == %f then
SerialList = unix_g("ls /dev/{tty,cu}.* | grep tty | sed -n -E "'s/\/dev\/tty\.(.+)/\1/p"'")' //"
end
end
// error("this feature has not been implemented for this operating system yet");
else
error("this feature has not been implemented for this operating system yet");
// elseif getos() == "Linux" then
// elseif then
// [rep, stat] = unix_g("dmesg | grep tty");
// [rep, stat] = unix_g("ls /dev/ttyACM*"); // alternatively
// setserial -bg /dev/ttyS*
// stty
end
endfunction
/*
This code is documented in AsciiDoc format
Suggested viewer FireFox plugin Asciidoctor.js Live Preview
sdefine()
Creates a serial port object (i.e. Scilab structure) given the required properties
Syntax:
*/
function [SerialObject, Result] = sdefine(Port, BaudRate, DataBits, Parity, StopBits, FlowControl, Terminator, TimeOut, InputBufferSize, OutputBufferSize, ReadAsyncMode, ByteOrder, Tag, OverWrite)
/*
Description:
The sdefine
function is an implementation of
MATLAB’s serial
function which creates a serial port object. At the moment the serial
object
is actually just a Scilab struct
with no methods. The Port
property (a Scilab string) must be specified but the rest of the
properties are optional and the function can set them to their default
values if not specified.
While creating the object it will warn the user if the object is not a
valid serial object. Valid serial objects are the one recognized by the
operating system, including the available
and open
ones. It will
check if the port with the given name is already defined, returning %f
if that’s the case, Unless the OverWrite
input has been set to %t
.
On Windows the Port
input is of the form COMx
where x
is a
positive integer.
Example:
s1 = sdefine("COM1")
s2 = sdefine(Port = 'COM2', BaudRate = 4800, Terminator = "cr")
Although it is possible to change the properties of the defined serial
objects using the dot .
operator
s2.BaudRate = 9600;
it is not recommended at all, and should be avoided at all costs. you
may always redefine the objects setting the OverWrite
input to %t
with the new properties. Otherwise, reading the information through the
.
operator is fine.
Source Code:
Click to see the source code
*/
if argn(1) < 1 then
warning("The SerialObject output argument must be present otherwise it can not be opned");
Result = %f;
return;
end
SerialObject = "UndefinedSerialObject";
global DefinedPorts;
global AvailablePorts;
if ~exists("Port","local") then
error("The Port must be specified");
end
if typeof(Port) ~= "string" then
warning("Port must be a string. Available ports at the moment are: " + strcat(slist(slist = "all"), ", "));
Result = %f;
Return;
end
// AvailablePorts = slist();
// if isempty(find(AvailablePorts == Port)) then
if ~isportavailable(Port) then
warning("The port " + string(Port) + " is not available at the moment. Available ports are: " + strcat(slist(), ", "));
end
// scilabcos compatible
// if size(strindex(strcat(unix_g("mode")), Port)) ~= [1, 1] then
// warning("The port " + Port + " is not available at the moment.");
// Result = %f;
// return;
// end
if ~exists("OverWrite", "local") then
OverWrite = %f;
end
if isportdefined(Port) then
if OverWrite == %f then
Result = %f;
SerialObject = "UndefinedSerialObject";
warning("The port is already defined. To over write it set OverWrite = %t ");
return;
else
sdelete(Port);
end
end
// try
// if ~int(Port) == Port | Port < 0 then
// error("Port must be a positive integer value");
// end
// catch
// error("Port must be a positive integer (numeric) value");
// end
// if getos() == "Windows" then
// Port = "COM" + string(Port);
// else
// error("this feature has not been implemented for this operating system yet");
// end
if ~exists("BaudRate","local") then
BaudRate = 9600;
end
if isempty(find(StandardBaudRates == BaudRate)) then
error(string(BaudRate) + " is not a standard baud rate. Available values are: " + strcat(string(StandardBaudRates), ", "));
end
if ~exists("Parity","local") then
Parity = "none";
end
if isempty(find(StandardParities == Parity)) then
error(string(Parity) + " is not a standard parity. Available values are: " + strcat(StandardParities, ", "));
end
if ~exists("DataBits","local") then
DataBits = 8;
end
if isempty(find(StandardDataBits == DataBits)) then
error(string(DataBits) + " is not a standard data bit. Available values are: " + strcat(string(StandardDataBits), ", "));
end
if ~exists("StopBits","local") then
StopBits = 1;
end
if isempty(find(StandardStopBits == StopBits)) then
error(string(StopBits) + " is not a standard StopBits. Available values are: " + strcat(string(StandardStopBits), ", "));
end
if ~exists("FlowControl","local") then
FlowControl = "none";
end
if isempty(find(FlowControls == FlowControl)) then
error(string(FlowControl) + " is not a standard FlowControl. Available values are: " + strcat(string(FlowControls), ", "));
end
if ~exists("Terminator","local") then
Terminator = "binary";
end
if isempty(find(Terminators == Terminator)) then
error(string(Terminator) + " is not a standard Terminator. Available values are: " + strcat(Terminators, ", "));
end
if ~exists("TimeOut","local") then
TimeOut = 10;
end
// check integers
// try
// if ~int(TimeOut) == TimeOut | TimeOut < 0 then
// if ~isscalar(TimeOut) | typeof(TimeOut) ~= "constant" | TimeOut < 0 then
if typeof(TimeOut) ~= "constant" | TimeOut < 0 then
error("TimeOut must be a positive integer value");
end
// catch
// error("TimeOut must be a positive integer (numeric) value");
// end
if ~exists("InputBufferSize","local") then
InputBufferSize = 512;
end
if modulo(InputBufferSize, 1) | InputBufferSize < 0 then
error("InputBufferSize must be a positive integer value");
end
if ~exists("OutputBufferSize","local") then
OutputBufferSize = 512;
elseif getos() ~= "Windows" then
error("OutputBufferSize feature is only for Wondows");
end
if modulo(OutputBufferSize, 1) | OutputBufferSize < 0 then
error("OutputBufferSize must be a positive integer value");
end
if ~exists("ReadAsyncMode","local") then
ReadAsyncMode = "continuous";
end
if isempty(find(ReadAsyncModes == ReadAsyncMode)) then
error(string(ReadAsyncMode) + " is not a standard ReadAsyncMode. Available values are: " + strcat(ReadAsyncModes, ", "));
end
if ~exists("ByteOrder","local") then
ByteOrder = "littleEndian";
end
if isempty(find(ByteOrders == ByteOrder)) then
error(string(ByteOrder) + " is not a standard ByteOrder. Available values are: " + strcat(ByteOrders, ", "));
end
// SerialObject = 0;
SerialObject = struct("Port", Port, "BaudRate", BaudRate, "DataBits", DataBits, "Parity", Parity, "StopBits", StopBits, "FlowControl", FlowControl, "Terminator", Terminator, "TimeOut", TimeOut, "InputBufferSize", InputBufferSize, "OutputBufferSize", OutputBufferSize, "Type", "serial", "Name", "Serial-" + Port, "SerialName", "");
// SerialObject = struct("Port", Port, "BaudRate", BaudRate, "DataBits", DataBits, "Parity", Parity, "StopBits", StopBits, "FlowControl", FlowControl, "Terminator", Terminator, "Type", "serial", "Name", "Serial-" + Port);
DefinedPorts = cat(1, DefinedPorts, Port);
endfunction
/*
This code is documented in AsciiDoc format
Suggested viewer FireFox plugin Asciidoctor.js Live Preview
sopen()
Opens the serial port object to get ready for send and receive (same as
MATLAB fopen
)
Syntax:
*/
function [Result, ResultSerialPort, SerialName] = sopen(SerialPort, Access, Reopen)
/*
Parameters
*/
AccessArguments = ["r", "r+", "w", "w+", "a", "a+"];
/*
Description:
The SerialPort
input must be a defined serial port object defined by
serial
function otherwise it will return %f
for Result
. The list
of defined serial objects can be found using the
slist(PortList = "defined")
command. The Access
input can be
set to "r"
, "r+"
, "w"
, "w+"
, "a"
, "a+"
. The function will
make sure the specified port is a valid, defined and available serial
port. If the Reopen
input has been set to %t
the function will close
it and reestablish the connection.
Source Code:
Click to see the source code
*/
Result = isvalidserialobject(SerialPort, Behaviour = "warning");
SerialName = "";
ResultSerialPort = SerialPort;
if Result == %f then
return;
end
// if typeof(SerialPort) ~= "st" then
// error("The SerialPort input must be a SerialObject")
// end
global OpenPorts;
if ~exists("Access","local") then
Access = "r+";
end
if isempty(find(AccessArguments == Access)) then
error(string(Access) + " is not a valid access argument. Available values are: " + strcat(AccessArguments, ", "));
end
if typeof(SerialPort) == "st" then
Port = SerialPort.Port;
// elseif typeof(SerialPort) == "string" then
else
error("This feature is not implemented yet. The sopen SerialPort must be a serial port structure made through serial function.");
// Port = SerialPort;
end
// try
if ~exists("Reopen","local") then
Reopen = %f;
end
if isportopen(SerialPort) then
if Reopen == %f then
warning("The port " + Port + " is already open");
SerialName = getserialname(Port);
ResultSerialPort.SerialName = SerialName;
Result = %f;
return;
else
sclose(SerialPort);
[Result, SerialName, ResultSerialPort]= sopen(SerialPort, Access);
return;
end
end
if ~isportdefined(SerialPort) then
// warning("The port is not defined. I will attemt to make one with the default properties");
// SerialPort = serial(Port);
warning("The port " + Port + " is not defined. Defined Ports are: " + strcat(DefinedPorts, ", "));
Result = %f;
return;
end
if ~isportavailable(SerialPort) then
warning("The port " + string(Port) + " is not available. Available ports are: " + strcat(slist(), ", "));
Result = %f;
return;
end
Digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
if getos() == "Windows" then
// if strtod(part(Port, $)) < 10 then
// if size(str2code(part(Port, 4:length(Port)))) == [1, 1] then
if ~isempty(find(part(Port, 4:length(Port)) == Digits)) then
SerialName = TCL_EvalStr("set " + "Serial_" + Port +" [open " + Port + " " + Access + "]");
else
SerialName = TCL_EvalStr("set " + "Serial_" + Port +" [open " + "\\\\.\\" + Port + " " + Access + "]");
end
else
error("this feature has not been implemented for this operating system yet");
end
// SerialName = TCL_GetVar("Serial-" + Port);
// SerialPort.SerialName = SerialName;
ResultSerialPort.SerialName = SerialName;
OpenPorts = cat(1, OpenPorts, [Port, SerialName]);
//// SerialPort.SerialName = SerialName;
Result(1) = TCL_EvalStr("fconfigure " + SerialName + " -mode " + string(SerialPort.BaudRate) + "," + part(SerialPort.Parity, 1) + "," + string(SerialPort.DataBits) + "," + string(SerialPort.StopBits)) == "";
Result(2) = TCL_EvalStr("fconfigure " + SerialName + " -translation " + SerialPort.Terminator) == "";
Result(3) = TCL_EvalStr("fconfigure " + SerialName + " -blocking 0") == ""; // this one has to do with sync and async I think
Result(4) = TCL_EvalStr("fconfigure " + SerialName + " -timeout " + string(SerialPort.TimeOut * 100)) == "";
if getos() == "Windows" then
Result(5) = TCL_EvalStr("fconfigure " + SerialName + " -sysbuffer " + "{" + string(SerialPort.InputBufferSize) + " " + string(SerialPort.OutputBufferSize) + "}") == "";
else
Result(5) = TCL_EvalStr("fconfigure " + SerialName + " -sysbuffer " + string(SerialPort.InputBufferSize)) == "";
end
select SerialPort.FlowControl
case "hardware" then
if getos() == "Windows" then
handshake = "dtrdsr";
else
handshake = "rtscts";
end
case "software" then
handshake = "xonxoff";
else
handshake = "none";
end
Result(6) = TCL_EvalStr("fconfigure " + SerialName + " -handshake " + handshake) == "";
// catch
// error("Failed opening port. The SerialPort input must be a SerialObject");
//// sclose(SerialPort);
// TCL_EvalStr("set closeresult [catch {close " + SerialName + "}]");
// end
Result = Result(1) & Result(2) & Result(3) & Result(4) & Result(5) & Result(6);
if Result == %f then
sclose(Port);
wanting("Opening was not sucessful!")
return;
end
endfunction
/*
sprint()
writes text to the serial devoice (similar to the MATLAB fprintf)
Syntax:
<Result> = sprint(<SerialPort => SerialPort, <Message => Message, <Mode = "syn"/"async">)
Description:
The SerialPort
is a serial port object defined by the serial
function or a string of a valid serial port such as COM1
. The
Message
is a Scilab string which can be a formatted text created by
Scilab’s msprintf
function or a SCPI / SCI command known to the serial
device.
Example:
sprint(s1, 'RS232?');
sprint(s1,'*IDN?');
sprint(s1, msprintf('%s','RS232?'));
sprint(s1, msprintf('ch:%d scale:%d', 1, 20e-3), 'sync');
sinfo()
Check the input and output buffer for available bytes and the status of the port
Syntax:
[InutBytesAvailable, <OutputBytesAvailable>, <Status>, <Result>] = sinfo(SerialPort)
Tutorials:
Example 01:
In this example (inspired by this tutorial) you will learn how to communicate with an Arduino microcontroller (MCU) expansion board and a Windows PC, through serial port. By the end of this example you will be able to read the value of a potentiometer, while this can be also expanded to reading any other sensors as well. To follow along the example you require the hardware including an Arduino Uno MCU development board, a potentiometer, wiring and breadboard.
Alternatively you can use SimulIDE to simulate the hardware and the Null-modem emulator (com0com) one Windows, to stablish a pair of virtual serial ports.
The Arduino code is:
int potPin = A0;
long val = 0;
long val_ = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
val = ((long) analogRead(potPin));
if (val != val_) {
val_ = val;
Serial.println(val);
}
}
find the port connected to the Arduino board by running the command:
slist(Verbose = %t, PortList = "all")
This will show you are the serial ports recognized by the operating
system, including the "available"
and "open"`s. Under `Description
you should be able to find the Arduino serial port.
Scilab code
Click to see the source code
*/
s7 = sdefine(Port = "COM7", BaudRate = 9600, Parity = 'none', DataBits = 8, StopBits = 1, OverWrite = %t); // Assuming COM7 is the port you got from above command
sopen(SerialPort = s7, Access = 'r');
pData = [];
pTime = [];
nData = csvTextScan(part(sget(s7), 1:$-1), ',');
pData = [pData, nData(2)];
pTime = [pTime, nData(1)];
plot(pTime, pData);
while %t
drawlater();
nData = csvTextScan(part(sget(s7), 1:$-1), ',');
pData = [pData, nData(2)];
pTime = [pTime, nData(1)];
clf();
plot(pTime, pData);
drawnow();
sleep(1000);
end
sclose(s7);
sdelete(s7);
/*
SimulIDE model
Click to see the source code
<circuit type="simulide_0.1"> Arduino Uno-17: <item itemtype="Arduino" hflip="1" rotation="0" x="-252" valLabRot="0" Mhz="16" valLabely="0" id="Arduino Uno" valLabelx="0" labelrot="0" vflip="1" labely="-21" Ser_Port="true" labelx="54" objectName="Arduino Uno-17" Program="sketch_noDelay_20190228_1/sketch_noDelay_20190228_1.ino.standard.hex" Ser_Monitor="true" Show_id="true" y="-244"/> Potentiometer-15: <item itemtype="Potentiometer" hflip="1" rotation="0" x="4" valLabRot="0" Show_res="true" valLabely="-42" id="Potentiometer-15" valLabelx="-17" labelrot="0" vflip="1" labely="-24" Resistance="10" labelx="0" objectName="Potentiometer-15" Value_Ohm="8380" Show_id="false" y="-252" Unit=" kO"/> Connector-24: <item pointList="4,-236,4,-188,-100,-188" itemtype="Connector" hflip="1" rotation="0" endpinid="Arduino Uno-17-PC0" x="4" valLabRot="0" valLabely="0" id="Connector-24" valLabelx="0" labelrot="0" vflip="1" labely="-24" labelx="0" objectName="Connector-24" startpinid="Potentiometer-15-PinM" Show_id="false" y="-236" enodeid="Circ_eNode-25"/> Connector-26: <item pointList="-12,-252,-12,-164,-100,-164" itemtype="Connector" hflip="1" rotation="0" endpinid="Arduino Uno-17-GND1" x="-12" valLabRot="0" valLabely="0" id="Connector-26" valLabelx="0" labelrot="0" vflip="1" labely="-24" labelx="-16" objectName="Connector-26" startpinid="Potentiometer-15-PinA" Show_id="false" y="-252" enodeid="enode-26"/> Connector-28: <item pointList="20,-252,20,-148,-100,-148" itemtype="Connector" hflip="1" rotation="0" endpinid="Arduino Uno-17-V5V" x="20" valLabRot="0" valLabely="0" id="Connector-28" valLabelx="0" labelrot="0" vflip="1" labely="-24" labelx="-16" objectName="Connector-28" startpinid="Potentiometer-15-PinB" Show_id="false" y="-252" enodeid="enode-28"/> PlotterWidget-56: <item focus="false" frameGeometry="" maximumHeight="200" childrenRegion="" windowFilePath="" autoFillBackground="false" sizePolicy="" palette="" toolTip="" accessibleName="" styleSheet="" layoutDirection="0" minimumSize="" windowIconText="" windowModified="false" rect="" statusTip="" windowOpacity="1" toolTipDuration="-1" acceptDrops="false" updatesEnabled="true" visible="false" isActiveWindow="true" objectName="PlotterWidget-56" itemtype="Plotter" maximumSize="" contextMenuPolicy="1" pos="" cursor="" font="MS Shell Dlg 2,7.8,-1,5,50,0,0,0,0,0" height="200" locale="" geometry="" minimumSizeHint="" whatsThis="" y="791" accessibleDescription="" MaxVolt="500" minimumWidth="200" inputMethodHints="0" x="0" baseSize="" maximized="false" windowIcon="" width="265" childrenRect="" normalGeometry="" MinVolt="0" enabled="true" mouseTracking="false" minimized="false" frameSize="" sizeHint="" fullScreen="false" sizeIncrement="" size="" windowTitle="" maximumWidth="1000" modal="false" focusPolicy="0" windowModality="0" minimumHeight="200"/> SerialPortWidget-57: <item focus="false" frameGeometry="" maximumHeight="170" childrenRegion="" windowFilePath="" autoFillBackground="false" sizePolicy="" palette="" toolTip="" accessibleName="" SettingsProp="COM6,0,3,0,0,0" styleSheet="" layoutDirection="0" minimumSize="" windowIconText="" windowModified="false" rect="" statusTip="" windowOpacity="1" toolTipDuration="-1" acceptDrops="false" updatesEnabled="true" visible="true" isActiveWindow="true" objectName="SerialPortWidget-57" itemtype="SerialPort" maximumSize="" contextMenuPolicy="1" pos="" cursor="" font="MS Shell Dlg 2,7.8,-1,5,50,0,0,0,0,0" height="170" locale="" geometry="" minimumSizeHint="" whatsThis="" y="806" accessibleDescription="" minimumWidth="0" inputMethodHints="0" x="528" baseSize="" maximized="false" windowIcon="" width="450" childrenRect="" normalGeometry="" enabled="true" mouseTracking="false" minimized="false" frameSize="" sizeHint="" fullScreen="false" sizeIncrement="" size="" windowTitle="Settings" maximumWidth="450" modal="false" focusPolicy="0" windowModality="0" minimumHeight="0"/> </circuit>
Result:
Nomenclature / Glossary:
For those who are not familiar with serial communication, some terms used in the practice can be difficult to grasp. In this section we will try to explain those terms.
-
message: a serial message is 1 byte or 8 bits, which is able to represent between 0-255.
-
terminator: indicates how a message should end. The common terminator is a carriage return indicated as
"cr"
in this toolbox. -
buffer: is like a container on the on both sides of the communication ports. The sender stores the data there before flushing them through the port and the receiver stores them there before dumping them over to the users space. The buffers have limited size which if exceeds the oldest data will be discarded. The size of buffer can be set through
InputBufferSize
andOutputBufferSize
serial object property, which can not exceed the maximum provided by the hardwareMaxInputBufferSize
andMaxOutputBufferSize
. If you do not flush/read the data on the sender/receiver side in time it can lead to irreversible data loss. -
checksum: in simple terms is basically a signature attached to each message, known by the receiver, which can be used to verify that the data is not garbled.
-
polling and streaming: when requesting one single measurements from a sensor, it is called polling. If we read data from the sensor given a certain frequency it is called streaming.
-
Serial Command Interface (SCI): firstly used by Motorola in the 1970s, is basically a language known by the serial device (e.g. MCU) to do certain things upon receiving certain messages.
-
serial peripheral interface ( SPI )
-
universal asynchronous receiver/transmitter (UART)
-
USART
-
Standard Commands for Programmable Instruments (SCPI)
-
Transistor–transistor logic (TTL)
-
TTY: teletypewriter, teletype, terminal
-
Serial Port Profile (SPP)
Abbreviations:
-
EIA Electronic Industries Alliance
-
ANSI American National Standards Institute
-
TIA Telecommunications Industry Association
-
DIN Deutsches Institut für Normung
-
RS Recommended Standard
-
232
-
DTE Data Terminal Equipment eg. IBM computer, printer, plotter etc
-
DCE Data Communication/circuit-terminating Equipment eg. modem, multiplexors, etc
-
-
422, 449, 485, 530
-
-
ASCII: American Standard Code for Information Interchange
Pinout and Signals
Connectors used to be in the form of D-sub series or Mini-DIN
Serial and Parallel ports were found in two different forms, DB-25 and DE-9 (which is mistakenly also referred to as DB-9).
port (e.g. , DB-25, DE-9 …),voltage (TTL 5V, True RS-232 12V), communication standards (RS-232, USB), data transmission method (parallel or serial)
DE-9 | DB-25 | acronym / abbreviation | Name | typical purpose | DTE | DCE |
---|---|---|---|---|---|---|
1 |
8 |
DCD |
Data Carrier Detect |
DCE is receiving a carrier from a remote DCE |
in |
out |
2 |
3 |
RxD |
Received Data |
Carries data from DCE to DTE |
in |
out |
3 |
2 |
TxD |
Transmit Data |
Carries data from DTE to DCE |
out |
in |
4 |
20 |
DTR |
Data Terminal Ready |
DTE is ready to receive, initiate, or continue a call |
out |
in |
5 |
7 |
GND |
Common Ground |
Zero voltage reference (signal ground) |
- |
- |
6 |
6 |
DSR |
Data Set Ready |
DCE is ready to receive and send data |
in |
out |
7 |
4 |
RTR |
Ready To Receive |
DTE is ready to receive data from DCE |
out |
in |
7 |
4 |
RTS |
Request To Send |
flow control, DTE requests the DCE prepare to transmit data |
out |
in |
8 |
5 |
CTS |
Clear To Send |
DCE is ready to accept data from the DTE |
in |
out |
9 |
22 |
RI |
Ring Indicator |
DCE has detected an incoming ring signal on the telephone line |
in |
out |
1 |
PG |
Protective Ground |
Frame / Chassis Ground |
- |
- |
|
9 |
||||||
10 |
||||||
11 |
||||||
12 |
SDCD |
Secondary Carrier Detect |
Tone from a modem |
in |
out |
|
13 |
SCTS |
Secondary Clear To Send |
in |
out |
||
14 |
STD |
Secondary Transmitted Data |
out |
in |
||
15 |
ST |
Send Timing |
||||
16 |
SRD |
Secondary Received Data |
in |
out |
||
17 |
RT |
receive timing |
||||
18 |
Loopback |
|||||
19 |
SRTS |
Secondary Request To Send |
out |
in |
||
21 |
Loopback |
|||||
23 |
Signal rate selection |
|||||
24 |
TT |
Transmitter Timing |
||||
25 |
References
-
[Esposito2009] Joel M. Esposito, Tutorial: Serial Communication in Matlab, 2009, URL