Difference between revisions of "826"

From Sensoray Technical Wiki
Jump to: navigation, search
(Silent Install (Windows))
(Software)
Line 490: Line 490:
  
 
===Custom Installation and Re-distribution (Windows)===
 
===Custom Installation and Re-distribution (Windows)===
Sensoray's installer uses the NSIS installation system.  It is created from a .NSI script.  The core API is installed as follows:
+
Sensoray's installer uses the NSIS installation system.  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 555: Line 555:
 
The demo is written using .NET libraries (version 3.5). These are also available from Microsoft https://www.microsoft.com/en-us/download/details.aspx?id=25150.  The executable can be silently installed using this command:
 
The demo is written using .NET libraries (version 3.5). These are also available from Microsoft https://www.microsoft.com/en-us/download/details.aspx?id=25150.  The executable can be silently installed using this command:
 
  "dotnetfx35setup.exe /qb"
 
  "dotnetfx35setup.exe /qb"
 
 
 
  
  
Line 563: Line 560:
 
:''I want to run the installer silently.  Do you have any way to do this?''
 
:''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.  Starting with version 3.3.9, there are additional command line options to quiet the installation.
+
There are many options.  For re-distribution, you may create your own installation package.  Starting with version 3.3.9, there are additional command line options to quiet the setup.exe installater from command line or batch file.
  
 
:''What are the options for silent install?''
 
:''What are the options for silent install?''
Line 576: Line 573:
  
 
:''Is there an additional command to not install the demo programs?''
 
:''Is there an additional command to not install the demo programs?''
Yes, in version 3.3.9, the following command will install just the required DLLs and system libraries.
+
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 /no_demos"
 
  "setup.exe /S /no_driver /no_demos"
  
Line 583: Line 580:
 
Unfortunately, there is no way around this.  Windows requires confirmation from the user for driver install, even if the driver is signed.
 
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. How do I prevent this?''
+
:''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.
  
If running the setup from a standard windows console, the Windows User Account Control (UAC) will pop-up.  This is part of Windows security and cannot by by-passed by Sensoray as the installer must install to system directors.  The installer is signed and one way to avoid the pop-up is to launch the setup from command line in a Windows Command Prompt Window started in administrator mode. Another approach is launching the setup silently from an user with administrator privileges.
 
  
 
===Labview===
 
===Labview===

Revision as of 15:47, 17 June 2016

Model 826 board

Sensoray's model 826 is a versatile analog and digital I/O system on a PCI Express board. It has 48 digital I/Os with edge detection, sixteen 16-bit analog inputs, eight 16-bit analog outputs, six 32-bit counter channels, a watchdog timer with fail-safe controller, and a flexible signal router. The board's high performance, compact size, and abundant resources make it ideally suited for a wide range of measurement and control applications.

Contents

Counters

Snapshot counts upon match

When a snapshot is caused by counts equal to a compare register, the snapshot counts will always be equal to the compare register value.

How to use interrupts

I want to use interrupts to perform actions after a time delay. I see that counters have an "Interrupt System (IRQ)" signal but have no idea how to access it.

Every hardware IRQ is associated with a blocking API function. In the case of counter IRQs the function is S826_CounterSnapshotRead(). A counter IRQ is automatically generated when a counter snapshot is captured. The API has been designed to handle interrupts for you so that you need not be concerned with the complexities of interrupt handlers -- simply call the API function and IRQs will automatically be generated and handled.

A simple way to implement a delayed interrupt is to configure the counter to count down, preload the counter with the desired time delay, and have it capture a snapshot (and thus generate an IRQ) when it reaches zero counts. To wait for the interrupt, call S826_CounterSnapshotRead() with a non-zero tmax value (maximum wait time, which must be longer than the delay time). The function will return upon interrupt and you can then perform the desired actions. For example:

#include "826api.h"

// Wait 0.5 seconds while other threads are allowed to run ------------------

// Configure the delay timer:
S826_CounterModeWrite(0, 0, 0x01400020);      // Configure counter0: 1 MHz down counter, auto preload @startup.
S826_CounterPreloadWrite(0, 0, 0, 500000);    // Delay time in microseconds (0.5 seconds).
S826_CounterSnapshotConfigWrite(0, 0,         // Configure snapshots:
    S826_SSRMASK_ZERO                         //  capture snapshot when counts==0
    | (S826_SSRMASK_ZERO << 16),              //  disable subsequent snapshots when counts==0
    S826_BITSET);                             //  don't alter any other snapshot enables

