Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers VBus.cpp Source File

VBus.cpp

00001 /*
00002     Copyright (c) 2010 Wimpie
00003 
00004     Based on the VBus� Protocol Specification see http://goo.gl/HP6ZY
00005     and http://hobbyelektronik.org/w/index.php/VBus-Decoder
00006 
00007     VBus� en Resol� are registrated trademarks see http://www.resol.de
00008 
00009     Debugtrace.h -> http://mbed.org/users/snatch59/programs/DebugTrace/gpdz54
00010 
00011     Permission is hereby granted, free of charge, to any person obtaining a copy
00012     of this software and associated documentation files (the "Software"), to deal
00013     in the Software without restriction, including without limitation the rights
00014     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00015     copies of the Software, and to permit persons to whom the Software is
00016     furnished to do so, subject to the following conditions:
00017 
00018     The above copyright notice and this permission notice shall be included in
00019     all copies or substantial portions of the Software.
00020 
00021     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00022     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00023     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00024     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00025     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00026     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00027     THE SOFTWARE.
00028 */
00029 
00030 #include "VBus.h"
00031 #define DEBUG 0
00032 
00033 #if DEBUG
00034 #include "DebugTrace.h"
00035 DebugTrace pc_VBus(ON, TO_SERIAL);
00036 #endif
00037 
00038 static uint8_t CalcCrc(const unsigned char *Buffer, int Offset, int Length);
00039 float CalcTemp(char Byte1, char Byte2);
00040 
00041 VBus::VBus(PinName tx, PinName rx)
00042         : _Serial(tx, rx) {
00043     _sdcard=false;
00044     _all=false;
00045     ClearMax();
00046     Init(0);
00047 }
00048 
00049 void VBus::Init(int addr=0) {
00050 
00051     _Serial.baud(9600);
00052     _Serial.format(8,Serial::None,1);
00053     m_timeout=2;
00054 
00055     if (addr!=0)
00056         networkaddress=addr;
00057     else
00058         networkaddress=ResolAddress;
00059 
00060 }
00061 
00062 void VBus::SDcardAvailable(bool status) {
00063     _sdcard=status;
00064 }
00065 
00066 void  VBus::InjectSeptet(unsigned char *Buffer, int Offset, int Length) {
00067     for (unsigned int i = 0; i < Length; i++) {
00068         if (Septet & (1 << i)) {
00069             Buffer [Offset + i] |= 0x80;
00070         }
00071     }
00072 }
00073 
00074 bool VBus::Read() {
00075     int F;
00076     char c;
00077     bool start,stop,quit;
00078 
00079     start = true;
00080     stop = false;
00081     quit = false;
00082     Bufferlength=0;
00083 
00084     m_timer.reset();
00085     m_timer.start();
00086 
00087     while ((!stop) and (!quit))  {
00088         if (_Serial.readable()) {
00089             c=_Serial.getc();
00090 
00091             if (c == Sync) {
00092                 if (start) {
00093                     start=false;
00094                     Bufferlength=0;
00095 //#if DEBUG
00096 //                    pc_VBus.traceOut("\r\n");
00097 //#endif
00098                 } else {
00099                     if (Bufferlength<20) {
00100                         m_timer.stop();
00101                         m_timer.reset();
00102                         m_timer.start();
00103                         Bufferlength=0;
00104                     } else
00105                         stop=true;
00106                 }
00107             }
00108 //#if DEBUG
00109 //            pc_VBus.traceOut("%X ",c);
00110 //#endif
00111             if ((!start) and (!stop)) {
00112                 Buffer[Bufferlength]=c;
00113                 Bufferlength++;
00114             }
00115         }
00116         if ((m_timeout > 0) &&  (m_timer.read() > m_timeout )) {
00117             quit=true;
00118 //#if DEBUG
00119 //            pc_VBus.traceOut("Timeout %i",m_timer.read());
00120 //#endif
00121         }
00122     }
00123 
00124     m_timer.stop();
00125 
00126 #if DEBUG
00127 
00128     pc_VBus.traceOut("\r\nBuffer %i \r\n",Bufferlength);
00129     for (int i=0; i<Bufferlength;i++) {
00130         pc_VBus.traceOut("%X ",Buffer[i]);
00131     }
00132     pc_VBus.traceOut("\r\n");
00133 
00134 #endif
00135     if (!quit) {
00136         Destination_address = Buffer[2] << 8;
00137         Destination_address |= Buffer[1];
00138         Source_address = Buffer[4] << 8;
00139         Source_address |= Buffer[3];
00140         ProtocolVersion = (Buffer[5]>>4) + (Buffer[5] &(1<<15));
00141 
00142         Command = Buffer[7] << 8;
00143         Command |= Buffer[6];
00144         Framecnt = Buffer[8];
00145         Checksum = Buffer[9];  //TODO check if Checksum is OK
00146 #if DEBUG
00147         pc_VBus.traceOut("\r\nDestination %X",Destination_address);
00148         pc_VBus.traceOut("\r\nSource %X",Source_address);
00149         pc_VBus.traceOut("\r\nProtocol version %X",ProtocolVersion);
00150         pc_VBus.traceOut("\r\nCommand %X",Command);
00151         pc_VBus.traceOut("\r\nFramecnt %X", Framecnt);
00152         pc_VBus.traceOut("\r\nChecksum %X\r\n", Checksum);
00153 #endif
00154         // only analyse Commands 0x100 = Packet Contains data for slave
00155         // with correct length = 10 bytes for HEADER and 6 Bytes  for each frame
00156 
00157         if ((Command==0x0100) and (Bufferlength==10+Framecnt*6)) {
00158 
00159             // Frame info for the Resol ConergyDT5
00160             // check VBusprotocol specification for other products
00161 
00162             // This library is made for the ConergyDT5 (0x3271)
00163 
00164             //Offset  Size    Mask    Name                    Factor  Unit
00165             //0       2               Temperature sensor 1    0.1     &#65533;C
00166             //2       2               Temperature sensor 2    0.1     &#65533;C
00167             //4       2               Temperature sensor 3    0.1     &#65533;C
00168             //6       2               Temperature sensor 4    0.1     &#65533;C
00169             //8       1               Pump speed pump         1       1
00170             //9       1               Pump speed pump 2       1
00171             //10      1               Relay mask              1
00172             //11      1               Error mask              1
00173             //12      2               System time             1
00174             //14      1               Scheme                  1
00175             //15      1       1       Option PostPulse        1
00176             //15      1       2       Option thermostat       1
00177             //15      1       4       Option HQM              1
00178             //16      2               Operating hours relay 1 1
00179             //18      2               Operating hours relay 2 1
00180             //20      2               Heat quantity           1       Wh
00181             //22      2               Heat quantity           1000    Wh
00182             //24      2               Heat quantity           1000000 Wh
00183             //26      2               Version 0.01
00184             //
00185             // Each frame has 6 bytes
00186             // byte 1 to 4 are data bytes -> MSB of each bytes
00187             // byte 5 is a septet and contains MSB of bytes 1 to 4
00188             // byte 6 is a checksum
00189             //
00190             //*******************  Frame 1  *******************
00191 
00192             F=FOffset;
00193 
00194             Septet=Buffer[F+FSeptet];
00195             InjectSeptet(Buffer,F,4);
00196 
00197             // 'collector1' Temperatur Sensor 1, 15 bits, factor 0.1 in C
00198             Sensor1_temp =CalcTemp(Buffer[F+1], Buffer[F]);
00199             // 'store1' Temperature sensor 2, 15 bits, factor 0.1 in C
00200             Sensor2_temp =CalcTemp(Buffer[F+3], Buffer[F+2]);
00201 
00202             //*******************  Frame 2  *******************
00203             F=FOffset+FLength;
00204 
00205             Septet=Buffer[F+FSeptet];
00206             InjectSeptet(Buffer,F,4);
00207 
00208             Sensor3_temp =CalcTemp(Buffer[F+1], Buffer[F]);
00209             Sensor4_temp =CalcTemp(Buffer[F+3], Buffer[F+2]);
00210 
00211             //*******************  Frame 3  *******************
00212             F=FOffset+FLength*2;
00213 
00214             Septet=Buffer[F+FSeptet];
00215             InjectSeptet(Buffer,F,4);
00216 
00217             PumpSpeed1 = (Buffer[F] & 0X7F);
00218             PumpSpeed2 = (Buffer[F+1] & 0X7F);
00219             RelaisMask = Buffer[F+2];
00220             ErrorMask  = Buffer[F+3];
00221 
00222             //*******************  Frame 4  *******************
00223             F=FOffset+FLength*3;
00224 
00225             Septet=Buffer[F+FSeptet];
00226             InjectSeptet(Buffer,F,4);
00227 #if DEBUG
00228             pc_VBus.traceOut("\r\nFrame 4 %i %i %i %i ",Buffer[F],Buffer[F+1],Buffer[F+2],Buffer[F+3]);
00229 #endif
00230             SystemTime = Buffer[F+1] << 8 | Buffer[F];
00231             Scheme    =  Buffer[F+2];
00232 
00233             OptionPostPulse  = (Buffer[F+3] & 0x01);
00234             OptionThermostat = ((Buffer[F+3] & 0x02) >> 1);
00235             OptionHQM  = ((Buffer[F+3] & 0x04) >> 2);
00236 
00237             //*******************  Frame 5  *******************
00238             F=FOffset+FLength*4;
00239 
00240             Septet=Buffer[F+FSeptet];
00241             InjectSeptet(Buffer,F,4);
00242 #if DEBUG
00243             pc_VBus.traceOut("\r\nFrame 5 %i %i %i %i ",Buffer[F],Buffer[F+1],Buffer[F+2],Buffer[F+3]);
00244 #endif
00245             OperatingHoursRelais1=Buffer[F+1] << 8 | Buffer[F];
00246             OperatingHoursRelais2=Buffer[F+3] << 8| Buffer[F+2];
00247 
00248             //*******************  Frame 6  *******************
00249             F=FOffset+FLength*5;
00250 
00251             Septet=Buffer[F+FSeptet];
00252             InjectSeptet(Buffer,F,4);
00253 #if DEBUG
00254             pc_VBus.traceOut("\r\nFrame 6 %i %i %i %i ",Buffer[F],Buffer[F+1],Buffer[F+2],Buffer[F+3]);
00255 #endif
00256             HeatQuantity=(Buffer[F+1] << 8 | Buffer[F])+(Buffer[F+3] << 8| Buffer[F+2])*1000;
00257 
00258             //*******************  Frame 7  *******************
00259             F=FOffset+FLength*6;
00260 
00261             Septet=Buffer[F+FSeptet];
00262             InjectSeptet(Buffer,F,4);
00263 #if DEBUG
00264             pc_VBus.traceOut("\r\nFrame 7 %i %i %i %i ",Buffer[F],Buffer[F+1],Buffer[F+2],Buffer[F+3]);
00265 #endif
00266             HeatQuantity=HeatQuantity+(Buffer[F+1] << 8 | Buffer[F])*1000000;
00267             Version=Buffer[F+3] << 8| Buffer[F+2];
00268 
00269             ///******************* End of frames ****************
00270 
00271             if (Sensor1_temp>Sensor1_temp_max)
00272                 Sensor1_temp_max=Sensor1_temp;
00273             if (Sensor2_temp>Sensor2_temp_max)
00274                 Sensor2_temp_max=Sensor2_temp;
00275             if (Sensor3_temp>Sensor3_temp_max)
00276                 Sensor3_temp_max=Sensor3_temp;
00277             if (Sensor4_temp>Sensor4_temp_max)
00278                 Sensor4_temp_max=Sensor4_temp;
00279 
00280 #if DEBUG
00281 
00282             /*           pc_VBus.traceOut("\r\nSensor 1 %f", Sensor1_temp);
00283                        pc_VBus.traceOut("\r\nSensor 2 %f", Sensor2_temp);
00284                        pc_VBus.traceOut("\r\nSensor 3 %f", Sensor3_temp);
00285                        pc_VBus.traceOut("\r\nSensor 4 %f", Sensor4_temp);
00286                        pc_VBus.traceOut("\r\nPumpSpeed1 %i", PumpSpeed1);
00287                        pc_VBus.traceOut("\r\nPumpSpeed2 %i", PumpSpeed2);
00288                        pc_VBus.traceOut("\r\nRelaismask %i", RelaisMask);
00289                        pc_VBus.traceOut("\r\nErrorMask %i", ErrorMask);
00290                        pc_VBus.traceOut("\r\nSystemTime %i", SystemTime);
00291                        pc_VBus.traceOut("\r\nSystem %i", Scheme);
00292                        pc_VBus.traceOut("\r\nOptionPostPulse %i", OptionPostPulse);
00293                        pc_VBus.traceOut("\r\nOptionThermostat %i", OptionThermostat);
00294                        pc_VBus.traceOut("\r\nOptionHQM %i", OptionHQM);
00295                        pc_VBus.traceOut("\r\nOperatingHoursRelais1 %i", OperatingHoursRelais1);
00296                        pc_VBus.traceOut("\r\nOperatingHoursRelais2 %i", OperatingHoursRelais2);*/
00297             pc_VBus.traceOut("\r\nHeatQuantity %i", HeatQuantity);
00298 
00299 #endif
00300         }
00301     }
00302 
00303     return !quit;
00304 }
00305 
00306 void VBus::SaveToSDcard(char* datetime, char* date,char* dayfn) {
00307     char fn[17];
00308     strcpy(fn,"/sd/vb");
00309     strcat(fn,dayfn);
00310     strcat(fn,".csv");
00311 
00312     //****************
00313     // filename vbyymmdd.csv
00314     //
00315     // detailed dayinfo, each 5 minutes
00316     //
00317     // dd.mm.yy hh:mm:ss;v1;v2;v3;v4;v5;v6;v7;...
00318     //
00319     //****************
00320 #if DEBUG
00321     pc_VBus.traceOut("%s;%4.1f;%4.1f;%4.1f;%4.1f;%i;%i;%i;%i;%i;%i;%i;%i;%i;%i;%i%;%i;%i\r\n",datetime,
00322                      Sensor1_temp, Sensor2_temp,Sensor3_temp, Sensor4_temp,
00323                      PumpSpeed1,PumpSpeed2,
00324                      RelaisMask,ErrorMask,SystemTime,Scheme,OptionPostPulse,
00325                      OptionThermostat, OptionHQM, OperatingHoursRelais1,OperatingHoursRelais2,HeatQuantity,Version
00326                     );
00327 #endif
00328 
00329     if (_sdcard) {
00330         FILE *fp = fopen(fn, "a");
00331         if (fp) {
00332             fprintf(fp,"%s;%4.1f;%4.1f;%4.1f;%4.1f;%i;%i;%i;%i;%i;%i;%i;%i;%i;%i;%i%;%i;%i\r\n",datetime,
00333                     Sensor1_temp, Sensor2_temp,Sensor3_temp, Sensor4_temp,
00334                     PumpSpeed1,PumpSpeed2,
00335                     RelaisMask,ErrorMask,SystemTime,Scheme,OptionPostPulse,
00336                     OptionThermostat, OptionHQM, OperatingHoursRelais1,OperatingHoursRelais2,HeatQuantity,Version
00337                    );
00338             fclose(fp);
00339         }
00340     }
00341 }
00342 
00343 void VBus::ClearMax() {
00344     Sensor1_temp_max=0.0;
00345     Sensor2_temp_max=0.0;
00346     Sensor3_temp_max=0.0;
00347     Sensor4_temp_max=0.0;
00348 }
00349 
00350 void VBus::make_Header (unsigned int DAdr,unsigned int SAdr,unsigned char Ver,unsigned int Cmd,unsigned char AFrames) {
00351     unsigned char Buffer[10]={Sync,(uint8_t)DAdr,DAdr>>8,(uint8_t)SAdr,SAdr>>8,Ver,(uint8_t)Cmd,Cmd>>8,AFrames};
00352     Buffer[9]=CalcCrc(Buffer,1,8);
00353     for (unsigned bo=0;bo<=9;bo++) {
00354         _Serial.putc(Buffer[bo]);
00355     }
00356 }
00357 
00358 static uint8_t CalcCrc(const unsigned char *Buffer, int Offset, int Length) {
00359     static uint8_t Crc= 0x7F;
00360 
00361     for (unsigned int i = 0; i < Length; i++) {
00362         Crc = (Crc - Buffer [Offset + i]) & 0x7F;
00363     }
00364     return Crc;
00365 }
00366 
00367 float CalcTemp(char Byte1, char Byte2) {
00368     int v;
00369     v = Byte1 << 8 | Byte2;
00370 
00371     if (Byte1 == 0xFF)
00372         v = v - 0x10000;
00373 
00374     if (v==SENSORNOTCONNECTED)
00375         v=0;
00376     return (float)((float) v * 0.1);
00377 }