選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

173 行
4.8KB

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