Close

Firmware

A project log for Data Logger

A simple and extensible data logger with Bluetooth

brian-cornellBrian Cornell 10/12/2018 at 19:590 Comments

Detailed operation of the firmware is best obtained by studying the code.  This log describes general operation.  The firmware can be divided into four sections:

  1. Command
  2. Communications
  3. Logging
  4. Timing

The Command section handles operator input.  Logger is configured thru the Bluetooth SPP interface.  All commands are 1~2 characters in length and contain a variable number of parameters depending on their function.  Data is parsed, bounds checked and stored as binary data in control structures.

All Communications is handled by an RS232 module.  Data received generates an interrupt which is processed by a function called from the ISR.  Received data is stored in a buffer which is terminated when a carriage return (CR) is received.  Receive operations occur in the background via ISR; the foreground process can poll for status of received data, clear the buffer, and process once a CR is received.

Data transmission is done by the foreground process.  In command mode responses to commands are printed using the standard C library printf function.  This calls putch in the RS232 module to send the formatted output.  In logging mode data transmission is performed by the TxLog function.  TxLog is called on each pass thru the logging loop.

CTS/RTS flow control is used between the MCU and Bluetooth module to prevent data loss.

The Logging code can be further broken down into three areas:  analog, digital, and buffer management.

Analog logging is done by polling.  When logging is started, the foreground control loop calls the PollAnalog function.  It's responsible for determining what channels are active, the evaluation condition(s), measurement, data capture, and evaluating / executing output conditions.

Since the MCU has only one ADC, each channel that's monitored is done so in a four-step process:

  1. Select the channel
  2. Acquire (e.g. charge S&H cap)
  3. Convert
  4. Evaluate

It takes four calls of the PollAnalog function to get thru each active channel.  This limits the maximum sample rate but makes for much more efficient code which is necessary on this memory constrained MCU.

Linear hysteresis is employed for analog evaluations.  The user can specify how many successive samples must meet criteria before an event is logged.  Since it is operating in a polled environment to say that it is linear is not entirely true; the timing will vary based on logging activity which changes the time constant of the filter.

Digital logging is interrupt driven and uses the IOC (Interrupt On Change) feature.  When logging is enabled for a digital pin a change in its logic state triggers an interrupt.  An event record is created and written to the logging buffer.  To minimize the overhead in the ISR the hysteresis feature isn't available on digital pins; this means that external debounce / signal conditioning is necessary.

Buffer management is about getting event data out of logger.  Both analog & digital events call wrBuffer to create an event record.  The data varies based on type, but all events contain record type, sequence number, and elapsed time.  Reference logger.h for all the details.  Records are written to a circular buffer.  If full a status record is added (space is reserved for it) to note and subsequent event data is discarded until space is free.

During logging the foreground process calls TxLog on every pass to process buffer data.  Once a complete record is transmitted the buffer count is decremented & pointers are updated.

System Timing is performed in the ISR and controlled by two timers.  Timer1 is driven by an external [tuning fork] crystal and provides a precise interrupt every second.  Timer2 is driven by the MCU's internal oscillator at a frequency of 1kHz which allows 1mS timing.  The combination of timer 1 & 2 allow the timing of events down to the millisecond.  Timer1 also provides service for the user-available countdown timer.

Timer1 is also used to maintain Timer2's accuracy based on the mS count when Timer1's ISR is called.  The MCU's OSCTUNE register is adjusted in one-bit increments each second until the two are synchronized.

Discussions