Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

195 lines
5.0KB

  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.available()) {
  68. SysCall::yield();
  69. }
  70. // Discard input.
  71. do {
  72. delay(10);
  73. } while(Serial.available() && Serial.read() >= 0);
  74. #endif // WAIT_TO_START
  75. #if USE_DS1307
  76. // connect to RTC
  77. Wire.begin();
  78. if (!RTC.begin()) {
  79. error("RTC failed");
  80. }
  81. // set date time callback function
  82. SdFile::dateTimeCallback(dateTime);
  83. DateTime now = RTC.now();
  84. cout << now << endl;
  85. #endif // USE_DS1307
  86. // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  87. if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) {
  88. sd.initErrorHalt();
  89. }
  90. // create a new file in root, the current working directory
  91. char name[] = "logger00.csv";
  92. for (uint8_t i = 0; i < 100; i++) {
  93. name[6] = i/10 + '0';
  94. name[7] = i%10 + '0';
  95. if (sd.exists(name)) {
  96. continue;
  97. }
  98. logfile.open(name);
  99. break;
  100. }
  101. if (!logfile.is_open()) {
  102. error("file.open");
  103. }
  104. cout << F("Logging to: ") << name << endl;
  105. cout << F("Type any character to stop\n\n");
  106. // format header in buffer
  107. obufstream bout(buf, sizeof(buf));
  108. bout << F("millis");
  109. #if USE_DS1307
  110. bout << F(",date,time");
  111. #endif // USE_DS1307
  112. for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
  113. bout << F(",sens") << int(i);
  114. }
  115. logfile << buf << endl;
  116. #if ECHO_TO_SERIAL
  117. cout << buf << endl;
  118. #endif // ECHO_TO_SERIAL
  119. }
  120. //------------------------------------------------------------------------------
  121. void loop() {
  122. uint32_t m;
  123. // wait for time to be a multiple of interval
  124. do {
  125. m = millis();
  126. } while (m % LOG_INTERVAL);
  127. // use buffer stream to format line
  128. obufstream bout(buf, sizeof(buf));
  129. // start with time in millis
  130. bout << m;
  131. #if USE_DS1307
  132. DateTime now = RTC.now();
  133. bout << ',' << now;
  134. #endif // USE_DS1307
  135. // read analog pins and format data
  136. for (uint8_t ia = 0; ia < SENSOR_COUNT; ia++) {
  137. #if ADC_DELAY
  138. analogRead(ia);
  139. delay(ADC_DELAY);
  140. #endif // ADC_DELAY
  141. bout << ',' << analogRead(ia);
  142. }
  143. bout << endl;
  144. // log data and flush to SD
  145. logfile << buf << flush;
  146. // check for error
  147. if (!logfile) {
  148. error("write data failed");
  149. }
  150. #if ECHO_TO_SERIAL
  151. cout << buf;
  152. #endif // ECHO_TO_SERIAL
  153. // don't log two points in the same millis
  154. if (m == millis()) {
  155. delay(1);
  156. }
  157. if (!Serial.available()) {
  158. return;
  159. }
  160. logfile.close();
  161. cout << F("Done!");
  162. SysCall::halt();
  163. }