Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ------------------------------------------------------------------------------------------------------------
- -ID- -Node Type-
- 0 - Special allocation in JeeLib RFM12 driver - reserved for OOK use
- 1-4 - Control nodes
- 5-10 - Energy monitoring nodes
- 11-14 --Un-assigned --
- 15-16 - Base Station & logging nodes
- 17-30 - Environmental sensing nodes (temperature humidity etc.)
- 31 - Special allocation in JeeLib RFM12 driver - Node31 can communicate with nodes on any network group
- -------------------------------------------------------------------------------------------------------------
- TODO: set kamser pins
- */
- #include <jeelib.h> // make sure V12 (latest) is used if using RFM69CW
- #include <onewire.h>
- #include <dallastemperature.h>
- #include <avr wdt.h="">
- //********************************************Kamstrup Stuff Start********************************************
- #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 x 10","GJ x 10","minutes","Bitfield",
- "s","ms","days","RTC-Q","Datetime"};
- //********************************************Kamstrup Stuff End********************************************
- #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.
- const int nodeID = 10; // emonTx RFM12B node ID
- const int networkGroup = 210; // emonTx RFM12B wireless network group - needs to be same as emonBase and emonGLCD
- 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
- #define RF69_COMPAT 0 // set to 1 to use RFM69CW
- //********************************************Kamstrup Stuff Start********************************************
- // Pin definitions
- #define PIN_KAMSER_RX 1 // Kamstrup IR interface RX
- #define PIN_KAMSER_TX 1 // Kamstrup IR interface TX
- //********************************************Kamstrup Stuff End********************************************
- #define ONE_WIRE_BUS 4 // Data wire is plugged into port 2 on the Arduino
- OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
- DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
- // By using direct addressing its possible to make sure that as you add temperature sensors
- // the temperature sensor to variable mapping will not change.
- // To find the addresses of your temperature sensors use the: **temperature_search sketch**
- DeviceAddress address_T1 = { 0x28, 0x22, 0x70, 0xEE, 0x02, 0x00, 0x00, 0xB8 };
- typedef struct {
- int power; // power
- int pulse; // pulses
- int T1; // temperature sensor 1
- //********************************************Kamstrup Stuff Start********************************************
- int Energy;
- int CurrentPower;
- int Temperaturet1;
- int Temperaturet2;
- int Temperaturediff;
- int Flow;
- int Volumen1;
- int Volumen2;
- //********************************************Kamstrup Stuff Start********************************************
- } Payload;
- Payload emontx;
- const int LEDpin = 9;
- // Pulse counting settings
- long pulseCount = 0; // Number of pulses, used to measure energy.
- unsigned long pulseTime,lastTime; // Used to measure power.
- double power, elapsedWh; // power and energy
- int ppwh = 10; // 1000 pulses/kwh = 1 pulse per wh - Number of pulses per wh - found or set on the meter.
- //********************************************Kamstrup Stuff Start********************************************
- // Kamstrup optical IR serial
- #define KAMTIMEOUT 2000 // Kamstrup timeout after transmit
- #define POLLINTERVAL 20000 // Polling interval
- SoftwareSerial kamSer(PIN_KAMSER_RX, PIN_KAMSER_TX, false); // Initialize serial
- // last poll variable
- long lastpoll;
- //********************************************Kamstrup Stuff End********************************************
- void setup() {
- Serial.begin(57600);
- Serial.println("emonTX Temperature power pulse example");
- Serial.println("OpenEnergyMonitor.org");
- //********************************************Kamstrup Stuff Start********************************************
- // setup kamstrup serial
- pinMode(PIN_KAMSER_RX,INPUT);
- pinMode(PIN_KAMSER_TX,OUTPUT);
- kamSer.begin(KAMBAUD);
- // initialize lastpoll value
- lastpoll = 0;
- //********************************************Kamstrup Stuff End********************************************
- sensors.begin();
- rf12_initialize(nodeID, RF_freq, networkGroup); // initialize RF
- rf12_sleep(RF12_SLEEP);
- pinMode(LEDpin, OUTPUT);
- digitalWrite(LEDpin, HIGH);
- 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
- }
- void loop()
- {
- //********************************************Kamstrup Stuff Start********************************************
- // check if it is time to do a poll
- if(millis() - lastpoll > POLLINTERVAL or lastpoll == 0) {
- // 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);
- // update lastpoll
- lastpoll = millis();
- //********************************************Kamstrup Stuff End********************************************
- sensors.requestTemperatures(); // Send the command to get temperatures
- emontx.T1 = sensors.getTempC(address_T1) * 100;
- emontx.pulse = pulseCount; pulseCount=0;
- Serial.print(emontx.power);
- Serial.print("W ");
- Serial.println(emontx.pulse);
- send_rf_data(); // *SEND RF DATA* - see emontx_lib
- digitalWrite(LEDpin, HIGH); delay(2); digitalWrite(LEDpin, LOW); // flash LED
- }
- }
- // kamReadReg - read a Kamstrup register
- float 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 (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;
- }
- //********************************************Kamstrup Stuff End********************************************
- // The interrupt routine - runs each time a falling edge of a pulse is detected
- void onPulse()
- {
- lastTime = pulseTime; //used to measure time between pulses.
- pulseTime = micros();
- pulseCount++; //pulseCounter
- emontx.power = int((3600000000.0 / (pulseTime - lastTime))/ppwh); //Calculate power
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement