Thanks for the answer. Now it works like expected.

The solution to set the channels in a loop...

cannel_desc[i] = PACK(ni_6071e_analog_channels[i], ret, AREF_GROUND);

while the 'ret' argument is needed and used from the a4l_find_range function: .

Just for info in case somebody faces similar issues, here the code
from the updated initialisation funciton ...


a4l_desc_t      arm_device;
unsigned        ni_6071e_analog_channels[16] =
{0,1,2,4,5,6,16,17,18,19,21,23,32,33,34,35};
unsigned        channel_desc[16];
double                  range_settings[16] = {5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 
5, 5,
10, 10, 10, };
a4l_chinfo_t   *ni_6071e_analog_channel_infos[16];
a4l_rnginfo_t  *ni_6071e_analog_range_infos[16];

int analog_init = 0;

void init_arm()
{
   int          i = 0;
   int          ret;
   double       Range_Value;
   double       Range_Max;
   double       Range_Min;

   ret = a4l_open (&arm_device, "analogy0");

   if (ret != 0)
   {
      printf ("[EXOARM] Error while opening the arm device, return
code=%d \n", ret);
      return;
   }
     arm_device.sbdata = malloc(arm_device.sbsize);


   ret = a4l_fill_desc (&arm_device);

   if (ret != 0)
   {
      printf ("[EXOARM] Error while calling fill_desc(), return
code=%d \n", ret);
      return;
   }


   for (i=0; i<16; i ++)
   {
      ret = a4l_get_chinfo (&arm_device, 0,
ni_6071e_analog_channels[i], &ni_6071e_analog_channel_infos[i]);
      if (ret != 0)
      {
         printf ("[EXOARM] Error invoking a4l_get_chinfo on channel
%d, return code=%d \n", ni_6071e_analog_channels[i], ret);
      }
      ret = a4l_get_rnginfo (&arm_device, 0,
ni_6071e_analog_channels[i], 0, &ni_6071e_analog_range_infos[i]);
      if (ret != 0)
      {
         printf ("[EXOARM] Error invoking a4l_get_chinfo on channel
%d, return code=%d \n", ni_6071e_analog_channels[i], ret);
      }
   }

   //setting up the range
   for(i=0;i <16; i++)
   {
      Range_Value = range_settings[i];
      if (Range_Value < 0)
      {
         Range_Min = Range_Value;
      }
      else
      {
         Range_Min = 0.0;
      }
      Range_Max = abs(Range_Value);

      ret = a4l_find_range
            (  &arm_device,                 //device
               0,                           //subindex
               ni_6071e_analog_channels[i], //idx channel
               A4L_RNG_VOLT_UNIT,                           //unit
               Range_Min,
               Range_Max,
               &ni_6071e_analog_range_infos[i]
               );
      if ((ret == -ENOENT) || (ret == -EINVAL))
      {
         printf("Error while configuring ranges 6071\n");
      }
          else
          {
             //set the range on the board
                 channel_desc[i] = PACK(ni_6071e_analog_channels[i], ret, 
AREF_GROUND);
          }
   printf("Ch: %d Rng set: %.1lf Calc val: %d \n",
ni_6071e_analog_channels[i], range_settings[i], ret);//,
ni_6071e_analog_range_infos[i].min,
ni_6071e_analog_range_infos[i].max);
   }//end for loop

   analog_init = 1;
}

2011/9/14 Alexis Berlemont <[email protected]>:
> Hi,
>
> Sorry for the late reply.
>
> On Wed, Sep 7, 2011 at 9:37 PM, Thomas Krüger
> <[email protected]> wrote:
>> Dear all,
>>
>> I am using a DAQ card from national instruments 6071E to measure
>> analog values. It works fine but I have some problems changing the
>> range:
>>
>> I found the a4l_find_range function and it works well, seeing the
>> range_info changes according to my wishes. But I realise that the only
>> function that uses the range information is the a4l_rawtod. It works
>> for the range conversion but technically the range is never changed on
>> the card itself (switching to another internal gain) and so the value
>> I coming out at the end is wrong (mismatch between the setting on the
>> io-card and a4l_rawtod).
>>
>
> Yes. The only interest of a4l_find_range() is to locate the most
> suitable range descriptor according to the min and max value.
>
>> Which function do I have to use or how to pass this information to the card?
>
> You should pass the index of the selected range to thet third argument
> of a4l_sync_read: the channel descriptor. Some helper macros are
> available so as to make the setting of the channel descriptor (a
> little bit) more easier.
>
> Sorry, in the doxygen documentation of a4l_sync_read, there should be
> a link to the anchor: "Channel macros".
>
> Here is the quote from the Doxygen documentation.
> Channel macros
> Specific precompilation macros and constants useful for the channels
> descriptors tab located in the command structure
>
> #define         CHAN(a)   ((a) & 0xffff)
>        Channel indication macro.
> #define         RNG(a)   (((a) & 0xff) << 16)
>        Range definition macro.
> #define         AREF(a)   (((a) & 0xf) << 24)
>        Reference definition macro.
> #define         FLAGS(a)   ((a) & CR_FLAGS_MASK)
>        Flags definition macro.
> #define         PACK(a, b, c)   (CHAN(a) | RNG(b) | AREF(c))
>        Channel + range + reference definition macro.
> #define         PACK_FLAGS(a, b, c, d)   (CHAN(a) | RNG(b) | AREF(c) | 
> FLAGS(d))
>        Channel + range + reference + flags definition macro.
> #define         AREF_GROUND   0x00
>        Analog reference is analog ground.
> #define         AREF_COMMON   0x01
>        Analog reference is analog common.
> #define         AREF_DIFF   0x02
>        Analog reference is differential.
> #define         AREF_OTHER   0x03
>        Analog reference is undefined.
>
> I think this API should be improved; there is an ugly flaw: with
> a4l_find_range() you can retrieve the range descriptor but you have to
> pass the index of the range descriptor to a4l_sync_read (..., ...,
> PACK(0, range_index, ...), ...). This design problem forces the
> developer to use a4l_get_rnginfo() so as to deduce the related index.
>
> I will try to enrich the API so as to make the things easier.
>
>>
>> Thanks for your answers in advance.
>>
>> Cheers,
>> Thomas
>>
>>
>> My test program:
>>
>> // simple build cmd: g++ test-pcimio.c -I/usr/xenomai/include/
>> -lxenomai -lnative -lanalogy -lpthread -lrtdm -L/usr/xenomai/lib
>> // execute #./a.out
>>
>>
>> #include <time.h>
>> #include <stdio.h>
>> #include <string.h>
>> #include <stdint.h>
>> #include <stdlib.h>
>> #include <errno.h>
>> #include <xenomai/analogy/analogy.h>
>>
>> /*
>>  * Initialization function, activated once by PolyORB (at startup)
>> */
>> a4l_desc_t      arm_device;
>> int             ni_6071e_analog_channels[16] =
>> {0,1,2,4,5,6,16,17,18,19,21,23,32,33,34,35};
>> int                             range_settings[16] = {-5, -10, -10, 5,
>> 5, 5, 5, -5, -5, -5, -5,
>> 10, 10, 10, -0.5, 0.5};
>> a4l_chinfo_t   *ni_6071e_analog_channel_infos[16];
>> a4l_rnginfo_t  *ni_6071e_analog_range_infos[16];
>>
>> int analog_init = 0;
>>
>> void init_arm()
>> {
>>   int          i = 0;
>>   int          ret;
>>   double       Range_Value;
>>   double       Range_Max;
>>   double       Range_Min;
>>
>>   ret = a4l_open (&arm_device, "analogy0");
>>
>>   if (ret != 0)
>>   {
>>      printf ("[EXOARM] Error while opening the arm device, return
>> code=%d \n", ret);
>>      return;
>>   }
>>     arm_device.sbdata = malloc(arm_device.sbsize);
>>
>>
>>   ret = a4l_fill_desc (&arm_device);
>>
>>   if (ret != 0)
>>   {
>>      printf ("[EXOARM] Error while calling fill_desc(), return
>> code=%d \n", ret);
>>      return;
>>   }
>>
>>
>>   for (i=0; i<16; i ++)
>>   {
>>      ret = a4l_get_chinfo (&arm_device, 0,
>> ni_6071e_analog_channels[i], &ni_6071e_analog_channel_infos[i]);
>>      if (ret != 0)
>>      {
>>         printf ("[EXOARM] Error invoking a4l_get_chinfo on channel
>> %d, return code=%d \n", ni_6071e_analog_channels[i], ret);
>>      }
>>      ret = a4l_get_rnginfo (&arm_device, 0,
>> ni_6071e_analog_channels[i], 0, &ni_6071e_analog_range_infos[i]);
>>      if (ret != 0)
>>      {
>>         printf ("[EXOARM] Error invoking a4l_get_chinfo on channel
>> %d, return code=%d \n", ni_6071e_analog_channels[i], ret);
>>      }
>>   }
>>
>>   //setting up the range
>>   for(i=0;i <16; i++)
>>   {
>>      Range_Value = range_settings[i];
>>      if (Range_Value < 0)
>>      {
>>         Range_Min = Range_Value;
>>      }
>>      else
>>      {
>>         Range_Min = 0.0;
>>      }
>>      Range_Max = abs(Range_Value);
>>
>>      ret = a4l_find_range
>>            (  &arm_device,                 //device
>>               0,                           //subindex
>>               ni_6071e_analog_channels[i], //idx channel
>>               A4L_RNG_VOLT_UNIT,                           //unit
>>               Range_Min,
>>               Range_Max,
>>               &ni_6071e_analog_range_infos[i]
>>               );
>>      if ((ret == -ENOENT) || (ret == -EINVAL))
>>      {
>>         printf("Error while configuring ranges 6071\n");
>>      }
>>
>>   }//end for loop
>>
>>   analog_init = 1;
>> }
>>
>> void arm_poll_acquisition_board()
>> {
>>   int i;
>>   double tmp;
>>   int ret;
>>   uint8_t raw[128];
>>
>>   if (analog_init == 0) {
>>      printf("[arm] Runtime Error - Periodic task activated before
>> proper initialization.\n");
>>      return;
>>   }
>>
>>
>>   for (i=0; i<16; i++)
>>   {
>>      ret = a4l_sync_read (&arm_device, 0,
>> ni_6071e_analog_channels[i], 0, &raw, 128);
>>      if (ret <= 0)
>>      {
>>          printf("[arm] Error while acquiring the data\n");
>>      }
>>
>>      ret = a4l_rawtod (ni_6071e_analog_channel_infos[i],
>> ni_6071e_analog_range_infos[i], &tmp, &raw, 1);
>>
>>      if (ret <= 0)
>>      {
>>          printf("[arm] Error while converting the data\n");
>>      }
>>      else
>>      {
>>        if(i != 0)
>> {
>> printf(";");
>> }
>>          printf("%lf", tmp);
>>
>>        }
>>   }
>> printf("]\n[");
>>   return;
>> }
>>
>>
>>
>> int main ()
>> {
>>   init_arm ();
>>   while (1)
>>   {
>>      arm_poll_acquisition_board();
>>      sleep (4);
>>   }
>> }
>>
>> _______________________________________________
>> Xenomai-help mailing list
>> [email protected]
>> https://mail.gna.org/listinfo/xenomai-help
>>
>

_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help

Reply via email to