Real Time Data Logging

Started 5th January 2017, Finished 10th February 2017

The aim is to use an ATMega 328 with an ADS1115 analogue to digital converter to record readings from three channels to SD card at a rate of around 200 x 3 channels (= 600) samples per second. It is desired to record the absolute real time (year, month, day, hour, minute, second, microsecond) that the samples are measured at and for this time to be accurate.

The first piece of code is [1] an interrupt driven library for the I2C bus which is used to talk to the ADS1115. This library can process queues of I2C commands under interrupts. A queue of three commands is set up, these read the ADC value (which takes two commands) and then initiate the next read.

I'm using the ADC multiplexer so the initiate command steps through the three channels. When an ADC conversion is complete the ADS1115 signals this using the 'Alert' pin, which is connected to pin 2 (Arduino notation) on the ATMega 328, the resulting interrupt is used to call a function to set up another queue of I2C commands (advancing the multiplexer and incrementing the address to store the ADC value in).

The second piece of code is [2] the "SD Fat" library, which provides routines for writing to SD cards. This is a big piece of work covering various aspects of using SD cards. It comes with several example programs, the one I have borrowed from is AnalogBinLogger, this is capable of sampling five ATMega 328 analog pins 5,000 times per second (25,000 samples per second).

Data is written in a series of 512 byte blocks structured as follows:

const size_t DATA_DIM16 = 249; // 3 * 83
struct block16_t 
  unsigned short count;    // count of data values
  unsigned short overrun;  // count of overruns since last block
  unsigned long  seconds;
  unsigned long  microseconds;
  unsigned short data[DATA_DIM16];
  unsigned short spare;

On running the program asks for you to type r followed by return, data is then recorded to a file with an automatically generated file name. Logging stops when any character followed by return is typed or when the maximum file size defined in the code is reached.

To get absolute real times a GPS module is used. This provides a serial stream of the real times and a 1 pulse per second signal (PPS) which is accurate to the microsecond level. Software is required to tell the GPS module what to do and to parse the serial stream that comes back - I used the compact NeoGPS library [3].

The GPS module requires a serial port, the only hardware port on the ATMega 328p is being used for debugging, so it is necessary to implement a serial port in software. I used AltSoftSerial [4].

The result of all this is that pins 8 and 9 connect to the GPS module for serial data. Pin 3 connects to the PPS output.

A further complication is that GPS data may not always be available, so a DS321 real time clock (RTC) has its PPS output connected to pin 4. If you're using the same ebay board, changes to its battery charging circuit are wise, see Wireless sensor data logger.

The RTC and GPS are combined to give the accurate real time in microseconds and this is used to time-stamp the data blocks written to the SD card.

Photos show the set up.

RTDL setup, David PillingRTDL setup, David Pilling

The processor is running from 5V all the peripherals use 3.3V, as a result the two pieces of protoboard contain eight single FET level shifters [5]. In addition there is an AMS1117 voltage regulator providing 3.3V.

On the left of the white breadboard are three potentiometers feeding test voltages into the ADC.

Two photos showing the SD card module interface
RTDL setup, David PillingRTDL setup, David Pilling

Two photos showing the GPS and RTC module interfaces
RTDL setup, David PillingRTDL setup, David Pilling

Given the speed of the ADC the code is good enough. However it could be made better by optimising the two PPS interrupt routines, which do complicated (and time consuming) calculations. Another idea would be to use the ATMega timer capture register for the PPS signal, which would mean not using it for the software serial port (and using a different software serial port implementation).


I used a lot of freely available software. Credit to the people who wrote it and made it available.

Software sources:

  1. avr-i2c - A simple, interrupt driven I2C API for Atmel AVR processors
  2. SdFat - Arduino FAT16/FAT32 Library
  3. NeoGPS - NMEA and ublox GPS parser for Arduino, configurable to use as few as 10 bytes of RAM
  4. AltSoftSerial - Software emulated serial using hardware timers for improved compatibility
  5. Bi-Directional MOSFET Voltage Level Converter 3.3V to 5V


Click to return to index

Page last modified on March 27, 2017, at 02:16 AM
Powered by PmWiki