Here’s a simple circuit I
came up with as part of
another project I was
working on to measure
the acceleration of a
model rocket in flight.
While my original data
storage requirements
for that project were
very specific (and very
basic), I realized that
the datalogging circuit
and code had many
other uses.
This datalogger is
suitable for just
about any application
where a small, cheap,
low power circuit is
needed to sample
analog voltages,
convert them to digital
values, and store a
modest amount of data
in non-volatile memory.
42
January 2008
●●●●
SINGLE CHIP, FOUR
CHANNEL
DATALOGGER
The circuit shown in Figure 1
is based on a Microchip
PIC16F876A microcontroller. This
chip has a built-in, five channel
10-bit analog-to-digital converter
(ADC), but only four channels are
shown being used. It is very simple
to modify the code to use from one
to all five ADC channels (more on
this later).
A linear voltage regulator (such
as the LM78L05) powers the PIC
and any five volt tolerant sensors
which may be added to the circuit.
One mode-select jumper is used to
place the microcontroller in data
acquisition mode or in “data dump”
mode. An in-circuit serial programming (ICSP) header is included to
reprogram the PIC after the circuit
has been assembled, along with a
diode to prevent the programming
voltage from getting into the rest of
the circuit via the five volt bus.
The 876A contains three
different types of memory: 368 bytes
of RAM, 256 bytes of EEPROM, and
8,192 words of Flash program
memory. There isn’t enough RAM or
EEPROM for serious data storage,
and the Flash memory is for the program code, so where can our data go?
Well, if we are very careful,
we can use the WRITECODE
and READCODE instructions in
PICBASIC PRO (available at www.
melabs.com) to store that data in
the Flash program memory. The
code listing (available at www.
nutsvolts.com) only uses about 400
words of program memory. That
leaves nearly 7,800 words for data
storage; enough to capture more
than 1,900 samples of the four
10-bit ADC values.
The code starts out by defining
variables, and the most important of
these is the “pointer” variable. This
defines the address in the Flash
memory at which the data will be
written during data acquisition. The
initial value of this variable is set at
an address beyond the last word of
program code, so there is a bit of
unused memory between code and
data. If you modify and recompile
the code, you must check how
many words your new code occupies and adjust the initial pointer
value accordingly to make sure your
data cannot overwrite your code.
Next, the code checks the
status of the mode select jumper on
pin RA4 and jumps to either the
data acquisition loop or the data
dump loop. The two loops are very
similar in structure, using the same
variables to cycle through the ADC
channels and either write to or read
from the Flash memory. Each loop is
terminated with an END command,
so that when all of the memory has
been written or read, the PIC will
enter a power-saving sleep mode.
The number of ADC channels
used is determined by the “channel”
variable, which is used to set
the number of times the ADCIN
command is executed in each pass
through the data acquisition loop.