Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SoftwareSerial.h>
- //Kamstrup setup
- // Kamstrup Multical 601
- word const kregnums[] = { 0x003C,0x0050,0x0056,0x0057,0x0059,0x004a,0x0044 };
- char* kregstrings[] = { "Energy","Current Power","Temperature t1","Temperature t2","Temperature diff", "Flow", "Volumen 1" };
- #define NUMREGS 7 // Number of registers above
- #define KAMBAUD 1200
- // Units
- char* units[65] = {"","Wh","kWh","MWh","GWh","j","kj","Mj",
- "Gj","Cal","kCal","Mcal","Gcal","varh","kvarh","Mvarh","Gvarh",
- "VAh","kVAh","MVAh","GVAh","kW","kW","MW","GW","kvar","kvar","Mvar",
- "Gvar","VA","kVA","MVA","GVA","V","A","kV","kA","C","K","l","m3",
- "l/h","m3/h","m3xC","ton","ton/h","h","hh:mm:ss","yy:mm:dd","yyyy:mm:dd",
- "mm:dd","","bar","RTC","ASCII","m3 x 10","ton xr 10","GJ x 10","minutes","Bitfield",
- "s","ms","days","RTC-Q","Datetime"};
- // Pin definitions
- #define PIN_KAMSER_RX 9 // Kamstrup IR interface RX
- #define PIN_KAMSER_TX 10 // Kamstrup IR interface TX
- #define PIN_LED 13 // Standard Arduino LED
- // Kamstrup optical IR serial
- #define KAMTIMEOUT 300 // Kamstrup timeout after transmit
- SoftwareSerial kamSer(PIN_KAMSER_RX, PIN_KAMSER_TX, false); // Initialize serial
- void setup () {
- Serial.begin(57600);
- pinMode(PIN_LED, OUTPUT);
- digitalWrite(PIN_LED, 0);
- // setup kamstrup serial
- pinMode(PIN_KAMSER_RX,INPUT);
- pinMode(PIN_KAMSER_TX,OUTPUT);
- kamSer.begin(KAMBAUD);
- delay(200);
- //Serial.println("\n[testKamstrup]");
- // poll the Kamstrup registers for data
- for (int kreg = 0; kreg < NUMREGS; kreg++) {
- kamReadReg(kreg);
- delay(100);
- }
- }
- void loop () {
- // poll the Kamstrup registers for data
- for (int kreg = 0; kreg < NUMREGS; kreg++) {
- kamReadReg(kreg);
- delay(100);
- }
- digitalWrite(PIN_LED, digitalRead(PIN_KAMSER_RX));
- delay(1000);
- }
- // kamReadReg - read a Kamstrup register
- float kamReadReg(unsigned short kreg) {
- byte recvmsg[40]; // buffer of bytes to hold the received data
- float rval; // this will hold the final value
- // prepare message to send and send it
- byte sendmsg[] = { 0x3f, 0x10, 0x01, (kregnums[kreg] >> 8), (kregnums[kreg] & 0xff) };
- kamSend(sendmsg, 5);
- // listen if we get an answer
- unsigned short rxnum = kamReceive(recvmsg);
- // check if number of received bytes > 0
- if(rxnum != 0){
- // decode the received message
- rval = kamDecode(kreg,recvmsg);
- // print out received value to terminal (debug)
- Serial.print(kregstrings[kreg]);
- Serial.print(": ");
- Serial.print(rval);
- Serial.print(" ");
- Serial.println();
- return rval;
- }
- }
- // kamSend - send data to Kamstrup meter
- void kamSend(byte const *msg, int msgsize) {
- // append checksum bytes to message
- byte newmsg[msgsize+2];
- for (int i = 0; i < msgsize; i++) { newmsg[i] = msg[i]; }
- newmsg[msgsize++] = 0x00;
- newmsg[msgsize++] = 0x00;
- int c = crc_1021(newmsg, msgsize);
- newmsg[msgsize-2] = (c >> 8);
- newmsg[msgsize-1] = c & 0xff;
- // build final transmit message - escape various bytes
- byte txmsg[20] = { 0x80 }; // prefix
- int txsize = 1;
- for (int i = 0; i < msgsize; i++) {
- if (newmsg[i] == 0x06 or newmsg[i] == 0x0d or newmsg[i] == 0x1b or newmsg[i] == 0x40 or newmsg[i] == 0x80) {
- txmsg[txsize++] = 0x1b;
- txmsg[txsize++] = newmsg[i] ^ 0xff;
- } else {
- txmsg[txsize++] = newmsg[i];
- }
- }
- txmsg[txsize++] = 0x0d; // EOF
- // send to serial interface
- for (int x = 0; x < txsize; x++) {
- kamSer.write(txmsg[x]);
- }
- }
- // kamReceive - receive bytes from Kamstrup meter
- unsigned short kamReceive(byte recvmsg[]) {
- byte rxdata[50]; // buffer to hold received data
- unsigned long rxindex = 0;
- unsigned long starttime = millis();
- kamSer.flush(); // flush serial buffer - might contain noise
- byte r;
- // loop until EOL received or timeout
- while(r != 0x0d){
- // handle rx timeout
- if(millis()-starttime > KAMTIMEOUT) {
- Serial.println("Timed out listening for data");
- return 0;
- }
- // handle incoming data
- if (kamSer.available()) {
- // receive byte
- r = kamSer.read();
- if(r != 0x40) { // don't append if we see the start marker
- // append data
- rxdata[rxindex] = r;
- rxindex++;
- }
- }
- }
- // remove escape markers from received data
- unsigned short j = 0;
- for (unsigned short i = 0; i < rxindex -1; i++) {
- if (rxdata[i] == 0x1b) {
- byte v = rxdata[i+1] ^ 0xff;
- if (v != 0x06 and v != 0x0d and v != 0x1b and v != 0x40 and v != 0x80){
- Serial.print("Missing escape ");
- Serial.println(v,HEX);
- }
- recvmsg[j] = v;
- i++; // skip
- } else {
- recvmsg[j] = rxdata[i];
- }
- j++;
- }
- // check CRC
- if (crc_1021(recvmsg,j)) {
- Serial.println("CRC error: ");
- return 0;
- }
- return j;
- }
- // kamDecode - decodes received data
- float kamDecode(unsigned short const kreg, byte const *msg) {
- // skip if message is not valid
- if (msg[0] != 0x3f or msg[1] != 0x10) {
- return false;
- }
- if (msg[2] != (kregnums[kreg] >> 8) or msg[3] != (kregnums[kreg] & 0xff)) {
- return false;
- }
- // decode the mantissa
- long x = 0;
- for (int i = 0; i < msg[5]; i++) {
- x <<= 8;
- x |= msg[i + 7];
- }
- // decode the exponent
- int i = msg[6] & 0x3f;
- if (msg[6] & 0x40) {
- i = -i;
- };
- float ifl = pow(10,i);
- if (msg[6] & 0x80) {
- ifl = -ifl;
- }
- // return final value
- return (float )(x * ifl);
- }
- // crc_1021 - calculate crc16
- long crc_1021(byte const *inmsg, unsigned int len){
- long creg = 0x0000;
- for(unsigned int i = 0; i < len; i++) {
- int mask = 0x80;
- while(mask > 0) {
- creg <<= 1;
- if (inmsg[i] & mask){
- creg |= 1;
- }
- mask>>=1;
- if (creg & 0x10000) {
- creg &= 0xffff;
- creg ^= 0x1021;
- }
- }
- }
- return creg;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement