libraries / Mitov / Mitov_BMP180_Pressure.hon commit Added link to project report (97a3ba0)
   1////////////////////////////////////////////////////////////////////////////////
   2//                                                                            //
   3//     This software is supplied under the terms of a license agreement or    //
   4//     nondisclosure agreement with Mitov Software and may not be copied      //
   5//     or disclosed except in accordance with the terms of that agreement.    //
   6//         Copyright(c) 2002-2016 Mitov Software. All Rights Reserved.        //
   7//                                                                            //
   8////////////////////////////////////////////////////////////////////////////////
   9
  10#ifndef _MITOV_BMP180_h
  11#define _MITOV_BMP180_h
  12
  13#include <Mitov.h>
  14#include <Wire.h> //I2C Arduino Library
  15
  16namespace Mitov
  17{
  18
  19        const byte BMP180_Address = 0x77; // 7-bit address
  20        const byte BMP180_REG_CONTROL = 0xF4;
  21        const byte BMP180_REG_RESULT = 0xF6;
  22
  23        const byte BMP180_COMMAND_TEMPERATURE = 0x2E;
  24        const byte BMP180_COMMAND_PRESSURE0 = 0x34;
  25        const byte BMP180_COMMAND_PRESSURE1 = 0x74;
  26        const byte BMP180_COMMAND_PRESSURE2 = 0xB4;
  27        const byte BMP180_COMMAND_PRESSURE3 = 0xF4;
  28//---------------------------------------------------------------------------
  29        enum BMP180_PressureResolution { prLow, prStandard, prHigh, prHighest };
  30//---------------------------------------------------------------------------
  31        class BMP180_Pressure : public EnabledComponent, public Mitov::ClockingSupport
  32        {
  33                typedef Mitov::EnabledComponent inherited;
  34
  35        public:
  36                OpenWire::SourcePin                             PressureOutputPin;
  37                OpenWire::SourcePin                             TemperatureOutputPin;
  38                OpenWire::TypedSourcePin<bool>  ErrorOutputPin;
  39
  40        protected:
  41                enum TState { stCoeff, stIdle, stTemperature, stPressure };
  42
  43        public:
  44                BMP180_PressureResolution       Resolution : 2;
  45                bool    InFahrenheit : 1;
  46
  47        protected:
  48                bool    FClocked : 1;
  49                TState  FState : 2;
  50
  51                uint32_t        FStartTime;
  52                uint32_t        FInterval;
  53
  54                int16_t         AC1,AC2,AC3,VB1,VB2,MB,MC,MD;
  55                uint16_t        AC4,AC5,AC6; 
  56                double c5,c6,mc,md,x0,x1,x2,y0,y1,y2,p0,p1,p2;
  57                float T;
  58
  59        protected:
  60                bool WriteBytes( byte *values, char length )
  61                {
  62                        Wire.beginTransmission( BMP180_Address );
  63                        Wire.write(values,length);
  64                        bool AError = ( Wire.endTransmission() != 0 );
  65                        ErrorOutputPin.SetValue( AError, true );
  66
  67                        return ( ! AError );
  68                }
  69
  70                bool ReadBytes( byte *values, byte length )
  71                {
  72                        Wire.beginTransmission( BMP180_Address );
  73                        Wire.write(values[0]);
  74                        bool AError = ( Wire.endTransmission() != 0 );
  75//                      Serial.println( AError );
  76                        ErrorOutputPin.SetValue( AError, true );
  77                        if ( ! AError )
  78                        {
  79//                              Serial.println( "READ" );
  80                                Wire.requestFrom( BMP180_Address, length );
  81                                while(Wire.available() != length) ; // wait until bytes are ready
  82
  83                                while( length-- )
  84                                        *values++ = Wire.read();                
  85
  86/*
  87                                values += length;
  88                                while( length-- )
  89                                        *--values = Wire.read();                
  90*/
  91                        }
  92
  93                        return ( ! AError );
  94                }
  95
  96                uint32_t ReadBytes( byte length )
  97                {
  98/*
  99                        union T24BitData
 100                        {
 101                                uint8_t         Bytes[ 4 ];
 102                                uint32_t        Value;
 103                        };
 104
 105                        T24BitData AData;
 106                        AData.Value = 0;
 107
 108                        ReadBytes( AData.Bytes + 3 - length, length );
 109
 110                        return AData.Value;
 111*/
 112                        uint8_t         ABytes[ 4 ];
 113                        ABytes[0] = BMP180_REG_RESULT;
 114
 115                        ReadBytes( ABytes, length );
 116
 117                        uint32_t        AValue = 0;
 118                        for( int i = 0; i < length; ++i )
 119                        {
 120                                AValue <<= 8;
 121                                AValue |= ABytes[ i ];
 122                        }
 123
 124                        return AValue;
 125                }
 126
 127                void StartReading( byte AType, TState AState, uint32_t AInterval )
 128                {
 129                        byte data[ 2 ] = 
 130                        {
 131                                BMP180_REG_CONTROL
 132                        };
 133
 134                        data[ 1 ] = AType;
 135
 136//                      Serial.println( "StartReading" );
 137                        if( WriteBytes(data, 2))
 138                        {
 139//                              Serial.println( "STATE" );
 140
 141                                FState = AState;
 142                                FInterval = AInterval;
 143                                FStartTime = millis();
 144                        }
 145                }
 146
 147                bool    ReadUnsignedInt(char address, uint16_t &value)
 148                {
 149                        unsigned char data[2];
 150
 151                        data[0] = address;
 152                        if (ReadBytes(data,2))
 153                        {
 154                                value = (((uint16_t)data[0]<<8)|(uint16_t)data[1]);
 155                                return( true );
 156                        }
 157
 158                        value = 0;
 159                        return( false );
 160                }
 161
 162                bool    ReadInt(char address, int16_t &value)
 163                {
 164                        return ReadUnsignedInt( address, *(uint16_t *)&value );
 165                }
 166
 167                void StartReadingTemp()
 168                {
 169                        if( FState == stCoeff )
 170                        {
 171//                              Serial.println( "TEST0" );
 172                                if( !
 173                                        (
 174                                                ReadInt(0xAA,AC1) &&
 175                                                ReadInt(0xAC,AC2) &&
 176                                                ReadInt(0xAE,AC3) &&
 177                                                ReadUnsignedInt(0xB0,AC4) &&
 178                                                ReadUnsignedInt(0xB2,AC5) &&
 179                                                ReadUnsignedInt(0xB4,AC6) &&
 180                                                ReadInt(0xB6,VB1) &&
 181                                                ReadInt(0xB8,VB2) &&
 182                                                ReadInt(0xBA,MB) &&
 183                                                ReadInt(0xBC,MC) &&
 184                                                ReadInt(0xBE,MD)
 185                                        )
 186                                )
 187                                        return;
 188
 189                                // All reads completed successfully!
 190
 191                                // If you need to check your math using known numbers,
 192                                // you can uncomment one of these examples.
 193                                // (The correct results are commented in the below functions.)
 194
 195                                // Example from Bosch datasheet
 196                                // AC1 = 408; AC2 = -72; AC3 = -14383; AC4 = 32741; AC5 = 32757; AC6 = 23153;
 197                                // B1 = 6190; B2 = 4; MB = -32768; MC = -8711; MD = 2868;
 198
 199                                // Example from http://wmrx00.sourceforge.net/Arduino/BMP180-Calcs.pdf
 200                                // AC1 = 7911; AC2 = -934; AC3 = -14306; AC4 = 31567; AC5 = 25671; AC6 = 18974;
 201                                // VB1 = 5498; VB2 = 46; MB = -32768; MC = -11075; MD = 2432;
 202
 203                                // Compute floating-point polynominals:
 204
 205                                double c3 = 160.0 * pow(2,-15) * AC3;
 206                                double c4 = pow(10,-3) * pow(2,-15) * AC4;
 207                                double b1 = pow(160,2) * pow(2,-30) * VB1;
 208                                c5 = (pow(2,-15) / 160) * AC5;
 209                                c6 = AC6;
 210                                mc = (pow(2,11) / pow(160,2)) * MC;
 211                                md = MD / 160.0;
 212                                x0 = AC1;
 213                                x1 = 160.0 * pow(2,-13) * AC2;
 214                                x2 = pow(160,2) * pow(2,-25) * VB2;
 215                                y0 = c4 * pow(2,15);
 216                                y1 = c4 * c3;
 217                                y2 = c4 * b1;
 218                                p0 = (3791.0 - 8.0) / 1600.0;
 219                                p1 = 1.0 - 7357.0 * pow(2,-20);
 220                                p2 = 3038.0 * 100.0 * pow(2,-36);
 221
 222//                              Serial.println( "TEST1" );
 223                                FState = stIdle;
 224                        }
 225
 226                        StartReading( BMP180_COMMAND_TEMPERATURE, stTemperature, 5 );
 227                }
 228
 229                void StartReadingPressure()
 230                {
 231                        switch( Resolution )
 232                        {
 233                                case prLow:                     StartReading( BMP180_COMMAND_PRESSURE0, stPressure, 5 ); break;
 234                                case prStandard:        StartReading( BMP180_COMMAND_PRESSURE1, stPressure, 8 ); break;
 235                                case prHigh:            StartReading( BMP180_COMMAND_PRESSURE2, stPressure, 14 ); break;
 236                                case prHighest:         StartReading( BMP180_COMMAND_PRESSURE3, stPressure, 26 ); break;
 237                        }
 238                }
 239
 240                bool IsIdle() { return (( FState == stCoeff ) || ( FState == stIdle )); }
 241
 242        protected:
 243                virtual void DoClockReceive( void *_Data ) override
 244                {
 245                        if( IsIdle() )
 246                                StartReadingTemp();
 247
 248                        else
 249                                FClocked = true;
 250                }
 251
 252        protected:
 253                virtual void SystemStart()
 254                {
 255                        if( Enabled )
 256                                if( ! ClockInputPin.IsConnected() )
 257                                        StartReadingTemp();
 258
 259                        inherited::SystemStart();
 260                }
 261
 262                virtual void SystemLoopBegin( unsigned long currentMicros )
 263                {
 264                        if( ! Enabled )
 265                        {
 266                                if( ! IsIdle() )
 267                                        if( FState == stTemperature )
 268                                                ReadBytes( 2 );
 269
 270                                        else
 271                                                ReadBytes( 3 );
 272
 273                                FState = stIdle;
 274                        }
 275
 276                        else
 277                        {
 278                                if( IsIdle() )
 279                                {
 280                                        if( FClocked || ( ! ClockInputPin.IsConnected() ))
 281                                                StartReadingTemp();
 282                                }
 283
 284                                else
 285                                {
 286                                        unsigned long ACurrentMillis = millis();
 287//                                      Serial.println( "TEST2" );
 288                                        if( ACurrentMillis - FStartTime >= FInterval )
 289                                                if( FState == stTemperature )
 290                                                {
 291                                                        float tu = ReadBytes( 2 );
 292//                                                      Serial.print( "T1: " ); Serial.println( tu );
 293                                                        //example from Bosch datasheet
 294                                                        //tu = 27898;
 295
 296                                                        //example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf
 297                                                        //tu = 0x69EC;
 298
 299                                                        float a = c5 * (tu - c6);
 300                                                        T = a + (mc / (a + md));
 301
 302                                                        if( InFahrenheit )
 303                                                                T = T * ( 9.0/5.0 ) + 32.0;
 304
 305                                                        TemperatureOutputPin.Notify( &T );
 306                                                        StartReadingPressure();                                                 
 307                                                }
 308
 309                                                else
 310                                                {
 311                                                        float pu = ReadBytes( 3 );
 312//                                                      Serial.print( "P1: " ); Serial.println( pu );
 313                                                        pu /= 256.0;
 314//                                                      pu = (data[0] * 256.0) + data[1] + (data[2]/256.0);
 315
 316                                                        //example from Bosch datasheet
 317                                                        //pu = 23843;
 318
 319                                                        //example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf, pu = 0x982FC0;   
 320                                                        //pu = (0x98 * 256.0) + 0x2F + (0xC0/256.0);
 321                
 322                                                        float s = T - 25.0;
 323                                                        float x = (x2 * pow(s,2)) + (x1 * s) + x0;
 324                                                        float y = (y2 * pow(s,2)) + (y1 * s) + y0;
 325                                                        float z = (pu - x) / y;
 326                                                        float P = (p2 * pow(z,2)) + (p1 * z) + p0;
 327
 328                                                        PressureOutputPin.Notify( &P );
 329
 330//                                                      Serial.println( "VVVVVV" );
 331                                                        if( ClockInputPin.IsConnected() )
 332                                                        {
 333//                                                              Serial.println( "PPPPP" );
 334                                                                FState = stIdle;
 335                                                                if( FClocked )
 336                                                                {
 337//                                                                      Serial.println( "TTTTTTT" );
 338                                                                        FClocked = false;
 339                                                                        StartReadingTemp();
 340                                                                }
 341                                                        }
 342
 343                                                        else
 344                                                                StartReadingTemp();
 345                                                }
 346
 347                                }
 348                        }
 349
 350/*
 351                        if( ! Enabled )
 352                                if( FClocked || ( ! ClockInputPin.IsConnected() ))
 353                                        ReadCompass();
 354*/
 355                        inherited::SystemLoopBegin( currentMicros );
 356                }
 357
 358        public:
 359                BMP180_Pressure() :
 360                        FClocked( false ),
 361                        Resolution( prStandard ),
 362                        FState( stCoeff ),
 363                        InFahrenheit( false )
 364                {
 365                }
 366        };
 367}
 368
 369#endif