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
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
Generated on Fri Jul 22 2022 15:22:19 by
1.7.2