Paul van der Wielen
/
MT382_serial
Reading Utility metering data using MBED
mt382.h
- Committer:
- pwheels
- Date:
- 2012-09-30
- Revision:
- 2:b386810af678
- Parent:
- 1:633092f351c6
File content as of revision 2:b386810af678:
#ifndef MBED_H #include "mbed.h" #endif /* * Copyright (c) 2012 Paul van der Wielen, Pro-Serv * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to use * and implement the software for none commercial reason and usage only and * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * Usage and assumptions: * interfacing an MT382 smart meter using P1 port, schematic is fairly simple and * provides for an isolated connection to the outside world, schematic to foloow in due time. * * Overview of used record codes & formats * 0-0:96.1.1(5A424556303035303936303530313132) Serialno meter in hexadecimal ascii code * 1-0:1.8.1(00185.000*kWh) * Total consumpion tarif 1 (night) * 1-0:1.8.2(00084.000*kWh) * Total consumpion tarif 2 (day) * 1-0:2.8.1(00013.000*kWh) * Total delivery tarif 1 (night) * 1-0:2.8.2(00019.000*kWh) * Total delivery tarif 2 (day) * 0-0:96.14.0(0001) 1 Actual tarif (1) * 1-0:1.7.0(0000.98*kW) * Current usage * 1-0:2.7.0(0000.00*kW) * Current delivery * 0-0:17.0.0(999*A) Maximum current by phase * 0-0:96.3.10(1) Position of switch * 0-0:96.13.1() 1 Message (numeric) * 0-0:96.13.0() 1 Message (text) * 0-1:24.1.0(3) Other equipment on M-Bus * 0-1:96.1.0(3238313031353431323030333330313132) Serialno of gasmeter * 0-1:24.3.0(120517020000)(08)(60)(1)(0-1:24.2.1)(m3) Time of last gas measurement (120517020000 = 17 mei 2012 2uur * (00124.477) * Total consumption gas * 0-1:24.4.0(1) Position of gas valve? * *-Implemented, 1-planned for later date */ namespace MT { class MT382 { protected: DigitalOut *_out; Timeout *_delay; Serial *_dev; float _defDelay; int _defBaud; int _defBits; int _defParity; int _defStop; // array with items to find in data stream char _l_mt[7][8]; char _mt_temp[32]; char _mt_line[64]; char _mt_data[512]; double _mt_res[7]; // stream status (1 = start char , 2 = stop char) int _mt_sts; int _mt_pnt; int _mt_flg; void init(PinName po, PinName tx, PinName rx) { _out = new DigitalOut( po ); _out->write(1); _dev = new Serial(tx, rx); _delay = new Timeout; _defBaud = 9600; _defBits = 7; _defParity = 2; _defStop = 1; setComm(); } public: friend class Timeout; /* PinDetect constructor(s) & overloading */ MT382() { error("Provide valid PinName for out, tx & rx"); } MT382(PinName po, PinName tx, PinName rx) { init( po, tx, rx); } /* PinDetect destructor */ ~MT382() { if ( _delay ) delete( _delay ); if ( _out ) delete( _out ); if ( _dev ) delete( _dev ); } // adjust communication parameters as needed void setComm(int baud = 9600, int bits = 7, int parity = 2, int stop = 1) { _defBaud = baud; _dev->baud(_defBaud); _defBits = bits; _defParity = parity; _defStop = stop; switch (_defParity) { case 0: _dev->format(_defBits, Serial::None, _defStop); break; case 1: _dev->format(_defBits, Serial::Odd, _defStop); break; case 2: _dev->format(_defBits, Serial::Even, _defStop); break; default: _dev->format(_defBits, Serial::None, _defStop); break; } } // adjust timeout value void setTime(float maxtime = 5.0) { _defDelay = maxtime; } // adjust the value match strings void setMatch(char * m0 = "", char * m1 = "", char * m2 = "", char * m3 = "", char * m4 = "", char * m5 = "", char * m6 = "") { strcpy (_l_mt[0],m0); strcpy (_l_mt[1],m1); strcpy (_l_mt[2],m2); strcpy (_l_mt[3],m3); strcpy (_l_mt[4],m4); strcpy (_l_mt[5],m5); strcpy (_l_mt[6],m6); } // signal time out condition void isr_delay() { _mt_sts = 0x80; _delay->detach(); } // get data from 'smart meter' int getReading () { _delay->attach(this, &MT382::isr_delay, _defDelay); _out->write(0); _mt_pnt = 0; _mt_sts = 0; while((_mt_sts & 0x02) == 0 && (_mt_sts & 0x80) == 0) { if(_dev->readable()) { // get available character from MT382 char mt_tst = _dev->getc(); // remove any ascii NULL character if (mt_tst != 0x00) { _mt_data[_mt_pnt++] = mt_tst; if (_mt_data[_mt_pnt-1] == '/') { _mt_sts = 1; } if (_mt_data[_mt_pnt-1] == '!') { _mt_sts = _mt_sts | 0x02; _delay->detach(); _out->write(1); } } } } int mt_tmp = 0; _mt_flg = 0; int mt_elem = sizeof(_l_mt)/sizeof(_l_mt[0]); if ((_mt_sts == 0x03) && ((_mt_sts & 0x80) == 0)){ for (int buf_pnt = 0; buf_pnt <= _mt_pnt; buf_pnt++) { _mt_line[mt_tmp++] = _mt_data[buf_pnt]; if (_mt_data[buf_pnt] == 0x0a) { _mt_line[mt_tmp] = 0x00; if ((_mt_flg & 0x01) == 0x01) { // special case handling -> param 5 strncpy (_mt_temp, strchr(_mt_line,'(') + 1, strchr(_mt_line,')') - strchr(_mt_line,'(') - 1); _mt_res[(_mt_flg >> 4) & 0x0f] = strtod(_mt_temp, NULL); _mt_flg = 0; } for (int j = 0; j < mt_elem; j++) { if (strstr (_mt_line, _l_mt[j])) { for (int cnt = 0; cnt < sizeof(_mt_temp); cnt++) { _mt_temp[cnt] = 0x00; } if (j < 6) { strncpy (_mt_temp, strchr(_mt_line,'(') + 1, strchr(_mt_line,'*') - strchr(_mt_line,'(') - 1); } else { // flag special case due to inconsistent formating of raw data _mt_flg = j << 4 | 0x01; } _mt_res[j] = strtod(_mt_temp, NULL); } } mt_tmp = 0; } } } else { return -1; } return 0; } // return raw data character count int getCount(void) { return _mt_pnt; } // return selected value double getValue(int param = 0) { return _mt_res[param]; } // return raw data char * getRaw(void) { return _mt_data; } // return pointer to array with collected data double * getArray(void) { return _mt_res; } }; }; // namespace MT ends. using namespace MT;