Last active
November 22, 2015 19:03
-
-
Save kenci/2c024b6b7244e07fee64 to your computer and use it in GitHub Desktop.
Pulse decoder for S0 Interface
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // Produce a formatted string in a buffer corresponding to the value provided. | |
| // If the 'width' parameter is non-zero, the value will be padded with leading | |
| // zeroes to achieve the specified width. The number of characters added to | |
| // the buffer (not including the null termination) is returned. | |
| // | |
| unsigned | |
| fmtUnsigned(unsigned long val, char *buf, unsigned bufLen, byte width) | |
| { | |
| if (!buf || !bufLen) | |
| return(0); | |
| // produce the digit string (backwards in the digit buffer) | |
| char dbuf[10]; | |
| unsigned idx = 0; | |
| while (idx < sizeof(dbuf)) | |
| { | |
| dbuf[idx++] = (val % 10) + '0'; | |
| if ((val /= 10) == 0) | |
| break; | |
| } | |
| // copy the optional leading zeroes and digits to the target buffer | |
| unsigned len = 0; | |
| byte padding = (width > idx) ? width - idx : 0; | |
| char c = '0'; | |
| while ((--bufLen > 0) && (idx || padding)) | |
| { | |
| if (padding) | |
| padding--; | |
| else | |
| c = dbuf[--idx]; | |
| *buf++ = c; | |
| len++; | |
| } | |
| // add the null termination | |
| *buf = '\0'; | |
| return(len); | |
| } | |
| // | |
| // Format a floating point value with number of decimal places. | |
| // The 'precision' parameter is a number from 0 to 6 indicating the desired decimal places. | |
| // The 'buf' parameter points to a buffer to receive the formatted string. This must be | |
| // sufficiently large to contain the resulting string. The buffer's length may be | |
| // optionally specified. If it is given, the maximum length of the generated string | |
| // will be one less than the specified value. | |
| // | |
| // example: fmtDouble(3.1415, 2, buf); // produces 3.14 (two decimal places) | |
| // | |
| void | |
| fmtDouble(double val, byte precision, char *buf, unsigned bufLen) | |
| { | |
| if (!buf || !bufLen) | |
| return; | |
| // limit the precision to the maximum allowed value | |
| const byte maxPrecision = 6; | |
| if (precision > maxPrecision) | |
| precision = maxPrecision; | |
| if (--bufLen > 0) | |
| { | |
| // check for a negative value | |
| if (val < 0.0) | |
| { | |
| val = -val; | |
| *buf = '-'; | |
| bufLen--; | |
| } | |
| // compute the rounding factor and fractional multiplier | |
| double roundingFactor = 0.5; | |
| unsigned long mult = 1; | |
| for (byte i = 0; i < precision; i++) | |
| { | |
| roundingFactor /= 10.0; | |
| mult *= 10; | |
| } | |
| if (bufLen > 0) | |
| { | |
| // apply the rounding factor | |
| val += roundingFactor; | |
| // add the integral portion to the buffer | |
| unsigned len = fmtUnsigned((unsigned long)val, buf, bufLen); | |
| buf += len; | |
| bufLen -= len; | |
| } | |
| // handle the fractional portion | |
| if ((precision > 0) && (bufLen > 0)) | |
| { | |
| *buf++ = '.'; | |
| if (--bufLen > 0) | |
| buf += fmtUnsigned((unsigned long)((val - (unsigned long)val) * mult), buf, bufLen, precision); | |
| } | |
| } | |
| // null-terminate the string | |
| *buf = '\0'; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //----------------------------------------------------------------------------------------------- | |
| // JSON functions | |
| //----------------------------------------------------------------------------------------------- | |
| //----------------------------------------------------------------------------------------------- | |
| // JSON structure characters | |
| //----------------------------------------------------------------------------------------------- | |
| //JSON structure uses " = 34 | |
| char jsonS[] = {'{',34,'\0'}; //JSON start characters | |
| char jsonB1[] = {34,':',34,'\0'}; //JSON characters between key and value | |
| char jsonB2[] = {34,',',34,'\0'}; //JSON characters between each data pair | |
| char jsonE[] = {34,'}','\0'}; //JSON end characters | |
| //----------------------------------------------------------------------------------------------- | |
| // Adds start of JSON characters | |
| //----------------------------------------------------------------------------------------------- | |
| char * srtJSON ( char * destination ) | |
| { | |
| strcat(destination,jsonS); | |
| } | |
| //----------------------------------------------------------------------------------------------- | |
| // Adds a JSON key and data pair to the string | |
| //----------------------------------------------------------------------------------------------- | |
| char * addJSON ( char * destination, const char * source, const double value ) | |
| { | |
| strcat(destination,source); | |
| strcat(destination,jsonB1); | |
| char buf[20]; fmtDouble(value,3,buf); | |
| strcat(destination,buf); | |
| strcat(destination,jsonB2); | |
| } | |
| //----------------------------------------------------------------------------------------------- | |
| // Adds end of JSON characters | |
| //----------------------------------------------------------------------------------------------- | |
| char * endJSON ( char * destination ) | |
| { | |
| str[strlen(destination)-3]='\0'; | |
| strcat(destination,jsonE); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //--------------------------------------------------------------------- | |
| // Pulse String Decoder | |
| // GNU GPL openenergymonitor.org | |
| // Author: Trystan Lea | |
| //--------------------------------------------------------------------- | |
| unsigned long times[12]; //Array holds incoming pulse times | |
| unsigned long count[12]; //Array holds incoming pulse count | |
| int ti,ci; //times and counts index | |
| int iStr = 0; //inString index | |
| char inString[14]; //String for fetching each number | |
| //--------------------------------------------------------------------- | |
| // Pulse String Decoder method | |
| // | |
| //String looks like this 2100:5,3200:4 = timeA,countA,timeB,countB | |
| //Decode pulse string splits the string up and identifies if number is a time or a count | |
| //--------------------------------------------------------------------- | |
| void decode_pulse_string() | |
| { | |
| if (Serial.available()) | |
| { | |
| char inChar = Serial.read(); //Read in serial characters | |
| if (inChar == ',' || inChar == ':' || inChar == '\n') //if any of the characters that define end of a number | |
| { | |
| inString[iStr] = '\0'; //end the string | |
| long value = atol(inString); //convert the string to a long | |
| if (inChar == ':') {times[ti] = value; ti++;} //Every value before : is a time | |
| if (inChar == ',' || inChar == '\n') {count[ci] += value; ci++;} //Every value before , is a count | |
| iStr=0; //reset inString index ready for the next argument | |
| if (inChar == '\n') {ti = 0; ci = 0;} //Reset count and times index ready for the next line | |
| } | |
| else | |
| { | |
| inString[iStr] = inChar; //Add another character to the string | |
| iStr++; | |
| } | |
| } | |
| } | |
| double getPower(int pin, double kwh_per_pulse) //Return power | |
| { | |
| return (3600000.0 * 1000 * kwh_per_pulse) / times[pin] * 1000; | |
| } | |
| double getkWhInc(int pin, double kwh_per_pulse) | |
| { | |
| double kwhInc = (count[pin]*kwh_per_pulse) * 1000; //Return Energy | |
| return kwhInc; | |
| } | |
| void resetkWhInc(int pin) | |
| { | |
| count[pin]=0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //--------------------------------------------------------------------- | |
| // Pulse String Decoder Sketch with Ethernet forwarding | |
| // GNU GPL openenergymonitor.org | |
| // Author: Trystan Lea | |
| // Modified: kenci | |
| // Added DSB1820 Sensors | |
| //--------------------------------------------------------------------- | |
| #include <Ethernet.h> | |
| #include <SPI.h> | |
| #include <OneWire.h> | |
| #include <DallasTemperature.h> | |
| #define ONE_WIRE_BUS_PIN 2 | |
| OneWire oneWire(ONE_WIRE_BUS_PIN); | |
| DallasTemperature sensors(&oneWire); | |
| DeviceAddress vorlauf = { 0x28, 0x35, 0x9F, 0xC4, 0x06, 0x00, 0x00, 0x26 }; | |
| DeviceAddress rucklauf = { 0x28, 0xD9, 0x01, 0xDE, 0x06, 0x00, 0x00, 0x44 }; | |
| DeviceAddress warmwasser = { 0x28, 0x48, 0xE5, 0xC4, 0x06, 0x00, 0x00, 0x24 }; | |
| double temp_warmwasser, temp_vorlauf, temp_rucklauf; | |
| byte mac[] = {0x54,0x55,0x53,0x10,0x04,0x28}; | |
| char server[] = "home.keno.lan"; | |
| IPAddress ip(192,168,1,177); | |
| #define port 80 | |
| EthernetClient client; | |
| char str[320]; //Increase this if not all of your json string is being sent. | |
| unsigned long utimeT; | |
| unsigned long utimeW; //Update time | |
| //Float to string functions, see attached: ftoa | |
| //thanks to Don Kinzer arduino forums | |
| void fmtDouble(double val, byte precision, char *buf, unsigned bufLen = 0xffff); | |
| unsigned fmtUnsigned(unsigned long val, char *buf, unsigned bufLen = 0xffff, byte width = 0); | |
| void setup() | |
| { | |
| Serial.begin(115200); //Needs to be 115200 for fast transfer between pulse counting arduino and this arduino | |
| // start the Ethernet connection: | |
| if (Ethernet.begin(mac) == 0) { | |
| Serial.println("Failed to configure Ethernet using DHCP"); | |
| // no point in carrying on, so do nothing forevermore: | |
| // try to congifure using IP address instead of DHCP: | |
| Ethernet.begin(mac, ip); | |
| } | |
| // Initialize the Temperature measurement library | |
| sensors.begin(); | |
| // set the resolution to 10 bit (Can be 9 to 12 bits .. lower is faster) | |
| sensors.setResolution(vorlauf, 10); | |
| sensors.setResolution(rucklauf, 10); | |
| sensors.setResolution(warmwasser, 10); | |
| // give the Ethernet shield a second to initialize: | |
| delay(1000); | |
| Serial.println("connecting..."); | |
| } | |
| void loop() | |
| { | |
| decode_pulse_string(); //Method decodes string send from pulse counting arduino | |
| if(millis()-utimeT>300000) { | |
| utimeT = millis(); | |
| // Command all devices on bus to read temperature | |
| sensors.requestTemperatures(); | |
| temp_warmwasser = printTemperature(warmwasser); | |
| temp_vorlauf = printTemperature(vorlauf); | |
| temp_rucklauf = printTemperature(rucklauf); | |
| if(temp_vorlauf || temp_rucklauf || temp_warmwasser) | |
| { | |
| strcpy(str,""); //URL | |
| srtJSON(str); //Start JSON | |
| if(temp_vorlauf) addJSON(str,"temp_warmwaser",temp_warmwasser); //JSON line 1 | |
| if(temp_vorlauf) addJSON(str,"temp_vorlauf",temp_vorlauf); //JSON line 2 | |
| if(temp_rucklauf) addJSON(str,"temp_rucklauf",temp_rucklauf); //JSON line 3 | |
| endJSON(str); //End JSON | |
| if (client.connect(server, port)) { | |
| Serial.println("connected"); | |
| Serial.println("sending: /emoncms/api/post.json?apikey=xxxxxxxxxxxxxxxxxxxxxxxxxxx&node=41&json="); | |
| Serial.print(str); | |
| client.print("GET /emoncms/api/post.json?apikey=xxxxxxxxxxxxxxxxxxxxxxxxxxx&node=41&json="); //Add in your postin url here, there's more info on the web side of things in data modules and builds on the website | |
| client.println(str); //Send the string | |
| client.stop(); | |
| } | |
| } | |
| } | |
| if (millis()-utimeW>10000) | |
| { | |
| //Serial.println("Alle 10 Sekunden"); | |
| utimeW = millis(); | |
| //------------------------------------------------------------------------------------------- | |
| // 3) Create a string to be sent to the server | |
| //------------------------------------------------------------------------------------------- | |
| strcpy(str,""); //URL | |
| srtJSON(str); //Start JSON | |
| addJSON(str,"P0_power",getPower(0, 0.0005)); //JSON line 1 | |
| //addJSON(str,"P0_kwh", getkWhInc(0, 0.0005)); //JSON line 2 | |
| addJSON(str,"P1_power",getPower(1, 0.001)); //JSON line 1 | |
| //addJSON(str,"P1_kwh", getkWhInc(1, 0.001)); //JSON line 2 | |
| addJSON(str,"P2_power",getPower(2, 0.0005)); //JSON line 1 | |
| //addJSON(str,"P2_kwh", getkWhInc(2, 0.0005)); //JSON line 2 | |
| addJSON(str,"P3_power",getPower(3, 0.0005)); //JSON line 1 | |
| //addJSON(str,"P3_kwh", getkWhInc(3, 0.0005)); //JSON line 2 | |
| addJSON(str,"P4_power",getPower(4, 0.0005)); //JSON line 1 | |
| //addJSON(str,"P4_kwh", getkWhInc(4, 0.0005)); //JSON line 2 | |
| addJSON(str,"P5_power",getPower(5, 0.0005)); //JSON line 1 | |
| //addJSON(str,"P5_kwh", getkWhInc(5, 0.0005)); //JSON line 2 | |
| addJSON(str,"P6_power",getPower(6, 0.001)); //JSON line 1 | |
| //addJSON(str,"P6_kwh", getkWhInc(6, 0.001)); //JSON line 2 | |
| /* | |
| addJSON(str,"P7_power",getPower(7, 0.005)); //JSON line 1 | |
| addJSON(str,"P7_kwh", getkWhInc(7, 0.005)); //JSON line 2 | |
| addJSON(str,"P8_power",getPower(8, 0.005)); //JSON line 1 | |
| addJSON(str,"P8_kwh", getkWhInc(8, 0.005)); //JSON line 2 | |
| addJSON(str,"P9_power",getPower(9, 0.005)); //JSON line 1 | |
| addJSON(str,"P9_kwh", getkWhInc(9, 0.005)); //JSON line 2 | |
| addJSON(str,"P10_power",getPower(10, 0.005)); //JSON line 1 | |
| addJSON(str,"P10_kwh", getkWhInc(10, 0.005)); //JSON line 2*/ | |
| //and so on... | |
| //watch going out of range on the json string it has 150 characters, increase it in setup if you need to | |
| endJSON(str); //End JSON | |
| //------------------------------------------------------------------------------------------- | |
| // 4) Send the string to the server | |
| //------------------------------------------------------------------------------------------- | |
| if (client.connect(server, port)) { | |
| Serial.println("connected"); | |
| Serial.println("sending: /emoncms/api/post.json?apikey=xxxxxxxxxxxxxxxxxxxxxxx&node=51&json="); | |
| Serial.print(str); | |
| client.print("GET /emoncms/api/post.json?apikey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&node=51&json="); //Add in your postin url here, there's more info on the web side of things in data modules and builds on the website | |
| client.println(str); //Send the string | |
| client.stop(); | |
| resetkWhInc(0); | |
| resetkWhInc(1); | |
| resetkWhInc(2); | |
| resetkWhInc(3); | |
| resetkWhInc(4); | |
| resetkWhInc(5); | |
| resetkWhInc(6); | |
| /*resetkWhInc(7); | |
| resetkWhInc(8); | |
| resetkWhInc(9); | |
| resetkWhInc(10); | |
| */ | |
| } else { | |
| Serial.println("connection failed"); | |
| } | |
| } | |
| } | |
| /*-----( Declare User-written Functions )-----*/ | |
| float printTemperature(DeviceAddress deviceAddress) | |
| { | |
| float tempC = sensors.getTempC(deviceAddress); | |
| if (tempC == -127.00) | |
| { | |
| return 0; | |
| } | |
| else | |
| { | |
| return tempC; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //--------------------------------------------------------------------- | |
| // Pulse String Decoder Sketch with Ethernet forwarding | |
| // GNU GPL openenergymonitor.org | |
| // Author: Trystan Lea | |
| //--------------------------------------------------------------------- | |
| #include <Ethernet.h> | |
| #include <SPI.h> | |
| byte mac[] = {0x54,0x55,0x53,0x10,0x04,0x28}; | |
| char server[] = "home.keno.lan"; | |
| IPAddress ip(192,168,1,177); | |
| #define port 80 | |
| EthernetClient client; | |
| char str[320]; //Increase this if not all of your json string is being sent. | |
| unsigned long utime; //Update time | |
| //Float to string functions, see attached: ftoa | |
| //thanks to Don Kinzer arduino forums | |
| void fmtDouble(double val, byte precision, char *buf, unsigned bufLen = 0xffff); | |
| unsigned fmtUnsigned(unsigned long val, char *buf, unsigned bufLen = 0xffff, byte width = 0); | |
| void setup() | |
| { | |
| Serial.begin(115200); //Needs to be 115200 for fast transfer between pulse counting arduino and this arduino | |
| // start the Ethernet connection: | |
| if (Ethernet.begin(mac) == 0) { | |
| Serial.println("Failed to configure Ethernet using DHCP"); | |
| // no point in carrying on, so do nothing forevermore: | |
| // try to congifure using IP address instead of DHCP: | |
| Ethernet.begin(mac, ip); | |
| } | |
| // give the Ethernet shield a second to initialize: | |
| delay(1000); | |
| Serial.println("connecting..."); | |
| } | |
| void loop() | |
| { | |
| decode_pulse_string(); //Method decodes string send from pulse counting arduino | |
| if (millis()-utime>10000) | |
| { | |
| utime = millis(); | |
| //------------------------------------------------------------------------------------------- | |
| // 3) Create a string to be sent to the server | |
| //------------------------------------------------------------------------------------------- | |
| strcpy(str,""); //URL | |
| srtJSON(str); //Start JSON | |
| addJSON(str,"P0_power",getPower(0, 0.0005)); //JSON line 1 | |
| addJSON(str,"P0_kwh", getkWhInc(0, 0.0005)); //JSON line 2 | |
| addJSON(str,"P1_power",getPower(1, 0.001)); //JSON line 1 | |
| addJSON(str,"P1_kwh", getkWhInc(1, 0.001)); //JSON line 2 | |
| addJSON(str,"P2_power",getPower(2, 0.0005)); //JSON line 1 | |
| addJSON(str,"P2_kwh", getkWhInc(2, 0.0005)); //JSON line 2 | |
| addJSON(str,"P3_power",getPower(3, 0.0005)); //JSON line 1 | |
| addJSON(str,"P3_kwh", getkWhInc(3, 0.0005)); //JSON line 2 | |
| addJSON(str,"P4_power",getPower(4, 0.0005)); //JSON line 1 | |
| addJSON(str,"P4_kwh", getkWhInc(4, 0.0005)); //JSON line 2 | |
| addJSON(str,"P5_power",getPower(5, 0.0005)); //JSON line 1 | |
| addJSON(str,"P5_kwh", getkWhInc(5, 0.0005)); //JSON line 2 | |
| addJSON(str,"P6_power",getPower(6, 0.001)); //JSON line 1 | |
| addJSON(str,"P6_kwh", getkWhInc(6, 0.001)); //JSON line 2 | |
| /* | |
| addJSON(str,"P7_power",getPower(7, 0.005)); //JSON line 1 | |
| addJSON(str,"P7_kwh", getkWhInc(7, 0.005)); //JSON line 2 | |
| addJSON(str,"P8_power",getPower(8, 0.005)); //JSON line 1 | |
| addJSON(str,"P8_kwh", getkWhInc(8, 0.005)); //JSON line 2 | |
| addJSON(str,"P9_power",getPower(9, 0.005)); //JSON line 1 | |
| addJSON(str,"P9_kwh", getkWhInc(9, 0.005)); //JSON line 2 | |
| addJSON(str,"P10_power",getPower(10, 0.005)); //JSON line 1 | |
| addJSON(str,"P10_kwh", getkWhInc(10, 0.005)); //JSON line 2*/ | |
| //and so on... | |
| //watch going out of range on the json string it has 150 characters, increase it in setup if you need to | |
| endJSON(str); //End JSON | |
| //------------------------------------------------------------------------------------------- | |
| // 4) Send the string to the server | |
| //------------------------------------------------------------------------------------------- | |
| if (client.connect(server, port)) { | |
| Serial.println("connected"); | |
| Serial.println("sending: /emoncms/api/post.json?apikey=xxxxxxxxxxxxxxxxxxxxxxxxx&node=51&json="); | |
| Serial.print(str); | |
| client.print("GET /emoncms/api/post.json?apikey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&node=51&json="); //Add in your postin url here, there's more info on the web side of things in data modules and builds on the website | |
| client.println(str); //Send the string | |
| client.stop(); | |
| resetkWhInc(0); | |
| resetkWhInc(1); | |
| resetkWhInc(2); | |
| resetkWhInc(3); | |
| resetkWhInc(4); | |
| resetkWhInc(5); | |
| resetkWhInc(6); | |
| /*resetkWhInc(7); | |
| resetkWhInc(8); | |
| resetkWhInc(9); | |
| resetkWhInc(10); | |
| */ | |
| } else { | |
| Serial.println("connection failed"); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment