Serial Logger

From Hamsterworks Wiki!

Jump to: navigation, search

Sometimes you just need to get data from your Arduino and log it on a PC. You also want to timestamp it. How hard can that be?

I haven't been able to find anything that does it so I've hacked one up.

It is very primitive, just opening the serial port and logging data. Set the Serial port properties in device manager (defaults are 9600-9-N-1, no flow control).

This timestamps in UTC - well... that is what Microsoft say GetSystemTime() returns - but it isn't. GetSystemTime makes now allowances for leap seconds.

If you want to log in local time change GetSystemTime() to GetLocalTime(), and then have the joys of missing hours, doubled hours and apparently out of order records when daylight savings comes and goes.

Sample output

Here's the Arduino test sketch:

void setup() 
{ 
  Serial.begin(9600); 
} 

void loop() 
{ 
  Serial.println("Hello!"); 
  delay(1000);
} 

Writing to the screen

C:>serial_logger.exe COM5
2012-07-04 09:28:26 Hello!
2012-07-04 09:28:27 Hello!
2012-07-04 09:28:27 Hello!
2012-07-04 09:28:29 Hello!
2012-07-04 09:28:30 Hello!
^C

Logging to a file

C:\>serial_logger.exe COM5 data.txt
^C
C:\>type data.txt
2012-07-04 09:30:15.731 Hello!
2012-07-04 09:30:16.714 Hello!
2012-07-04 09:30:17.696 Hello!
2012-07-04 09:30:18.679 Hello!

Source code

I'm also a UNIX programmer so have badly abused the Windows API. It compiles under Microsoft Visual C++ express.

// serial_logger.cpp : Reads lines from a serial port and outputs them with a timestamp
//
// Author: Mike Field <hamster@snap.net.nz>
//
// Supplied as is, where is.
//

#include "stdafx.h"
#include "windows.h"

static char usage[] =  "\n"
                       "Usage: serial_logger [/l] COMx [logfile.txt]\n"
                       "\n"
                       "The '/l' will cause it to log in localtime rather than UTC\n"
                       "\n"
                       "Remember that COM ports above COM8 can be addressed with \\\\.\\COMx\n\n";

int main(int argc, char *argv[])
{
  char buffer[1024];
  int pos = 0;
  int c = 0;
  int localtime = 0;
  FILE *f;

  if(argc > 1 && strcmp("/l",argv[1])==0) {
    localtime = 1;
    argc--;
    argv++;
  }

  if(argc != 2 && argc != 3) {
    fprintf(stderr,usage);
    return 0;
  }

  f = fopen(argv[1],"r+");
  if(f == NULL) {
    fprintf(stderr,"Unable to open input\n");
    return 0;
  }

  for(;;) {
    c = getc(f);

    if(c == EOF) { Sleep(100); continue; }

    if(c == '\r')   continue;

    if(c == '\n') {
      SYSTEMTIME st;
      FILE *log;

      buffer[pos] = 0;
      pos = 0;
      if(localtime)
 	GetLocalTime(&st);
      else
        GetSystemTime(&st);

      if(argc == 3) {
        log = fopen(argv[2],"a+");
        if(log == NULL) {
          fprintf(stderr,"Unable to open log file\r\n");
          break;
        }

        fprintf(log, "%04i-%02i-%02i %02i:%02i:%02i.%03i ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
        fprintf(log, "%s\r\n",buffer);
        fclose(log);
      } else {
        printf("%04i-%02i-%02i %02i:%02i:%02i.%03i ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
        printf("%s\r\n",buffer);
      }  
    } else if(pos < sizeof(buffer)-2)
      buffer[pos++] = c;
  }

  // Never get here
  fclose(f);
  return 0;
}

Binary

Here's the binary: File:Serial logger.zip

Personal tools