// Now do the delay:
S826_CounterStateWrite(0, 0, 1);              // Start the delay timer running.
S826_CounterSnapshotRead(0, 0,                // Block while waiting for timer:
   NULL, NULL, NULL,                          //  ignore snapshot counts, timestamp and reason
   S826_WAIT_INFINITE);                       //  disable function timeout

printf("Delay time has elapsed!");            // TODO: INSERT YOUR DESIRED ACTIONS HERE

Note that your program cannot do anything else while it waits for S826_CounterSnapshotRead() to return. To get around this you can call the function in a separate thread so that while the thread is waiting for the interrupt, other threads can do productive work.

Periodic timer

How can I use a counter to call a function periodically?

Configure the counter so that it repeatedly counts down to zero and then preloads. The preload value determines the time period. A snapshot is captured every time zero counts is reached, which causes S826_CounterSnapshotRead() to return, whereupon you can call your periodic function.

#include "826api.h"

// Call PeriodicFunction() 10 times per second

S826_CounterModeWrite(0, 0, 0x01C02020);      // Counter0: 1 MHz down counter; preload @startup and counts==0.
S826_CounterPreloadWrite(0, 0, 0, 100000);    // Period in microseconds (0.1 seconds).
S826_CounterSnapshotConfigWrite(0, 0,         // Configure snapshots:
    S826_SSRMASK_ZERO,                        //  capture snapshot when counts==0
    S826_BITWRITE);                           //  disable all other snapshot triggers
S826_CounterStateWrite(0, 0, 1);              // Start the periodic timer running.

while (1) {                                   // Repeat forever:
  S826_CounterSnapshotRead(0, 0,              //   Block while waiting for elapsed period:
      NULL, NULL, NULL,                       //    ignore snapshot values
      S826_WAIT_INFINITE);                    //    disable function timeout
  PeriodicFunction();                         //   Execute the periodic function.
}

Programming incremental encoders

Basic operation

Which functions should I use for incremental encoders?

The flexible counter architecture allows for many options, but basic operation works as follows:

First configure and enable the counter channel:

#include "826api.h"

S826_CounterModeWrite(0, 0, 0x00000070);  // Configure counter 0 as incremental encoder interface.
S826_CounterStateWrite(0, 0, 1);          // Start tracking encoder counts.

To read the instantaneous encoder counts without invoking a snapshot:

uint counts;
S826_CounterRead(0, 0, &counts);          // Read current encoder counts.
printf("Encoder counts = %d\n", counts);  // Display encoder counts.

In some cases, when reading the instantaneous counts you may need to know when the counts were sampled. For example, two ordered pairs of (counts, time) are needed for speed measurement (dc/dt). You could rely on the determinism of your software and operating system to sample the counts at precise times, but there's an easier and much more accurate way: trigger a snapshot (via software command) and then read the counts and exact sample time (accurate to within one microsecond):

uint counts;      // encoder counts when the snapshot was captured
uint timestamp;   // time the snapshot was captured

S826_CounterSnapshot(0, 0);               // Trigger snapshot on counter 0.
S826_CounterSnapshotRead(0, 0,            // Read the snapshot:
    &counts, &timestamp, NULL,            //  receive the snapshot info here
    0);                                   //  no need to wait for snapshot; it's already been captured
printf("Counts = %d at time = %d\n", counts, timestamp);

The encoder counts can be changed to an arbitrary value at any time. This is typically done when the encoder is at a known reference position (e.g., at startup or whenever mechanical registration is required), but not at other times as it would disrupt position tracking. To change the counts, write the new counts value to the Preload0 register and then call S826_CounterPreload() to force a preload:

S826_CounterPreloadWrite(0, 0, 0, 12345); // Write desired counts value (12345) to Preload0 register.
S826_CounterPreload(0, 0, 0, 0);          // Jam Preload0 value into counter.

Using interrupts

This code snippet employs hardware interrupts to block the calling thread until the encoder counts equals a particular value. Other threads are allowed to run while the calling thread waits for the counter to reach the target value. A snapshot is captured when the target count is reached. The snapshot generates an interrupt request, which in turn causes S826_CounterSnapshotRead() to return. The example ignores the snapshot counts (which will always equal the target value), the timestamp, and the reason code (which will always indicate a Match0 event).

