/* $Id: tsl.c,v 1.12 2004/01/26 06:58:50 james Exp james $ tsl, temperature sensor data logger Copyright (C) 2000 James Cameron (quozl@us.netrek.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef lint static char vcid[] = "$Id: tsl.c,v 1.12 2004/01/26 06:58:50 james Exp james $"; #endif /* lint */ #include #include #include #include #include #include #define MAXSENSOR 4 /* compile support for conversion from celcius to fahrenheit */ #define FEATURE_CONVERSION 1 #ifdef TSL_DJGPP /* ftp://sunsite.anu.edu.au/pub/pc/simtelnet/gnu/djgpp/v2tk/pmcom10.zip */ #include <../contrib/pmcom/com.h> char serial; void serial_open(char *device) { int result; serial = atoi(device)-1; result = COMPortOpen(serial, (long) 2400, 8, 'N', 2, 0, NULL); switch(result) { case 0: COMSetDtr(serial, 1); return; case COMERR_NOCHIP: printf("tsl: COMPortOpen: No UART chip detected for that serial port\n"); exit(1); case COMERR_NOMEMORY: printf("tsl: COMPortOpen: No memory to allocate receive buffer\n"); exit(1); case COMERR_GENERAL: printf("tsl: COMPortOpen: Library setup failure\n"); exit(1); default: printf("tsl: COMPortOpen: unknown status\n"); exit(1); } } void serial_halt() { COMSetDtr(serial, 0); } void serial_resume() { COMSetDtr(serial, 1); } char *serial_read(char *buffer, int size) { char *p, c; int l; p = buffer; l = 0; for(;;) { int result; result = COMReadChar(serial, &c, NULL); switch (result) { case 0: break; case COMERR_RXOVERFLOW: printf("tsl: COMReadChar: receive buffer overflow\n"); continue; case COM_BUFEMPTY: continue; } *p++ = (char) (c & 0xff); l++; if (c == '\n' || l == size-1) { *p++ = '\0'; return buffer; } } } #else /* TSL_DJGPP */ #include #include FILE *serial; void serial_open(char *device) { int fd; struct termios termios; serial = fopen(device, "r" ); if (serial == NULL) { char buffer[1024]; sprintf(buffer, "fopen: %s", device); perror(buffer); exit(1); } /* set the serial port characteristics */ fd = fileno(serial); if (tcgetattr(fd, &termios) < 0) { perror("tcgetattr"); exit(1); } if (cfsetospeed(&termios, B2400) < 0) { perror("cfsetospeed"); exit(1); } if (cfsetispeed(&termios, B2400) < 0) { perror("cfsetispeed"); exit(1); } if (tcsetattr(fd, TCSANOW, &termios) < 0) { perror("tcsetattr"); exit(1); } } void serial_halt() { /* not required, operating system buffers data */ } void serial_resume(char *device) { /* not required, operating system buffers data */ } char *serial_read(char *buffer, int size) { char *p; p = fgets(buffer, size, serial); if (p == NULL) { perror("fgets"); exit(1); } return p; } #endif /* TSL_DJGPP */ int main ( int argc, char *argv[] ) { char *device, *p, buffer[128], *pad = " "; char *name = "%4.4d%3.3d.log"; FILE *output = NULL; int i, number, sample, was, seen[MAXSENSOR]; #ifdef FEATURE_CONVERSION int cf = 0; #endif time_t now; struct tm *tm; float datum[MAXSENSOR]; int breaker = 0; /* reset sensor result array */ for (i=0; i 1) { device = argv[1]; printf("Selected input serial port %s\n", device); } /* allow user to specify sample recording rate */ sample = 30; if (argc > 2) { sample = atoi(argv[2]); printf("Selected sample recording rate %d seconds\n", sample); } /* allow user to specify recording file name */ if (argc > 3) { name = argv[3]; printf("Selected recording file name %s\n", name); } #ifdef FEATURE_CONVERSION /* allow user to specify conversion */ if (argc > 4) { cf = atoi(argv[4]); if (cf) printf("Selected conversion from celcius to fahrenheit\n"); } #endif /* open the serial port, causing DTR to be raised and the sensor to run */ serial_open(device); atexit(serial_halt); printf("Awaiting data from microcontroller ...\r"); /* infinite loop */ for(;;) { /* get a line of data from the sensor */ p = serial_read(buffer, 128); /* remove the terminating lf or cr */ p = buffer + strlen(buffer) - 1; while (*p == '\r' || *p == '\n') { *p-- = '\0'; if (p < buffer) break; } /* remove preceeding lf or cr */ p = buffer; while (*p == '\r' || *p == '\n') p++; /* establish timestamp for this sample */ now = time(NULL); tm = localtime(&now); /* check packet header for reset detection */ if (*p == 'R') { printf("Microcontroller reports version %s\n\n", p+2); #ifdef FEATURE_CONVERSION /* if conversion to fahrenheit is enabled in tsl, check that the reset message from the microcontroller agrees, and if not, turn off conversion mode */ if (cf) { if (strstr(p, " F")) { printf("Warning: microcontroller is set to fahrenheit, disabling conversion\n\n"); cf = 0; } } #endif #ifdef FEATURE_DECIMAL_HOURS printf( "%s+---------+--------+--------+--------+--------+\n" "%s| Time | DS1 | DS2 | DS3 | DS4 |\n" "%s+---------+--------+--------+--------+--------+\n", pad, pad, pad); #else printf( "%s+-------------------+--------+--------+--------+--------+\n" "%s| Year-Day Time | DS1 | DS2 | DS3 | DS4 |\n" "%s+-------------------+--------+--------+--------+--------+\n", pad, pad, pad); #endif continue; } /* ignore any other packet header other than sensor reports */ if (!isdigit(*p)) continue; /* decode the sensor number */ number = atoi(p)-1; if (number < 0 || number > MAXSENSOR-1) continue; /* check for missing blank, ignore the line as corrupt */ p++; if (*p != ' ') continue; /* check for verbose mode additional data, and skip it */ if (strlen(p) > 9) p += 11; /* read and decode the data */ p++; sscanf(p, "%f", &datum[number]); #ifdef FEATURE_CONVERSION /* celcius to fahrenheit conversion */ if (cf) datum[number] = datum[number] * 9.0 / 5.0 + 32.0; #endif /* we've seen this sensor, start a countdown */ seen[number] = 5; /* display the current samples */ #ifdef FEATURE_DECIMAL_HOURS printf("%s| %7.4f |", pad, (float) tm->tm_hour + (float) tm->tm_min / 60.0 + (float) tm->tm_sec / 3600.0); #else printf("%s| %04d-%03d %02d:%02d:%02d |", pad, tm->tm_year+1900, tm->tm_yday+1, tm->tm_hour, tm->tm_min, tm->tm_sec); #endif for (i=0; itm_year+1900, tm->tm_yday+1); if (output == NULL) { output = fopen(new, "a"); if (output == NULL) { perror(new); exit(1); } strcpy(old, new); } else { if (strcmp(old, new)) { fclose(output); output = fopen(new, "a"); if (output == NULL) { perror(new); exit(1); } strcpy(old, new); } } /* gnuplot deserves a blank line for a new sample range, aka run */ if (!breaker) { fprintf(output, "\n"); breaker++; } /* format the file output, comma separated value list */ #ifdef FEATURE_DECIMAL_HOURS fprintf(output, "%7.4f", (float) tm->tm_hour + (float) tm->tm_min / 60.0 + (float) tm->tm_sec / 3600.0); #else fprintf(output, "%04d,%03d,%02d,%02d,%02d", tm->tm_year+1900, tm->tm_yday+1, tm->tm_hour, tm->tm_min, tm->tm_sec); #endif for (i=0; i 59) { fclose(output); output = NULL; } /* force display to new line */ printf("\n"); } } }