[OpenTRV-dev] OT: need help with reading my heat meter

Bo Herrmannsen EMAIL ADDRESS HIDDEN
Wed May 29 20:14:46 BST 2013


Hi.. moved the pi out to my utility closet and now trying to read it via
IR.... when i reverse rx and tx it will not output anything... and if i
reverse again it just returns 0.00

could it be the code that is wrong?

#include <SoftwareSerial.h>


// Kamstrup Multical 601
word const kregnums[] = {
0x003C,0x0050,0x0056,0x0057,0x0059,0x004a,0x0044,0x0045 };
char* kregstrings[]   = { "Energy","Current Power","Temperature
t1","Temperature t2","Temperature diff", "Flow", "Volumen 1", "Volumen 2" };
#define NUMREGS 8
#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 x 10","GJ x
10","minutes","Bitfield",
        "s","ms","days","RTC-Q","Datetime"};

// Pin definitions

#define PIN_KAMSER_RX  6  // Kamstrup IR interface RX Port 3 DIO
#define PIN_KAMSER_TX  7  // Kamstrup IR interface TX Port 4 DIO


// Kamstrup optical IR serial
#define KAMTIMEOUT 2000      // Kamstrup timeout after transmit
#define POLLINTERVAL 5000  // Polling interval
SoftwareSerial kamSer(PIN_KAMSER_RX, PIN_KAMSER_TX, true);  // Initialize
serial

// last poll variable
long lastpoll;


void setup() {
  // setup pins
  pinMode(PIN_KAMSER_RX,INPUT);
  pinMode(PIN_KAMSER_TX,OUTPUT);

  // initialize kamstrup serial interface
  kamSer.begin(KAMBAUD);

  // initialize serial interface (connected to linksys router)
  Serial.begin(9600);

  // initialize lastpoll value
  lastpoll = 0;
}

void loop() {

  // check if it is time to do a poll
  if(millis() - lastpoll > POLLINTERVAL or lastpoll == 0) {

    // get Kamstrup data from meter
    for (int kreg = 0; kreg < NUMREGS; kreg++) {
      kamReadReg(kreg);
      delay(100);
    }

    // send a newline to have linksys process the data
    Serial.println("");

    // update lastpoll
    lastpoll = millis();
  }


  // loop delay
  delay(500);

};


// kamReadReg - read a Kamstrup register
void kamReadReg(unsigned short kreg) {

  byte recvmsg[30];  // 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
    if (rval != false) {
      Serial.print(rval);
    }

  }
  Serial.print(rval);
  Serial.print(",");

}

// 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) {
      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;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.opentrv.org.uk/pipermail/opentrv-dev/attachments/20130529/69ba0bd5/attachment.html>


More information about the OpenTRV-dev mailing list