Test and Measurement Forum

Serial ADC-16

Post your Linux discussions here

Serial ADC-16

Postby Wipster » Fri Oct 02, 2009 3:55 pm

Hi,

I am a linux user with an ADC-16 and I have a query about what I can and cannot do, and what I can and cannot post. I see there is a linux server application available where you read off that programs memory to get the results from the adc but for me this approach seems a bit hacks. Am I allowed to write my own program to open more of the functionality (ie full 8bit - 16bit) and get the results from the datalogger? and if so can I post the source here for anyone interested?

I have noticed that the specs of how to communicate is defined in the datasheet so does this mean I am fine?

Thanks and best regards,
Wip
Wipster
User
User
 
Posts: 3
Joined: Fri Oct 02, 2009 3:24 pm

Postby ziko » Mon Oct 05, 2009 4:31 pm

Hi there are two ways to access the ADC16, either via the serial port as a normal RS232 device using no drivers. Or you can use the drivers we provide, if you go to our software download page you will find some Linux drivers also available.

The user manual will give you information on both the serial protocol and the function calls if you choose to use the drivers.

Kind regards
Ziko

Technical Specialist
ziko
Zen Master
Zen Master
 
Posts: 1705
Joined: Fri Dec 01, 2006 10:03 am
Location: St Neots

Postby Wipster » Tue Oct 06, 2009 3:43 pm

Thanks ziko

I have made my own, however I have run into a confusing issue. I am running my channels in differential mode, do both inputs have to be below 2.5V to give an accurate difference or does the difference just have to be less then 2.5V?
The reason for asking this is I have differing results in linux windows and on my volt meter.
I have checked with my driver and your driver in linux and they get the same results (330mv ish) however picolog in windows gets 190mv ish, despite the fact all are sending the same request bytes.
And just to mix it up my volt meter which is usualy spoton with single ended readings in windows and linux, reports 210mv diference.

Best regards,
Wip
Wipster
User
User
 
Posts: 3
Joined: Fri Oct 02, 2009 3:24 pm

Postby Wipster » Mon Oct 12, 2009 8:21 am

Anyone seen this issue with their ADC-16 or other device?
Wipster
User
User
 
Posts: 3
Joined: Fri Oct 02, 2009 3:24 pm

Re: Serial ADC-16

Postby ziko » Tue Nov 03, 2009 9:50 am

Hi Wipster,

Sorry for the delay, forums were going through some modifications recently and I am just catching up.

The difference can be 5V there is a CMMR that you have to take into account, and it looks to me that as long as you do not exceed either +/-3.5V you should be ok.

Also are you using the Linux driver or are you communicating with the device using the serial protocol?

What are your input voltages?

Kind regards
Ziko

Technical Specialist
ziko
Zen Master
Zen Master
 
Posts: 1705
Joined: Fri Dec 01, 2006 10:03 am
Location: St Neots

Re: Serial ADC-16

Postby Wipster » Mon Dec 07, 2009 1:52 pm

Hi,

I was comparing the readings from picolog in windows and the linux driver and the serial implementation I wrote. Both linux readings where the same but the windows one was different.
The voltage inputs where higher then the picolog can read in reference to ground, probably around the 5-6v mark if I remember correctly but only had a small difference between them.
It might be an issue with power from the port with the higher voltages it was comparing, it was two different laptops one linux and one windows.

For those of you who are interested bellow is my serial code, it uses one thread to read the datalogger as fast as possible and the main thread to output from the register. Its a bit crude but works and was my first experiment with threads.

Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <math.h>
#include <sys/ioctl.h>

typedef struct {
   int *results, *chanres;
   char *chanmode;
   char model, version;
} container;

