From cosm library example and lifts from a lot of others particularly from Stanley in Kuala Lumpur. Use your own DS18B20 addresses, keys etc. */ #include // Dallas temp #include // Dallas Temp #include // Ethernet #include // Ethernet #include // Cosm lib #include // Cosm lib #include // Nokia 5110 #include // SD card, and is all it needs #include // from "Date As Filename" #include "RTClib.h" // from "Date As Filename" #include "Wire.h" // Original RTC lib for LCD, SD, serial // This is also used by #define DS1307_ADDRESS 0x68 RTC_DS1307 RTC; static PCD8544 lcd; File myFile; char filename[] = "00000000.CSV"; // Custom symbols static const byte DEGREES_CHAR = 1; static const byte degrees_glyph[] = { 0x00, 0x07, 0x05, 0x07, 0x00 }; static const byte SLASH_CHAR = 2; static const byte slash_glyph[] = {0x00,0x20,0x10,0x08}; byte InThermo[8] = { 0x28, 0x69, 0xC2, 0xB0, 0x03, 0x00, 0x00, 0X9F}; byte OutThermo[8] = { 0x28, 0x7A, 0x8B, 0xC0, 0x03, 0x00, 0x00, 0x2F}; byte DrainThermo[8] = { 0x28, 0x09, 0xA9, 0xC0, 0x03, 0x00, 0x00, 0x95}; #define ONE_WIRE_BUS 3 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; char cosmKey[] = "l6abs...... tralala.........t0Zz0g"; int second, minute, hour, weekDay, monthDay, month, year; int k=0; int Conv; float InTemp, OutTemp, DrainTemp; float diff, kW, Daily, FlowMax; float kWh=0.00; float Max = 0.00; float MaxRise =0.00; float flowRate; unsigned int flowLitres; unsigned long totalLitres; unsigned long oldTime; unsigned int frac; // Define the strings for our datastream IDs char sensorId0[] = "InThermo"; char sensorId1[] = "OutThermo"; char sensorId2[] = "DrainThermo"; char calcId1[] = "diff"; char calcId2[] = "flowRate"; char calcId3[] = "kW"; const int bufferSize = 140; char bufferValue[bufferSize]; // enough space to store the string we're going to send CosmDatastream datastreams[] = { CosmDatastream(sensorId0, strlen(sensorId0), DATASTREAM_FLOAT), CosmDatastream(sensorId1, strlen(sensorId1), DATASTREAM_FLOAT), CosmDatastream(sensorId2, strlen(sensorId2), DATASTREAM_FLOAT), CosmDatastream(calcId1, strlen(calcId1), DATASTREAM_FLOAT), CosmDatastream(calcId2, strlen(calcId2), DATASTREAM_FLOAT), CosmDatastream(calcId3, strlen(calcId3), DATASTREAM_FLOAT), }; // Finally, wrap the datastreams into a feed CosmFeed feed(83153, datastreams, 6); /*put your number here */ EthernetClient client; CosmClient cosmclient(client); byte sensorInterrupt = 0; // 0 = pin 2; 1 = pin 3 byte sensorPin = 2; // // The flow sensor outputs approximately 4.5 Hz/litre/minute of flow. float calibrationFactor = 5.5; volatile byte pulseCount; void setup() { lcd.begin(84, 48); // Register the custom symbols... lcd.createChar(DEGREES_CHAR, degrees_glyph); lcd.createChar(SLASH_CHAR, slash_glyph); Wire.begin(); Serial.begin(9600); Serial.print(" filename "); delay(300);//Wait for newly restarted system to stabilize lcd.setCursor (0,0); lcd.print("Initializing"); delay(2000); lcd.setCursor (0,1); pinMode(10, OUTPUT); if (!SD.begin(4)) { lcd.print("failed!"); delay (2000); return; } lcd.print("init. OK!"); delay(2000); getFileName(); Serial.println(filename); lcd.clear(); Serial.println("LABEL,Time,InTemp,OutTemp,diff,DrainTemp"); sensors.setResolution(InThermo, 12); sensors.setResolution(OutThermo, 12); sensors.setResolution(DrainThermo, 12); Serial.println("Starting multiple datastream upload to Cosm..."); Serial.println(); while (Ethernet.begin(mac) != 1) { Serial.println("Error getting IP address via DHCP, trying again..."); delay(10000); } pinMode(sensorPin, INPUT); digitalWrite(sensorPin, HIGH); pulseCount = 0; flowRate = 0.0; flowLitres = 0; totalLitres = 0; oldTime = 0; // The Hall-effect sensor is connected to pin 17 (A3) which uses interrupt 0. // Configured to trigger on a FALLING state change (transition from HIGH // state to LOW state) attachInterrupt(sensorInterrupt, pulseCounter, FALLING); } void loop() { GetClock(); if (hour == 0 && minute == 0 && second <2) { getFileName(); Daily = kWh - Daily; MaxRise = 0; } myFile = SD.open(filename, FILE_WRITE);//<<<<<<<<<<<<< OPEN if((millis() - oldTime) > 1000) // Only process counters once per second { detachInterrupt(sensorInterrupt); flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor; oldTime = millis(); flowLitres = (flowRate / 60); totalLitres += flowLitres; // During testing it can be useful to output the literal pulse count value so you // can compare that and the calculated flow rate against the data sheets for the // flow sensor. Uncomment the following two lines to display the count value. Serial.print(pulseCount, DEC); Serial.print(" "); // Write the calculated value to the serial port. Because we want to output a // floating point value and print() can't handle floats we have to do some trickery // to output the whole number part, then a decimal point, then the fractional part. // Print the flow rate for this second in litres / minute Serial.print(int(flowRate)); // Print the integer part of the variable Serial.print("."); // Print the decimal point // Determine the fractional part. The 10 multiplier gives us 1 decimal place. frac = (flowRate - int(flowRate)) * 10; Serial.print(frac, DEC) ; // Print the fractional part of the variable // Print the number of litres flowed in this second Serial.print(" "); // Output separator Serial.print(flowLitres); // Print the cumulative total of litres flowed since starting Serial.print(" "); // Output separator Serial.print(totalLitres); /* lcd.setCursor(0, 1); lcd.print(int(totalLitres / 1000)); lcd.print(" Litres"); */ // Reset the pulse counter so we can start incrementing again pulseCount = 0; // Enable the interrupt again now that we've finished sending output attachInterrupt(sensorInterrupt, pulseCounter, FALLING); } if (flowRate > 2) { running(); } else { standing(); } Serial.print("DATA,TIME, "); int ret=0; //get the values from the DS8B20's sensors.requestTemperatures(); float InTemp = (sensorValue(InThermo)); float OutTemp = (sensorValue(OutThermo)); float DrainTemp = (sensorValue(DrainThermo)); float diff = OutTemp - InTemp; if (diff > MaxRise) { MaxRise = diff; } kW = diff * flowRate; Conv = diff * 100 / (DrainTemp - InTemp); kWh = kWh + (kW / 3600); if (kW > Max) { Max = kW; } datastreams[0].setFloat(InTemp); datastreams[1].setFloat(OutTemp); datastreams[2].setFloat(DrainTemp); datastreams[3].setFloat(diff); datastreams[4].setFloat(flowRate); datastreams[5].setFloat(kW); Serial.print(InTemp); Serial.print(" , "); Serial.print(OutTemp); Serial.print(" , "); Serial.print(DrainTemp); Serial.println(" , "); // myFile.close();//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>CLOSE } // loop ends here //sensorValue function float sensorValue (byte deviceAddress[]) { float tempC = sensors.getTempC (deviceAddress); return tempC; } byte bcdToDec(byte val) { // Convert binary coded decimal to normal decimal numbers return ( (val/16*10) + (val%16) ); } void GetClock(){ // Reset the register pointer Wire.beginTransmission(DS1307_ADDRESS); byte zero = 0x00; Wire.write(zero); Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS, 7); second = bcdToDec(Wire.read()); minute = bcdToDec(Wire.read()); hour = bcdToDec(Wire.read() & 0b111111); //24 hour time weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday monthDay = bcdToDec(Wire.read()); month = bcdToDec(Wire.read()); year = bcdToDec(Wire.read()); } void getFileName(){ DateTime now = RTC.now(); filename[0] = (now.year()/1000)%10 + '0'; //To get 1st digit from year() filename[1] = (now.year()/100)%10 + '0'; //To get 2nd digit from year() filename[2] = (now.year()/10)%10 + '0'; //To get 3rd digit from year() filename[3] = now.year()%10 + '0'; //To get 4th digit from year() filename[4] = now.month()/10 + '0'; //To get 1st digit from month() filename[5] = now.month()%10 + '0'; //To get 2nd digit from month() filename[6] = now.day()/10 + '0'; //To get 1st digit from day() filename[7] = now.day()%10 + '0'; //To get 2nd digit from day() } void running() { lcd.setCursor(0,0); lcd.print("In"); lcd.setCursor(31,0); lcd.print("\001C "); lcd.setCursor(0,1); lcd.print("Out"); lcd.setCursor(31,1); lcd.print("\001C "); lcd.setCursor(0,2); lcd.print("Drain"); lcd.setCursor(31,2); lcd.print("\001C "); lcd.setCursor(0,3); lcd.print("F"); lcd.setCursor(5,3); lcd.print("l"); lcd.setCursor(10,3); lcd.print("ow"); lcd.setCursor(24,3); lcd.print("l"); lcd.setCursor(28,3); lcd.print("\002"); lcd.print("m"); lcd.setCursor(39,3); lcd.print("i"); lcd.setCursor(44,3); lcd.print("n"); lcd.setCursor(14,4); lcd.print("Conv %"); lcd.setCursor(21,5); lcd.print("kW"); lcd.setCursor(49,0); lcd.print(InTemp); lcd.setCursor(49,1); lcd.print (OutTemp); lcd.setCursor(49,2); lcd.print(DrainTemp); lcd.setCursor(49,3); if(int(flowRate) < 10) { lcd.print(" "); } lcd.print((int)flowRate); // Print the integer part of the variable lcd.print('.'); // Print the decimal point lcd.print(frac, DEC) ; // Print the fractional part of the variable lcd.setCursor(49,4); lcd.print(Conv); lcd.setCursor(49,5); lcd.print(kW); k=k+1; if (k>9 ) { int ret = cosmclient.put(feed, cosmKey); // SEND FEED TO COSM myFile = SD.open(filename, FILE_WRITE);//<<<<<<<<<<<<< OPEN myFile.print(monthDay); myFile.print("/"); myFile.print(month); myFile.print("/"); myFile.print(year); myFile.print(", "); myFile.print(hour); myFile.print(":"); myFile.print(minute); myFile.print(":"); myFile.print(second); myFile.print(", "); myFile.print(InTemp); myFile.print(", "); myFile.print(OutTemp); myFile.print(", "); myFile.print(DrainTemp); myFile.print(", "); myFile.print(kW); myFile.print(", "); myFile.print(Conv); myFile.println(); myFile.close();//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>CLOSE k=0; } } void standing() { lcd.setCursor(10, 0); lcd.print("kWh"); lcd.setCursor(6,1); lcd.print("PREVIOUS DAY"); lcd.setCursor(0,2); lcd.print("kWh"); lcd.setCursor(0,3); lcd.print("kW max"); lcd.setCursor(0,4); lcd.print("max flow"); lcd.setCursor(0,5); lcd.print("max rise"); lcd.setCursor(30,0); lcd.print(kWh); lcd.setCursor(30,2); lcd.print(Daily); lcd.setCursor(30,3); lcd.print(Max); lcd.setCursor(30,4); lcd.print(FlowMax); lcd.setCursor(30,5); lcd.print(MaxRise); } void daily() { ; } void pulseCounter() { pulseCount++; }