Monday, October 18, 2010

I wanted to read out a Lakeshore 218 Temperature monitor through a serial connection, but Lakeshore does not supply a program to extract any data, so I have to write my own... Here is how I stumbled in setting up a connection to the monitor:

First I have to connect a serial to USB adapter and find a driver for it for Linux. Luckily, the one I bought (Radioshack brand) uses a Prolific chipset for which there are preinstalled drivers available, so it worked plug and play (which I figured out only after plugging it into a terminal software and sending some messages back and forth with another PC). I also had to use the device name /dev/ttyUSB0 and not /dev/usb/ttyUSB0 as was suggested in some other articles on the net.

I am using Code::Blocks IDE 8.02 for Ubuntu on KDE to write a program that will determine how much data there is on the monitor, and then query each dataset, while writing all the data into a .csv file.

I am writing this in plain C, as this seems to be the most straightforward way of getting the data. It is recommended in several places to use threaded querying, separate threads for sending and reading and other stuff, but I am just trying to get something to work before I delve into some more exotic stuff that I will have to debug.

I dug through a few tutorials that were relatively unsuccessful, and finally stumbled upon a wikibook explaining the termios.h header file that was referenced in some other tutorials. It had this convenient piece of code (that originally asked you to supply an argument when opening the program to specify the serial device to open, but I modified it to statically open my USB to serial adapter (/dev/ttyUSB0)).



#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
 
int main(int argc,char** argv)
{
        struct termios tio;
        struct termios stdio;
        int tty_fd;
        fd_set rdset;
 
        unsigned char c='D';
 
//        printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]);
        memset(&stdio,0,sizeof(stdio));
        stdio.c_iflag=0;
        stdio.c_oflag=0;
        stdio.c_cflag=0;
        stdio.c_lflag=0;
        stdio.c_cc[VMIN]=1;
        stdio.c_cc[VTIME]=0;
        tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
        tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
        fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);       // make the reads non-blocking
 
 
 
 
        memset(&tio,0,sizeof(tio));
        tio.c_iflag=0;
        tio.c_oflag=0;
        tio.c_cflag=CS8|CREAD|CLOCAL;           // 8n1, see termios.h for more information
        tio.c_lflag=0;
        tio.c_cc[VMIN]=1;
        tio.c_cc[VTIME]=5;
 
        tty_fd=open(argv[1], O_RDWR | O_NONBLOCK);      
        cfsetospeed(&tio,B115200);            // 115200 baud
        cfsetispeed(&tio,B115200);            // 115200 baud
 
        tcsetattr(tty_fd,TCSANOW,&tio);
        while (c!='q')
        {
                if (read(tty_fd,&c,1)>0)        write(STDOUT_FILENO,&c,1);              // if new data is available on the serial port, print it out
                if (read(STDIN_FILENO,&c,1)>0)  write(tty_fd,&c,1);                     // if new data is available on the console, send it to the serial port
        }
 
        close(tty_fd);
}