- From: Anders Blomdell <anders.blomdell_at_control.lth.se>
- Date: Tue, 26 Jun 2007 18:02:25 +0200
Anders Blomdell wrote:
> Anders Blomdell wrote:
>> Anders Blomdell wrote:
>>> Anders Blomdell wrote:
>>>> Frank Mori Hess wrote:
>>>>> On Thursday 21 June 2007 13:36, you wrote:
>>>>>> I know (I'll get to it as soon as I have figured out how to use the NI
>>>>>> pci-6221 with quadrature encoders).
>>>>> See the enums in comedi.h, in particular enum ni_gpct_mode_bits. You'll
>>>>> need to use one of the NI_GPCT_COUNTING_MODE_QUADRATURE_XN_BITS bitfields,
>>>>> instead of the NI_GPCT_COUNTING_MODE_NORMAL_BITS that the simple counting
>>>>> demo uses. And maybe some of the NI_GPCT_INDEX_* bits. It might actually
>>>>> be useful to look at the ni 6601/6602 register level programming manual.
>>>> That only partially works, what happens is that whatever
>>>> NI_GPCT_COUNTING_MODE_QUADRATURE_XN_BITS is selected, the counter starts to
>>>> count down on each edge on CTR{0/1}A (PFI 8/PFI 3) but remains stationary
>>>> regardless of activity on CTR{0/1}B (PFI 10/PFI 11). To me this indicates that
>>>> the counter is not in encoder mode, because a failure in the routing of the B
>>>> signal should result in the counter changing one value only (X0 -> X1 -> X0
>>>> transitions should gige one up and one down event). Direction is changed if
>>>> NI_GPCT_COUNTING_DIRECTION_UP_BITS is set.
>>>>
>>>> Where can I find the documentation where M_Offset_G0_Counting_Mode, etc are
>>>> found (the only document I have found on NI's site is "NI M Series Register Map
>>>> (Preliminay)"
>>> The following hack (gleaned after getting a working example in the NI
>>> nimhddk_linux26/nimseries register level programming), makes it work:
>>>
>>> case NITIO_G0_Counting_Mode_Reg:
>>> ni_writew(bits, M_Offset_G0_Counting_Mode);
>>> bits = 0x26a0;
>>> ni_writew(bits, M_Offset_G0_MSeries_ABZ);
>>> break;
>>>
>>> Seems like we (I?) need to add functionality to do the equivalent of (see
>>> attached NI/RLP example for context):
>>>
>>> board->G0_MSeries_ABZ.setG0_A_Select(9);
>>> board->G0_MSeries_ABZ.setG0_B_Select(21);
>>> board->G0_MSeries_ABZ.flush();
>>>
>>> any comments on what it should look like (or is it already there, but hidden by
>>> my ignorance)?
>> I have looked a little more on the comedi code. The functionality seems to be
>> lacking (or I'm totally blind). Which of the following implementations is preferred:
>>
>> 1. Adding INSN_CONFIG_SET_ABZ_SRC, which accepts two arguments:
>> index [0=A, 1=B, 2=Z]
>> source [1-10=PFI0-PFI9, 21-26=PFI10-PFI15, 31=DISABLED, ...]
>>
>> 2. Adding INSN_CONFIG_SET_A_SRC, INSN_CONFIG_SET_B_SRC, INSN_CONFIG_SET_Z_SRC,
>> which accepts 1 argument:
>> source [1-10=PFI0-PFI9, 21-26=PFI10-PFI15, 31=DISABLED, ...]
>>
>> 3. Modify INSN_CONFIG_SET_GATE_SRC to accept
>> index [2=A, 3=B, 4=Z]
>> source [1-10=PFI0-PFI9, 21-26=PFI10-PFI15, 31=DISABLED, ...]
>>
>> 4. None of the above, please fill in a rough sketch on dotted line below:
>>
>> ...........................................
> Selected #3 above, patches to comedi & comedilib are included. Have not got Z
> signal to work, but at least A/B works (will get back if I find what is missing)...
OK, with slightly modified demo/gpct_encoder.c I got Z to work as well
Regards
Anders Blomdell
--
Anders Blomdell Email: anders.blomdell_at_control.lth.se
Department of Automatic Control
Lund University Phone: +46 46 222 4625
P.O. Box 118 Fax: +46 46 138118
SE-221 00 Lund, Sweden
/*
* NI quadrature encoder example.
* Part of Comedilib
*
* Copyright (c) 2007 Anders Blomdell <anders.blomdell_at_control.lth.se>
*
* This file may be freely modified, distributed, and combined with
* other software, as long as proper attribution is given in the
* source code.
*/
/*
* Requirements: A board with a National Instruments general-purpose
* counter, and comedi driver version 0.7.74 or newer.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <comedilib.h>
#include <math.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <ctype.h>
#include "examples.h"
int ni_gpct_start_encoder(comedi_t *device, unsigned subdevice,
unsigned int initial_value,
int a, int b, int z)
{
int retval;
lsampl_t counter_mode;
retval = reset_counter(device, subdevice);
/* set initial counter value by writing to channel 0 */
retval = comedi_data_write(device, subdevice, 0, 0, 0, initial_value);
/* set "load a" register to initial_value by writing to channel 1 */
retval = comedi_data_write(device, subdevice, 1, 0, 0, initial_value);
/* set "load b" register to initial_value by writing to channel 2 */
retval = comedi_data_write(device, subdevice, 2, 0, 0, initial_value);
set_gate_source(device, subdevice, 0, NI_GPCT_DISABLED_GATE_SELECT);
set_gate_source(device, subdevice, 1, NI_GPCT_DISABLED_GATE_SELECT);
set_gate_source(device, subdevice, 2, a);
set_gate_source(device, subdevice, 3, b);
set_gate_source(device, subdevice, 4, z);
counter_mode = (NI_GPCT_COUNTING_MODE_QUADRATURE_X4_BITS |
NI_GPCT_COUNTING_DIRECTION_HW_UP_DOWN_BITS);
if (z != NI_GPCT_DISABLED_GATE_SELECT) {
counter_mode |= NI_GPCT_INDEX_ENABLE_BIT;
}
retval = set_counter_mode(device, subdevice, counter_mode);
if(retval < 0) return retval;
retval = arm(device, subdevice, NI_GPCT_ARM_IMMEDIATE);
if(retval < 0) return retval;
return 0;
}
int main(int argc, char *argv[])
{
comedi_t *device = NULL;
int subdevice = -1;
int a = NI_GPCT_DISABLED_GATE_SELECT;
int b = NI_GPCT_DISABLED_GATE_SELECT;
int z = NI_GPCT_DISABLED_GATE_SELECT;
unsigned int initial_value = 0;
int retval;
struct parsed_options options;
{
int c;
while (-1 != (c = getopt(argc, argv, "f:s:a:b:z:i:"))) {
switch (c) {
case 'f':
device = comedi_open(optarg);
if(!device) {
comedi_perror(optarg);
exit(-1);
}
break;
case 's':
subdevice = strtoul(optarg, NULL, 0);
break;
case 'a':
/* TODO: Should we pass the value directly, i.e. could anybody
* be interested in values besides PFIx/DISABLED */
a = NI_GPCT_PFI_GATE_SELECT(strtoul(optarg, NULL, 0));
break;
case 'b':
/* TODO: Should we pass the value directly, i.e. could anybody
* be interested in values besides PFIx/DISABLED */
b = NI_GPCT_PFI_GATE_SELECT(strtoul(optarg, NULL, 0));
break;
case 'z':
/* TODO: Should we pass the value directly, i.e. could anybody
* be interested in values besides PFIx/DISABLED */
z = NI_GPCT_PFI_GATE_SELECT(strtoul(optarg, NULL, 0));
break;
case 'i':
initial_value = strtoul(optarg, NULL, 0);
break;
}
}
}
/*FIXME: check that device is counter */
printf("Initiating encoder on subdevice %d.\n", subdevice);
retval = ni_gpct_start_encoder(device, subdevice, initial_value, a, b, z);
if(retval < 0) return retval;
return 0;
}
Received on 2007-06-26Z15:02:25