S826_CounterCompareWrite(0, 0, 0,         // Set Compare0 register to target value:
    5000);                                //  5000 counts (for this example)
S826_CounterSnapshotConfigWrite(0, 0,     // Enable snapshots:
    S826_SSRMASK_MATCH0,                  //  when counts==Compare0
    S826_BITWRITE);                       //  disable all other snapshot triggers
S826_CounterSnapshotRead(0, 0,            // Wait for counter to reach target counts:
    NULL, NULL, NULL,                     //  ignore snapshot counts, timestamp and reason
    S826_WAIT_INFINITE);                  //  disable function timeout
printf("Counter reached target counts");

In some cases you may want to wait for more than one counter event at the same time. This example shows how to wait for the encoder counts to reach an upper or lower limit (whichever occurs first). Furthermore, it will only wait for a limited amount of time. To set this up, the count limits are programmed into Compare registers and then snapshots are enabled for matches to both Compare registers. To set a limit on how long to wait, a time limit value is specified by tmax when calling S826_CounterSnapshotRead. Since a snapshot can be caused by different events, we must know what triggered a snapshot in order to decide how to handle it; this is indicated by the snapshot's reason flags.

uint counts;      // encoder counts when the snapshot was captured
uint timestamp;   // time the snapshot was captured
uint reason;      // event(s) that caused the snapshot
uint errcode;     // API error code

S826_CounterCompareWrite(0, 0, 0, 3000);  // Set Compare0 register to low limit (3000 counts)
S826_CounterCompareWrite(0, 0, 1, 4000);  // Set Compare1 register to high limit (4000 counts)
S826_CounterSnapshotConfigWrite(0, 0,     // Enable snapshots:
    S826_SSRMASK_MATCH0                   //  when counts==low limit
    | S826_SSRMASK_MATCH1,                //  or when counts==high limit
    S826_BITWRITE);                       //  disable all other snapshot triggers
errcode = S826_CounterSnapshotRead(0, 0,  // Wait for a snapshot:
    &counts, &timestamp, &reason,         //  receive the snapshot info here
    10000000);                            //  timeout if wait exceeds 10 seconds (10000000 us)

switch (errcode) {                        // Decode and handle the snapshot:
  case S826_ERR_NOTREADY:
    printf("Timeout -- counter didn't hit limits within 10 seconds; current counts = %d", counts);
    break;
  case S826_ERR_OK:
    if (reason & S826_SSRMASK_MATCH0)
      printf("Counter reached upper limit at timestamp %d", timestamp);
    if (reason & S826_SSRMASK_MATCH1)
      printf("Counter reached lower limit at timestamp %d", timestamp);
}

Output pulse every N encoder pulses

Can the 826 generate an output pulse every N shaft encoder pulses?

A short (20 ns) pulse can be generated with one counter ("counterA") and one general-purpose I/O (DIO). A longer output pulse can be generated with two counters ("counterA" and "counterB") and one DIO.

First, initialize the 826:

  • Configure counterA as an incremental encoder interface.
  • Configure counterA to capture snapshots upon Compare register matches.
  • Configure counterA's ExtOut mode (OM=1) to output a pulse upon Compare register match.
  • Case 1: Short output pulse:
    • Program the signal router to output counterA's ExtOut signal on the DIO. The pulse duration will be 20 ns and consequently an external pull-up must be added to the DIO to speed up the rising edge of the output pulse (see Using external pull-up resistors for details).
  • Case 2: Output pulse with programmable duration:
    • Configure counterB as a pulse generator, using counterA's ExtOut as a preload trigger. Program the preload counts to the desired pulse width.
    • Program the signal router to output counterB's ExtOut signal on the DIO.

After initializing, program counterA's Compare register with the encoder counts that are to trigger the next output pulse, then wait for a snapshot. When the counts matches the Compare register, a snapshot will be captured and the output pulse will automatically be generated. Upon receiving the snapshot, the application must write into the Compare register the counts corresponding to the next output pulse, before the counter reaches that value.

Unexpected snapshots

Why do I occasionally get two snapshots (upon counts match) from my incremental encoder when only one is expected?

Assuming your encoder has not changed direction, the unexpected snapshots are probably being triggered by noise or slow edges on the encoder clock signals. This is possible even when the snapshot timestamps are identical, because encoder clocks are sampled every 20 nanoseconds whereas timestamp counts are incremented only once per microsecond.

