Advertisement
Guest User

Untitled

a guest
Mar 20th, 2018
440
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.99 KB | None | 0 0
  1. #include <SoftwareSerial.h>
  2.  
  3. //Kamstrup setup
  4. // Kamstrup Multical 601
  5. word const kregnums[] = { 0x003C,0x0050,0x0056,0x0057,0x0059,0x004a,0x0044 };
  6. char* kregstrings[] = { "Energy","Current Power","Temperature t1","Temperature t2","Temperature diff", "Flow", "Volumen 1" };
  7. #define NUMREGS 7 // Number of registers above
  8. #define KAMBAUD 1200
  9.  
  10. // Units
  11. char* units[65] = {"","Wh","kWh","MWh","GWh","j","kj","Mj",
  12. "Gj","Cal","kCal","Mcal","Gcal","varh","kvarh","Mvarh","Gvarh",
  13. "VAh","kVAh","MVAh","GVAh","kW","kW","MW","GW","kvar","kvar","Mvar",
  14. "Gvar","VA","kVA","MVA","GVA","V","A","kV","kA","C","K","l","m3",
  15. "l/h","m3/h","m3xC","ton","ton/h","h","hh:mm:ss","yy:mm:dd","yyyy:mm:dd",
  16. "mm:dd","","bar","RTC","ASCII","m3 x 10","ton xr 10","GJ x 10","minutes","Bitfield",
  17. "s","ms","days","RTC-Q","Datetime"};
  18.  
  19. // Pin definitions
  20. #define PIN_KAMSER_RX 9 // Kamstrup IR interface RX
  21. #define PIN_KAMSER_TX 10 // Kamstrup IR interface TX
  22. #define PIN_LED 13 // Standard Arduino LED
  23.  
  24. // Kamstrup optical IR serial
  25. #define KAMTIMEOUT 300 // Kamstrup timeout after transmit
  26. SoftwareSerial kamSer(PIN_KAMSER_RX, PIN_KAMSER_TX, false); // Initialize serial
  27.  
  28.  
  29. void setup () {
  30. Serial.begin(57600);
  31.  
  32. pinMode(PIN_LED, OUTPUT);
  33. digitalWrite(PIN_LED, 0);
  34.  
  35. // setup kamstrup serial
  36. pinMode(PIN_KAMSER_RX,INPUT);
  37. pinMode(PIN_KAMSER_TX,OUTPUT);
  38. kamSer.begin(KAMBAUD);
  39.  
  40. delay(200);
  41.  
  42. //Serial.println("\n[testKamstrup]");
  43. // poll the Kamstrup registers for data
  44. for (int kreg = 0; kreg < NUMREGS; kreg++) {
  45. kamReadReg(kreg);
  46. delay(100);
  47. }
  48. }
  49.  
  50. void loop () {
  51. // poll the Kamstrup registers for data
  52. for (int kreg = 0; kreg < NUMREGS; kreg++) {
  53. kamReadReg(kreg);
  54. delay(100);
  55. }
  56.  
  57. digitalWrite(PIN_LED, digitalRead(PIN_KAMSER_RX));
  58. delay(1000);
  59. }
  60.  
  61. // kamReadReg - read a Kamstrup register
  62. float kamReadReg(unsigned short kreg) {
  63.  
  64. byte recvmsg[40]; // buffer of bytes to hold the received data
  65. float rval; // this will hold the final value
  66.  
  67. // prepare message to send and send it
  68. byte sendmsg[] = { 0x3f, 0x10, 0x01, (kregnums[kreg] >> 8), (kregnums[kreg] & 0xff) };
  69. kamSend(sendmsg, 5);
  70.  
  71. // listen if we get an answer
  72. unsigned short rxnum = kamReceive(recvmsg);
  73.  
  74. // check if number of received bytes > 0
  75. if(rxnum != 0){
  76.  
  77. // decode the received message
  78. rval = kamDecode(kreg,recvmsg);
  79.  
  80. // print out received value to terminal (debug)
  81. Serial.print(kregstrings[kreg]);
  82. Serial.print(": ");
  83. Serial.print(rval);
  84. Serial.print(" ");
  85. Serial.println();
  86.  
  87. return rval;
  88. }
  89. }
  90.  
  91. // kamSend - send data to Kamstrup meter
  92. void kamSend(byte const *msg, int msgsize) {
  93.  
  94. // append checksum bytes to message
  95. byte newmsg[msgsize+2];
  96. for (int i = 0; i < msgsize; i++) { newmsg[i] = msg[i]; }
  97. newmsg[msgsize++] = 0x00;
  98. newmsg[msgsize++] = 0x00;
  99. int c = crc_1021(newmsg, msgsize);
  100. newmsg[msgsize-2] = (c >> 8);
  101. newmsg[msgsize-1] = c & 0xff;
  102.  
  103. // build final transmit message - escape various bytes
  104. byte txmsg[20] = { 0x80 }; // prefix
  105. int txsize = 1;
  106. for (int i = 0; i < msgsize; i++) {
  107. if (newmsg[i] == 0x06 or newmsg[i] == 0x0d or newmsg[i] == 0x1b or newmsg[i] == 0x40 or newmsg[i] == 0x80) {
  108. txmsg[txsize++] = 0x1b;
  109. txmsg[txsize++] = newmsg[i] ^ 0xff;
  110. } else {
  111. txmsg[txsize++] = newmsg[i];
  112. }
  113. }
  114. txmsg[txsize++] = 0x0d; // EOF
  115.  
  116. // send to serial interface
  117. for (int x = 0; x < txsize; x++) {
  118. kamSer.write(txmsg[x]);
  119. }
  120.  
  121. }
  122.  
  123. // kamReceive - receive bytes from Kamstrup meter
  124. unsigned short kamReceive(byte recvmsg[]) {
  125.  
  126. byte rxdata[50]; // buffer to hold received data
  127. unsigned long rxindex = 0;
  128. unsigned long starttime = millis();
  129.  
  130. kamSer.flush(); // flush serial buffer - might contain noise
  131.  
  132. byte r;
  133.  
  134. // loop until EOL received or timeout
  135. while(r != 0x0d){
  136.  
  137. // handle rx timeout
  138. if(millis()-starttime > KAMTIMEOUT) {
  139. Serial.println("Timed out listening for data");
  140. return 0;
  141. }
  142.  
  143. // handle incoming data
  144. if (kamSer.available()) {
  145.  
  146. // receive byte
  147. r = kamSer.read();
  148. if(r != 0x40) { // don't append if we see the start marker
  149. // append data
  150. rxdata[rxindex] = r;
  151. rxindex++;
  152. }
  153.  
  154. }
  155. }
  156.  
  157. // remove escape markers from received data
  158. unsigned short j = 0;
  159. for (unsigned short i = 0; i < rxindex -1; i++) {
  160. if (rxdata[i] == 0x1b) {
  161. byte v = rxdata[i+1] ^ 0xff;
  162. if (v != 0x06 and v != 0x0d and v != 0x1b and v != 0x40 and v != 0x80){
  163. Serial.print("Missing escape ");
  164. Serial.println(v,HEX);
  165. }
  166. recvmsg[j] = v;
  167. i++; // skip
  168. } else {
  169. recvmsg[j] = rxdata[i];
  170. }
  171. j++;
  172. }
  173.  
  174. // check CRC
  175. if (crc_1021(recvmsg,j)) {
  176. Serial.println("CRC error: ");
  177. return 0;
  178. }
  179.  
  180. return j;
  181.  
  182. }
  183.  
  184. // kamDecode - decodes received data
  185. float kamDecode(unsigned short const kreg, byte const *msg) {
  186.  
  187. // skip if message is not valid
  188. if (msg[0] != 0x3f or msg[1] != 0x10) {
  189. return false;
  190. }
  191. if (msg[2] != (kregnums[kreg] >> 8) or msg[3] != (kregnums[kreg] & 0xff)) {
  192. return false;
  193. }
  194.  
  195. // decode the mantissa
  196. long x = 0;
  197. for (int i = 0; i < msg[5]; i++) {
  198. x <<= 8;
  199. x |= msg[i + 7];
  200. }
  201.  
  202. // decode the exponent
  203. int i = msg[6] & 0x3f;
  204. if (msg[6] & 0x40) {
  205. i = -i;
  206. };
  207. float ifl = pow(10,i);
  208. if (msg[6] & 0x80) {
  209. ifl = -ifl;
  210. }
  211.  
  212. // return final value
  213. return (float )(x * ifl);
  214.  
  215. }
  216.  
  217. // crc_1021 - calculate crc16
  218. long crc_1021(byte const *inmsg, unsigned int len){
  219. long creg = 0x0000;
  220. for(unsigned int i = 0; i < len; i++) {
  221. int mask = 0x80;
  222. while(mask > 0) {
  223. creg <<= 1;
  224. if (inmsg[i] & mask){
  225. creg |= 1;
  226. }
  227. mask>>=1;
  228. if (creg & 0x10000) {
  229. creg &= 0xffff;
  230. creg ^= 0x1021;
  231. }
  232. }
  233. }
  234. return creg;
  235. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement