On boot, logs 10 seconds of current draw information from an INA169 breakout board to an SD card.
Dependencies: SDFileSystem mbed
main.cpp@0:c407693ac016, 2015-07-24 (annotated)
- Committer:
- ShawnHymel
- Date:
- Fri Jul 24 13:48:24 2015 +0000
- Revision:
- 0:c407693ac016
Initial release. Used in the SBC Benchmarking video.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ShawnHymel | 0:c407693ac016 | 1 | /** |
ShawnHymel | 0:c407693ac016 | 2 | * Current Log-O-Matic |
ShawnHymel | 0:c407693ac016 | 3 | * Author: Shawn Hymel @ SparkFun Electronics |
ShawnHymel | 0:c407693ac016 | 4 | * Date: July 1, 2015 |
ShawnHymel | 0:c407693ac016 | 5 | * |
ShawnHymel | 0:c407693ac016 | 6 | * Measures current using an INA169 breakout board. Stores current and timestamp |
ShawnHymel | 0:c407693ac016 | 7 | * to an SD card. |
ShawnHymel | 0:c407693ac016 | 8 | * |
ShawnHymel | 0:c407693ac016 | 9 | * INA169 Vout -> Pin 15 |
ShawnHymel | 0:c407693ac016 | 10 | * SD Card DI -> Pin 5 |
ShawnHymel | 0:c407693ac016 | 11 | * SD Card DO -> Pin 6 |
ShawnHymel | 0:c407693ac016 | 12 | * SD Card SCK -> Pin 7 |
ShawnHymel | 0:c407693ac016 | 13 | * SD Card CS -> Pin 8 |
ShawnHymel | 0:c407693ac016 | 14 | * |
ShawnHymel | 0:c407693ac016 | 15 | * This code is beerware; if you see me (or any other SparkFun |
ShawnHymel | 0:c407693ac016 | 16 | * employee) at the local, and you've found our code helpful, please |
ShawnHymel | 0:c407693ac016 | 17 | * buy us a round! |
ShawnHymel | 0:c407693ac016 | 18 | * |
ShawnHymel | 0:c407693ac016 | 19 | * Distributed as-is; no warranty is given. |
ShawnHymel | 0:c407693ac016 | 20 | */ |
ShawnHymel | 0:c407693ac016 | 21 | |
ShawnHymel | 0:c407693ac016 | 22 | #include "mbed.h" |
ShawnHymel | 0:c407693ac016 | 23 | #include "SDFileSystem.h" |
ShawnHymel | 0:c407693ac016 | 24 | |
ShawnHymel | 0:c407693ac016 | 25 | #define DEBUG 1 // 1 to print to console. 0 to turn off. |
ShawnHymel | 0:c407693ac016 | 26 | #define MAX_FILES 100 // Maximum number of log files to store on SD |
ShawnHymel | 0:c407693ac016 | 27 | #define DELAY_MS 0.02 // Time between samples (in seconds) |
ShawnHymel | 0:c407693ac016 | 28 | #define NUM_SAMPLES 500 // Number of samples to collect |
ShawnHymel | 0:c407693ac016 | 29 | #define RS 0.5 // Value of RS (sensing resistor) in ohms |
ShawnHymel | 0:c407693ac016 | 30 | #define RL 10000 // Value of RL (output resistor) in ohms |
ShawnHymel | 0:c407693ac016 | 31 | |
ShawnHymel | 0:c407693ac016 | 32 | // Digital output (status LED) |
ShawnHymel | 0:c407693ac016 | 33 | DigitalOut status_led(LED1); |
ShawnHymel | 0:c407693ac016 | 34 | |
ShawnHymel | 0:c407693ac016 | 35 | // Analog input (pin 15) |
ShawnHymel | 0:c407693ac016 | 36 | AnalogIn ain(p15); |
ShawnHymel | 0:c407693ac016 | 37 | |
ShawnHymel | 0:c407693ac016 | 38 | // USB serial (tx, rx) |
ShawnHymel | 0:c407693ac016 | 39 | Serial pc(USBTX, USBRX); |
ShawnHymel | 0:c407693ac016 | 40 | |
ShawnHymel | 0:c407693ac016 | 41 | // SD card (SPI pins) |
ShawnHymel | 0:c407693ac016 | 42 | SDFileSystem sd(p5, p6, p7, p8, "sd"); |
ShawnHymel | 0:c407693ac016 | 43 | |
ShawnHymel | 0:c407693ac016 | 44 | // Global variables |
ShawnHymel | 0:c407693ac016 | 45 | const char file_root[] = "idata"; |
ShawnHymel | 0:c407693ac016 | 46 | const char file_suffix[] = ".csv"; |
ShawnHymel | 0:c407693ac016 | 47 | char filename[20]; |
ShawnHymel | 0:c407693ac016 | 48 | Timer timer; |
ShawnHymel | 0:c407693ac016 | 49 | |
ShawnHymel | 0:c407693ac016 | 50 | // Return true if file (or directory) 'filename' is present in directory 'root' |
ShawnHymel | 0:c407693ac016 | 51 | // Based on: https://developer.mbed.org/forum/mbed/topic/463/ |
ShawnHymel | 0:c407693ac016 | 52 | bool exists(char * root, char *filename) |
ShawnHymel | 0:c407693ac016 | 53 | { |
ShawnHymel | 0:c407693ac016 | 54 | DIR *d = opendir(root); |
ShawnHymel | 0:c407693ac016 | 55 | struct dirent *p; |
ShawnHymel | 0:c407693ac016 | 56 | bool found = false; |
ShawnHymel | 0:c407693ac016 | 57 | if ( d != NULL ) |
ShawnHymel | 0:c407693ac016 | 58 | { |
ShawnHymel | 0:c407693ac016 | 59 | while ( !found && (p = readdir(d)) != NULL ) |
ShawnHymel | 0:c407693ac016 | 60 | { |
ShawnHymel | 0:c407693ac016 | 61 | if ( strcmp(p->d_name, filename) == 0 ) |
ShawnHymel | 0:c407693ac016 | 62 | found = true; |
ShawnHymel | 0:c407693ac016 | 63 | } |
ShawnHymel | 0:c407693ac016 | 64 | } |
ShawnHymel | 0:c407693ac016 | 65 | closedir(d); |
ShawnHymel | 0:c407693ac016 | 66 | return found; |
ShawnHymel | 0:c407693ac016 | 67 | } |
ShawnHymel | 0:c407693ac016 | 68 | |
ShawnHymel | 0:c407693ac016 | 69 | // Main |
ShawnHymel | 0:c407693ac016 | 70 | int main( void ) |
ShawnHymel | 0:c407693ac016 | 71 | { |
ShawnHymel | 0:c407693ac016 | 72 | FILE *file; |
ShawnHymel | 0:c407693ac016 | 73 | char str[5]; |
ShawnHymel | 0:c407693ac016 | 74 | int i; |
ShawnHymel | 0:c407693ac016 | 75 | int led_state; |
ShawnHymel | 0:c407693ac016 | 76 | float voltage_in; |
ShawnHymel | 0:c407693ac016 | 77 | float current; |
ShawnHymel | 0:c407693ac016 | 78 | float timestamp; |
ShawnHymel | 0:c407693ac016 | 79 | |
ShawnHymel | 0:c407693ac016 | 80 | // Debugging start |
ShawnHymel | 0:c407693ac016 | 81 | #if DEBUG == 1 |
ShawnHymel | 0:c407693ac016 | 82 | printf("\n\r"); |
ShawnHymel | 0:c407693ac016 | 83 | printf("-------------------\n\r"); |
ShawnHymel | 0:c407693ac016 | 84 | printf("Current Log-O-Matic\n\r"); |
ShawnHymel | 0:c407693ac016 | 85 | printf("-------------------\n\r"); |
ShawnHymel | 0:c407693ac016 | 86 | #endif |
ShawnHymel | 0:c407693ac016 | 87 | |
ShawnHymel | 0:c407693ac016 | 88 | // Create next file in sequence |
ShawnHymel | 0:c407693ac016 | 89 | for ( i = 0; i < MAX_FILES; i++ ) { |
ShawnHymel | 0:c407693ac016 | 90 | |
ShawnHymel | 0:c407693ac016 | 91 | // Construct filename |
ShawnHymel | 0:c407693ac016 | 92 | strcpy(filename, file_root); |
ShawnHymel | 0:c407693ac016 | 93 | sprintf(str, "%d", i); |
ShawnHymel | 0:c407693ac016 | 94 | strcat(filename, str); |
ShawnHymel | 0:c407693ac016 | 95 | strcat(filename, file_suffix); |
ShawnHymel | 0:c407693ac016 | 96 | |
ShawnHymel | 0:c407693ac016 | 97 | // If file exists, skip to next. If not, create it. |
ShawnHymel | 0:c407693ac016 | 98 | if ( exists("/sd", filename) ) { |
ShawnHymel | 0:c407693ac016 | 99 | #if DEBUG == 1 |
ShawnHymel | 0:c407693ac016 | 100 | printf ("%s found\n\r", filename); |
ShawnHymel | 0:c407693ac016 | 101 | #endif |
ShawnHymel | 0:c407693ac016 | 102 | if ( i == (MAX_FILES - 1) ) { |
ShawnHymel | 0:c407693ac016 | 103 | error("ERROR: Too many files!\n\r"); |
ShawnHymel | 0:c407693ac016 | 104 | return -1; |
ShawnHymel | 0:c407693ac016 | 105 | } |
ShawnHymel | 0:c407693ac016 | 106 | } else { |
ShawnHymel | 0:c407693ac016 | 107 | #if DEBUG == 1 |
ShawnHymel | 0:c407693ac016 | 108 | printf ("%s not found. Creating.\n\r", filename); |
ShawnHymel | 0:c407693ac016 | 109 | #endif |
ShawnHymel | 0:c407693ac016 | 110 | break; |
ShawnHymel | 0:c407693ac016 | 111 | } |
ShawnHymel | 0:c407693ac016 | 112 | } |
ShawnHymel | 0:c407693ac016 | 113 | |
ShawnHymel | 0:c407693ac016 | 114 | // Construct absolute path to file |
ShawnHymel | 0:c407693ac016 | 115 | strcpy(filename, "/sd/"); |
ShawnHymel | 0:c407693ac016 | 116 | strcat(filename, file_root); |
ShawnHymel | 0:c407693ac016 | 117 | sprintf(str, "%d", i); |
ShawnHymel | 0:c407693ac016 | 118 | strcat(filename, str); |
ShawnHymel | 0:c407693ac016 | 119 | strcat(filename, file_suffix); |
ShawnHymel | 0:c407693ac016 | 120 | |
ShawnHymel | 0:c407693ac016 | 121 | // Open file for writing |
ShawnHymel | 0:c407693ac016 | 122 | #if DEBUG == 1 |
ShawnHymel | 0:c407693ac016 | 123 | printf("Opening %s\n\r", filename); |
ShawnHymel | 0:c407693ac016 | 124 | #endif |
ShawnHymel | 0:c407693ac016 | 125 | file = fopen(filename, "w"); |
ShawnHymel | 0:c407693ac016 | 126 | if ( file == NULL ) { |
ShawnHymel | 0:c407693ac016 | 127 | error("ERROR: Could not open file for writing!\n\r"); |
ShawnHymel | 0:c407693ac016 | 128 | return -1; |
ShawnHymel | 0:c407693ac016 | 129 | } |
ShawnHymel | 0:c407693ac016 | 130 | |
ShawnHymel | 0:c407693ac016 | 131 | // Write header to file |
ShawnHymel | 0:c407693ac016 | 132 | fprintf(file, "Time,Current\n\r"); |
ShawnHymel | 0:c407693ac016 | 133 | |
ShawnHymel | 0:c407693ac016 | 134 | // Start timer and begin sampling |
ShawnHymel | 0:c407693ac016 | 135 | led_state = 0; |
ShawnHymel | 0:c407693ac016 | 136 | #if DEBUG == 1 |
ShawnHymel | 0:c407693ac016 | 137 | printf("Sampling. Do not remove SD card!\n\r"); |
ShawnHymel | 0:c407693ac016 | 138 | #endif |
ShawnHymel | 0:c407693ac016 | 139 | timer.start(); |
ShawnHymel | 0:c407693ac016 | 140 | for ( i = 0; i < NUM_SAMPLES; i++ ) { |
ShawnHymel | 0:c407693ac016 | 141 | |
ShawnHymel | 0:c407693ac016 | 142 | // Write data to csv file |
ShawnHymel | 0:c407693ac016 | 143 | timestamp = timer.read(); |
ShawnHymel | 0:c407693ac016 | 144 | voltage_in = ain * 3.3; |
ShawnHymel | 0:c407693ac016 | 145 | current = (voltage_in * 1000) / (RS * RL); |
ShawnHymel | 0:c407693ac016 | 146 | fprintf(file, "%2.2f,%1.3f\n", timestamp, current); |
ShawnHymel | 0:c407693ac016 | 147 | #if DEBUG == 1 |
ShawnHymel | 0:c407693ac016 | 148 | printf("%2.2f, %1.3f\n\r", timestamp, current); |
ShawnHymel | 0:c407693ac016 | 149 | #endif |
ShawnHymel | 0:c407693ac016 | 150 | |
ShawnHymel | 0:c407693ac016 | 151 | // Toggle LED to show logging |
ShawnHymel | 0:c407693ac016 | 152 | led_state ^= 1; |
ShawnHymel | 0:c407693ac016 | 153 | status_led = led_state; |
ShawnHymel | 0:c407693ac016 | 154 | |
ShawnHymel | 0:c407693ac016 | 155 | // Wait until next sample cycle as defined by sample delay |
ShawnHymel | 0:c407693ac016 | 156 | while ( (timer.read() - timestamp) < DELAY_MS ); |
ShawnHymel | 0:c407693ac016 | 157 | } |
ShawnHymel | 0:c407693ac016 | 158 | |
ShawnHymel | 0:c407693ac016 | 159 | // Close file |
ShawnHymel | 0:c407693ac016 | 160 | #if DEBUG == 1 |
ShawnHymel | 0:c407693ac016 | 161 | printf("Done! Closing file"); |
ShawnHymel | 0:c407693ac016 | 162 | #endif |
ShawnHymel | 0:c407693ac016 | 163 | fclose(file); |
ShawnHymel | 0:c407693ac016 | 164 | |
ShawnHymel | 0:c407693ac016 | 165 | // Turn off LED to show done |
ShawnHymel | 0:c407693ac016 | 166 | status_led = 0; |
ShawnHymel | 0:c407693ac016 | 167 | |
ShawnHymel | 0:c407693ac016 | 168 | return 0; |
ShawnHymel | 0:c407693ac016 | 169 | } |