« Close

Datasheets and User Guides

App Notes

Software & Driver

 

4.3.6 - Timers & Counters

There are eight IOTypes used to write or read timer and counter information:

LJ_ioGET_COUNTER
LJ_ioPUT_COUNTER_ENABLE  //UpdateConfig will be set.
LJ_ioGET_COUNTER_ENABLE
LJ_ioPUT_COUNTER_RESET
LJ_ioGET_TIMER
LJ_ioPUT_TIMER_VALUE
LJ_ioPUT_TIMER_MODE  //UpdateConfig will be set.
LJ_ioGET_TIMER_MODE

In addition to specifying the channel number, the following mode constants are passed in the value parameter when doing a request with the timer mode IOType:

LJ_tmPWM16                //16-bit PWM output
LJ_tmPWM8                 //8-bit PWM output
LJ_tmRISINGEDGES32        //Period input (32-bit, rising edges)
LJ_tmFALLINGEDGES32       //Period input (32-bit, falling edges)
LJ_tmDUTYCYCLE            //Duty cycle input
LJ_tmFIRMCOUNTER          //Firmware counter input
LJ_tmFIRMCOUNTERDEBOUNCE  //Firmware counter input (with debounce)
LJ_tmFREQOUT              //Frequency output
LJ_tmQUAD                 //Quadrature input
LJ_tmTIMERSTOP            //Timer stop input (odd timers only)
LJ_tmSYSTIMERLOW          //System timer low read
LJ_tmSYSTIMERHIGH         //System timer high read
LJ_tmRISINGEDGES16        //Period input (16-bit, rising edges)
LJ_tmFALLINGEDGES16       //Period input (16-bit, falling edges)

The following are special channels, used with the get/put config IOTypes, to configure a parameter that applies to all timers/counters:

LJ_chNUMBER_TIMERS_ENABLED  //UpdateConfig will be set if writing.
LJ_chTIMER_CLOCK_BASE       //UpdateConfig will be set if writing.
LJ_chTIMER_CLOCK_DIVISOR    //UpdateConfig will be set if writing.

With the clock base special channel above, the following constants are passed in the value parameter to select the frequency:

LJ_tc750KHZ  //Fixed 750 kHz clock base.
LJ_tcSYS     //System clock: 48 MHz.

Following is example pseudocode for configuring various timers and a hardware counter:

//First, an add/go/get block to configure the timers and counters.

//Enable all 6 timers.  Timer0-Timer5 will appear on FIO0-FIO5.
AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, 6, 0, 0);

//Enable Counter0.  It will use the next available line, FIO6.
AddRequest (lngHandle, LJ_ioPUT_COUNTER_ENABLE, 0, 1, 0, 0);

//All output timers use the same timer clock, which is
//determined by the base clock divided by the clock divisor.
//Set the timer clock base to 48 MHz.
AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tcSYS, 0, 0);

//Set the timer clock divisor to 48, creating a 1 MHz timer clock.
AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, 48, 0, 0);

//Configure Timer0 as 8-bit PWM.  It will have a frequency
//of 1M/256 = 3906.25 Hz.
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 0, LJ_tmPWM8, 0, 0);

//Initialize the 8-bit PWM with a 50% duty cycle.
AddRequest (lngHandle, LJ_ioPUT_TIMER_VALUE, 0, 32768, 0, 0);

//Configure Timer1 as frequency output.
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 1, LJ_tmFREQOUT, 0, 0);

//Initialize frequency output at 1M/(2*5) = 100 kHz.
AddRequest (lngHandle, LJ_ioPUT_TIMER_VALUE, 1, 5, 0, 0);

//Configure Timer2 as a firmware counter with debounce.
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 2, LJ_tmFIRMCOUNTERDEBOUNCE, 0, 0);

//Configure Timer2 for negative edges (bit 8 of value clear) with
//a debounce period of 87 ms.
AddRequest (lngHandle, LJ_ioPUT_TIMER_VALUE, 2, 1, 0, 0);

//Configure Timer3 as duty cycle input.
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 3, LJ_tmDUTYCYCLE, 0, 0);

//Configure Timers 4 & 5 as quadrature input.  Two timers
//are needed for phases A & B.
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 4, LJ_tmQUAD, 0, 0);
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 5, LJ_tmQUAD, 0, 0);

//Execute the requests.
GoOne (lngHandle);

The LabJackUD driver uses the low-level TimerCounter function. That function has a single UpdateConfig bit that must be set to change modes, clock configuration, or enabled/disabled status. When the UpdateConfig bit is set, all timers and counters are re-initialized. The following pseudocode demonstrates reading input timers/counters and updating the values of output timers, which does not cause the UpdateConfig bit to be set. The e-functions are used in the following pseudocode, but some applications might combine the following calls into a single add/go/get block so that a single low-level call is used.


//Change Timer0 PWM duty cycle to 25%.
ePut (lngHandle, LJ_ioPUT_TIMER_VALUE, 0, 49152, 0);

