A:
Introduction
Communicating with USB devices in MATLAB, or
virtually any application software, involves a few
simple steps. Unlike RS232 based devices which are
connected to physical COM ports, USB devices are
assigned a logical handle
by operating systems when they are first plugged in.
This process is known as enumeration.
Once a USB device has been
enumerated, it is ready for use by the host computer
software. For the host application software to
communicate with the USB device, it must first obtain
the handle assigned to the USB device during the
enumeration process. The handle can be obtained using an
open function along with
some specific information about the USB device.
Information that can be used to obtain a handle to a USB
device include, serial number,
product ID, or vendor
ID. Once the handle is obtained, it is used to allow the
application to read and write information, to and from,
the USB device. Once the application has finished
with all communication with the USB device, the handle
is closed. The handle is generally closed when the
application terminates.
The AduHid DLL provides all the
functions to open a handle, read and write data, and
close the handle of ADU USB devices. The ADUHID dll can
be used directly from a MATLAB application.
The MATLAB data Acquisition ToolKit is not required to
communicate with ADU interfaces.
For this tutorial we will use MATLAB to communicate
with an ADU258 USB Solid State
Relay I/O
Interface. The application will open the
ADU258, send comands and receive data using various ADU
comands to operate the interface, and
then close the ADU258. Although we are using an
ADU258 in this tutorial, the code can be modified to suit
any of the ADU Data Acquisition
and Control Products.
Figure
1: ADU258 USB Solid-State Relay I/O Interface
Before we dissect the code, the
full MATLAB .m file is listed here, followed by the
Command Window Output. (Download entire project at bottom of page)
ptrResult=libpointer('int8Ptr',zeros(1,8));
ProductID = 258;
vp = libpointer('voidPtr',zeros(1,1));
if not(libisloaded('AduHid64'))
loadlibrary('AduHid64','AduHidMatlab.h');
end
device_handle = calllib('AduHid64','OpenAduDevice',1000);
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('sk0') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
pause (2)
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('rk0') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
pause (2);
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('mk255') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
pause (2);
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('mk0') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('PA') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
result = calllib('AduHid64','ReadAduDevice',device_handle,ptrResult,8,vp,500);
if result == 0
fprintf('\nError During ADU Read\n');
end
x=char(ptrResult.value);
reading=str2num(x);
fprintf('\nDecimal value of PORT A is %i \n', reading);
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('RPA') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
result = calllib('AduHid64','ReadAduDevice',device_handle,ptrResult,8,vp,500);
if result == 0
fprintf('\nError During ADU Read\n');
end
x=char(ptrResult.value);
fprintf('\nPORTA value in binary is %s \n',x);
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('RE0') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
result = calllib('AduHid64','ReadAduDevice',device_handle,ptrResult,8,vp,500);
if result == 0
fprintf('\nError During ADU Read\n');
end
x=char(ptrResult.value);
reading=str2num(x);
fprintf('\nEvent Counter 0 value is %i \n',reading);
clear vp ptrResult reading;
calllib('AduHid64','CloseAduDevice',device_handle);
unloadlibrary('AduHid64');
When run, the code displays the
following in the Command Window.
Figure
2: Command Window Output
B:
Lets have a look at the code......
1. Set up variables and pointers to be used by
function calls.
The ADU products use NULL terminated ASCII strings to
communicate, with the longest string being 8 bytes.
Here we initiate a pointer to create a 8 byte array
to store the received data. We then set the
variable ProductID to 258 and then the vp
pointer is initalized as a single byte. This variable is
used to store bytes received and bytes sent
by the function calls.
ptrResult=libpointer('int8Ptr',zeros(1,8));
ProductID = 258;
vp = libpointer('voidPtr',zeros(1,1));
2. Load Libraries.
To allow function calls to the ADU258 within MATLAB we
must load the libraries including the AduHid64.dll and
AduHidMatlab.h files. It is important to use the
AduHidMatlab.h header file and NOT the AduHid.h file
normally included with our dll. This is because
MATLAB does not recognize the BOOL format used in the
original Windows header. The AduHidMatlab.h file was
created only for use in MATLAB.
if not(libisloaded('AduHid64'))
loadlibrary('AduHid64','AduHidMatlab.h');
end
3. Obtain handle to ADU Device.
To communicate with the ADU258 we must first open a
handle to it. This can be done in one three types
of calls. For this example we open a handle to the first ADU
device detected. This should only be used if there
is only one ADU connected to the host computer. If more
than one ADU is connected you can either open the handle
by SerialNumber or ProductID.
device_handle = calllib('AduHid64','OpenAduDevice',1000);
4. Send/Receive commands and data from the
ADU258.
The ADU258 features 8 Solid-State relays ( K0 to K7),
and 8 digital inputs divided into two 4-bit ports (
PA0-PA3, PB0-PB3). Each of the digital input lines
has a 16-bit event counter associated with it. The
command format the ADU258, and all ADU2xx products, uses
is very intuative and consists of Null terminated ASCII strings. Here we will perform some random tasks to
demonstrate how to send commands and receive data from
the ADU258.
In section 4a we send the SK0 command to turn on relay
K0, and then wait for 2 seconds
In section 4b, we send the RK0 command to open relay K0,
and then wait for 2 seconds
In section 4c, we send the MK255 command to turn on all
8 relays, and then wait for two seconds
In section 4d, we send the MK0 command to turn off all
eight relays.
To read data from any ADU device a read command must be
sent (PA, for example). This is done using a
WriteAduDevice function call. Note that the
PA
command is sent with [int8('PA')
0 0] which produces the ASCII string "PA" followed
by two NULLs ( recommended). To retrieve
the data, a ReadAduDevice function call is
implemented. For details on all ADU function
calls see: ADUHid
Functions.
The returned data for the PA command is in the format of
2 ASCII characters
ranging from 00 to 15 and it should be
converted to an actual number to allow use of the data
in calculations, plotting, etc. This is accomplished
with the x=char(ptrResult.value); and
reading=str2num(x); statements.
In section 4e, we send the PA command to read PORTA in
decimal format. We then read the data, which is in
the format of a null terminated ASCII string, and
convert it to a number using the str2num
function. the number is then output to the command
window.
In section 4f, we send the RPA command to read PORTA in
binary format. We then read the data, which is in
the format of a null terminated ASCII string, and output
it to the command window.
In section 4f, we send the RE0 command to read the event
counter on PA0 in decimal format. We then read the
data, which is in the format of a null terminated ASCII
string, and convert it to a number using the
str2num function. The number is then output to the
command window.
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('sk0') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
pause (2)
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('rk0') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
pause (2);
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('mk255') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
pause (2);
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('mk0') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('PA') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
result = calllib('AduHid64','ReadAduDevice',device_handle,ptrResult,8,vp,500);
if result == 0
fprintf('\nError During ADU Read\n');
end
x=char(ptrResult.value);
reading=str2num(x);
fprintf('\nDecimal value of PORT A is %i \n', reading);
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('RPA') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
result = calllib('AduHid64','ReadAduDevice',device_handle,ptrResult,8,vp,500);
if result == 0
fprintf('\nError During ADU Read\n');
end
x=char(ptrResult.value);
fprintf('\nPORTA value in binary is %s \n',x);
result = calllib('AduHid64','WriteAduDevice',device_handle,libpointer('voidPtr',[int8('RE0') 0 0]),8,vp,500);
if result == 0
fprintf('\nError During ADU Write\n');
end
result = calllib('AduHid64','ReadAduDevice',device_handle,ptrResult,8,vp,500);
if result == 0
fprintf('\nError During ADU Read\n');
end
x=char(ptrResult.value);
reading=str2num(x);
fprintf('\nEvent Counter 0 value is %i \n',reading);
5. Before terminating program, clear variables,
release ADU258 Handle and unload the library.
Before exiting the program the variables are cleared,
the ADU258 handle is released, and the libraries are
unloaded.
It is important that the handle for an ADU device is
opened when the application opens, and closed only when
the application terminates. DO NOT open and
close the handle for each read or write as Windows may put the ADU258 into suspend mode causing a loss of
configuration data.
clear vp ptrResult reading;
calllib('AduHid64','CloseAduDevice',device_handle);
unloadlibrary('AduHid64');
Download the tutorial and associated libraries here:
MATLAB ADU2xx
Tutorial ( Windows 64-Bit) ZIP
Authored by Tom Fortin, April 2021
|