Code for 'Smart Regulator' featured in 'Model Engineer', November 2020 on. Contains all work to August 2020 including all code described. Top level algorithm development is quite spares, leaving some work for you! Any questions - jon@jons-workshop.com

Dependencies:   mbed BufferedSerial Servo2 PCT2075 I2CEeprom FastPWM

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers baro.cpp Source File

baro.cpp

00001 #ifdef  INC_BARO
00002 
00003 #include "mbed.h"
00004 #include "baro.h"
00005 #include "BufferedSerial.h"
00006 
00007 //BufferedSerial  pc          (PA_2, PA_3, 512, 4, NULL);    //  Pins 16, 17    tx, rx to pc via usb lead
00008 //I2C i2c                     (PB_7, PB_6);   //  Pins 58, 59 For 24LC64 eeprom
00009 extern  BufferedSerial  pc;
00010 extern  I2C i2c;
00011 const int ACK     = 1;
00012 const int NAK     = 0;
00013 const int NOM_PASCALS   = 100000;
00014 const int HYSTERESIS_PASCALS = 50;
00015 
00016 MPL3115A2::MPL3115A2    ()  {   //  Constructor
00017         good = true;
00018 //        mode = 0x39;  //  continuous convert
00019         mode = 0x38;    //  one shot
00020         Temp = Pres = Alti = Adju = 0.0;
00021         if  (!RegRd (0x0c, 1, dest))
00022             good = false;
00023         else if (dest[0] != 196)
00024             good = false;
00025 }
00026 
00027 bool    MPL3115A2::busy_check  ()  {
00028     char    c;
00029     RegRd   (0x26, 1, &c);
00030     c &= 2;
00031     if  (c == 0)
00032         return  false;  //  free, i.e. not busy
00033     return  true;       //  busy, conversion in progress
00034 }
00035 
00036 void    MPL3115A2::reset_zero_inHg  ()  {
00037     double tmp;
00038     Adju = 0.0;
00039     tmp = inHg_vacuum (); //  sets Adju
00040     Adju = tmp;
00041 }
00042 double  MPL3115A2::Temperature ()  {    return  Temp;   }
00043 double  MPL3115A2::Pressure    ()  {    return  Pres;   }
00044 double  MPL3115A2::Altitude    ()  {    return  Alti;   }
00045 double  MPL3115A2::inHg_vacuum ()  {
00046     double  inHg = 0.0 - Pres;   //  one atmospheres worth of Pascals. Note 1 bar is not the same, 1 bar = 100000 Pa
00047     inHg *= 0.000295299833;
00048     return  inHg - Adju;
00049 }
00050 void    MPL3115A2::mode_alti   ()  {
00051 //    mode = 0xb9;
00052     mode = 0xb8;
00053 }
00054 void    MPL3115A2::mode_pres   ()  {
00055 //    mode = 0x39;
00056     mode = 0x38;
00057 }
00058 /*********************************************************\
00059 * IIC Write Register
00060 \*********************************************************/
00061 bool MPL3115A2::RegWr  (int reg, char val)
00062 {
00063     bool    rv = true;
00064     i2c.start   ();
00065     if  (i2c.write   (0xc0)     != ACK) rv = false;  //  Returns '0' - NAK was received '1' - ACK was received, '2' - timeout
00066     if  (i2c.write   (reg)      != ACK) rv = false;
00067     if  (i2c.write   (val)      != ACK) rv = false;
00068     i2c.stop    ();
00069     return  rv;
00070 }
00071 
00072 /*********************************************************\
00073 * IIC Read One Or More Registers into array
00074 \*********************************************************/
00075 bool MPL3115A2::RegRd  (int reg1, int len, char *array)
00076 {
00077     int acknak;
00078     bool    rv = true;
00079     i2c.start   ();
00080     if  (i2c.write   (0xc0) != ACK)     rv = false;  //  Returns '0' - NAK was received '1' - ACK was received, '2' - timeout
00081     if  (i2c.write   (reg1) != ACK)     rv = false;
00082     i2c.start   ();             // Send Repeat Start
00083     if  (i2c.write   (0xc1) != ACK)     rv = false;
00084     acknak = ACK;
00085     while (len > 0) {                                 // Read Register Values
00086         len--;
00087         if  (len == 0)    acknak = NAK;
00088         *array++ = i2c.read    (acknak);
00089     }
00090     i2c.stop    ();
00091     return  rv;
00092 }
00093 
00094 bool    MPL3115A2::Update    ()   {   //  Returns true on apparent success
00095     bool    rv = true;
00096     int32_t ta;
00097     if  (busy_check())  {   //  "User shall read the value of the OST bit before writing to this bit again." - done here.
00098         pc.printf   ("Call to Barometer Update while busy error\r\n");
00099         return  false;  //  Can not initiate new conversion, will not update Temp, Pres, Alti
00100     }
00101     Pres = Alti = -1.0; //  Gives added clue if call to Update fails
00102     if  (!RegRd (1, 5, dest))       rv = false;    //  Read 3 pressure + 2 temperature registers, then kick-start new conversion
00103     if  (!RegWr (0x26, mode | 2))   rv = false;    //  bit 1 is OST one shot mode, bits 3-5 are 128x oversampling. This starts new conversion
00104     if  (!rv)
00105         return  false;  //  register read or write failed, Pres and Alti = -1.0 also
00106     Temp = ((double) ((dest[3] << 4) | (dest[4] >> 4))) / 16.0; //  Temperature
00107     if  (mode & 0x80)  {    //  Altimeter mode
00108         ta = (dest[0] << 24) | (dest[1] << 16) | ((dest[2] & 0xf0) << 8);   //  preserve sign bit
00109         ta /= (1 << 12);
00110         Alti = ((double) ta) / 16.0;
00111         Pres = 0.0;
00112     }
00113     else    {   //  Pressure mode
00114         Pres = ((double) ((dest[0] << 12) | (dest[1] << 4) | (dest[2] >> 4))) / 4.0;
00115         Alti = 0.0;
00116     }
00117     return  true;
00118 }
00119 
00120 
00121 /*
00122 int main()
00123 {
00124     double  Pres, Alt, inHg, Heat;
00125     i2c.frequency(400000);      //  Speed 400000 max.
00126     class   MPL3115A2   baro    ;
00127     int q;      //  Note address bits 3-1 to match addr pins on 24LC16 memory device
00128     for (int i = 0; i < 255; i += 2)    {   //  Search for devices at all possible i2c addresses
00129         i2c.start();
00130         wait_ms (1);
00131         q = i2c.write(i);   //  may return error code 2 when no start issued
00132         switch  (q) {
00133             case    ACK:
00134                 pc.printf   ("I2C device found at 0x%x\r\n", i);
00135             case    NAK:      //  Device not seen at this address
00136                 break;
00137             case    2:      //  write reports timeout
00138                 pc.printf   ("I2C Timeout at addr %2x\r\n", i);
00139                 break;
00140             default:
00141                 pc.printf   ("Unknown error %d in check_24LC64\r\n", q);
00142                 break;
00143         }
00144     }
00145     i2c.stop();
00146     baro.mode_pres  ();
00147     pc.printf   ("baro good flag %s\r\n", baro.good ? "true":"false");
00148     bool    rv;
00149     q = -3;
00150     while(1) {
00151         q++;
00152         if  (q == 0)    baro.reset_zero_inHg();
00153         myled = 1; // LED is ON
00154         wait(0.3); // 200 ms
00155 //        pc.printf   ("busy_check %s\r\n", baro.busy_check() ? "true":"false");
00156         myled = 0; // LED is OFF
00157         wait(0.8); // 1 sec
00158 //        pc.printf   ("busy_check %s\r\n", baro.busy_check() ? "true":"false");
00159         rv  = baro.Update ();
00160         Pres = baro.Pressure();
00161         Alt = baro.Altitude();
00162         inHg = baro.inHg_vacuum();
00163         Heat = baro.Temperature();
00164 const int NOM_PASCALS   = 100000;
00165 const int HYSTERESIS_PASCALS = 50;
00166         if  (Pres > (NOM_PASCALS + HYSTERESIS_PASCALS))
00167             pump = 1;
00168         if  (Pres < (NOM_PASCALS - HYSTERESIS_PASCALS))
00169             pump = 0;
00170 //        pc.printf   ("Pres\t%.2f Pa\tAlt\t%.1f m\t%+000.1f inHg\tTemp\t%.1f C, %s\r\n", baro.Pressure(), baro.Altitude(), baro.inHg_vacuum (), baro.Temperature(), rv ? "true":"false");
00171         pc.printf   ("Pres\t%.2f Pa\tAlt\t%.1f m\t%+000.1f inHg\tTemp\t%.1f C, %s\r\n", Pres, Alt, inHg, Heat, rv ? "true":"false");
00172 //        rv  = baro.Update ();
00173     }
00174 }
00175 */
00176 #endif