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

baro.cpp

Committer:
JonFreeman
Date:
2020-12-05
Revision:
5:6ca3e7ffc553
Parent:
3:43cb067ecd00

File content as of revision 5:6ca3e7ffc553:

#ifdef  INC_BARO

#include "mbed.h"
#include "baro.h"
#include "BufferedSerial.h"

//BufferedSerial  pc          (PA_2, PA_3, 512, 4, NULL);    //  Pins 16, 17    tx, rx to pc via usb lead
//I2C i2c                     (PB_7, PB_6);   //  Pins 58, 59 For 24LC64 eeprom
extern  BufferedSerial  pc;
extern  I2C i2c;
const int ACK     = 1;
const int NAK     = 0;
const int NOM_PASCALS   = 100000;
const int HYSTERESIS_PASCALS = 50;

MPL3115A2::MPL3115A2    ()  {   //  Constructor
        good = true;
//        mode = 0x39;  //  continuous convert
        mode = 0x38;    //  one shot
        Temp = Pres = Alti = Adju = 0.0;
        if  (!RegRd (0x0c, 1, dest))
            good = false;
        else if (dest[0] != 196)
            good = false;
}

bool    MPL3115A2::busy_check  ()  {
    char    c;
    RegRd   (0x26, 1, &c);
    c &= 2;
    if  (c == 0)
        return  false;  //  free, i.e. not busy
    return  true;       //  busy, conversion in progress
}

void    MPL3115A2::reset_zero_inHg  ()  {
    double tmp;
    Adju = 0.0;
    tmp = inHg_vacuum (); //  sets Adju
    Adju = tmp;
}
double  MPL3115A2::Temperature ()  {    return  Temp;   }
double  MPL3115A2::Pressure    ()  {    return  Pres;   }
double  MPL3115A2::Altitude    ()  {    return  Alti;   }
double  MPL3115A2::inHg_vacuum ()  {
    double  inHg = 0.0 - Pres;   //  one atmospheres worth of Pascals. Note 1 bar is not the same, 1 bar = 100000 Pa
    inHg *= 0.000295299833;
    return  inHg - Adju;
}
void    MPL3115A2::mode_alti   ()  {
//    mode = 0xb9;
    mode = 0xb8;
}
void    MPL3115A2::mode_pres   ()  {
//    mode = 0x39;
    mode = 0x38;
}
/*********************************************************\
* IIC Write Register
\*********************************************************/
bool MPL3115A2::RegWr  (int reg, char val)
{
    bool    rv = true;
    i2c.start   ();
    if  (i2c.write   (0xc0)     != ACK) rv = false;  //  Returns '0' - NAK was received '1' - ACK was received, '2' - timeout
    if  (i2c.write   (reg)      != ACK) rv = false;
    if  (i2c.write   (val)      != ACK) rv = false;
    i2c.stop    ();
    return  rv;
}

/*********************************************************\
* IIC Read One Or More Registers into array
\*********************************************************/
bool MPL3115A2::RegRd  (int reg1, int len, char *array)
{
    int acknak;
    bool    rv = true;
    i2c.start   ();
    if  (i2c.write   (0xc0) != ACK)     rv = false;  //  Returns '0' - NAK was received '1' - ACK was received, '2' - timeout
    if  (i2c.write   (reg1) != ACK)     rv = false;
    i2c.start   ();             // Send Repeat Start
    if  (i2c.write   (0xc1) != ACK)     rv = false;
    acknak = ACK;
    while (len > 0) {                                 // Read Register Values
        len--;
        if  (len == 0)    acknak = NAK;
        *array++ = i2c.read    (acknak);
    }
    i2c.stop    ();
    return  rv;
}

bool    MPL3115A2::Update    ()   {   //  Returns true on apparent success
    bool    rv = true;
    int32_t ta;
    if  (busy_check())  {   //  "User shall read the value of the OST bit before writing to this bit again." - done here.
        pc.printf   ("Call to Barometer Update while busy error\r\n");
        return  false;  //  Can not initiate new conversion, will not update Temp, Pres, Alti
    }
    Pres = Alti = -1.0; //  Gives added clue if call to Update fails
    if  (!RegRd (1, 5, dest))       rv = false;    //  Read 3 pressure + 2 temperature registers, then kick-start new conversion
    if  (!RegWr (0x26, mode | 2))   rv = false;    //  bit 1 is OST one shot mode, bits 3-5 are 128x oversampling. This starts new conversion
    if  (!rv)
        return  false;  //  register read or write failed, Pres and Alti = -1.0 also
    Temp = ((double) ((dest[3] << 4) | (dest[4] >> 4))) / 16.0; //  Temperature
    if  (mode & 0x80)  {    //  Altimeter mode
        ta = (dest[0] << 24) | (dest[1] << 16) | ((dest[2] & 0xf0) << 8);   //  preserve sign bit
        ta /= (1 << 12);
        Alti = ((double) ta) / 16.0;
        Pres = 0.0;
    }
    else    {   //  Pressure mode
        Pres = ((double) ((dest[0] << 12) | (dest[1] << 4) | (dest[2] >> 4))) / 4.0;
        Alti = 0.0;
    }
    return  true;
}


/*
int main()
{
    double  Pres, Alt, inHg, Heat;
    i2c.frequency(400000);      //  Speed 400000 max.
    class   MPL3115A2   baro    ;
    int q;      //  Note address bits 3-1 to match addr pins on 24LC16 memory device
    for (int i = 0; i < 255; i += 2)    {   //  Search for devices at all possible i2c addresses
        i2c.start();
        wait_ms (1);
        q = i2c.write(i);   //  may return error code 2 when no start issued
        switch  (q) {
            case    ACK:
                pc.printf   ("I2C device found at 0x%x\r\n", i);
            case    NAK:      //  Device not seen at this address
                break;
            case    2:      //  write reports timeout
                pc.printf   ("I2C Timeout at addr %2x\r\n", i);
                break;
            default:
                pc.printf   ("Unknown error %d in check_24LC64\r\n", q);
                break;
        }
    }
    i2c.stop();
    baro.mode_pres  ();
    pc.printf   ("baro good flag %s\r\n", baro.good ? "true":"false");
    bool    rv;
    q = -3;
    while(1) {
        q++;
        if  (q == 0)    baro.reset_zero_inHg();
        myled = 1; // LED is ON
        wait(0.3); // 200 ms
//        pc.printf   ("busy_check %s\r\n", baro.busy_check() ? "true":"false");
        myled = 0; // LED is OFF
        wait(0.8); // 1 sec
//        pc.printf   ("busy_check %s\r\n", baro.busy_check() ? "true":"false");
        rv  = baro.Update ();
        Pres = baro.Pressure();
        Alt = baro.Altitude();
        inHg = baro.inHg_vacuum();
        Heat = baro.Temperature();
const int NOM_PASCALS   = 100000;
const int HYSTERESIS_PASCALS = 50;
        if  (Pres > (NOM_PASCALS + HYSTERESIS_PASCALS))
            pump = 1;
        if  (Pres < (NOM_PASCALS - HYSTERESIS_PASCALS))
            pump = 0;
//        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");
        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");
//        rv  = baro.Update ();
    }
}
*/
#endif