Writing Code to Interface Channel 8 to a Serial Port A/D Converter

Introduction

Channel 8 can be easily modified to work with most serial port A/D devices. These connect to your PC through the RS232 serial port and typically use ASCII string command protocols. To operate your RS232 A/D converter with Channel 8 should require a minimum amount of C code and consist mostly of writing and reading characters to a COM port..

Channel 8 Architecture

Channel 8 consists of three separate programs that run concurrently under Linux, and a series of files to hold configuration data and constants. The relationship of each of these is shown here. A detailed discussion of each program and the various files is given in the Channel 8 documentation here.

You can see that Ch8RndServer.run is the program that communicates with the external hardware, whatever that may be. Ch8RndServer.run, as you have downloaded it, does not communicate with any external device but rather generates random numbers. Ch8RndServer.run is a Linux server running on port 3490. This means that any client calling port 3490 will receive a string of 8 numbers in reply. By changing Ch8RndServer.run the Channel 8 logging and webserver programs will get current analog data from your A/D.

To use Channel 8 with your serial port A/D, it will be necessary to modify the program Ch8RndServer.c, re-compile it, under a new name, and then run it in place of Ch8RndServer.run. Before doing that, however, it is best to write and de-bug the C code that will be needed to communicate with the A/D converter. Often the manufacturer will provide a detailed description of the ASCII protocols, and these are usually very simple - sometimes only a single command is required for the device to produce a string of readings in response.

SI430 Simple Interface Example

The SI430 interface was described in Project 1 and consists of a simple microprocessor with an A/D converter that connects to the serial port of a PC. The SI430 A/D converter has eight 10-bit channels that read from 0 to +5 Vdc. To receive a reading from one of the channels on the A/D converter, the requesting PC sends the channel number out over the serial line in ASCII text. The SI430 responds within 100 milliseconds with a string of numbers representing the A/D counts for that channel. The counts run from 0 to 1023 (2^10), and are proportional to the voltage applied to that channel such that 0 Vdc = 0 counts and 1023 counts = +5.000 Vdc.

So the code to communicate to theSI430 serial A/D converter will consist of a few very simple steps:

  1. Open the Serial Port
  2. Write the Desired Channel Number out to the Serial Port
  3. Wait for the SI430 to Respond
  4. Read in the String of Characters that are the A/D Counts
  5. Process the A/D Counts into Vdc

The best way to develop the code is to write a separate program. When it works, you can simply paste the code into Ch8RnDServer.c , re-compile and give the completed program a new name.

Here is some C code that requests a reading from channel 0 of the SI430 converter and then prints the received A/D counts to the screen. This simple program can be used as a starting point for development:

/* Serial Interface Program */
#include stdlib.h
#include stdio.h
#include time.h
main()
{
FILE *fptr;
char IP[5];
printf("Trying ttyS0 Port! \n");
fptr = fopen ("/dev/ttyS0", "r+");
fprintf(fptr, "0");
usleep(100000);
fgets(IP, 5, fptr);
fclose(fptr);
printf("Device Output %s \n", IP);
}

Note that the serial port, ttyS0, is treated like a normal file. In this way read and write operations are simplified. The program simply writes the channel number, "0", to the serial port and waits for a response. The SI430 replies with a string of up to four string characters that are the A/D counts

In order to try the program, compile using the following Linux command:

gcc -O serial1.c

The PC COM1 serial port in Linux is named ttyS0 and it is a standard Linux device that you can read or write to, just like a file. However you must first change the Linux permissions for serial port 0 so the program is allowed read and write to the RS232 port:

chmod 777 /dev/ttyS0

You can also set the serial port communication parameters: baud rate, handshaking, etc using the Linux stty command. Use stty --help for a summary of the command syntax. Most Linux systems default the serial ports to 9600 baud, 8 bits, 1 stop bit and no handshaking. Check the specifications of your serial A/D to be sure these parameters are set correctly.

To run the compiled SI430 interface program:

./a.out
Trying ttyS0 Port!
Device Output 789

Now that the basic program works, we can calculate the voltage using the following formula:

Vdc = (C/1024) * 5

Where C = the incoming counts and Vdc is the reading on the channel in volts..

Data Format for Channel 8 Client Programs

Now that we have a way to get readings from the external A/D in units of Vdc, we are ready to format the received data for the other Channel 8 clients. The format needed is very straightforward and consists of a single string that has 5-digit values for each channel separated by a single space, as shown below:

0.123 1.234 2.345 3.456 4.567 5.678 6.789 7.890

Note that each value must have the same number of digits, even if they are zeroes: the client programs parse this string into the eight separate substrings and determine the values in Vdc and then apply Scale and Offset Factors. Any missing places or extra digits in the string will cause the parsing scheme to produce incorrect values.

With the above requirements in mind, here is the final serial interface program that collects values from all 8 SI430 A/D channels, converts them to Vdc and formats a string for passing to client programs:

/* Serial Interface Program */
#include stdlib.h
#include stdio.h
#include time.h
#include string.h

main()
{

FILE *fptr;
char IP[5];
char *Vlu;
char Val[50];
double v[7];
double volts;
int ctr = 0;

while (ctr <8)
{
fptr = fopen ("/dev/ttyS0", "r+");
fprintf(fptr, "%d", ctr);
usleep(100000);
fgets(IP, 5, fptr);
volts = atof(IP);
v[ctr] = 5*volts/1024;
fclose(fptr);
usleep(100000);
ctr++;
}

ctr = 0;
while (ctr < 8)
{
asprintf(&Vlu, "%5.3f ", v[ctr]);
strcat(Val, Vlu);
ctr++;
}

printf("%s ", Val);

}

Now that the A/D interface code has been verified, it is simply a matter of inserting it into the Ch8RndServer.c file, compiling and testing it with the rest of the Channel 8 system. The section of Ch8RndServer.c that is appropriate is identified by the comments:

"// ------ Put A/D Code Here ---------"

and

" // ------------ End A/D Code ----------------".

Be sure to remove the code for generating random numbers.

Note that if the floating-point A/D values in volts are kept in an array named v[], the correct string will be automatically generated by the existing code for random values. This code is duplicated in the above example.

Final SI430 Server Program

Once the code has been placed into Ch8RndServer.c, it is no longer a random number generator and the entire file should be renamed appropriately. You could use Ch8SI430Server.c and compile it to Ch8SI430Server.run.

The final complete Ch8SI430Server.c program is shown here.

Testing Ch8SI430Server.run

The new server can be tested after it is compiled as follows:

First, kill Ch8RndServer.run if this process is active. It is using the same port as Ch8SI430Server.run, and this will cause problems if two programs are listening to the same port. You can list the active processes in Linux with the ps -A command. Then kill -9 the Ch8RndServer.run process ID.

The Channel 8 distribution contains a program called simpleclient.c. Compile this with gcc -O simpleclient.c and copy: cp a.out simpleclient.run

The simpleclient.run program will call port 3490 and print the string returned by the Ch8SI430Server to the PC screen. Here is the syntax:

./simpleclient.run localhost

The localhost is simply your PC running Ch8SI430Server.run. What you should see is the value of each of the 8 channels in Vdc on a single line, with each reading separated by a single space.

Running the New Server with Channel 8

To enable the new A/D interface, simply run the new Ch8SI430Server.run file instead of Ch8RndServer.run when starting up Channel 8.

./Ch8SI430Server.run&

A batch program is handy if you need to change the ttyS0 port permissions and set a baud rate for the RS232 port.