Reading Utility metering data using MBED

Dependencies:   mbed

Committer:
pwheels
Date:
Sun Sep 30 11:38:39 2012 +0000
Revision:
2:b386810af678
Parent:
1:633092f351c6
Added function as to return pointer to data array, ; adjusted main() as to provide an example of it's usage

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pwheels 0:bacf1c9b9afc 1 #ifndef MBED_H
pwheels 0:bacf1c9b9afc 2 #include "mbed.h"
pwheels 0:bacf1c9b9afc 3 #endif
pwheels 0:bacf1c9b9afc 4 /*
pwheels 0:bacf1c9b9afc 5 * Copyright (c) 2012 Paul van der Wielen, Pro-Serv
pwheels 0:bacf1c9b9afc 6 *
pwheels 0:bacf1c9b9afc 7 * Permission is hereby granted, free of charge, to any person obtaining a copy
pwheels 0:bacf1c9b9afc 8 * of this software and associated documentation files (the "Software"), to use
pwheels 0:bacf1c9b9afc 9 * and implement the software for none commercial reason and usage only and
pwheels 0:bacf1c9b9afc 10 * subject to the following conditions:
pwheels 0:bacf1c9b9afc 11 *
pwheels 0:bacf1c9b9afc 12 * The above copyright notice and this permission notice shall be included in
pwheels 0:bacf1c9b9afc 13 * all copies or substantial portions of the Software.
pwheels 0:bacf1c9b9afc 14 *
pwheels 0:bacf1c9b9afc 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
pwheels 0:bacf1c9b9afc 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
pwheels 0:bacf1c9b9afc 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
pwheels 0:bacf1c9b9afc 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
pwheels 0:bacf1c9b9afc 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
pwheels 0:bacf1c9b9afc 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
pwheels 0:bacf1c9b9afc 21 * THE SOFTWARE.
pwheels 0:bacf1c9b9afc 22 *
pwheels 0:bacf1c9b9afc 23 * Usage and assumptions:
pwheels 0:bacf1c9b9afc 24 * interfacing an MT382 smart meter using P1 port, schematic is fairly simple and
pwheels 0:bacf1c9b9afc 25 * provides for an isolated connection to the outside world, schematic to foloow in due time.
pwheels 0:bacf1c9b9afc 26 *
pwheels 0:bacf1c9b9afc 27 * Overview of used record codes & formats
pwheels 0:bacf1c9b9afc 28 * 0-0:96.1.1(5A424556303035303936303530313132) Serialno meter in hexadecimal ascii code
pwheels 1:633092f351c6 29 * 1-0:1.8.1(00185.000*kWh) * Total consumpion tarif 1 (night)
pwheels 1:633092f351c6 30 * 1-0:1.8.2(00084.000*kWh) * Total consumpion tarif 2 (day)
pwheels 1:633092f351c6 31 * 1-0:2.8.1(00013.000*kWh) * Total delivery tarif 1 (night)
pwheels 1:633092f351c6 32 * 1-0:2.8.2(00019.000*kWh) * Total delivery tarif 2 (day)
pwheels 1:633092f351c6 33 * 0-0:96.14.0(0001) 1 Actual tarif (1)
pwheels 1:633092f351c6 34 * 1-0:1.7.0(0000.98*kW) * Current usage
pwheels 1:633092f351c6 35 * 1-0:2.7.0(0000.00*kW) * Current delivery
pwheels 1:633092f351c6 36 * 0-0:17.0.0(999*A) Maximum current by phase
pwheels 1:633092f351c6 37 * 0-0:96.3.10(1) Position of switch
pwheels 1:633092f351c6 38 * 0-0:96.13.1() 1 Message (numeric)
pwheels 1:633092f351c6 39 * 0-0:96.13.0() 1 Message (text)
pwheels 1:633092f351c6 40 * 0-1:24.1.0(3) Other equipment on M-Bus
pwheels 1:633092f351c6 41 * 0-1:96.1.0(3238313031353431323030333330313132) Serialno of gasmeter
pwheels 1:633092f351c6 42 * 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
pwheels 1:633092f351c6 43 * (00124.477) * Total consumption gas
pwheels 1:633092f351c6 44 * 0-1:24.4.0(1) Position of gas valve?
pwheels 1:633092f351c6 45 * *-Implemented, 1-planned for later date
pwheels 0:bacf1c9b9afc 46 */
pwheels 0:bacf1c9b9afc 47
pwheels 0:bacf1c9b9afc 48 namespace MT {
pwheels 0:bacf1c9b9afc 49
pwheels 0:bacf1c9b9afc 50 class MT382 {
pwheels 0:bacf1c9b9afc 51
pwheels 0:bacf1c9b9afc 52 protected:
pwheels 0:bacf1c9b9afc 53 DigitalOut *_out;
pwheels 0:bacf1c9b9afc 54 Timeout *_delay;
pwheels 0:bacf1c9b9afc 55 Serial *_dev;
pwheels 0:bacf1c9b9afc 56 float _defDelay;
pwheels 0:bacf1c9b9afc 57 int _defBaud;
pwheels 0:bacf1c9b9afc 58 int _defBits;
pwheels 0:bacf1c9b9afc 59 int _defParity;
pwheels 0:bacf1c9b9afc 60 int _defStop;
pwheels 0:bacf1c9b9afc 61 // array with items to find in data stream
pwheels 0:bacf1c9b9afc 62 char _l_mt[7][8];
pwheels 0:bacf1c9b9afc 63 char _mt_temp[32];
pwheels 0:bacf1c9b9afc 64 char _mt_line[64];
pwheels 0:bacf1c9b9afc 65 char _mt_data[512];
pwheels 0:bacf1c9b9afc 66 double _mt_res[7];
pwheels 0:bacf1c9b9afc 67 // stream status (1 = start char , 2 = stop char)
pwheels 0:bacf1c9b9afc 68 int _mt_sts;
pwheels 0:bacf1c9b9afc 69 int _mt_pnt;
pwheels 0:bacf1c9b9afc 70 int _mt_flg;
pwheels 0:bacf1c9b9afc 71
pwheels 0:bacf1c9b9afc 72 void init(PinName po, PinName tx, PinName rx) {
pwheels 0:bacf1c9b9afc 73 _out = new DigitalOut( po );
pwheels 0:bacf1c9b9afc 74 _out->write(1);
pwheels 0:bacf1c9b9afc 75 _dev = new Serial(tx, rx);
pwheels 0:bacf1c9b9afc 76 _delay = new Timeout;
pwheels 0:bacf1c9b9afc 77 _defBaud = 9600;
pwheels 0:bacf1c9b9afc 78 _defBits = 7;
pwheels 0:bacf1c9b9afc 79 _defParity = 2;
pwheels 0:bacf1c9b9afc 80 _defStop = 1;
pwheels 0:bacf1c9b9afc 81 setComm();
pwheels 0:bacf1c9b9afc 82 }
pwheels 0:bacf1c9b9afc 83
pwheels 0:bacf1c9b9afc 84 public:
pwheels 0:bacf1c9b9afc 85
pwheels 0:bacf1c9b9afc 86 friend class Timeout;
pwheels 0:bacf1c9b9afc 87
pwheels 0:bacf1c9b9afc 88 /* PinDetect constructor(s) & overloading */
pwheels 0:bacf1c9b9afc 89 MT382() { error("Provide valid PinName for out, tx & rx"); }
pwheels 0:bacf1c9b9afc 90
pwheels 0:bacf1c9b9afc 91 MT382(PinName po, PinName tx, PinName rx) {
pwheels 0:bacf1c9b9afc 92 init( po, tx, rx);
pwheels 0:bacf1c9b9afc 93 }
pwheels 0:bacf1c9b9afc 94
pwheels 0:bacf1c9b9afc 95 /* PinDetect destructor */
pwheels 0:bacf1c9b9afc 96 ~MT382() {
pwheels 0:bacf1c9b9afc 97 if ( _delay ) delete( _delay );
pwheels 0:bacf1c9b9afc 98 if ( _out ) delete( _out );
pwheels 0:bacf1c9b9afc 99 if ( _dev ) delete( _dev );
pwheels 0:bacf1c9b9afc 100 }
pwheels 0:bacf1c9b9afc 101
pwheels 0:bacf1c9b9afc 102 // adjust communication parameters as needed
pwheels 0:bacf1c9b9afc 103 void setComm(int baud = 9600, int bits = 7, int parity = 2, int stop = 1) {
pwheels 0:bacf1c9b9afc 104 _defBaud = baud;
pwheels 0:bacf1c9b9afc 105 _dev->baud(_defBaud);
pwheels 0:bacf1c9b9afc 106 _defBits = bits;
pwheels 0:bacf1c9b9afc 107 _defParity = parity;
pwheels 0:bacf1c9b9afc 108 _defStop = stop;
pwheels 0:bacf1c9b9afc 109
pwheels 0:bacf1c9b9afc 110 switch (_defParity) {
pwheels 0:bacf1c9b9afc 111 case 0:
pwheels 0:bacf1c9b9afc 112 _dev->format(_defBits, Serial::None, _defStop);
pwheels 0:bacf1c9b9afc 113 break;
pwheels 0:bacf1c9b9afc 114 case 1:
pwheels 0:bacf1c9b9afc 115 _dev->format(_defBits, Serial::Odd, _defStop);
pwheels 0:bacf1c9b9afc 116 break;
pwheels 0:bacf1c9b9afc 117 case 2:
pwheels 0:bacf1c9b9afc 118 _dev->format(_defBits, Serial::Even, _defStop);
pwheels 0:bacf1c9b9afc 119 break;
pwheels 0:bacf1c9b9afc 120 default:
pwheels 0:bacf1c9b9afc 121 _dev->format(_defBits, Serial::None, _defStop);
pwheels 0:bacf1c9b9afc 122 break;
pwheels 0:bacf1c9b9afc 123 }
pwheels 0:bacf1c9b9afc 124 }
pwheels 0:bacf1c9b9afc 125
pwheels 0:bacf1c9b9afc 126 // adjust timeout value
pwheels 0:bacf1c9b9afc 127 void setTime(float maxtime = 5.0) {
pwheels 0:bacf1c9b9afc 128 _defDelay = maxtime;
pwheels 0:bacf1c9b9afc 129 }
pwheels 0:bacf1c9b9afc 130
pwheels 0:bacf1c9b9afc 131 // adjust the value match strings
pwheels 0:bacf1c9b9afc 132 void setMatch(char * m0 = "", char * m1 = "", char * m2 = "",
pwheels 0:bacf1c9b9afc 133 char * m3 = "", char * m4 = "", char * m5 = "", char * m6 = "") {
pwheels 0:bacf1c9b9afc 134 strcpy (_l_mt[0],m0);
pwheels 0:bacf1c9b9afc 135 strcpy (_l_mt[1],m1);
pwheels 0:bacf1c9b9afc 136 strcpy (_l_mt[2],m2);
pwheels 0:bacf1c9b9afc 137 strcpy (_l_mt[3],m3);
pwheels 0:bacf1c9b9afc 138 strcpy (_l_mt[4],m4);
pwheels 0:bacf1c9b9afc 139 strcpy (_l_mt[5],m5);
pwheels 0:bacf1c9b9afc 140 strcpy (_l_mt[6],m6);
pwheels 0:bacf1c9b9afc 141 }
pwheels 0:bacf1c9b9afc 142
pwheels 0:bacf1c9b9afc 143 // signal time out condition
pwheels 0:bacf1c9b9afc 144 void isr_delay() {
pwheels 0:bacf1c9b9afc 145 _mt_sts = 0x80;
pwheels 0:bacf1c9b9afc 146 _delay->detach();
pwheels 0:bacf1c9b9afc 147 }
pwheels 0:bacf1c9b9afc 148
pwheels 0:bacf1c9b9afc 149 // get data from 'smart meter'
pwheels 0:bacf1c9b9afc 150 int getReading () {
pwheels 0:bacf1c9b9afc 151
pwheels 0:bacf1c9b9afc 152 _delay->attach(this, &MT382::isr_delay, _defDelay);
pwheels 0:bacf1c9b9afc 153 _out->write(0);
pwheels 0:bacf1c9b9afc 154 _mt_pnt = 0;
pwheels 0:bacf1c9b9afc 155 _mt_sts = 0;
pwheels 0:bacf1c9b9afc 156
pwheels 0:bacf1c9b9afc 157 while((_mt_sts & 0x02) == 0 && (_mt_sts & 0x80) == 0) {
pwheels 0:bacf1c9b9afc 158 if(_dev->readable()) {
pwheels 1:633092f351c6 159 // get available character from MT382
pwheels 1:633092f351c6 160 char mt_tst = _dev->getc();
pwheels 1:633092f351c6 161 // remove any ascii NULL character
pwheels 1:633092f351c6 162 if (mt_tst != 0x00) {
pwheels 1:633092f351c6 163 _mt_data[_mt_pnt++] = mt_tst;
pwheels 1:633092f351c6 164 if (_mt_data[_mt_pnt-1] == '/') {
pwheels 1:633092f351c6 165 _mt_sts = 1;
pwheels 1:633092f351c6 166 }
pwheels 1:633092f351c6 167 if (_mt_data[_mt_pnt-1] == '!') {
pwheels 1:633092f351c6 168 _mt_sts = _mt_sts | 0x02;
pwheels 1:633092f351c6 169 _delay->detach();
pwheels 1:633092f351c6 170 _out->write(1);
pwheels 1:633092f351c6 171 }
pwheels 0:bacf1c9b9afc 172 }
pwheels 0:bacf1c9b9afc 173 }
pwheels 0:bacf1c9b9afc 174 }
pwheels 1:633092f351c6 175
pwheels 0:bacf1c9b9afc 176 int mt_tmp = 0;
pwheels 0:bacf1c9b9afc 177 _mt_flg = 0;
pwheels 0:bacf1c9b9afc 178 int mt_elem = sizeof(_l_mt)/sizeof(_l_mt[0]);
pwheels 0:bacf1c9b9afc 179 if ((_mt_sts == 0x03) && ((_mt_sts & 0x80) == 0)){
pwheels 0:bacf1c9b9afc 180 for (int buf_pnt = 0; buf_pnt <= _mt_pnt; buf_pnt++) {
pwheels 0:bacf1c9b9afc 181 _mt_line[mt_tmp++] = _mt_data[buf_pnt];
pwheels 0:bacf1c9b9afc 182 if (_mt_data[buf_pnt] == 0x0a) {
pwheels 0:bacf1c9b9afc 183 _mt_line[mt_tmp] = 0x00;
pwheels 0:bacf1c9b9afc 184 if ((_mt_flg & 0x01) == 0x01) {
pwheels 0:bacf1c9b9afc 185 // special case handling -> param 5
pwheels 0:bacf1c9b9afc 186 strncpy (_mt_temp, strchr(_mt_line,'(') + 1, strchr(_mt_line,')') - strchr(_mt_line,'(') - 1);
pwheels 0:bacf1c9b9afc 187 _mt_res[(_mt_flg >> 4) & 0x0f] = strtod(_mt_temp, NULL);
pwheels 0:bacf1c9b9afc 188 _mt_flg = 0;
pwheels 0:bacf1c9b9afc 189 }
pwheels 0:bacf1c9b9afc 190 for (int j = 0; j < mt_elem; j++) {
pwheels 0:bacf1c9b9afc 191 if (strstr (_mt_line, _l_mt[j])) {
pwheels 0:bacf1c9b9afc 192 for (int cnt = 0; cnt < sizeof(_mt_temp); cnt++) {
pwheels 0:bacf1c9b9afc 193 _mt_temp[cnt] = 0x00;
pwheels 0:bacf1c9b9afc 194 }
pwheels 0:bacf1c9b9afc 195 if (j < 6) {
pwheels 0:bacf1c9b9afc 196 strncpy (_mt_temp, strchr(_mt_line,'(') + 1, strchr(_mt_line,'*') - strchr(_mt_line,'(') - 1);
pwheels 0:bacf1c9b9afc 197 } else {
pwheels 0:bacf1c9b9afc 198 // flag special case due to inconsistent formating of raw data
pwheels 0:bacf1c9b9afc 199 _mt_flg = j << 4 | 0x01;
pwheels 0:bacf1c9b9afc 200 }
pwheels 0:bacf1c9b9afc 201 _mt_res[j] = strtod(_mt_temp, NULL);
pwheels 0:bacf1c9b9afc 202 }
pwheels 0:bacf1c9b9afc 203 }
pwheels 0:bacf1c9b9afc 204 mt_tmp = 0;
pwheels 0:bacf1c9b9afc 205 }
pwheels 0:bacf1c9b9afc 206 }
pwheels 0:bacf1c9b9afc 207 } else {
pwheels 0:bacf1c9b9afc 208 return -1;
pwheels 0:bacf1c9b9afc 209 }
pwheels 0:bacf1c9b9afc 210 return 0;
pwheels 0:bacf1c9b9afc 211 }
pwheels 0:bacf1c9b9afc 212
pwheels 1:633092f351c6 213 // return raw data character count
pwheels 1:633092f351c6 214 int getCount(void) {
pwheels 1:633092f351c6 215 return _mt_pnt;
pwheels 1:633092f351c6 216 }
pwheels 1:633092f351c6 217
pwheels 0:bacf1c9b9afc 218 // return selected value
pwheels 0:bacf1c9b9afc 219 double getValue(int param = 0) {
pwheels 0:bacf1c9b9afc 220 return _mt_res[param];
pwheels 0:bacf1c9b9afc 221 }
pwheels 1:633092f351c6 222
pwheels 1:633092f351c6 223 // return raw data
pwheels 1:633092f351c6 224 char * getRaw(void) {
pwheels 1:633092f351c6 225 return _mt_data;
pwheels 2:b386810af678 226 }
pwheels 2:b386810af678 227
pwheels 2:b386810af678 228 // return pointer to array with collected data
pwheels 2:b386810af678 229 double * getArray(void) {
pwheels 2:b386810af678 230 return _mt_res;
pwheels 2:b386810af678 231 }
pwheels 0:bacf1c9b9afc 232 };
pwheels 0:bacf1c9b9afc 233
pwheels 0:bacf1c9b9afc 234 }; // namespace MT ends.
pwheels 0:bacf1c9b9afc 235
pwheels 0:bacf1c9b9afc 236 using namespace MT;