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.

174 satır
4.9KB

  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 <SdFatUtil.h> // define FreeRam()
  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. while (!Serial){} // wait for Leonardo
  60. // pstr stores strings in flash to save RAM
  61. cout << endl << pstr("FreeRam: ") << FreeRam() << endl;
  62. #if WAIT_TO_START
  63. cout << pstr("Type any character to start\n");
  64. while (Serial.read() <= 0) {}
  65. delay(400); // catch Due reset problem
  66. #endif // WAIT_TO_START
  67. #if USE_DS1307
  68. // connect to RTC
  69. Wire.begin();
  70. if (!RTC.begin()) error("RTC failed");
  71. // set date time callback function
  72. SdFile::dateTimeCallback(dateTime);
  73. DateTime now = RTC.now();
  74. cout << now << endl;
  75. #endif // USE_DS1307
  76. // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  77. if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) sd.initErrorHalt();
  78. // create a new file in root, the current working directory
  79. char name[] = "LOGGER00.CSV";
  80. for (uint8_t i = 0; i < 100; i++) {
  81. name[6] = i/10 + '0';
  82. name[7] = i%10 + '0';
  83. if (sd.exists(name)) continue;
  84. logfile.open(name);
  85. break;
  86. }
  87. if (!logfile.is_open()) error("file.open");
  88. cout << pstr("Logging to: ") << name << endl;
  89. cout << pstr("Type any character to stop\n\n");
  90. // format header in buffer
  91. obufstream bout(buf, sizeof(buf));
  92. bout << pstr("millis");
  93. #if USE_DS1307
  94. bout << pstr(",date,time");
  95. #endif // USE_DS1307
  96. for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
  97. bout << pstr(",sens") << int(i);
  98. }
  99. logfile << buf << endl;
  100. #if ECHO_TO_SERIAL
  101. cout << buf << endl;
  102. #endif // ECHO_TO_SERIAL
  103. }
  104. //------------------------------------------------------------------------------
  105. void loop() {
  106. uint32_t m;
  107. // wait for time to be a multiple of interval
  108. do {
  109. m = millis();
  110. } while (m % LOG_INTERVAL);
  111. // use buffer stream to format line
  112. obufstream bout(buf, sizeof(buf));
  113. // start with time in millis
  114. bout << m;
  115. #if USE_DS1307
  116. DateTime now = RTC.now();
  117. bout << ',' << now;
  118. #endif // USE_DS1307
  119. // read analog pins and format data
  120. for (uint8_t ia = 0; ia < SENSOR_COUNT; ia++) {
  121. #if ADC_DELAY
  122. analogRead(ia);
  123. delay(ADC_DELAY);
  124. #endif // ADC_DELAY
  125. bout << ',' << analogRead(ia);
  126. }
  127. bout << endl;
  128. // log data and flush to SD
  129. logfile << buf << flush;
  130. // check for error
  131. if (!logfile) error("write data failed");
  132. #if ECHO_TO_SERIAL
  133. cout << buf;
  134. #endif // ECHO_TO_SERIAL
  135. // don't log two points in the same millis
  136. if (m == millis()) delay(1);
  137. if (!Serial.available()) return;
  138. logfile.close();
  139. cout << pstr("Done!");
  140. while (1);
  141. }