P1 poort slimme meter – Data naar EmonCMS (Arduino)
Bron: woutertp1Â @ Github
Smart-meter-P1
==============
Readout of Dutch smart meter P1-port using Arduino and logging to EmonCMS.
What do you need?
—————–
* Any Arduino, although a Duemilanove might not work due to high memory usage(>16k)
* A RJ11 cable (check if it has 4 wires!)
Optionally:
———–
* A small resistor to limit the 40mA output from Arduino to a maximum of 30mA as specified in DSMR2.2
* Arduino ethernet shield (Wiznet based)
* A computer or server running EmonCMS (http://www.openenergymonitor.org)
How does it work?
—————–
During the setup process after powering the Arduino, 5volt is enabled to pin4. This in turn enables the logging from the Smart Meter. Once the Smart Meter has ended sending the telegram, the Arduino (tries to) decode it. This solution does not require an inverter, such as an 7404.
Will it work for me?
——————–
I don’t have a gasmeter, so if you want to read that from your Smart Meter, you’ll have to extend the code. Just follow the output from the Smart Meter, which you can also output to the serial window (uncomment ‘Serial.println(inputString);’). Also, you can decode other parts of the telegram, which I wasn’t interested in (such as current tariff). If you want to send your data to Cosm, just change the httpRequest function to your needs.
Are there any issues?
———————
An Arduino is really not suitable for large string operations, but it kinda works in my situation. I’m suspecting that larger P1 telegram messages (with length >1) might not fully work. Also, the first telegram it receives should really be ignored, although that could be a timing issue. I have been running my setup for several weeks nonstop now and it still functions absolutely perfect. The Arduino continues to send updates to EmonCMS, even after server-reboots.
Additions or fixes to my code are more than welcome. Just know that this is my third Arduino project and that most code has been copied from much smarter and more capable developers.
Also, if you ruin your P1 port or Smart Meter: not my problem.
Todo
———————
* Nothing. I have bought a Plugwise Smile P1 and will use that to replace the Arduino.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
/* -------------How to wire Arduino to Smart meter using RJ11 cable------------- Note: make sure to place a small resistor between between 5V & ground. Current from an Arduino output pin is 40mA, while 30mA is allowed on the P1 port. Yellow to pin 9 Red to ground Black to pin 4 -------------Example P1 telegram---------------------------- /ISk5\2ME382-1003 0-0:96.1.1(4B414C37303035303739393336333132) 1-0:1.8.1(00053.950*kWh) 1-0:1.8.2(00081.586*kWh) 1-0:2.8.1(00003.303*kWh) 1-0:2.8.2(00009.299*kWh) 0-0:96.14.0(0002) 1-0:1.7.0(0000.03*kW) 1-0:2.7.0(0000.00*kW) 0-0:17.0.0(0999.00*kW) 0-0:96.3.10(1) 0-0:96.13.1() 0-0:96.13.0() ! */ #include <SoftwareSerial.h> #include <SPI.h> #include <Ethernet.h> byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; IPAddress ip(192,168,1,201); IPAddress server(192,168,1,150); EthernetClient client; const int requestPin = 4; int incomingByte = 0; int pos181; int pos182; int pos281; int pos282; int P1_pos; int P2_pos; String inputString; String T181; String T182; String T281; String T282; String P1; String P2; int counter = 0; SoftwareSerial mySerial(9, 8, true); // RX, TX, inverted void setup () { Serial.begin(9600); delay(1000); mySerial.begin(9600); delay(1000); Ethernet.begin(mac, ip); delay(1000); Serial.print("My IP address: "); Serial.println(Ethernet.localIP()); pinMode(requestPin, OUTPUT); digitalWrite(requestPin, HIGH); } void loop () { while (mySerial.available() > 0) { incomingByte = mySerial.read(); incomingByte &= ~(1 << 7); // forces 0th bit of x to be 0. all other bits left alone. char inChar = (char)incomingByte; inputString += inChar; } //If output from Smart meter is long enough, process it. Length needs to be checked individually just in case if (inputString.length() > 100) { //Serial.println(inputString); pos181 = inputString.indexOf("1-0:1.8.1", 0); T181 = inputString.substring(pos181 + 10, pos181 + 17); Serial.println("T181 = " + T181); pos182 = inputString.indexOf("1-0:1.8.2", pos181 + 1); T182 = inputString.substring(pos182 + 10, pos182 + 17); Serial.println("T182 = " + T182); pos281 = inputString.indexOf("1-0:2.8.1", pos182 + 1); T281 = inputString.substring(pos281 + 10, pos281 + 17); Serial.println("T281 = " + T281); pos282 = inputString.indexOf("1-0:2.8.2", pos281 + 1); T282 = inputString.substring(pos282 + 10, pos282 + 17); Serial.println("T282 = " + T282); P1_pos = inputString.indexOf("1-0:1.7.0", pos282 + 1); P1 = inputString.substring(P1_pos + 10, P1_pos + 17); Serial.println("P1 = " + P1); P2_pos = inputString.indexOf("1-0:2.7.0", P1_pos + 1); P2 = inputString.substring(P2_pos + 10, P2_pos + 17); Serial.println("P2 = " + P2); Serial.println(counter); httpRequest(); inputString = "0"; delay(1000); client.stop(); if (counter < 6) { counter++; } else { counter = 0; } } } void httpRequest() { // if there's a successful connection: if (client.connect(server, 80)) { if ( counter < 6 ) { client.println("GET /emoncms3/api/post?apikey=c2bc8720aa9e34cd9a661b1a7f400531&json={P1:" + P1 + ",P2:" + P2 + "} HTTP/1.1"); Serial.println("GET /emoncms3/api/post?apikey=c2bc8720aa9e34cd9a661b1a7f400531&json={P1:" + P1 + ",P2:" + P2 + "} HTTP/1.1"); } if ( counter > 5 ) { client.println("GET /emoncms3/api/post?apikey=c2bc8720aa9e34cd9a661b1a7f400531&json={T1:" + T181 + ",T2:" + T182 + ",T7:" + T281 + ",T8:" + T282 + ",P1:" + P1 + ",P2:" + P2 + "} HTTP/1.1"); Serial.println("GET /emoncms3/api/post?apikey=c2bc8720aa9e34cd9a661b1a7f400531&json={T1:" + T181 + ",T2:" + T182 + ",T7:" + T281 + ",T8:" + T282 + ",P1:" + P1 + ",P2:" + P2 + "} HTTP/1.1"); } client.println("Host: 192.168.1.150"); client.println("User-Agent: arduino-ethernet"); client.println("Connection: close"); client.println(); Serial.println("Connection OK!"); } else { Serial.println("connection failed"); client.stop(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
void dhcp_dns() { //----------------------------------------------------------------------------------- // Get DHCP address // Putting DHCP setup and DNS lookup in the main loop allows for: // powering nanode before ethernet is connected //----------------------------------------------------------------------------------- if (ether.dhcpExpired()) dhcp_status = 0; // if dhcp expired start request for new lease by changing status if (!dhcp_status){ #ifdef UNO wdt_disable(); #endif dhcp_status = ether.dhcpSetup(); // DHCP setup #ifdef UNO wdt_enable(WDTO_8S); #endif Serial.print("DHCP status: "); // print Serial.println(dhcp_status); // dhcp status if (dhcp_status){ // on success print out ip's ether.printIp("IP: ", ether.myip); ether.printIp("GW: ", ether.gwip); static byte dnsip[] = {8,8,8,8}; ether.copyIp(ether.dnsip, dnsip); ether.printIp("DNS: ", ether.dnsip); //ether.copyIp(ether.hisip, hisip); // un-comment for posting to static IP server (no domain name) //ether.hisport = 3000; //dns_status = 1; // un-comment for posting to static IP server (no domain name) } else { ethernet_error = 1; } } //----------------------------------------------------------------------------------- // Get server address via DNS //----------------------------------------------------------------------------------- if (dhcp_status && !dns_status){ #ifdef UNO wdt_disable(); #endif dns_status = ether.dnsLookup(website); // Attempt DNS lookup #ifdef UNO wdt_enable(WDTO_8S); #endif; Serial.print("DNS status: "); // print Serial.println(dns_status); // dns status if (dns_status){ ether.printIp("SRV: ", ether.hisip); // server ip } else { ethernet_error = 1; } } } |