If this is what is happening, unexpected snapshots can be prevented by calling S826_CounterFilterWrite() to establish a clock filter. A small filter value is usually sufficient -- just enough to clean up clock edges, but not so long that valid encoder counts will be missed. For example, this will set the clock filter to 100 ns (index input will not be filtered):

#define FILT_NS    100                // Filter time in ns -- change as desired to multiple of 20.
#define FILT_RES   20                 // Filter resolution in nanoseconds.
#define FILT_CLK   (1 << 30)          // Bit flag to enable clock filtering.
S826_CounterFilterWrite(0, 0,         // Activate clock filter on counter 0.
    FILT_CLK + FILT_NS / FILT_RES);

Another way to handle this is to configure the Match snapshot trigger to become automatically disabled when it fires. Note that if you use this method, you will need to re-enable the Match trigger to capture snapshots of subsequent matches.

S826_CounterSnapshotConfigWrite(0, 5, // Configure snapshots on counter 5:
   S826_SSRMASK_MATCH0                //  enable snapshot upon Match0 (counts==Compare0 register)
   | (S826_SSRMASK_MATCH0 << 16),     //  disable subsequent Match0 snapshots upon Match0 
   S826_BITWRITE);                    //  disable all other snapshot triggers

ExtOut timing

What is the delay from input clock to ExtOut?

The input clock is sampled every 20 ns, so a clock edge is recognized 0 to 20 ns after the edge. The counts change 20 ns after the edge is recognized. ExtOut changes 20 ns after the counter transitions to zero (or match value). So, the delay from input clock edge to ExtOut edge is 40 to 60 ns.

Using external pull-up resistors

My PWM stops working when it outputs high frequencies. Why does this happen and how can I prevent it?