//Change Timer1 frequency output to 1M/(2*50) = 10 kHz.
ePut (lngHandle, LJ_ioPUT_TIMER_VALUE, 1, 50, 0);

//Read count from Timer2.  This is an unsigned 32-bit value.
eGet (lngHandle, LJ_ioGET_TIMER, 2, &dblValue, 0);

//Read duty-cycle from Timer3.
eGet (lngHandle, LJ_ioGET_TIMER, 3, &dblValue, 0);

//The duty cycle read returns a 32-bit value where the
//least significant word (LSW) represents the high time
//and the most significant word (MSW) represents the low
//time.  The times returned are the number of cycles of
//the timer clock.  In this case the timer clock was set
//to 1 MHz, so each cycle is 1 microsecond.
dblHighCycles = (double)(((unsigned long)dblValue) % (65536));
dblLowCycles = (double)(((unsigned long)dblValue) / (65536));
dblDutyCycle = 100 * dblHighCycles / (dblHighCycles + dblLowCycles));
dblHighTime = 0.000001 * dblHighCycles;
dblLowTime = 0.000001 * dblLowCycles;

//Read the quadrature count from Timer4.  Timer5 would return the
//same value.  This is a signed 32-bit value.
eGet (lngHandle, LJ_ioGET_TIMER, 4, &dblValue, 0);

//Read the count from Counter0.  This is an unsigned 32-bit value.
eGet (lngHandle, LJ_ioGET_COUNTER, 0, &dblValue, 0);

Following is pseudocode to reset the input timers and the counter:


//Reset the firmware counter (Timer2) to zero, by writing a
//value of zero.
ePut (lngHandle, LJ_ioPUT_TIMER_VALUE, 2, 0, 0);

//Reset the duty-cycle measurement (Timer3) to zero, by writing
//a value of zero.  The duty-cycle measurement is continuously
//updated, so a reset is normally not needed, but one reason
//to reset to zero is to detect whether there has been a new
//measurement or not.
ePut (lngHandle, LJ_ioPUT_TIMER_VALUE, 3, 0, 0);

//Reset the quadrature counters (Timer4 & Timer5) to zero, by
//writing a value of zero to either one.
ePut (lngHandle, LJ_ioPUT_TIMER_VALUE, 4, 0, 0);

//Reset Counter0 to zero.
ePut (lngHandle, LJ_ioPUT_COUNTER_RESET, 0, 1, 0);

Note that if a timer/counter is read and reset at the same time (in the same Add/Go/Get block), the read will return the value just before reset.

6 comments

Hi Labjackers,

i'm testing a few UD functions with an UE9, because i'm trying to adapt the LJUDDElphi.pas to an style  how usual in Delphi. I will send you this later.

Here my question: "Enable/disable the DAC's"

I can set and read this state by using

ePut(LjHandle, LJ_ioPUT_DAC_ENABLE, 0, 0|1, 0) and

eGet(LjHandle, LJ_ioGet_DAC_ENABLE, 0, DoubleValue, 0)

but the hardware output value (measured by digital voltmeter) stays active.

Where is my "brain error"?

Thanks for your answer

Gottfried

We say in our team: "The problem is sitting most in front of the computer"

(...sorry, April 1 is today. In Germany we are not always seriously this day.).

Those two commands/IOTypes are related to the state of the DACs being enabled or disabled  To set the DAC voltage you will want something like this:

ePut(LjHandle, LJ_ioPUT_DAC, 0, DoubleValue, 0)

For DAC documentation and example pseudocode for the UD driver look at Section 4.3.4 of the UE9 User's Guide. 

Thanks for your answer, but it is not the answer for my problem (controlling an UE9), sorry:

- I can set outputput voltages (LJ_ioPUT_DAC, DoubleValue = 0.02 ... 4.86).

- I can enable the output state directly (LJ_ioPUT_DAC_ENABLE, DoubleValue = 1) and implicitly (LJ_ioPUT_DAC).

- I can disable the output state (LJ_ioPUT_DAC_ENABLE, DoubleValue = 0)

- I can read the output state(enabled or disabled: returned DoubleValue = 1|0). But the physical outputs are not in high impedance state.

   (see chapter 2.8: "The DACS on the UE9 can be disabled. When disabled they are placed in a high-impedance state")

Conditions:

  Device: UE9 (Hardware = 1.1; Control = 2.11; Comm = 1.4; Bootloader = 1.14)

  Software: UD-DLL = 3.25; WinXP; Program language = Delphi5/Delphi6

 

This detail has caused a lot of confusion, so as of control firmware 1.98 the DACs are always enabled. We will get the user's guide updated accordingly. 

Are there any working C programs that uses quadrature counter (or any other function for that matter?)  I have been trying to figure out most of the functionality by reverse engineering python outputs. This has been a hit-or-miss affair!

 

Thanks in advance

 

There are various C examples, but the VC6 archive has the most.  In fact, in that archive check out the example "UE9_Quadrature".