|
EV Logger
A MSP430 based datalogger for an electric vehicle
|
Data Structures | |
| struct | RingBuffer |
| A ring buffer which can be attached to given (preallocated) memory area. More... | |
| struct | SampleBuffer |
| A structure to contain one 'set' of samples from the vehicle. More... | |
Macros | |
| #define | rb_getused_m(b) ((b->tail==b->head) ? 0:(b->head - b->tail + b->len) % b->len) |
| Quick facility to get the used value of a ring buffer. More... | |
| #define | rb_getfree_m(b) ((b->tail==b->head) ? b->len : (b->tail - b->head + b->len) % b->len) |
| Quick facility to get the free value of a ring buffer. More... | |
| #define | rb_reset_m(b) do {b->tail = b->head = 0} while (0) |
| Reset a ring buffer to its original empty state. More... | |
| #define | S1_PORT_OUT P1OUT |
| #define | S1_PORT_REN P1REN |
| #define | S1_PORT_IES P1IES |
| #define | S1_PORT_IE P1IE |
| #define | S1_PORT_IFG P1IFG |
| #define | S1_PIN _BV(7) |
| #define | S2_PORT_OUT P2OUT |
| #define | S2_PORT_REN P2REN |
| #define | S2_PORT_IES P2IES |
| #define | S2_PORT_IE P2IE |
| #define | S2_PORT_IFG P2IFG |
| #define | S2_PIN _BV(2) |
| #define | SD_RINGBUF_LEN 2048 |
| Ring buffer length for the SD card, should be a multiple of 2 of the sector size (512 bytes) | |
| #define | SD_RINGBUF_MASK (SD_RINGBUF_LEN - 1) |
| The ring buffer mask value. More... | |
| #define | ADC_CHANNELS 7 |
| The number of ADC channels that we will sample from. More... | |
| #define | ACCEL_CHANNELS 3 |
| The number of accelerometer channels (typically 3) to be sampled from. More... | |
Typedefs | |
| typedef struct RingBuffer | RingBuffer |
| typedef struct SampleBuffer | SampleBuffer |
Functions | |
| void | logger_init (void) |
| Set up the hardware for logging functionality, including the configuration of required peripherals such as the ADC and Accelerometer. More... | |
| void | update_lcd (RingBuffer *buf) |
| Update the LCD with the current status of the logger, including buffer usage, data file size and SD card utilisation. More... | |
| void | start_logger (RingBuffer *sdbuf) |
| Set up the SD card and the FATFS filesystem handler before commencing the logging service. More... | |
| FRESULT | sd_write (RingBuffer *rb, char *writebuf, FIL *fil, uint16_t n) |
| Write n bytes from a ring buffer to an SD card controlled by fatfs. More... | |
| uint8_t | ringbuf_write (RingBuffer *buf, char *data, uint16_t n) |
| Write n bytes to a RingBuffer. More... | |
| uint8_t | ringbuf_read (RingBuffer *buf, char *read_buffer, uint16_t n) |
| Read n bytes from a ring buffer. More... | |
| void | logger_enable (void) |
| Enable TA1 to begin logging by setting mode control to "up" mode, counter counts to TAxCCR0. More... | |
| void | logger_disable (void) |
| Disable TA1 to halt logging by setting mode control to STOP. More... | |
| interrupt (TIMER1_A0_VECTOR) | |
| Interrupt service routine for Timer A1 (TA1), where we should log one block of data. More... | |
| interrupt (PORT1_VECTOR) | |
| Interrupt vector for button S1 which is used for enabled and disabling logging. More... | |
| interrupt (PORT2_VECTOR) | |
| Interrupt vector for button S2. | |
Variables | |
| static volatile uint32_t | time |
| static volatile uint8_t | logger_running |
| static volatile uint8_t | file_open |
| static char | s [UART_BUF_LEN] |
| static char | ringbuf [SD_RINGBUF_LEN] |
| static char | writebuf [512] |
| static RingBuffer | sdbuf |
| A RingBuffer that we will use to buffer sets of samples that are to be moved to the SD card. | |
| static volatile SampleBuffer | sb |
| A SampleBuffer to store a single set of readings before they are transferred into the SD transaction buffer. More... | |
| FATFS | FatFs |
| A FATFS filesystem object which we use to handle files and directories on the SD Card. More... | |
| FIL | fil |
| A pointer to the data file. | |
| DWORD | fsz |
| Stores the current size of the data file. | |
| char * | RingBuffer::buffer |
| A pointer to the start of the character buffer to be used by this ring buffer. | |
| uint16_t | RingBuffer::head |
| A pointer to the head of the ring buffer (the next free byte available for writing). | |
| uint16_t | RingBuffer::tail |
| A pointer to the tail of the ring buffer (the next unread byte) | |
| uint16_t | RingBuffer::len |
| The length of the ring buffer. | |
| uint16_t | RingBuffer::mask |
| This value is a ring buffer intrinsic and is automatically generated. | |
| uint8_t | RingBuffer::overflow |
| A flag that will be set non-zero if a buffer overflow occurs (the head tries to "overtake" the tail. | |
| volatile uint16_t | SampleBuffer::adc [ADC_CHANNELS] |
| Storage for the ADC channels. | |
| volatile uint16_t | SampleBuffer::accel [ACCEL_CHANNELS] |
| Storage for the accelerometer channels. | |
| #define ACCEL_CHANNELS 3 |
The number of accelerometer channels (typically 3) to be sampled from.
This must be set correctly such that the DMA transfer system will work correctly.
| #define ADC_CHANNELS 7 |
The number of ADC channels that we will sample from.
It is vital that this is correctly set such that the DMA system will work properly.
| #define rb_getfree_m | ( | b | ) | ((b->tail==b->head) ? b->len : (b->tail - b->head + b->len) % b->len) |
Quick facility to get the free value of a ring buffer.
| b | A pointer to the buffer which we wish to query |
| #define rb_getused_m | ( | b | ) | ((b->tail==b->head) ? 0:(b->head - b->tail + b->len) % b->len) |
Quick facility to get the used value of a ring buffer.
| b | A pointer to the buffer which we wish to query |
| #define rb_reset_m | ( | b | ) | do {b->tail = b->head = 0} while (0) |
Reset a ring buffer to its original empty state.
| b | A pointer to the buffer which we wish to query |
| #define SD_RINGBUF_MASK (SD_RINGBUF_LEN - 1) |
The ring buffer mask value.
This is automatically calculated.
| interrupt | ( | TIMER1_A0_VECTOR | ) |
Interrupt service routine for Timer A1 (TA1), where we should log one block of data.
We do this by copying the current SampleBuffer into the RingBuffer used for SD transactions. There is no processing of the data since it is too slow – this is left to post-processing on a desktop machine. We then trigger the next conversion runs for the ADC and accelerometer such that next time we enter this ISR, new data will be in the SampleBuffer sb.
| interrupt | ( | PORT1_VECTOR | ) |
Interrupt vector for button S1 which is used for enabled and disabling logging.
We should debounce the button press using the system ticks timer, and then enable or disable logging as required.
| void logger_disable | ( | void | ) |
Disable TA1 to halt logging by setting mode control to STOP.
The flag logger_running is deasserted so that the start_logger() loop notices and cleanly flushes and closes the data file. We also write to the LCD to show that logging has stopped.
| void logger_enable | ( | void | ) |
Enable TA1 to begin logging by setting mode control to "up" mode, counter counts to TAxCCR0.
The flag variable logger_running is asserted such that the start_logger() loop notices that logging has started as should open the data file if it has not already done so. We also write to the LCD to show that logging has been started.
| void logger_init | ( | void | ) |
Set up the hardware for logging functionality, including the configuration of required peripherals such as the ADC and Accelerometer.
Timer A1 (TA1) is configured to interrupt at the log frequency (1kHz), the interrupt service routine (ISR) is TIMER1_A0_ISR() also found in this file (please see that function's documentation for details of what is done in the ISR).
| uint8_t ringbuf_read | ( | RingBuffer * | buf, |
| char * | read_buffer, | ||
| uint16_t | n | ||
| ) |
Read n bytes from a ring buffer.
This is done via a fast memcpy operation and as such, there is logic in this function to transparently handle the copy even if we're wrapping over the boundary of the ring buffer.
| buf | A pointer to the ring buffer we want to write to |
| read_buffer | Copy data into this array |
| n | The number of bytes to be read from the ring buffer |
| uint8_t ringbuf_write | ( | RingBuffer * | buf, |
| char * | data, | ||
| uint16_t | n | ||
| ) |
Write n bytes to a RingBuffer.
This is done via a fast memcpy operation and as such, there is logic in this function to transparently handle the copy even if we're wrapping over the boundary of the ring buffer.
| buf | A pointer to the ring buffer we want to write to |
| data | A pointer to the data to be written |
| n | The number of bytes to be written to the ring buffer |
| FRESULT sd_write | ( | RingBuffer * | rb, |
| char * | writebuf, | ||
| FIL * | fil, | ||
| uint16_t | n | ||
| ) |
Write n bytes from a ring buffer to an SD card controlled by fatfs.
We turn on the red LED on the board during an SD write transaction such that the user can monitor the frequency and duration of writes. This is particularly helpful in watching for SD clock stretching which often causes buffer overflow.
| rb | A pointer to the ring buffer from which we will read the required data. |
| writebuf | A short buffer where we can temporarily place a single before before writing it to the card. |
| n | The number of bytes to be written to the card. |
| fil | A pointer to the file to which we want to write. |
| void start_logger | ( | RingBuffer * | sdbuf | ) |
Set up the SD card and the FATFS filesystem handler before commencing the logging service.
The controls regularly moving blocks of data from the SD buffer to the card using sd_write(), which is done when the SD buffer size has reached at least the sector size such that we write as quickly as possible. It also calls for LCD display updates (with update_lcd()) and handling opening/closing of the data file when logging starts/stops.
| sdbuf | A pointer to the SD card buffer. This is a RingBuffer that we will use to buffer incoming samples before they are logged to the SD card, such that we can write entire sectors at once. |
| void update_lcd | ( | RingBuffer * | buf | ) |
Update the LCD with the current status of the logger, including buffer usage, data file size and SD card utilisation.
| buf | A pointer to the RingBuffer which we are monitoring. |
| FATFS FatFs |
A FATFS filesystem object which we use to handle files and directories on the SD Card.
|
static |
A SampleBuffer to store a single set of readings before they are transferred into the SD transaction buffer.
1.8.6