int open_link(int fd) {
   
   int status, bits;
   struct termios options;
   char buf[3];

   fcntl(fd, F_SETFL, 0);
   tcgetattr(fd, &options);
   // Get attributes

   cfsetispeed(&options, B9600);
   cfsetospeed(&options, B9600);      

   options.c_cflag |= (CLOCAL | CREAD);
   options.c_cflag &= ~PARENB;
   options.c_cflag &= ~CSTOPB;
   options.c_cflag &= ~CSIZE;
   options.c_cflag |= CS8;
   options.c_cflag &= ~CRTSCTS;

   //options.c_lflag &= ~(ICANON | ECHO | ISIG);

   options.c_lflag = 0;

   options.c_iflag = 0;
   options.c_oflag = 0;

   options.c_cc[VTIME] = 6;
   options.c_cc[VMIN] = 3;
   // Generated Attributes

   tcflush(fd, TCIFLUSH);
   tcsetattr(fd, TCSANOW, &options);
   // Flush things and set the attribs

   ioctl(fd, TIOCMGET, &status);
   // Get Status   

   status |= TIOCM_RTS;
   status &= ~TIOCM_DTR;
   ioctl(fd, TIOCMSET, &status);
   // Set RTS high and DTR low

   sleep(2);    

   bits=read(fd,&buf,sizeof(buf));
   if ((buf[0] != 0x2B) || (bits != 3)) {
      return -1;
   }

   return 0;
}

int get_channel(int fd,
      int *voltage,
      unsigned char channel,
      unsigned char res,
      unsigned char single) {

   union {
      struct {
         unsigned char lbyte;
         unsigned char hbyte;
      } bytes;
   unsigned int returned;
   } numbers;

   unsigned char request;
   unsigned char buf[3]="";
   int bits;

   request = (channel) << 5; //Generate the channel

   request |= (res-1) << 1; //Resolution for that channel

   request |= (single); // If the channel is single ended

   write(fd, &request, 1);
   

   bits=read(fd,&buf,sizeof(buf));
   if (bits != 3) {
      return -1;
   }

   numbers.bytes.hbyte = buf[1];
   numbers.bytes.lbyte = buf[2];
   
   if (buf[0] == 0x2B) {
      (*voltage) = (numbers.returned*2500)/(pow(2,res)-1); // Positive number, do the adc math
   }   
   else {
      (*voltage) = 0-(numbers.returned*2500)/(pow(2,res)-1);   // Negative number, "
   }

return 0;
}

void *picoreader(void *args) {
   int i, fd, req;
   char buf[2];
   container *params =(container*)args;

   fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
   if (fd == -1) {
      printf("Unable to open /dev/ttyS0\n");
   }

   fcntl(fd, F_SETFL, 0);
   
   if (open_link(fd) == -1) {
      printf("Opening link failed\n");
   }

   req=0x01;

   write(fd, &req, 1);
   read(fd, &buf, sizeof(buf));

   params->model=buf[0];
   params->version=buf[1];

   while(1) {
      for (i=0; i<8; i++) {
         switch (params->chanmode[i]) {
            case 'S':
               get_channel(fd, &params->results[i], i, params->chanres[i], 1);
               break;
            case 'D':
               get_channel(fd, &params->results[i], i, params->chanres[i], 0);
               break;
            default:
               break;
         }
      }
   }

   close(fd);
   printf("Port closed\n");
}

void initparams(container *params) {
   params->results=(int*)malloc(sizeof(int) * 8);
   memset(params->results, 0, sizeof(int) * 8);

   params->chanres=(int*)malloc(sizeof(int) * 8);
   memset(params->chanres, 16, sizeof(int) * 8);

   params->chanmode=(char*)malloc(sizeof(char) * 8);
   memset(params->chanmode, '-', sizeof(char) * 8);

   params->model=0;
   params->version=0;
}

int main (void) {

   int i;   
   container params;
   pthread_t thread1;

   initparams(&params);   

   params.chanmode[0]='D'; //For testing perposes, set the first channel to difference mode (options are S for single end and D)
   
   printf("Starting\n");
   pthread_create(&thread1, NULL, picoreader, &params); // Spawn picoreader on a new thread and pass it the address of the results var

   sleep(8); // Sleep so the thread can stabilise and get first data. This could be replaced with a ready flag from the other thread.
   printf("Started\n");   

   printf("ADC-%i, Version:%i\n", params.model, params.version);

   while(1) {
      for (i=0; i<8; i++) {
         printf("%i ", params.results[i]); // Print what is in the variable
      }
      printf("\n");   
      sleep(1);
   }

   return 0;
}
Wipster
User
User
 
Posts: 3
Joined: Fri Oct 02, 2009 3:24 pm


Return to Linux

Who is online

Users browsing this forum: No registered users and 0 guests