You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AnalogLogger.ino 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // A simple data logger for the Arduino analog pins with optional DS1307
  2. // uses RTClib from https://github.com/adafruit/RTClib
  3. #include <SPI.h>
  4. #include "SdFat.h"
  5. #include "FreeStack.h"
  6. #define SD_CHIP_SELECT SS // SD chip select pin
  7. #define USE_DS1307 0 // set nonzero to use DS1307 RTC
  8. #define LOG_INTERVAL 1000 // mills between entries
  9. #define SENSOR_COUNT 3 // number of analog pins to log
  10. #define ECHO_TO_SERIAL 1 // echo data to serial port if nonzero
  11. #define WAIT_TO_START 1 // Wait for serial input in setup()
  12. #define ADC_DELAY 10 // ADC delay for high impedence sensors
  13. // file system object
  14. SdFat sd;
  15. // text file for logging
  16. ofstream logfile;
  17. // Serial print stream
  18. ArduinoOutStream cout(Serial);
  19. // buffer to format data - makes it eaiser to echo to Serial
  20. char buf[80];
  21. //------------------------------------------------------------------------------
  22. #if SENSOR_COUNT > 6
  23. #error SENSOR_COUNT too large
  24. #endif // SENSOR_COUNT
  25. //------------------------------------------------------------------------------
  26. // store error strings in flash to save RAM
  27. #define error(s) sd.errorHalt(F(s))
  28. //------------------------------------------------------------------------------
  29. #if USE_DS1307
  30. // use RTClib from Adafruit
  31. // https://github.com/adafruit/RTClib
  32. // The Arduino IDE has a bug that causes Wire and RTClib to be loaded even
  33. // if USE_DS1307 is false.
  34. #error remove this line and uncomment the next two lines.
  35. //#include <Wire.h>
  36. //#include <RTClib.h>
  37. RTC_DS1307 RTC; // define the Real Time Clock object
  38. //------------------------------------------------------------------------------
  39. // call back for file timestamps
  40. void dateTime(uint16_t* date, uint16_t* time) {
  41. DateTime now = RTC.now();
  42. // return date using FAT_DATE macro to format fields
  43. *date = FAT_DATE(now.year(), now.month(), now.day());
  44. // return time using FAT_TIME macro to format fields
  45. *time = FAT_TIME(now.hour(), now.minute(), now.second());
  46. }
  47. //------------------------------------------------------------------------------
  48. // format date/time
  49. ostream& operator << (ostream& os, DateTime& dt) {
  50. os << dt.year() << '/' << int(dt.month()) << '/' << int(dt.day()) << ',';
  51. os << int(dt.hour()) << ':' << setfill('0') << setw(2) << int(dt.minute());
  52. os << ':' << setw(2) << int(dt.second()) << setfill(' ');
  53. return os;
  54. }
  55. #endif // USE_DS1307
  56. //------------------------------------------------------------------------------
  57. void setup() {
  58. Serial.begin(9600);
  59. // Wait for USB Serial.
  60. while (!Serial) {
  61. SysCall::yield();
  62. }
  63. // F() stores strings in flash to save RAM
  64. cout << endl << F("FreeStack: ") << FreeStack() << endl;
  65. #if WAIT_TO_START
  66. cout << F("Type any character to start\n");
  67. while (Serial.read() <= 0) {
  68. SysCall::yield();
  69. }
  70. do {
  71. delay(10);
  72. } while(Serial.read() >= 0);
  73. #endif // WAIT_TO_START
  74. #if USE_DS1307
  75. // connect to RTC
  76. Wire.begin();
  77. if (!RTC.begin()) {
  78. error("RTC failed");
  79. }
  80. // set date time callback function
  81. SdFile::dateTimeCallback(dateTime);
  82. DateTime now = RTC.now();
  83. cout << now << endl;
  84. #endif // USE_DS1307
  85. // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  86. if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) {
  87. sd.initErrorHalt();
  88. }
  89. // create a new file in root, the current working directory
  90. char name[] = "logger00.csv";
  91. for (uint8_t i = 0; i < 100; i++) {
  92. name[6] = i/10 + '0';
  93. name[7] = i%10 + '0';
  94. if (sd.exists(name)) {
  95. continue;
  96. }
  97. logfile.open(name);
  98. break;
  99. }
  100. if (!logfile.is_open()) {
  101. error("file.open");
  102. }
  103. cout << F("Logging to: ") << name << endl;
  104. cout << F("Type any character to stop\n\n");
  105. // format header in buffer
  106. obufstream bout(buf, sizeof(buf));
  107. bout << F("millis");
  108. #if USE_DS1307
  109. bout << F(",date,time");
  110. #endif // USE_DS1307
  111. for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
  112. bout << F(",sens") << int(i);
  113. }
  114. logfile << buf << endl;
  115. #if ECHO_TO_SERIAL
  116. cout << buf << endl;
  117. #endif // ECHO_TO_SERIAL
  118. }
  119. //------------------------------------------------------------------------------
  120. void loop() {
  121. uint32_t m;
  122. // wait for time to be a multiple of interval
  123. do {
  124. m = millis();
  125. } while (m % LOG_INTERVAL);
  126. // use buffer stream to format line
  127. obufstream bout(buf, sizeof(buf));
  128. // start with time in millis
  129. bout << m;
  130. #if USE_DS1307
  131. DateTime now = RTC.now();
  132. bout << ',' << now;
  133. #endif // USE_DS1307
  134. // read analog pins and format data
  135. for (uint8_t ia = 0; ia < SENSOR_COUNT; ia++) {
  136. #if ADC_DELAY
  137. analogRead(ia);
  138. delay(ADC_DELAY);
  139. #endif // ADC_DELAY
  140. bout << ',' << analogRead(ia);
  141. }
  142. bout << endl;
  143. // log data and flush to SD
  144. logfile << buf << flush;
  145. // check for error
  146. if (!logfile) {
  147. error("write data failed");
  148. }
  149. #if ECHO_TO_SERIAL
  150. cout << buf;
  151. #endif // ECHO_TO_SERIAL
  152. // don't log two points in the same millis
  153. if (m == millis()) {
  154. delay(1);
  155. }
  156. if (!Serial.available()) {
  157. return;
  158. }
  159. logfile.close();
  160. cout << F("Done!");
  161. SysCall::halt();
  162. }