Advertisement
Guest User

Untitled

a guest
Mar 20th, 2018
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.51 KB | None | 0 0
  1. ------------------------------------------------------------------------------------------------------------
  2. -ID- -Node Type-
  3. 0 - Special allocation in JeeLib RFM12 driver - reserved for OOK use
  4. 1-4 - Control nodes
  5. 5-10 - Energy monitoring nodes
  6. 11-14 --Un-assigned --
  7. 15-16 - Base Station & logging nodes
  8. 17-30 - Environmental sensing nodes (temperature humidity etc.)
  9. 31 - Special allocation in JeeLib RFM12 driver - Node31 can communicate with nodes on any network group
  10. -------------------------------------------------------------------------------------------------------------
  11.  
  12. TODO: set kamser pins
  13.  
  14.  
  15. */
  16. #include <jeelib.h> // make sure V12 (latest) is used if using RFM69CW
  17. #include <onewire.h>
  18. #include <dallastemperature.h>
  19. #include <avr wdt.h="">
  20. //********************************************Kamstrup Stuff Start********************************************
  21. #include <softwareserial.h>
  22.  
  23. //Kamstrup setup
  24. // Kamstrup Multical 601
  25. word const kregnums[] = { 0x003C,0x0050,0x0056,0x0057,0x0059,0x004a,0x0044 };
  26. char* kregstrings[] = { "Energy","Current Power","Temperature t1","Temperature t2","Temperature diff", "Flow", "Volumen 1" };
  27. #define NUMREGS 7 // Number of registers above
  28. #define KAMBAUD 1200
  29.  
  30. // Units
  31. char* units[65] = {"","Wh","kWh","MWh","GWh","j","kj","Mj",
  32. "Gj","Cal","kCal","Mcal","Gcal","varh","kvarh","Mvarh","Gvarh",
  33. "VAh","kVAh","MVAh","GVAh","kW","kW","MW","GW","kvar","kvar","Mvar",
  34. "Gvar","VA","kVA","MVA","GVA","V","A","kV","kA","C","K","l","m3",
  35. "l/h","m3/h","m3xC","ton","ton/h","h","hh:mm:ss","yy:mm:dd","yyyy:mm:dd",
  36. "mm:dd","","bar","RTC","ASCII","m3 x 10","ton x 10","GJ x 10","minutes","Bitfield",
  37. "s","ms","days","RTC-Q","Datetime"};
  38.  
  39. //********************************************Kamstrup Stuff End********************************************
  40.  
  41. #define RF_freq RF12_868MHZ // Frequency of RF12B module can be RF12_433MHZ, RF12_868MHZ or RF12_915MHZ. You should use the one matching the module you have.
  42. const int nodeID = 10; // emonTx RFM12B node ID
  43. const int networkGroup = 210; // emonTx RFM12B wireless network group - needs to be same as emonBase and emonGLCD
  44.  
  45. const int UNO = 1; // Set to 0 if your not using the UNO bootloader (i.e using Duemilanove) - All Atmega's shipped from OpenEnergyMonitor come with Arduino Uno bootloader
  46.  
  47.  
  48. #define RF69_COMPAT 0 // set to 1 to use RFM69CW
  49.  
  50.  
  51. //********************************************Kamstrup Stuff Start********************************************
  52. // Pin definitions
  53. #define PIN_KAMSER_RX 1 // Kamstrup IR interface RX
  54. #define PIN_KAMSER_TX 1 // Kamstrup IR interface TX
  55.  
  56. //********************************************Kamstrup Stuff End********************************************
  57.  
  58. #define ONE_WIRE_BUS 4 // Data wire is plugged into port 2 on the Arduino
  59.  
  60.  
  61. OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
  62. DallasTemperature sensors(&amp;oneWire); // Pass our oneWire reference to Dallas Temperature.
  63.  
  64. // By using direct addressing its possible to make sure that as you add temperature sensors
  65. // the temperature sensor to variable mapping will not change.
  66. // To find the addresses of your temperature sensors use the: **temperature_search sketch**
  67. DeviceAddress address_T1 = { 0x28, 0x22, 0x70, 0xEE, 0x02, 0x00, 0x00, 0xB8 };
  68.  
  69. typedef struct {
  70. int power; // power
  71. int pulse; // pulses
  72. int T1; // temperature sensor 1
  73. //********************************************Kamstrup Stuff Start********************************************
  74. int Energy;
  75. int CurrentPower;
  76. int Temperaturet1;
  77. int Temperaturet2;
  78. int Temperaturediff;
  79. int Flow;
  80. int Volumen1;
  81. int Volumen2;
  82. //********************************************Kamstrup Stuff Start********************************************
  83.  
  84. } Payload;
  85. Payload emontx;
  86.  
  87. const int LEDpin = 9;
  88.  
  89. // Pulse counting settings
  90. long pulseCount = 0; // Number of pulses, used to measure energy.
  91. unsigned long pulseTime,lastTime; // Used to measure power.
  92. double power, elapsedWh; // power and energy
  93. int ppwh = 10; // 1000 pulses/kwh = 1 pulse per wh - Number of pulses per wh - found or set on the meter.
  94.  
  95. //********************************************Kamstrup Stuff Start********************************************
  96. // Kamstrup optical IR serial
  97. #define KAMTIMEOUT 2000 // Kamstrup timeout after transmit
  98. #define POLLINTERVAL 20000 // Polling interval
  99. SoftwareSerial kamSer(PIN_KAMSER_RX, PIN_KAMSER_TX, false); // Initialize serial
  100.  
  101. // last poll variable
  102. long lastpoll;
  103. //********************************************Kamstrup Stuff End********************************************
  104.  
  105.  
  106. void setup() {
  107. Serial.begin(57600);
  108. Serial.println("emonTX Temperature power pulse example");
  109. Serial.println("OpenEnergyMonitor.org");
  110.  
  111. //********************************************Kamstrup Stuff Start********************************************
  112.  
  113.  
  114. // setup kamstrup serial
  115. pinMode(PIN_KAMSER_RX,INPUT);
  116. pinMode(PIN_KAMSER_TX,OUTPUT);
  117. kamSer.begin(KAMBAUD);
  118.  
  119. // initialize lastpoll value
  120. lastpoll = 0;
  121. //********************************************Kamstrup Stuff End********************************************
  122.  
  123.  
  124. sensors.begin();
  125.  
  126. rf12_initialize(nodeID, RF_freq, networkGroup); // initialize RF
  127. rf12_sleep(RF12_SLEEP);
  128.  
  129. pinMode(LEDpin, OUTPUT);
  130. digitalWrite(LEDpin, HIGH);
  131.  
  132. attachInterrupt(1, onPulse, FALLING); // KWH interrupt attached to IRQ 1 = pin3 - hardwired to emonTx pulse jackplug. For connections see: http://openenergymonitor.org/emon/node/208
  133.  
  134.  
  135. }
  136.  
  137. void loop()
  138. {
  139.  
  140. //********************************************Kamstrup Stuff Start********************************************
  141. // check if it is time to do a poll
  142. if(millis() - lastpoll &gt; POLLINTERVAL or lastpoll == 0) {
  143.  
  144. // poll the Kamstrup registers for data
  145. for (int kreg = 0; kreg &lt; NUMREGS; kreg++) {
  146. kamReadReg(kreg);
  147. delay(100);
  148. }
  149.  
  150. digitalWrite(PIN_LED, digitalRead(PIN_KAMSER_RX));
  151. delay(1000);
  152.  
  153. // update lastpoll
  154. lastpoll = millis();
  155.  
  156. //********************************************Kamstrup Stuff End********************************************
  157.  
  158. sensors.requestTemperatures(); // Send the command to get temperatures
  159.  
  160. emontx.T1 = sensors.getTempC(address_T1) * 100;
  161. emontx.pulse = pulseCount; pulseCount=0;
  162.  
  163. Serial.print(emontx.power);
  164. Serial.print("W ");
  165. Serial.println(emontx.pulse);
  166.  
  167.  
  168.  
  169. send_rf_data(); // *SEND RF DATA* - see emontx_lib
  170.  
  171. digitalWrite(LEDpin, HIGH); delay(2); digitalWrite(LEDpin, LOW); // flash LED
  172.  
  173.  
  174.  
  175. }
  176.  
  177. }
  178.  
  179.  
  180. // kamReadReg - read a Kamstrup register
  181. float kamReadReg(unsigned short kreg) {
  182.  
  183. byte recvmsg[30]; // buffer of bytes to hold the received data
  184. float rval; // this will hold the final value
  185.  
  186. // prepare message to send and send it
  187. byte sendmsg[] = { 0x3f, 0x10, 0x01, (kregnums[kreg] &gt;&gt; 8), (kregnums[kreg] &amp; 0xff) };
  188. kamSend(sendmsg, 5);
  189.  
  190. // listen if we get an answer
  191. unsigned short rxnum = kamReceive(recvmsg);
  192.  
  193. // check if number of received bytes &gt; 0
  194. if(rxnum != 0){
  195.  
  196. // decode the received message
  197. rval = kamDecode(kreg,recvmsg);
  198.  
  199. // print out received value to terminal (debug)
  200. Serial.print(kregstrings[kreg]);
  201. Serial.print(": ");
  202. Serial.print(rval);
  203. Serial.print(" ");
  204. Serial.println();
  205.  
  206. return rval;
  207. }
  208.  
  209. }
  210.  
  211. // kamSend - send data to Kamstrup meter
  212. void kamSend(byte const *msg, int msgsize) {
  213.  
  214. // append checksum bytes to message
  215. byte newmsg[msgsize+2];
  216. for (int i = 0; i &lt; msgsize; i++) { newmsg[i] = msg[i]; }
  217. newmsg[msgsize++] = 0x00;
  218. newmsg[msgsize++] = 0x00;
  219. int c = crc_1021(newmsg, msgsize);
  220. newmsg[msgsize-2] = (c &gt;&gt; 8);
  221. newmsg[msgsize-1] = c &amp; 0xff;
  222.  
  223. // build final transmit message - escape various bytes
  224. byte txmsg[20] = { 0x80 }; // prefix
  225. int txsize = 1;
  226. for (int i = 0; i &lt; msgsize; i++) {
  227. if (newmsg[i] == 0x06 or newmsg[i] == 0x0d or newmsg[i] == 0x1b or newmsg[i] == 0x40 or newmsg[i] == 0x80) {
  228. txmsg[txsize++] = 0x1b;
  229. txmsg[txsize++] = newmsg[i] ^ 0xff;
  230. } else {
  231. txmsg[txsize++] = newmsg[i];
  232. }
  233. }
  234. txmsg[txsize++] = 0x0d; // EOF
  235.  
  236. // send to serial interface
  237. for (int x = 0; x &lt; txsize; x++) {
  238. kamSer.write(txmsg[x]);
  239. }
  240.  
  241. }
  242.  
  243. // kamReceive - receive bytes from Kamstrup meter
  244. unsigned short kamReceive(byte recvmsg[]) {
  245.  
  246. byte rxdata[50]; // buffer to hold received data
  247. unsigned long rxindex = 0;
  248. unsigned long starttime = millis();
  249.  
  250. kamSer.flush(); // flush serial buffer - might contain noise
  251.  
  252. byte r;
  253.  
  254. // loop until EOL received or timeout
  255. while(r != 0x0d){
  256.  
  257. // handle rx timeout
  258. if(millis()-starttime &gt; KAMTIMEOUT) {
  259. Serial.println("Timed out listening for data");
  260. return 0;
  261. }
  262.  
  263. // handle incoming data
  264. if (kamSer.available()) {
  265.  
  266. // receive byte
  267. r = kamSer.read();
  268. if(r != 0x40) { // don't append if we see the start marker
  269. // append data
  270. rxdata[rxindex] = r;
  271. rxindex++;
  272. }
  273.  
  274. }
  275. }
  276.  
  277. // remove escape markers from received data
  278. unsigned short j = 0;
  279. for (unsigned short i = 0; i &lt; rxindex -1; i++) {
  280. if (rxdata[i] == 0x1b) {
  281. byte v = rxdata[i+1] ^ 0xff;
  282. if (v != 0x06 and v != 0x0d and v != 0x1b and v != 0x40 and v != 0x80){
  283. Serial.print("Missing escape ");
  284. Serial.println(v,HEX);
  285. }
  286. recvmsg[j] = v;
  287. i++; // skip
  288. } else {
  289. recvmsg[j] = rxdata[i];
  290. }
  291. j++;
  292. }
  293.  
  294. // check CRC
  295. if (crc_1021(recvmsg,j)) {
  296. Serial.println("CRC error: ");
  297. return 0;
  298. }
  299.  
  300. return j;
  301.  
  302. }
  303.  
  304. // kamDecode - decodes received data
  305. float kamDecode(unsigned short const kreg, byte const *msg) {
  306.  
  307. // skip if message is not valid
  308. if (msg[0] != 0x3f or msg[1] != 0x10) {
  309. return false;
  310. }
  311. if (msg[2] != (kregnums[kreg] &gt;&gt; 8) or msg[3] != (kregnums[kreg] &amp; 0xff)) {
  312. return false;
  313. }
  314.  
  315. // decode the mantissa
  316. long x = 0;
  317. for (int i = 0; i &lt; msg[5]; i++) {
  318. x &lt;&lt;= 8;
  319. x |= msg[i + 7];
  320. }
  321.  
  322. // decode the exponent
  323. int i = msg[6] &amp; 0x3f;
  324. if (msg[6] &amp; 0x40) {
  325. i = -i;
  326. };
  327. float ifl = pow(10,i);
  328. if (msg[6] &amp; 0x80) {
  329. ifl = -ifl;
  330. }
  331.  
  332. // return final value
  333. return (float )(x * ifl);
  334.  
  335. }
  336.  
  337. // crc_1021 - calculate crc16
  338. long crc_1021(byte const *inmsg, unsigned int len){
  339. long creg = 0x0000;
  340. for(unsigned int i = 0; i &lt; len; i++) {
  341. int mask = 0x80;
  342. while(mask &gt; 0) {
  343. creg &lt;&lt;= 1;
  344. if (inmsg[i] &amp; mask){
  345. creg |= 1;
  346. }
  347. mask&gt;&gt;=1;
  348. if (creg &amp; 0x10000) {
  349. creg &amp;= 0xffff;
  350. creg ^= 0x1021;
  351. }
  352. }
  353. }
  354. return creg;
  355. }
  356.  
  357. //********************************************Kamstrup Stuff End********************************************
  358. // The interrupt routine - runs each time a falling edge of a pulse is detected
  359. void onPulse()
  360. {
  361. lastTime = pulseTime; //used to measure time between pulses.
  362. pulseTime = micros();
  363. pulseCount++; //pulseCounter
  364. emontx.power = int((3600000000.0 / (pulseTime - lastTime))/ppwh); //Calculate power
  365. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement