/* MiniDS18TDS_1.3.ino For a Mini Pearl Logger (Arduino Pro Mini, microSD card, RTC) with a TPL5110 low-power timer (determines logging interval by turning on the Arduino at a set interval). The main loop in the sketch is run once each time the Arduino is powered on. Logs data from a DF Robot TDS (total dissolved solids) sensor and a DS18B20 temperature sensor (one-wire). Water temperature from the DS18B20 is used to adjust the output of the TDS sensor. The DS18B20 is sensitive to timing and delays (it takes 750 ms to take a reading), and the error code (temperature = "85.00") is reported when timing is wrong. TDS results are based on the mean of SCOUNT consecutive readings (SCOUNT=30 by default). DF Robot supplies code to derive TDS results from the median of multiple readings, but that code is fragile, has an error, and does not work when using an external timer. Chris Fastie 7-10-2018 */ #include #include // https://github.com/greiman/SdFat/ #include #include // https://github.com/adafruit/RTClib/ #include // https://github.com/PaulStoffregen/OneWire #include // https://github.com/milesburton/Arduino-Temperature-Control-Library RTC_DS3231 rtc; // RTC will be the RTC_DS3231 object #define DS3231_I2C_ADDRESS 0x68 // I2C address of RTC SdFat SD; // SD will be the SdFat object #define donePin A3 // This pin signals to the TPL51100 to cut power #define ONE_WIRE_BUS 5 // DS18B20 data wire is plugged into digital pin 5 on the Arduino OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. float DS18; // variable for temperature from DS18B20 sensor // TDS #define TdsSensorPin A6 // TDS wire connects to this analog pin #define VREF 3.3 // analog reference voltage of the ADC #define SCOUNT 30 // ---Enter--- sample size for TDS readings float analogSum = 0; // for TDS float averageVoltage = 0,tdsValue = 0; // for TDS // end TDS char TmeStrng[] = "0000/00/00,00:00:00"; // string template for RTC time stamp long utc; // variable for the RTC: void setup() { Serial.begin(9600); Wire.begin(); // initialize the I2C interface sensors.begin(); // initialize the DallasTemperature sensors sensors.setResolution(12); // 12 is the highest resolution of the sensor sensors.requestTemperatures(); // read the onewire sensor once before starting loop rtc.begin(); // initialize the RTC if (!SD.begin(10)) { // initialize the SD card. CS pin is 10 Serial.println("No SD"); } else { Serial.println("SD OK"); } DS18 = (sensors.getTempCByIndex(0)); // read the DS18B20 sensor, the first reading is not used // Set the RTC time to the time this sketch was last compiled. Uncomment the following line, load the // sketch on the logger. Must comment out the line and reload for subsequent boots or the RTC time will be wrong: // rtc.adjust(DateTime((__DATE__), (__TIME__))); delay(750); pinMode(TdsSensorPin,INPUT); } void loop() { sensors.requestTemperatures(); // request the onewire temperature sensor well before reading the sensor DateTime now = rtc.now(); // read the time from the RTC, then construct a data string: sprintf(TmeStrng, "%04d/%02d/%02d,%02d:%02d:%02d", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second()); utc = (now.unixtime()); // time code (good for graphing) delay(500); DS18 = (sensors.getTempCByIndex(0)); // Read the onewire sensor Serial.println(TmeStrng); // for checking operation Serial.print(DS18); Serial.println(" DS18"); // start TDS aquisition and computation analogSum = 0; // take the mean of SCOUNT readings of the TDS sensor... for(int x = 0; x < SCOUNT; x++){ analogSum = analogSum + analogRead(TdsSensorPin); delay(40); } averageVoltage = (analogSum/SCOUNT) * (float)VREF / 1024.0; // compute the mean and scale for 8 bit and reference voltage float compensationCoefficient = 1.0+0.02*(DS18-25.0); // temperature compensation formula is: // fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0)); float compensationVoltage = averageVoltage/compensationCoefficient; // temperature compensation tdsValue = (133.42*compensationVoltage*compensationVoltage*compensationVoltage - 255.86*compensationVoltage*compensationVoltage + 857.39*compensationVoltage)*0.5; // convert voltage value to TDS value // end TDS aquisition and computation // display for debugging Serial.print("voltage: "); Serial.print(averageVoltage,2); Serial.println(" V "); Serial.print("TDS: "); Serial.print(tdsValue,0); Serial.println(" ppm"); Serial.println(); // write the data to the SD card: File dataFile = SD.open("datalogTDS.txt", FILE_WRITE); delay(40); dataFile.print(TmeStrng);dataFile.print(","); dataFile.print(utc);dataFile.print(","); dataFile.print(DS18);dataFile.print(","); dataFile.print(tdsValue);dataFile.print(","); dataFile.println(averageVoltage); dataFile.flush(); dataFile.close(); //delay (10000); // for testing with the following while-loop commented out while (1) // toggle donePin so TPL5110 will cut power and turn off logger { digitalWrite(donePin, HIGH); delay(1); digitalWrite(donePin, LOW); delay(1); } } // end main loop