The PWM signal (from the counter's ExtOut) is output by a DIO channel, which drives the signal to 0 V in the on state and is high-impedance in the off state. In the off state, the channel's internal 10K ohm resistor pulls up the signal to +5 V. This resistance (combined with circuit capacitance) slows down the signal's rise time, which delays its transition to logic '1'. As the off time decreases, the delay time (which is constant) becomes a higher percentage of the off time. When the off time becomes too short (i.e., when delay equals or exceeds off time), the PWM output will seem to "stop" because there is not enough time for the signal to reach logic '1'. This situation can arise when the PWM is operating at high frequencies or generating short positive pulses.

This phenomenon can be prevented by speeding up the signal rise time. This is done by adding an external pull-up resistor (and minimizing external capacitance) on the signal net. The following table shows nominal rise times for unloaded DIO pins. Lower resistance values may be needed to compensate external circuit capacitance, but do not use an external pull-up resistor having less than 220 ohms (to prevent excessive DIO output current).

External pull-up DIO rise time
None 200 ns
1.2K ohm 20 ns
680 ohm 10 ns

How to configure a counter for PWM operation

This example shows how to configure counter channel 0 to operate as a PWM generator with the output appearing on DIO channel 0. Note that you must call S826_SafeWrenWrite() before calling S826_DioOutputSourceWrite(); if you neglect to do this then the PWM signal will not appear on DIO 0.

#include "826api.h"

uint data[2]= {1, 0}; // DIO 0
S826_SafeWrenWrite(0, 2);                   // Enable writes to DIO signal router.
S826_DioOutputSourceWrite(0, data);         // Route counter0 output to DIO 0.
S826_CounterModeWrite(0, 0, 0x01682020);    // Configure counter0 for PWM, with auto-preload when starting.
S826_CounterPreloadWrite(0, 0, 0, 900);     // On time in us (0.9 ms).
S826_CounterPreloadWrite(0, 0, 1, 500);     // Off time in us (0.5 ms).
S826_CounterStateWrite(0, 0, 1);            // Start the PWM generator.

Fail-safe PWM generator

I'm using a PWM output to control a motor. Is there a way to automatically shut off the motor if my program crashes?

Yes, you can use the watchdog timer and fail-safe controller to force the PWM output to a constant state. To do this, configure the watchdog to activate safemode when it times out, as shown in this simplified block diagram:

Fail-safe PWM generator

Before enabling the PWM generator or watchdog, program the desired PWM failsafe level into the DIO channel's SafeData register; this specifies the signal that will be sent to your motor controller when your program crashes (which will shut off the motor). Note that the DIO output is active-low. The SafeEnable register is set to '1' by default, thus enabling fail-safe operation on the DIO channel. Next, program the watchdog interval and start the watchdog running. Finally, start the PWM running.

After enabling the watchdog, your program must periodically kick it to prevent it from timing out, by calling S826_WatchdogKick(). When your program is running normally, the PWM signal will appear on the DIO pin. If your program crashes (or fails to kick the watchdog in a timely manner), the watchdog will time-out and activate the fail-safe controller. This will switch the DIO pin to the level specified by the SafeData register, which in turn will halt the motor.

#include "826api.h"

#define CRASH_DET_SECONDS 0.5  // Halt motor if program fails to kick watchdog within this time.
#define MOTOR_HALT_LEVEL  0    // DIO pin level ('0'=5V, '1'=0V) that will halt motor.

uint wdtime[5] = {(uint)(50000000 * (CRASH_DET_SECONDS)), 1, 1, 0, 0}; // watchdog interval
uint dio_routing[2]= {1, 0};                                           // map counter0 to DIO 0
uint safe_data[2]= {MOTOR_HALT_LEVEL, 0};                              // fail-safe level

// Create a fail-safe PWM generator using counter0 and DIO 0.
S826_SafeWrenWrite(0, 2);                   // Enable writes to watchdog, router and SafeData.
S826_DioSafeWrite(0, safe_data, 2);         // Specify DIO state to use when program crashes.
S826_DioOutputSourceWrite(0, dio_routing);  // Route counter0 output to DIO 0.
S826_CounterModeWrite(0, 0, 0x01682020);    // Config counter0 for PWM; preload when starting.
S826_CounterPreloadWrite(0, 0, 0, 900);     // PWM on time in us (0.9 ms).
S826_CounterPreloadWrite(0, 0, 1, 500);     // PWM off time in us (0.5 ms).
S826_WatchdogConfigWrite(0, 0x10, wdtime);  // Set wdog interval; trig safemode upon timeout.

// Start the PWM generator running.
S826_WatchdogEnableWrite(0, 1);             // Start watchdog. PROGRAM MUST KICK IT FROM NOW ON!
S826_CounterStateWrite(0, 0, 1);            // Start the PWM generator.

Phase-locked PWM outputs

Some applications require multiple, phase-locked PWM outputs. Although the 826's counter channels do not directly support phase locking, it is possible to simulate phase-locked PWM outputs by using counters configured as hardware-triggered one-shots. This technique can be used in a variety of ways.

Example: quadrature generator

A quadrature generator can be implemented with three counter channels and two DIOs as shown below. Except for DIO load connections, no external wiring is required (counter and DIO interconnects are established by the board's programmable signal router).

Quadrature generator

The counter channels are configured as follows:

  • CH0 - PWM with output on DIO1.
  • CH1 - 1-shot with IndexSource=ExtOut0, preload upon Index. This delays Phase2 wrt Phase1.
  • CH2 - 1-shot with IndexSource=ExtOut1, preload upon Index, output on DIO2. This generates the Phase2 output pulse.

Example: 3-phase controller

A 3-phase PWM controller (shown below) can be created by extending the above example. This is implemented with five counter channels and three DIOs (channel numbers are arbitrarily assigned). Except for DIO load connections, no external wiring is required (counter and DIO interconnects are established by the board's programmable signal router).


3-phase PWM generator


In the above example, counter channels are configured as follows:

  • CH0 - PWM with output on DIO1.
  • CH1 - 1-shot with IndexSource=ExtOut0, preload upon Index. This delays Phase2 wrt Phase1.
  • CH3 - 1-shot with IndexSource=ExtOut1, preload upon Index. This delays Phase3 wrt Phase2.
  • CH2 - 1-shot with IndexSource=ExtOut1, preload upon Index, output on DIO2. This generates the Phase2 output pulse.
  • CH4 - 1-shot with IndexSource=ExtOut3, preload upon Index, output on DIO3. This generates the Phase3 output pulse.

Serial data capture

A counter channel can be used to capture serial data and timing information by leveraging its snapshot FIFO. This is especially useful for capturing data from irregularly-timed sources such as bar code wands. The basic idea is to apply the serial data signal to the counter's IX or ExtIn input and configure the counter to capture snapshots at signal edges. The computer can then simply allow the channel to acquire snapshots while it asynchronously reads and processes snapshots from the FIFO.

In each snapshot, only the timestamp and reason flags are of interest (counts are ignored). The reason flag indicates whether a snapshot was triggered by rising or falling edge and the timestamp indicates the time when the edge occurred. For example, in the serial data waveform shown below, the first rising edge (A) caused a snapshot to be captured when the timestamp generator value was 100, and the reason code indicates the snapshot was triggered by a rising edge.

Serial data capture

Any two consecutive snapshots represent a matched pair of rising/falling or falling/rising edges, corresponding to an interval during which the serial data value was '1' or '0', respectively. For example, in the waveform shown above, snapshots A and B bracket a '1' interval. It is possible to determine the binary value of the serial data from the first reason code, and the duration of the data value from the difference between the timestamps.

To see how this works, consider the above serial data waveform. The counter automatically captures a snapshot for each of the edge events A, B, C and D. When the computer considers snapshots A and B, it determines that the serial data was '1' during interval A-B because A was triggered by a serial data rising edge. Furthermore, it knows that the serial data held at '1' for 300 microseconds (the difference between the A and B timestamps). Similary, it can determine that interval B-C was a logic '0' lasting 200 microseconds, and C-D was a 400 microsecond logic '1'.

For maximum efficiency, consider using a dedicated thread to read the FIFO. This eliminates polling and makes the application event-driven because the thread can wait in S826_CounterSnapshotRead() for the next snapshot without wasting CPU time. Also, this decouples the timing of serial data acquisition from other tasks, thereby greatly simplifying overall software development and maintenance. If fast processing of the serial data is required, raise the thread priority to an appropriately high level.

Mode register decoder utility

Is there an easy way to convert a mode register value to a human readable description of counter settings?

Yes: download Sensoray's counter mode decoder utility program (Windows compatible). Run the program and enter the mode register value to see an English language description of the counter mode settings.

ADC

Calibration errors caused by missing shunt

On 826 SDKs earlier than version 3.2.0, analog calibration values will not be applied without J6 (labeled "Calibration Enable") installed. A missing shunt is intended to protect against accidental overwriting of calibration values, but in these SDKs it also prevents the reading of those values. This is resolved in SDK version 3.2.0 and above; in these versions the shunt functions as intended and must be installed only when calibrating the board (though leaving it installed all the time is okay).

If board calibration is incorrect, make sure J6 is installed or upgrade to SDK version 3.2.0 or higher. The 826 SDK can be downloaded from the 826 product page.

Apparent nonlinearity

To prevent high CMV, connect isolated source to ADC ground.

ADC linearity can be adversely affected by high common-mode voltage (CMV). This can happen when the ADC is used to measure an isolated voltage source such as a battery, thermocouple, or isolated power supply. Since the source is isolated, the CMV may float up or down until it exceeds the maximum allowed CMV of the ADC's input circuitry.

When measuring an isolated source, be sure to connect one side of the source to the ADC power supply ground as shown in the diagram to the right. This will prevent high CMV that might othewise result in apparent non-linearity or calibration errors.

ADC accuracy specification

Resolution and no missing codes are both 16 bits minimum.

PARAMETER VALUE UNITS
MIN TYP MAX
Integral Nonlinearity Error ±0.75 ±1.5 LSB
Differential Nonlinearity Error ±0.5 ±1.25 LSB
Gain Error ±2 ±40 LSB
Gain Error Temperature Drift ±0.3 ppm/°C
Zero Error ±0.8 mV
Zero Temperature Drift ±0.3 ppm/°C

Maximum input voltage

The analog inputs accept common mode voltages up to ±12V with no resulting input current or damage. CMV up to ±25V is tolerated continuously, though this will cause currents to flow in the analog inputs. CMV greater than 25V may be tolerated for brief intervals, but this can cause significant currents to flow in the analog inputs and is not specified nor guaranteed to be safe.

DAC

Linux Demo Sine Wave Generator counter error (-15)

The Linux sine wave generator demo may experience a timeout and exit with an error code -15 (S826_ERR_FIFOOVERFLOW). This occurs because the priority of the demo thread may be too low for the sample time. Linux is not a RTOS and the process (or interrupt) may be delayed and not complete the DAC output in the specified time.

Older version of the demo will exit when S826_ERR_FIFOOVERFLOW occurs. Later versions of the demo, however, will print an error code and continue outputting the sine wave.

In any case, if the DAC output sampling time requirements are very small and need to be precise, it is recommended to run the process at a higher priority. You may also consider using a low-latency or rt kernel.

To run the demo at a higher priority:

"nice -n 19 ./s826demo"

For Ubuntu low-latency kernel:

"sudo apt-get install linux-lowlatency linux-headers-lowlatency"

For Ubuntu rt kernel:

"sudo apt-get install linux-rt linux-headers-rt"

In extreme high performance cases, you may consider using the raw DAC write command (S826_DacRawWrite) instead of S826_DacDataWrite. You must make sure to understand the DAC ranges before doing so. This should normally not be necessary as S826_DacDataWrite is only marginally slower.

DAC accuracy specification

Resolution and monotonicity are both 16 bits minimum.

PARAMETER CONDITIONS VALUE UNITS
MIN TYP MAX
Integral Nonlinearity ±2 LSB
Differential Nonlinearity ±1 LSB
Gain Error ±4 ±20 LSB
Gain Temperature Coefficient ±2 ppm/°C
Unipolar Zero-Scale Error 5V unipolar range, 25°C
10V unipolar range, 25°C
5V unipolar range
10V unipolar range
±80
±100
±140
±150
±200
±300
±400
±600
µV
µV
µV
µV
V_offset Temperature Coefficient All unipolar ranges ±2 µV/°C
Bipolar Zero Error All bipolar ranges ±2 ±12 LSB

DIOs

Generating a burst of pulses

How can I make a DIO go active for 10ms and then inactive for another 10ms, and repeat this five times?

There are several ways to do this but the methods you can use depend on a number of factors. Here are two general strategies:

1. If high precision is not needed you can call S826_DioOutputWrite() multiple times, with 10ms software delays between the calls. The precision of this method depends on your operating system and system load. The code for this method is simple and straightforward.

2. If you need precise timing then you could use two counter channels. For example, using counter channels 0 and 1:

  • Counter 0: Configure as PWM generator with 10ms on/off times, with external enable. Connect its enable input to counter 1's output. The goal here is for counter 0 to enable counter 1 to output pulses; counter 0 will enable the PWM generator until 5 pulses have been generated.
  • Counter 1: Configure as event down-counter, with preload (value=5) upon enable, with external clock, with output active when counts not zero. Connect its clock input (must be external connection) to counter 0's output. The goal here is for counter 1 to count PWM pulses until it counts from 5 down to 0; it will then set its output low, thus disabling the PWM generator.

Example application: I2C Emulator

Can I use DIOs to communicate with I2C devices?

Have a look at Sensoray's I2C emulator, which uses two DIOs to bit-bang an I2C bus. This open source software implements a full-featured I2C master emulator with bus arbitration and bus-hang resolver. All 826-specific code resides in a hardware abstraction layer (HAL) — an architectural feature that should exist in all production-quality software.

Software

Custom Installation and Re-distribution (Windows)

Sensoray's installer uses the NSIS installation system. 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 at https://www.microsoft.com/en-us/download/details.aspx?id=2092 and https://www.microsoft.com/en-us/download/details.aspx?id=5582.

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 https://www.microsoft.com/en-us/download/details.aspx?id=25150. The executable can be silently installed using this command:

"dotnetfx35setup.exe /qb"


Silent Install (Windows)

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. Starting with version 3.3.9, there are additional command line options to quiet the setup.exe installater from command line or batch file.

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"
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 /no_demos"
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.


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).

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. To get required libraries on Ubuntu, type:
"sudo apt-get install mono-complete"

For a C# development environment, type:

"sudo apt-get install monodevelop"

Resources for custom driver development

I want to develop my own 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 and middleware, comprising a complete 826 API for Linux. The middleware core is operating system independent, which makes this SDK a great starting point for porting. The SDK can be found on the Downloads tab of the 826 product page. The SDK has been carefully designed for efficient and reliable operation in multi-threaded and multi-process applications, and consequently it can be easily ported to real-time operating systems.
  • 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.

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). We normally test first on Ubuntu LTS, but have a script to test builds on kernel versions 2.6.x, 3.x, and 4.x.

Cables

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.

See also

Personal tools
Namespaces

Variants
Actions
Toolbox