Difference between revisions of "826"
(→Oversampling) |
(→Usage) |
||
(879 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
[[File:826 photo.jpg|thumb|Model 826 board]] | [[File:826 photo.jpg|thumb|Model 826 board]] | ||
− | This is the | + | This is the top-level wiki page for Sensoray's [http://www.sensoray.com/products/826.htm model 826], a versatile analog and digital I/O system on a PCI Express board. The board has 48 digital I/Os with edge detection, sixteen 16-bit analog inputs, eight 16-bit analog outputs, six 32-bit counter channels with quadrature clock decoders, three-stage watchdog timer with fail-safe controller, and a flexible signal router. |
− | + | ;Related pages | |
− | + | Each board subsystem has a dedicated wiki page: | |
− | + | * [[826 ADC|ADC]] - analog input system | |
− | + | * [[826 DAC|DACs]] - analog output system | |
− | + | * [[826 DIOs|DIOs]] - general-purpose digital I/Os | |
− | + | * [[826 counters|Counters]] - counter/timers, including appnotes for interfacing incremental encoders | |
− | + | * [[826 watchdog|Watchdog]] - watchdog timer and fail-safe controller | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
+ | ;Please note: | ||
+ | * Code and circuit examples are intended to function as described, but this is not guaranteed. If you discover an error, please [http://www.sensoray.com/support/message.htm?s=Web%20feedback inform the webmaster]. | ||
+ | * In code examples, error checking has been simplified or omitted for clarity. It is recommended to always perform error checking in your production software. | ||
+ | * C language examples depend on header file <code>826api.h</code>, which should be included at the top of your source code like this: | ||
#include "826api.h" | #include "826api.h" | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ==Timestamp generator== | |
− | + | The timestamp generator is a free-running 32-bit counter that serves as a time reference. The counter increments once per microsecond and overflows (to zero, without notification) every 2<sup>32</sup> µs (approximately 71.6 minutes). It is a binary counter and consequently does not keep track of the date or time-of-day. At any moment, the current count may be sampled; such a sample is called a ''timestamp''. | |
− | + | A timestamp is automatically appended to every counter snapshot and to every ADC sample so that application programs can know (to within 1 µs) when each sample was acquired. Also, application programs can read the timestamp generator at any time to get a timestamp. | |
− | + | ===Usage=== | |
− | + | Timestamps are particularly useful for precisely measuring the elapsed time between hardware events. Calculation of elapsed time is easy (a single subtraction) as long as the time interval doesn't exceed 71.6 minutes. It can be used in a variety of ways, including [[826 counters#Measuring speed|measuring speed]] and [[826 counters#Serial data capture|capturing serial data]]. | |
− | + | If desired, an application program can directly read the current time as shown below: | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | // Read the timestamp generator's current count. | |
− | + | uint CurrentTimestamp(uint board) | |
− | + | { | |
− | + | uint t; | |
− | + | S826_TimestampRead(board, &t); | |
− | + | return t; | |
− | + | ||
− | + | ||
− | + | ||
} | } | ||
− | + | The following example shows a simple application of direct timestamp reads: | |
− | == | + | // Example: Use board0 to measure system Sleep() time. |
+ | uint t1, t0 = CurrentTimestamp(0); // Get start time. | ||
+ | Sleep(25); // Sleep approximately 25 ms. | ||
+ | t1 = CurrentTimestamp(0); // Get end time. | ||
+ | printf("Slept %d µs", t1 - t0); // Display actual sleep time. | ||
− | + | ==Board ID== | |
− | + | The "BOARD NUM" switches (at top edge of board near mounting bracket) assign the board ID used by software. The ID is binary coded on the four switches and can be programmed to any value from 0 (default) to 15. A board's ID determines the corresponding ''bit'' that will be set to '1' in the value returned by <code>S826_SystemOpen</code>. If you have a single 826 board, the return value will be <code>(2^ID)</code>. If you have multiple boards, the return value is the sum of <code>(2^ID)</code> for each board. You can enter the return value [http://www.sensoray.com/support/826_boardID.htm here] to quickly determine its meaning. | |
− | + | ;Examples | |
+ | * You have one board with ID set to 0, so the value returned by <code>S826_SystemOpen</code> will be <code>(2^0) = 1</code>. | ||
+ | * You have two boards with IDs set to 1 and 4, so the value returned by <code>S826_SystemOpen</code> will be <code>(2^1)+(2^4) = 2+16 = 18</code>. | ||
− | + | This code snippet will tell you the meaning of the value returned by <code>S826_SystemOpen</code>: | |
− | : | + | int id, flags = S826_SystemOpen(); |
+ | if (flags < 0) | ||
+ | printf("S826_SystemOpen returned error code %d", flags); | ||
+ | else if (flags == 0) | ||
+ | printf("No boards were detected"); | ||
+ | else { | ||
+ | printf("Boards were detected with these IDs:"); | ||
+ | for (id = 0; id < 16; id++) { | ||
+ | if (flags & (1 << id)) | ||
+ | printf(" %d", id); | ||
+ | } | ||
+ | } | ||
− | + | ==Hardware version== | |
− | + | ===Reading the PWB revision=== | |
− | + | The circuit board revision (PWB rev) is visible on the solder-side of the 826 board (opposite the mounting bracket, on the bottom corner). <code>S826_VersionRead</code> returns the PWB rev as a numeric value with decimal range [0:31], which corresponds to a text string in the standard ASME version letter sequence. The following code shows how to convert this 32-bit value to the alphabetic revision code seen on the board: | |
− | + | ||
− | + | ||
− | + | ||
− | + | // Read and display version info from board 0 | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | // Extract major_version, minor_version and build_number from a 32-bit version number: | |
− | + | #define VER_FIELDS(N) ((N) >> 24) & 0xFF, ((N) >> 16) & 0xFF, (N) & 0xFFFF | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | const char *revchar[] = { // ASME revision sequence | |
− | + | "A", "B", "C", "D", "E", "F", "G", "H", | |
− | + | "J", "K", "L", "M", "N", "P", "R", "T", | |
− | + | "U", "V", "W", "Y", "AA", "AB", "AC", "AD", | |
− | + | "AE", "AF", "AG", "AH", "AJ", "AK", "AL", "AM" | |
− | + | }; | |
− | + | ||
− | + | ||
− | + | ||
− | + | uint api, drv, bd, fpga; | |
− | + | int errcode = S826_VersionRead(0, &api, &drv, &bd, &fpga); // Read version info. | |
− | + | if (errcode == S826_ERR_OK) { // If no errors then display info: | |
− | + | printf("API version = %d.%d.%d\n", VER_FIELDS(api)); // API major.minor.build | |
− | + | printf("Driver version = %d.%d.%d\n", VER_FIELDS(drv)); // DRVR major.minor.build | |
− | + | printf("FPGA version = %d.%d.%d\n", VER_FIELDS(fpga)); // FPGA major.minor.build | |
− | + | printf("PWB revision = Rev %s\n", revchar[bd & 31]); // PWB rev as seen on circuit board | |
− | + | ||
− | + | ||
− | + | ||
} | } | ||
+ | else | ||
+ | printf(" S826_VersionRead returned error code %d", errcode); | ||
− | === | + | ===Rev C changes=== |
− | + | Sensoray has developed Revision C of the 826 circuit board. This change was necessary due to the impending EOL (end-of-life) of a critical component. Specifically, the critical component (PCI Express interface chip) and FPGA were removed and replaced by a new FPGA, which absorbed the functions of the two removed components. | |
− | + | <u>'''Applications and developers are not affected by this change'''</u> | |
− | + | The Rev C board is fully compatible with Rev B boards and applications: | |
− | + | * Mechanical attributes are unchanged, including board dimensions and placements of connectors, switches, indicator LEDs, and hold-down bracket. | |
+ | * Connector pinouts, electrical and timing specifications are unchanged. | ||
+ | * Rev C is 100% software compatible with Rev B on all software layers: application, API and driver (including user-developed drivers and APIs for RTOS, etc.). | ||
− | + | Rev B and Rev C boards can be used interchangeably in new and existing applications. From an application's perspective, the only detectable differences between Rev B and Rev C boards are the version numbers returned by the API function S826_VersionRead(): | |
+ | * S826_VersionRead() will report the PWB version as Rev B or Rev C as appropriate for the board's hardware version. | ||
+ | * S826_VersionRead() will report FPGA version 0.0.70 or higher for Rev C boards, or version 0.0.69 or lower for Rev B boards. | ||
− | + | ==Connector pinouts== | |
− | + | ||
− | + | ||
− | + | The following drawings show the pinouts of the board's header connectors as viewed from the top (component) side of the circuit board: | |
− | : | + | <gallery heights=350px widths=180px perrow=3> |
+ | File:826 pinout J1.gif | ||
+ | File:826 pinout J2.gif | ||
+ | File:826 pinout J3.gif | ||
+ | File:826 pinout J4.gif | ||
+ | File:826 pinout J5.gif | ||
+ | File:826 pinout P2.gif | ||
+ | </gallery> | ||
− | + | ==Software== | |
− | + | ===C examples=== | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | A variety of [http://www.sensoray.com/downloads/s826_example.c C programming examples] have been collected together in a common source file to illustrate how to program resources on the 826. | |
− | === | + | ===VB.NET demo=== |
− | + | To help you jump-start your project, we offer the [[826 demo (VB.NET)|VB.NET demo for model 826]]. This demo program provides a pre-built Windows executable with a GUI for nearly every hardware resource on the board. All source files are provided, along with a VisualStudio project. | |
− | + | ===Programming in C#=== | |
− | + | Each 826 SDK includes a C# demo application. These demos show how to call API functions from C#, and can serve as a useful starting point for a custom application. | |
− | + | ====Linux demo==== | |
− | + | In the Linux SDK, a C# GUI demo is available which uses Linux mono. To get the required libraries on Ubuntu, type: | |
+ | "sudo apt-get install mono-complete" | ||
+ | For a C# development environment, type: | ||
+ | "sudo apt-get install monodevelop" | ||
− | + | ====Pointer arguments==== | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | Many of the API functions have pointer arguments. This is no problem for C#, which allows you to pass function arguments by reference. To see how this is done, consider the <code>S826_AdcEnableRead</code> function: | |
− | + | The C prototype is: | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | int S826_AdcEnableRead(unsigned int board, unsigned int *enable); | |
− | : | + | So in C# you should declare the function this way: |
− | + | [DllImport("s826.dll", CallingConvention = CallingConvention.StdCall)] | |
+ | static extern Int32 S826_AdcEnableRead(UInt32 board, ref UInt32 enable); | ||
+ | Now you can call the function this way: | ||
− | + | Uint32 isEnabled; | |
+ | Int32 errcode = S826_AdcEnableRead(0, ref isEnabled); | ||
− | + | ===Labview=== | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | Before running an 826 virtual instrument (VI) under Labview, make sure you install the latest versions of the 826 DLL (s826.dll) and device driver (both are contained in the 826 SDK, which you can obtain from the ''Downloads'' tab of the [http://www.sensoray.com/products/826.htm 826 product page]). | |
− | + | Each VI is a basically a wrapper for a DLL function and consequently the VIs are dependent on the DLL, which in turn depends on the driver. Board hardware and firmware version numbers will be automatically read from the 826 board by software when all dependencies are satisfied -- it is not necessary to manually enter any board selection information except the board number, which is specified by the board's switch settings (factory default is board number 0). | |
− | + | ||
− | + | ||
− | + | ||
− | + | The VIs are not independently documented, but since each VI wraps a DLL function, the DLL documentation effectively explains the function of each associated VI. The DLL documentation can be found in the 826 product manual (download from the [http://www.sensoray.com/products/826.htm 826 product page] ''Documentation'' tab). | |
− | + | The VIs may be installed under Labview's instrument library (e.g., "instr.lib\Sensoray 826") or elsewhere if desired. Refer to Labview documentation for information about paths and other relevant topics. | |
− | + | ===Matlab=== | |
− | + | To use an 826 with Matlab you must first install the latest 64-bit versions of the 826 API (s826.dll) and device driver; these are both part of the 826 SDK, which you can obtain from the ''Downloads'' tab of the [http://www.sensoray.com/products/826.htm 826 product page]. You may then use Matlab's <code>loadlibrary()</code> function to enable access to the API, and <code>calllib()</code> to call API functions. The API functions are described in the 826 product manual, which can be found on the [http://www.sensoray.com/products/826.htm 826 product page] ''Documentation'' tab. The following example illustrates how this works. | |
− | + | Note: Matlab cannot execute <code>loadlibrary()</code> unless a compatible C compiler is installed on your computer. If Matlab complains about an "Error using loadlibrary" because "No supported compiler was found" then you must download and install one of the Matlab-compatible compilers (e.g., MinGW-w64) to resolve this issue. Please consult Mathworks for a list of compatible compilers. | |
− | + | % Simple Matlab example: turn on general-purpose digital I/O 2 *************************** | |
− | + | ||
− | + | % Change these values as required: | |
− | + | hdrPath = 'C:\Sensoray\826api.h'; % Path to API header | |
− | = | + | dllPath = 'C:\Windows\System32\s826.dll'; % Path to API executable |
− | + | board = 0; % Use 826 board #0 (i.e., board w/ID switches set to 0) | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | loadlibrary(dllPath, hdrPath, 'alias', 's826'); % Load the API. | |
− | + | boardflags = calllib('s826', 'S826_SystemOpen'); % Open API and detect all boards. | |
− | + | if (boardflags < 0) % If API failed to open | |
− | + | disp("S826_SystemOpen error"); % Report error. | |
− | + | else % Else | |
− | + | if (boardflags ~= bitshift(1, board)) % If board #0 was not detected | |
− | + | disp("Failed to detect 826 board"); % Report error (check board's switch settings). | |
+ | else % Else ... | ||
+ | buf = libpointer('uint32Ptr', [6 0]); % Allocate buffer for DIO state data. | ||
+ | errcode = calllib('s826', ... % Turn on DIO1 and DIO2. | ||
+ | 'S826_DioOutputWrite', board, buf, 0); | ||
+ | clear buf; % Free buffer. | ||
+ | if (errcode ~= S826_ERR_OK) | ||
+ | disp('DIO write problem') % Report error if DIO write failed. | ||
+ | end | ||
+ | end | ||
+ | errcode = calllib('s826', 'S826_SystemClose'); % Close API. | ||
+ | end | ||
+ | unloadlibrary s826; % Unload the API. | ||
− | ==== | + | ====Matlab SDK==== |
− | + | Sensoray offers an open-source software development kit for Matlab programmers, which you can obtain from the ''Downloads'' tab of the [http://www.sensoray.com/products/826.htm 826 product page]. The Matlab SDK includes two files: | |
+ | * <code>s826.m</code> is a class that defines useful constants and provides wrappers for all 826 API functions. Include this file in any project that interacts with model 826 boards. | ||
+ | * <code>s826_demo.m</code> is a short program that demonstrates how to use the s826 class. | ||
− | + | ===ROS (Robot Operating System)=== | |
− | + | Sensoray SDKs do not include a ROS package, but the Linux SDK has everything needed to create one. The simplest way to use ROS with model 826 is to install the Linux 826 device driver and API (shared library), and then call the API functions as shown in the following example. Note that this example is coded in C++, but you can easily call the API functions from Python or any other language. | |
− | + | /////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
− | + | // Simple ROS (Robot Operating System) example for Sensoray 826 PCI Express analog/digital IO board. | |
− | + | // Function: Publishes 16 analog inputs 10 times per second | |
− | + | /////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
− | + | ||
− | #define | + | #define X826(func) if ((errcode = (func)) != S826_ERR_OK) { printf("\nERROR: %d\n", errcode); return; } // Call function and process error |
− | + | ||
− | + | int PublishAINChannels() | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
{ | { | ||
− | + | int adcbuf[16]; // adc data buffer | |
− | + | uint slotlist; // timeslot flags | |
− | + | uint slot; // timeslot index (and ain channel number) | |
− | uint slotlist | + | uint board = 0; // board ID |
− | + | int errcode; | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | // Initialize data array for publisher | |
− | + | std_msgs::Int16MultiArray data_array; | |
− | + | data_array.layout.dim.push_back(std_msgs::MultiArrayDimension()); | |
− | + | data_array.layout.dim[0].label = "board-" + to_string(board) + " AIN"; | |
− | + | data_array.layout.dim[0].size = 16; | |
+ | data_array.layout.dim[0].stride = 1; | ||
+ | data_array.layout.data_offset = 0; | ||
+ | |||
+ | // Configure adc and start it running. | ||
+ | for (slot = 0; slot < 16, slot++ ) // Configure slots: chan = slot number, settle time = 20 us, range = +/-10 V | ||
+ | X826(S826_AdcSlotConfigWrite(board, slot, slot, 20, S826_ADC_GAIN_1)); | ||
+ | X826(S826_AdcSlotlistWrite(board, 0xFFFF, S826_BITWRITE)); // Enable all slots. | ||
+ | X826(S826_AdcTrigModeWrite(board, 0)); // Select continuous trigger mode. | ||
+ | X826(S826_AdcEnableWrite(board, 1)); // Start conversions. | ||
− | + | ROS_INFO("\tPublishing AIN Channels"); | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ros::Rate loop_rate(10); | |
− | + | ||
− | + | while (ros::ok()) | |
− | + | { | |
− | + | // Wait for next publish time. This is at top of loop so first ADC burst will complete before we try to read the data. | |
− | + | // Otherwise we might get bogus data the first time through the loop. | |
− | + | loop_rate.sleep(); | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | // Fetch ADC data | |
− | + | data_array.data.clear(); | |
− | + | slotlist = 0xFFFF; // from all 16 slots | |
+ | errcode = S826_AdcRead(board, adcbuf, NULL, &slotlist, 0); | ||
− | + | // Handle errors | |
− | + | if ((errcode != S826_ERR_OK) && (errcode != S826_ERR_MISSEDTRIG)) { // this app doesn't care about adc missed triggers | |
− | + | printf("\nERROR: %d\n", errcode); | |
− | + | break; | |
+ | } | ||
− | + | // Publish ADC data | |
− | + | for (slot = 0; slot < 16; slot++) { | |
− | + | // Publishing raw data (16-bit signed int). Convert to +/-10V by multiplying by 10/32768. | |
− | + | // example: cout << (double)(data_array.data[i] * 10) / 32768 << endl; | |
− | + | data_array.data.push_back((short)(adcbuf[slot] & 0xFFFF)); | |
− | + | } | |
− | + | analog_input_pub.publish(data_array); | |
− | + | } | |
− | + | S826_AdcEnableWrite(board, 0); // Halt conversions. | |
− | + | return errcode; | |
} | } | ||
− | === | + | ===Resources for custom driver development=== |
− | + | [[File:826 software stack.png|thumb|300px|826 software stack. The generic API is portable — to port, simply adapt the Linux driver and HAL for your OS/RTOS.]] | |
+ | :''I want to develop my own device driver for the 826. Does Sensoray offer any resources for custom driver development?'' | ||
− | + | Yes, we provide these resources free of charge: | |
− | + | * '''Linux Software Development Kit (SDK)''' - Includes source code for the 826 driver, hardware abstraction layer (HAL) and API middleware, comprising a complete 826 software stack for Linux. The generic API is operating system independent and thread-safe, which makes this SDK a great starting point for porting to any operating system. The stack has been carefully designed for reliable operation in and for easy porting to real-time operating systems. The SDK can be found on the Downloads tab of the [http://www.sensoray.com/products/826.htm 826 product page]. | |
+ | * '''Model 826 Technical Manual''' - This comprehensive manual explains the API and 826 hardware in detail (download from the Documentation tab of the [http://www.sensoray.com/products/826.htm 826 product page]). | ||
+ | * '''Register Map''' - A map of the board's hardware registers is available [http://www.sensoray.com/downloads/man_826_register_map.pdf here]. The registers are accessed through PCI BAR 2. Registers appear in both banked and flat address spaces. The banked space is only required for rev 0 boards; you should use the flat space exclusively if you have a later rev, as this will yield superior performance. | ||
− | + | ===Software updates=== | |
− | + | ||
− | + | 1. Windows 3.3.4 | |
+ | * C# demo application added to SDK. Error checking for invalid modes to S826_CounterModeWrite. | ||
+ | 2. Linux 3.3.5 | ||
+ | * C# GUI demo available, using Linux mono. | ||
− | === | + | ===Windows=== |
− | + | ====Custom installation and re-distribution==== | |
− | + | Sensoray's installer uses the Nullsoft Scriptable Install System ([https://en.wikipedia.org/wiki/Nullsoft_Scriptable_Install_System NSIS]). It is created from a .NSI script. The core API is installed as follows in NSI script code: | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
Section "Core API" | Section "Core API" | ||
Line 838: | Line 318: | ||
${EndIf} | ${EndIf} | ||
SectionEnd | SectionEnd | ||
− | |||
The drivers are installed via dpinst.exe in the NSI script as follows: | The drivers are installed via dpinst.exe in the NSI script as follows: | ||
Line 892: | Line 371: | ||
Yes, the full script is available [http://www.sensoray.com/wiki/index.php?title=826_NSIS_Install_Script here]. | Yes, the full script is available [http://www.sensoray.com/wiki/index.php?title=826_NSIS_Install_Script here]. | ||
− | ===Silent install | + | ====Silent install==== |
− | :''I want to run the installer silently. | + | |
+ | :''I want to run the installer silently. Do you have any way to do this?'' | ||
There are many options. For re-distribution, you may create your own installation package. Also, starting with version 3.3.9, there are additional command line options to quiet the setup.exe installer from command line or batch file. These options are described below. | There are many options. For re-distribution, you may create your own installation package. Also, starting with version 3.3.9, there are additional command line options to quiet the setup.exe installer from command line or batch file. These options are described below. | ||
Line 921: | Line 401: | ||
One work-around is to launch the setup in an Windows Command Prompt Window started in administrator mode (right-click and select "Run As Administrator"). Another approach is to launch the setup as a user with administrator privileges. User access control may also be disabled, but we do not recommend this for security reasons. | One work-around is to launch the setup in an Windows Command Prompt Window started in administrator mode (right-click and select "Run As Administrator"). Another approach is to launch the setup as a user with administrator privileges. User access control may also be disabled, but we do not recommend this for security reasons. | ||
− | === | + | ====Link error==== |
− | + | :''I'm using VisualStudio (VS) on a 64-bit machine to build a 32-bit application for the 826. VS reports that linking failed because it can't open s826.lib. What could be the problem?'' | |
− | + | You should use the 32-bit DLL (and its associated LIB) because you are building a 32-bit application (x86). Use the 64-bit version only when building 64-bit apps (x64). To avoid confusion, you can copy the 32-bit DLL and its associated LIB file from the install directory to your project directory, then point the linker to it there. Make sure to also point the debugger to the 32-bit DLL by setting its working directory. | |
− | + | Note: You will always use the 64-bit driver on a 64-bit OS regardless of 32/64-bit application type, but you don't need to select this as it is automatically installed by the SDK installer. | |
− | + | ====Windows 10 IoT==== | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | Sensoray has created a Universal driver (UD) for the 826 under OneCoreUAP-based editions of Windows. It is similar to the standard driver, but compiled as [https://docs.microsoft.com/en-us/windows-hardware/drivers/what-s-new-in-driver-development#universal-windows-drivers Universal]. This driver is in our SDK zip file under the "driver/sensoray_826_universal_driver" directory. Installation may be dependent on the specific Windows version. The inf is Windows Universal compatible. Sensoray does not currently have a demonstration Universal Windows App for the 826, but the .NET demo app may be portable. | |
− | + | ===Linux=== | |
− | + | ====Linux versions==== | |
− | + | :''Do you recommend specific Linux distributions for use with the 826?'' | |
− | + | ||
− | + | ||
− | + | We no longer support the obsolete kernel 2.4, but otherwise have no specific recommendation as it depends on the application (e.g., it might be desirable to use a low-latency kernel). The 826 driver is compatible with kernel versions 2.6 and higher. | |
− | + | ====Troubleshooting==== | |
− | + | :''The board worked yesterday but it doesn't work today. I didn't change anything. What could be the problem?'' | |
− | + | It's likely that the operating system upgraded the Linux kernel during an automatic update. See [[Linux Troubleshooting|this appnote]] for details. | |
− | + | ====Build errors==== | |
− | + | On some Linux distributions, "<code>sudo make install</code>" may issue messages like these: | |
− | + | * <code>modprobe: ERROR: could not insert 's826': Required key not available</code> | |
+ | * <code>SSL error:02001002:system library:fopen:No such file or directory: ../crypto/bio/bss_file.c</code> | ||
− | + | In such cases, it's likely that the 826 driver successfully installed and you are simply seeing a warning. You can confirm this by trying "<code>sudo modprobe s826</code>" and the 826 demo application. | |
− | + | =====Different gcc version===== | |
− | + | ''Why do I get the following error when building the demo?" | |
− | + | relocation R_X86_64_32S against `.bss' can not be used when making a PIE object; recompile with -fPIE | |
− | : | + | Answer: You have a newer version of gcc, so you must rebuild the middleware. To do this, switch to the SDK downloads directory and then: |
+ | * call "make lib" | ||
+ | * cd to middleware directory: "cd middleware" | ||
+ | * "cp *.a ../demo/" | ||
+ | * "cd .." | ||
− | + | Now rebuild the demo with the new .a files: | |
+ | * "make -C demo s826demo" | ||
− | + | ==Remote access== | |
+ | |||
+ | :''Is there any way to use an 826 with a laptop?'' | ||
+ | |||
+ | Not directly, because laptops don't provide exposed PCI Express slots. However, it is possible to locate the 826 in a host computer that does have PCIe slots and, with appropriate software, remotely access its interfaces from a laptop (e.g., via Ethernet or USB). | ||
+ | |||
+ | When designing such a system, it's important to consider that neither Ethernet nor USB are capable of real-time communication with register-based measurement and control hardware. Consequently, depending on the application, this may require the host to offload time-critical I/O functions from the laptop, such as interrupt handling, counter FIFO processing, and low-level register I/O sequences, in order to achieve real-time performance. | ||
+ | |||
+ | Functions that are not time-critical can be implemented in various ways. For example, the host computer could run a SNMP agent process that serves as a bridge between Ethernet and the 826. To do this, you will need to create a MIB and implement the associated functions in the agent. | ||
+ | |||
+ | ==Environmental specifications== | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! style="text-align:left;"| Parameter | ||
+ | ! style="text-align:left;"| Value | ||
+ | |- | ||
+ | |Pressure, operating | ||
+ | |650 to 1010 hPa | ||
+ | |- | ||
+ | |Humidity, operating | ||
+ | |20% to 80% RH, non-condensing | ||
+ | |} | ||
==Migrating from model 626== | ==Migrating from model 626== | ||
− | + | For users who are upgrading PCI systems to PCIe, we recommend model 826 as a replacement for model 626. | |
− | + | ===Porting guide=== | |
− | The | + | A migration aid is available to help C developers port applications to model 826. The aid consists of C code which provides, when feasible, equivalent 826 API calls for 626 API functions. In cases where equivalent functions are not available, compiler errors and runtime warnings are issued, and tips are given for resolving porting issues. |
+ | |||
+ | * [http://www.sensoray.com/downloads/port626.zip 626-to-826 migration aid] | ||
+ | |||
+ | ===Differences between models 626 and 826=== | ||
+ | |||
+ | The following table compares the interfaces on the two boards: | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! Interface | ||
+ | ! 626 | ||
+ | ! 826 | ||
+ | |- | ||
+ | | System bus | ||
+ | | PCI | ||
+ | | PCI Express | ||
+ | |- | ||
+ | | Counters | ||
+ | | 6 channels (3 A/B pairs)<br>24-bit resolution<br>24-bit sampling latch | ||
+ | | 6 channels (identical)<br>32-bit resolution<br>16-deep FIFO with timestamps | ||
+ | |- | ||
+ | | GPIOs | ||
+ | | 48 channels<br>40 w/edge detection (1 Msps)<br>no debounce<br>not fail-safe | ||
+ | | 48 channels<br>48 w/edge detection (50 Msps)<br>debounce filter<br>fail-safe outputs | ||
+ | |- | ||
+ | | Analog out | ||
+ | | 4 channels<br>14-bit resolution<br>20 Ksps<br>not fail-safe | ||
+ | | 8 channels<br>16-bit resolution<br>900 Ksps<br>fail-safe outputs | ||
+ | |- | ||
+ | | Analog in | ||
+ | | 16 channels<br>16-bit resolution<br>15 Ksps | ||
+ | | 16 channels<br>16-bit resolution<br>300 Ksps | ||
+ | |- | ||
+ | | Watchdog timer | ||
+ | | Single stage<br>4 shunt-selectable intervals | ||
+ | | 3 timer stages<br>software programmable intervals | ||
+ | |- | ||
+ | | Fail-safe controller | ||
+ | | n/a | ||
+ | | Integrated | ||
+ | |- | ||
+ | | Timestamp generator | ||
+ | | n/a | ||
+ | | 32 bits, 1 µs resolution | ||
+ | |} | ||
===Connector pinout differences=== | ===Connector pinout differences=== | ||
− | :''Do | + | :''Do models 826 and 626 have the same connectors and pinouts?'' |
− | + | Both boards have identical connector types, and all connector pinouts are identical except for analog connector J1. Model 826 has four additional analog outputs (channels 4-7) on pins 41, 43, 45 and 47. Model 626 uses these pins as remote sense inputs for analog output channels 0-3. | |
+ | [[File:826 vs 626 pinouts.gif|left|350px]] | ||
+ | {{Clear}} | ||
− | == | + | ===Software differences=== |
− | + | ;Driver and API | |
+ | Models 826 and 626 use different device drivers and APIs. The driver and API for each model is exclusive to that model and is not compatible with the other model. The drivers and APIs are necessarily different due to the expanded capabilities of model 826 and to significant hardware architecture differences between the two models. In addition, the 826 API provides blocking functions to simplify development of both event-driven and polling applications. | ||
+ | ;Application code | ||
+ | Since the APIs are different, it is necessary to revise application code when upgrading to model 826. Numerous examples can be found in this wiki to help in that endeavor. Also, consider using our [http://www.sensoray.com/downloads/port626.zip 626-to-826 migration aid] for C developers who are moving 626 applications to model 826. | ||
+ | |||
+ | ===Using 626 cables with the 826=== | ||
+ | |||
+ | :''I have a 7505TDIN breakout board and 7501C1 (50-pin cable) for the 626. Can I use these with the 826?'' | ||
+ | |||
+ | The 7505TDIN and 7501C are both compatible with the 826. However, we recommend using an 826C2 cable instead of the 7501C because it has a low profile header at one end that results in a denser cable stackup. That said, the 7501C cable can be used if it doesn't cause mechanical interference in your system. | ||
− | [[Category: | + | [[Category:826| ]] |
Latest revision as of 08:18, 15 February 2022
This is the top-level wiki page for Sensoray's model 826, a versatile analog and digital I/O system on a PCI Express board. The board has 48 digital I/Os with edge detection, sixteen 16-bit analog inputs, eight 16-bit analog outputs, six 32-bit counter channels with quadrature clock decoders, three-stage watchdog timer with fail-safe controller, and a flexible signal router.
- Related pages
Each board subsystem has a dedicated wiki page:
- ADC - analog input system
- DACs - analog output system
- DIOs - general-purpose digital I/Os
- Counters - counter/timers, including appnotes for interfacing incremental encoders
- Watchdog - watchdog timer and fail-safe controller
- Please note
- Code and circuit examples are intended to function as described, but this is not guaranteed. If you discover an error, please inform the webmaster.
- In code examples, error checking has been simplified or omitted for clarity. It is recommended to always perform error checking in your production software.
- C language examples depend on header file
826api.h
, which should be included at the top of your source code like this:
#include "826api.h"
Contents
|
[edit] Timestamp generator
The timestamp generator is a free-running 32-bit counter that serves as a time reference. The counter increments once per microsecond and overflows (to zero, without notification) every 232 µs (approximately 71.6 minutes). It is a binary counter and consequently does not keep track of the date or time-of-day. At any moment, the current count may be sampled; such a sample is called a timestamp.
A timestamp is automatically appended to every counter snapshot and to every ADC sample so that application programs can know (to within 1 µs) when each sample was acquired. Also, application programs can read the timestamp generator at any time to get a timestamp.
[edit] Usage
Timestamps are particularly useful for precisely measuring the elapsed time between hardware events. Calculation of elapsed time is easy (a single subtraction) as long as the time interval doesn't exceed 71.6 minutes. It can be used in a variety of ways, including measuring speed and capturing serial data.
If desired, an application program can directly read the current time as shown below:
// Read the timestamp generator's current count. uint CurrentTimestamp(uint board) { uint t; S826_TimestampRead(board, &t); return t; }
The following example shows a simple application of direct timestamp reads:
// Example: Use board0 to measure system Sleep() time. uint t1, t0 = CurrentTimestamp(0); // Get start time. Sleep(25); // Sleep approximately 25 ms. t1 = CurrentTimestamp(0); // Get end time. printf("Slept %d µs", t1 - t0); // Display actual sleep time.
[edit] Board ID
The "BOARD NUM" switches (at top edge of board near mounting bracket) assign the board ID used by software. The ID is binary coded on the four switches and can be programmed to any value from 0 (default) to 15. A board's ID determines the corresponding bit that will be set to '1' in the value returned by S826_SystemOpen
. If you have a single 826 board, the return value will be (2^ID)
. If you have multiple boards, the return value is the sum of (2^ID)
for each board. You can enter the return value here to quickly determine its meaning.
- Examples
- You have one board with ID set to 0, so the value returned by
S826_SystemOpen
will be(2^0) = 1
. - You have two boards with IDs set to 1 and 4, so the value returned by
S826_SystemOpen
will be(2^1)+(2^4) = 2+16 = 18
.
This code snippet will tell you the meaning of the value returned by S826_SystemOpen
:
int id, flags = S826_SystemOpen(); if (flags < 0) printf("S826_SystemOpen returned error code %d", flags); else if (flags == 0) printf("No boards were detected"); else { printf("Boards were detected with these IDs:"); for (id = 0; id < 16; id++) { if (flags & (1 << id)) printf(" %d", id); } }
[edit] Hardware version
[edit] Reading the PWB revision
The circuit board revision (PWB rev) is visible on the solder-side of the 826 board (opposite the mounting bracket, on the bottom corner). S826_VersionRead
returns the PWB rev as a numeric value with decimal range [0:31], which corresponds to a text string in the standard ASME version letter sequence. The following code shows how to convert this 32-bit value to the alphabetic revision code seen on the board:
// Read and display version info from board 0 // Extract major_version, minor_version and build_number from a 32-bit version number: #define VER_FIELDS(N) ((N) >> 24) & 0xFF, ((N) >> 16) & 0xFF, (N) & 0xFFFF const char *revchar[] = { // ASME revision sequence "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R", "T", "U", "V", "W", "Y", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AJ", "AK", "AL", "AM" }; uint api, drv, bd, fpga; int errcode = S826_VersionRead(0, &api, &drv, &bd, &fpga); // Read version info. if (errcode == S826_ERR_OK) { // If no errors then display info: printf("API version = %d.%d.%d\n", VER_FIELDS(api)); // API major.minor.build printf("Driver version = %d.%d.%d\n", VER_FIELDS(drv)); // DRVR major.minor.build printf("FPGA version = %d.%d.%d\n", VER_FIELDS(fpga)); // FPGA major.minor.build printf("PWB revision = Rev %s\n", revchar[bd & 31]); // PWB rev as seen on circuit board } else printf(" S826_VersionRead returned error code %d", errcode);
[edit] Rev C changes
Sensoray has developed Revision C of the 826 circuit board. This change was necessary due to the impending EOL (end-of-life) of a critical component. Specifically, the critical component (PCI Express interface chip) and FPGA were removed and replaced by a new FPGA, which absorbed the functions of the two removed components.
Applications and developers are not affected by this change
The Rev C board is fully compatible with Rev B boards and applications:
- Mechanical attributes are unchanged, including board dimensions and placements of connectors, switches, indicator LEDs, and hold-down bracket.
- Connector pinouts, electrical and timing specifications are unchanged.
- Rev C is 100% software compatible with Rev B on all software layers: application, API and driver (including user-developed drivers and APIs for RTOS, etc.).
Rev B and Rev C boards can be used interchangeably in new and existing applications. From an application's perspective, the only detectable differences between Rev B and Rev C boards are the version numbers returned by the API function S826_VersionRead():
- S826_VersionRead() will report the PWB version as Rev B or Rev C as appropriate for the board's hardware version.
- S826_VersionRead() will report FPGA version 0.0.70 or higher for Rev C boards, or version 0.0.69 or lower for Rev B boards.
[edit] Connector pinouts
The following drawings show the pinouts of the board's header connectors as viewed from the top (component) side of the circuit board:
[edit] Software
[edit] C examples
A variety of C programming examples have been collected together in a common source file to illustrate how to program resources on the 826.
[edit] VB.NET demo
To help you jump-start your project, we offer the VB.NET demo for model 826. This demo program provides a pre-built Windows executable with a GUI for nearly every hardware resource on the board. All source files are provided, along with a VisualStudio project.
[edit] Programming in C#
Each 826 SDK includes a C# demo application. These demos show how to call API functions from C#, and can serve as a useful starting point for a custom application.
[edit] Linux demo
In the Linux SDK, a C# GUI demo is available which uses Linux mono. To get the required libraries on Ubuntu, type:
"sudo apt-get install mono-complete"
For a C# development environment, type:
"sudo apt-get install monodevelop"
[edit] Pointer arguments
Many of the API functions have pointer arguments. This is no problem for C#, which allows you to pass function arguments by reference. To see how this is done, consider the S826_AdcEnableRead
function:
The C prototype is:
int S826_AdcEnableRead(unsigned int board, unsigned int *enable);
So in C# you should declare the function this way:
[DllImport("s826.dll", CallingConvention = CallingConvention.StdCall)] static extern Int32 S826_AdcEnableRead(UInt32 board, ref UInt32 enable);
Now you can call the function this way:
Uint32 isEnabled; Int32 errcode = S826_AdcEnableRead(0, ref isEnabled);
[edit] Labview
Before running an 826 virtual instrument (VI) under Labview, make sure you install the latest versions of the 826 DLL (s826.dll) and device driver (both are contained in the 826 SDK, which you can obtain from the Downloads tab of the 826 product page).
Each VI is a basically a wrapper for a DLL function and consequently the VIs are dependent on the DLL, which in turn depends on the driver. Board hardware and firmware version numbers will be automatically read from the 826 board by software when all dependencies are satisfied -- it is not necessary to manually enter any board selection information except the board number, which is specified by the board's switch settings (factory default is board number 0).
The VIs are not independently documented, but since each VI wraps a DLL function, the DLL documentation effectively explains the function of each associated VI. The DLL documentation can be found in the 826 product manual (download from the 826 product page Documentation tab).
The VIs may be installed under Labview's instrument library (e.g., "instr.lib\Sensoray 826") or elsewhere if desired. Refer to Labview documentation for information about paths and other relevant topics.
[edit] Matlab
To use an 826 with Matlab you must first install the latest 64-bit versions of the 826 API (s826.dll) and device driver; these are both part of the 826 SDK, which you can obtain from the Downloads tab of the 826 product page. You may then use Matlab's loadlibrary()
function to enable access to the API, and calllib()
to call API functions. The API functions are described in the 826 product manual, which can be found on the 826 product page Documentation tab. The following example illustrates how this works.
Note: Matlab cannot execute loadlibrary()
unless a compatible C compiler is installed on your computer. If Matlab complains about an "Error using loadlibrary" because "No supported compiler was found" then you must download and install one of the Matlab-compatible compilers (e.g., MinGW-w64) to resolve this issue. Please consult Mathworks for a list of compatible compilers.
% Simple Matlab example: turn on general-purpose digital I/O 2 *************************** % Change these values as required: hdrPath = 'C:\Sensoray\826api.h'; % Path to API header dllPath = 'C:\Windows\System32\s826.dll'; % Path to API executable board = 0; % Use 826 board #0 (i.e., board w/ID switches set to 0) loadlibrary(dllPath, hdrPath, 'alias', 's826'); % Load the API. boardflags = calllib('s826', 'S826_SystemOpen'); % Open API and detect all boards. if (boardflags < 0) % If API failed to open disp("S826_SystemOpen error"); % Report error. else % Else if (boardflags ~= bitshift(1, board)) % If board #0 was not detected disp("Failed to detect 826 board"); % Report error (check board's switch settings). else % Else ... buf = libpointer('uint32Ptr', [6 0]); % Allocate buffer for DIO state data. errcode = calllib('s826', ... % Turn on DIO1 and DIO2. 'S826_DioOutputWrite', board, buf, 0); clear buf; % Free buffer. if (errcode ~= S826_ERR_OK) disp('DIO write problem') % Report error if DIO write failed. end end errcode = calllib('s826', 'S826_SystemClose'); % Close API. end unloadlibrary s826; % Unload the API.
[edit] Matlab SDK
Sensoray offers an open-source software development kit for Matlab programmers, which you can obtain from the Downloads tab of the 826 product page. The Matlab SDK includes two files:
-
s826.m
is a class that defines useful constants and provides wrappers for all 826 API functions. Include this file in any project that interacts with model 826 boards. -
s826_demo.m
is a short program that demonstrates how to use the s826 class.
[edit] ROS (Robot Operating System)
Sensoray SDKs do not include a ROS package, but the Linux SDK has everything needed to create one. The simplest way to use ROS with model 826 is to install the Linux 826 device driver and API (shared library), and then call the API functions as shown in the following example. Note that this example is coded in C++, but you can easily call the API functions from Python or any other language.
/////////////////////////////////////////////////////////////////////////////////////////////////////////// // Simple ROS (Robot Operating System) example for Sensoray 826 PCI Express analog/digital IO board. // Function: Publishes 16 analog inputs 10 times per second /////////////////////////////////////////////////////////////////////////////////////////////////////////// #define X826(func) if ((errcode = (func)) != S826_ERR_OK) { printf("\nERROR: %d\n", errcode); return; } // Call function and process error int PublishAINChannels() { int adcbuf[16]; // adc data buffer uint slotlist; // timeslot flags uint slot; // timeslot index (and ain channel number) uint board = 0; // board ID int errcode; // Initialize data array for publisher std_msgs::Int16MultiArray data_array; data_array.layout.dim.push_back(std_msgs::MultiArrayDimension()); data_array.layout.dim[0].label = "board-" + to_string(board) + " AIN"; data_array.layout.dim[0].size = 16; data_array.layout.dim[0].stride = 1; data_array.layout.data_offset = 0; // Configure adc and start it running. for (slot = 0; slot < 16, slot++ ) // Configure slots: chan = slot number, settle time = 20 us, range = +/-10 V X826(S826_AdcSlotConfigWrite(board, slot, slot, 20, S826_ADC_GAIN_1)); X826(S826_AdcSlotlistWrite(board, 0xFFFF, S826_BITWRITE)); // Enable all slots. X826(S826_AdcTrigModeWrite(board, 0)); // Select continuous trigger mode. X826(S826_AdcEnableWrite(board, 1)); // Start conversions. ROS_INFO("\tPublishing AIN Channels"); ros::Rate loop_rate(10); while (ros::ok()) { // Wait for next publish time. This is at top of loop so first ADC burst will complete before we try to read the data. // Otherwise we might get bogus data the first time through the loop. loop_rate.sleep(); // Fetch ADC data data_array.data.clear(); slotlist = 0xFFFF; // from all 16 slots errcode = S826_AdcRead(board, adcbuf, NULL, &slotlist, 0); // Handle errors if ((errcode != S826_ERR_OK) && (errcode != S826_ERR_MISSEDTRIG)) { // this app doesn't care about adc missed triggers printf("\nERROR: %d\n", errcode); break; } // Publish ADC data for (slot = 0; slot < 16; slot++) { // Publishing raw data (16-bit signed int). Convert to +/-10V by multiplying by 10/32768. // example: cout << (double)(data_array.data[i] * 10) / 32768 << endl; data_array.data.push_back((short)(adcbuf[slot] & 0xFFFF)); } analog_input_pub.publish(data_array); } S826_AdcEnableWrite(board, 0); // Halt conversions. return errcode; }
[edit] Resources for custom driver development
- I want to develop my own device driver for the 826. Does Sensoray offer any resources for custom driver development?
Yes, we provide these resources free of charge:
- Linux Software Development Kit (SDK) - Includes source code for the 826 driver, hardware abstraction layer (HAL) and API middleware, comprising a complete 826 software stack for Linux. The generic API is operating system independent and thread-safe, which makes this SDK a great starting point for porting to any operating system. The stack has been carefully designed for reliable operation in and for easy porting to real-time operating systems. The SDK can be found on the Downloads tab of the 826 product page.
- Model 826 Technical Manual - This comprehensive manual explains the API and 826 hardware in detail (download from the Documentation tab of the 826 product page).
- Register Map - A map of the board's hardware registers is available here. The registers are accessed through PCI BAR 2. Registers appear in both banked and flat address spaces. The banked space is only required for rev 0 boards; you should use the flat space exclusively if you have a later rev, as this will yield superior performance.
[edit] Software updates
1. Windows 3.3.4
- C# demo application added to SDK. Error checking for invalid modes to S826_CounterModeWrite.
2. Linux 3.3.5
- C# GUI demo available, using Linux mono.
[edit] Windows
[edit] Custom installation and re-distribution
Sensoray's installer uses the Nullsoft Scriptable Install System (NSIS). It is created from a .NSI script. The core API is installed as follows in NSI script code:
Section "Core API" SectionIn RO ${If} ${RunningX64} SetOutPath "$WINDIR\system32"; !insertmacro DisableX64FSRedirection File "..\mid-826\code\Release64\s826.dll"; !insertmacro EnableX64FSRedirection SetOutPath "$WINDIR\SysWOW64"; File "..\mid-826\code\Release\s826.dll"; ${Else} SetOutPath "$WINDIR\system32"; File "..\mid-826\code\Release\s826.dll"; ${EndIf} SectionEnd
The drivers are installed via dpinst.exe in the NSI script as follows:
Section "Drivers" SectionIn RO CreateDirectory "$INSTDIR\driver\x64"; SetOutPath "$INSTDIR\driver\x64"; File "..\cd\driver\x64\dpinst.exe"; File "..\cd\driver\x64\s826.cat"; File "..\cd\driver\x64\s826.inf"; File "..\cd\driver\x64\s826.sys"; File "..\cd\driver\x64\s826filter.cat"; File "..\cd\driver\x64\s826filter.inf"; File "..\cd\driver\x64\s826filter.sys"; File "..\cd\driver\x64\WdfCoInstaller01009.dll"; CreateDirectory "$INSTDIR\driver\x32"; SetOutPath "$INSTDIR\driver\x32"; File "..\cd\driver\x32\dpinst.exe"; File "..\cd\driver\x32\s826.cat"; File "..\cd\driver\x32\s826.inf"; File "..\cd\driver\x32\s826.sys"; File "..\cd\driver\x32\s826filter.cat"; File "..\cd\driver\x32\s826filter.inf"; File "..\cd\driver\x32\s826filter.sys"; File "..\cd\driver\x32\WdfCoInstaller01009.dll"; MessageBox MB_OK "Driver installation dialog will pop-up. Follow the prompts and click Finish when done" ${If} ${RunningX64} ExecWait '"$INSTDIR\driver\x64\dpinst.exe" /f' ${Else} ExecWait '"$INSTDIR\driver\x32\dpinst.exe" /f' ${EndIf} NoInstallDriver: SectionEnd
- What other libraries does the installer install as part of the Core API?
The 826 is compiled with Microsoft Visual Studio C++ 2008. The re-distributables for C++ must be installed. The installer installs this library silently running the command:
"vcredist_x86.exe /q"
and the following additional command on 64-bit systems:
"vcredist_x64.exe /q"
These re-distributables are available from Microsoft for x64 and x86.
- Are any other libraries required? I installed the libraries above, but the demo doesn't work with my custom installer?
The demo is written using .NET libraries (version 3.5). These are also available from Microsoft here. The executable can be silently installed using this command:
"dotnetfx35setup.exe /qb"
- Could I obtain the full 826 NSI script as a template for creating my own installer?
Yes, the full script is available here.
[edit] Silent install
- I want to run the installer silently. Do you have any way to do this?
There are many options. For re-distribution, you may create your own installation package. Also, starting with version 3.3.9, there are additional command line options to quiet the setup.exe installer from command line or batch file. These options are described below.
- What are the options for silent install?
The basic silent install is invoked by running the following command from command line or batch script:
"setup.exe /S"
Please note that the /S is case sensitive and must be upper case.
- I've pre-installed the drivers and don't want to re-install them during the installation? Is there a command for that?
"setup.exe /S /no_driver=1"
- Is there an additional command to not install the demo programs?
Yes, in version 3.3.9, the following command will install the required DLLs and system libraries, but no drivers or demo programs.
"setup.exe /S /no_driver=1 /no_demos=1"
- I want to install the drivers silently, but there is always a pop-up to verify.
Unfortunately, there is no way around this. Windows requires confirmation from the user for driver install, even if the driver is signed.
- I'm running the setup silently, but it pops up a dialog to confirm if I want to make changes to the PC (User Account Control). How do I prevent this?
Windows controls this through User Access Control. If running the setup from a standard windows console, the Windows User Account Control (UAC) will pop-up. This cannot be by-passed by Sensoray because the installer installs files to system directories.
One work-around is to launch the setup in an Windows Command Prompt Window started in administrator mode (right-click and select "Run As Administrator"). Another approach is to launch the setup as a user with administrator privileges. User access control may also be disabled, but we do not recommend this for security reasons.
[edit] Link error
- I'm using VisualStudio (VS) on a 64-bit machine to build a 32-bit application for the 826. VS reports that linking failed because it can't open s826.lib. What could be the problem?
You should use the 32-bit DLL (and its associated LIB) because you are building a 32-bit application (x86). Use the 64-bit version only when building 64-bit apps (x64). To avoid confusion, you can copy the 32-bit DLL and its associated LIB file from the install directory to your project directory, then point the linker to it there. Make sure to also point the debugger to the 32-bit DLL by setting its working directory.
Note: You will always use the 64-bit driver on a 64-bit OS regardless of 32/64-bit application type, but you don't need to select this as it is automatically installed by the SDK installer.
[edit] Windows 10 IoT
Sensoray has created a Universal driver (UD) for the 826 under OneCoreUAP-based editions of Windows. It is similar to the standard driver, but compiled as Universal. This driver is in our SDK zip file under the "driver/sensoray_826_universal_driver" directory. Installation may be dependent on the specific Windows version. The inf is Windows Universal compatible. Sensoray does not currently have a demonstration Universal Windows App for the 826, but the .NET demo app may be portable.
[edit] Linux
[edit] Linux versions
- Do you recommend specific Linux distributions for use with the 826?
We no longer support the obsolete kernel 2.4, but otherwise have no specific recommendation as it depends on the application (e.g., it might be desirable to use a low-latency kernel). The 826 driver is compatible with kernel versions 2.6 and higher.
[edit] Troubleshooting
- The board worked yesterday but it doesn't work today. I didn't change anything. What could be the problem?
It's likely that the operating system upgraded the Linux kernel during an automatic update. See this appnote for details.
[edit] Build errors
On some Linux distributions, "sudo make install
" may issue messages like these:
-
modprobe: ERROR: could not insert 's826': Required key not available
-
SSL error:02001002:system library:fopen:No such file or directory: ../crypto/bio/bss_file.c
In such cases, it's likely that the 826 driver successfully installed and you are simply seeing a warning. You can confirm this by trying "sudo modprobe s826
" and the 826 demo application.
[edit] Different gcc version
Why do I get the following error when building the demo?"
relocation R_X86_64_32S against `.bss' can not be used when making a PIE object; recompile with -fPIE
Answer: You have a newer version of gcc, so you must rebuild the middleware. To do this, switch to the SDK downloads directory and then:
- call "make lib"
- cd to middleware directory: "cd middleware"
- "cp *.a ../demo/"
- "cd .."
Now rebuild the demo with the new .a files:
- "make -C demo s826demo"
[edit] Remote access
- Is there any way to use an 826 with a laptop?
Not directly, because laptops don't provide exposed PCI Express slots. However, it is possible to locate the 826 in a host computer that does have PCIe slots and, with appropriate software, remotely access its interfaces from a laptop (e.g., via Ethernet or USB).
When designing such a system, it's important to consider that neither Ethernet nor USB are capable of real-time communication with register-based measurement and control hardware. Consequently, depending on the application, this may require the host to offload time-critical I/O functions from the laptop, such as interrupt handling, counter FIFO processing, and low-level register I/O sequences, in order to achieve real-time performance.
Functions that are not time-critical can be implemented in various ways. For example, the host computer could run a SNMP agent process that serves as a bridge between Ethernet and the 826. To do this, you will need to create a MIB and implement the associated functions in the agent.
[edit] Environmental specifications
Parameter | Value |
---|---|
Pressure, operating | 650 to 1010 hPa |
Humidity, operating | 20% to 80% RH, non-condensing |
[edit] Migrating from model 626
For users who are upgrading PCI systems to PCIe, we recommend model 826 as a replacement for model 626.
[edit] Porting guide
A migration aid is available to help C developers port applications to model 826. The aid consists of C code which provides, when feasible, equivalent 826 API calls for 626 API functions. In cases where equivalent functions are not available, compiler errors and runtime warnings are issued, and tips are given for resolving porting issues.
[edit] Differences between models 626 and 826
The following table compares the interfaces on the two boards:
Interface | 626 | 826 |
---|---|---|
System bus | PCI | PCI Express |
Counters | 6 channels (3 A/B pairs) 24-bit resolution 24-bit sampling latch |
6 channels (identical) 32-bit resolution 16-deep FIFO with timestamps |
GPIOs | 48 channels 40 w/edge detection (1 Msps) no debounce not fail-safe |
48 channels 48 w/edge detection (50 Msps) debounce filter fail-safe outputs |
Analog out | 4 channels 14-bit resolution 20 Ksps not fail-safe |
8 channels 16-bit resolution 900 Ksps fail-safe outputs |
Analog in | 16 channels 16-bit resolution 15 Ksps |
16 channels 16-bit resolution 300 Ksps |
Watchdog timer | Single stage 4 shunt-selectable intervals |
3 timer stages software programmable intervals |
Fail-safe controller | n/a | Integrated |
Timestamp generator | n/a | 32 bits, 1 µs resolution |
[edit] Connector pinout differences
- Do models 826 and 626 have the same connectors and pinouts?
Both boards have identical connector types, and all connector pinouts are identical except for analog connector J1. Model 826 has four additional analog outputs (channels 4-7) on pins 41, 43, 45 and 47. Model 626 uses these pins as remote sense inputs for analog output channels 0-3.
[edit] Software differences
- Driver and API
Models 826 and 626 use different device drivers and APIs. The driver and API for each model is exclusive to that model and is not compatible with the other model. The drivers and APIs are necessarily different due to the expanded capabilities of model 826 and to significant hardware architecture differences between the two models. In addition, the 826 API provides blocking functions to simplify development of both event-driven and polling applications.
- Application code
Since the APIs are different, it is necessary to revise application code when upgrading to model 826. Numerous examples can be found in this wiki to help in that endeavor. Also, consider using our 626-to-826 migration aid for C developers who are moving 626 applications to model 826.
[edit] Using 626 cables with the 826
- I have a 7505TDIN breakout board and 7501C1 (50-pin cable) for the 626. Can I use these with the 826?
The 7505TDIN and 7501C are both compatible with the 826. However, we recommend using an 826C2 cable instead of the 7501C because it has a low profile header at one end that results in a denser cable stackup. That said, the 7501C cable can be used if it doesn't cause mechanical interference in your system.