LCOV - code coverage report
Current view: top level - firmware/hw_layer/sensors - lps25.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 6 40 15.0 %
Date: 2024-12-19 02:33:10 Functions: 1 3 33.3 %

          Line data    Source code
       1             : /**
       2             :  * @file        lps25.cpp
       3             :  * @brief       Driver for the ST LPS25HB pressure sensor
       4             :  *
       5             :  * At the moment uses bit-banged I2C driver
       6             :  *
       7             :  * @date February 6, 2020
       8             :  * @author Matthew Kennedy, (c) 2020
       9             :  */
      10             : 
      11             : #include "pch.h"
      12             : 
      13             : #include "lps25.h"
      14             : 
      15             : static constexpr uint8_t addr = 0x5C;
      16             : static constexpr uint8_t expectedWhoAmILps22 = 0xB1;
      17             : static constexpr uint8_t expectedWhoAmILps25 = 0xBD;
      18             : 
      19             : // Control register 1
      20             : #define LPS_CR1_PD (1 << 7)
      21             : #define LPS_CR1_ODR_25hz (4 << 4)
      22             : #define LPS_CR1_BDU (1 << 2)
      23             : 
      24             : // Status register flags
      25             : #define LPS_SR_P_DA (1 << 1)      // Pressure data available
      26             : 
      27             : #define REG_WhoAmI 0x0F
      28             : 
      29             : // register address different on LPS22 vs LPS25
      30             : #define REG_Cr1_Lps22 0x10
      31             : #define REG_Cr1_Lps25 0x20
      32             : #define REG_Status 0x27
      33             : #define REG_PressureOutXl 0x28
      34             : #define REG_PressureOutL 0x29
      35             : #define REG_PressureOutH 0x2A
      36             : 
      37           2 : bool Lps25::init(brain_pin_e scl, brain_pin_e sda) {
      38           2 :         if (!m_i2c.init(scl, sda)) {
      39           0 :                 return false;
      40             :         }
      41             : 
      42             :         // Read ident register
      43           2 :         auto whoAmI = m_i2c.readRegister(addr, REG_WhoAmI);
      44             : 
      45           2 :         switch (whoAmI)
      46             :         {
      47           0 :         case expectedWhoAmILps22:
      48           0 :                 m_type = Type::Lps22;
      49           0 :                 break;
      50           0 :         case expectedWhoAmILps25:
      51           0 :                 m_type = Type::Lps25;
      52           0 :                 break;
      53           2 :         default:
      54             :                 // chip not detected
      55           2 :                 return false;
      56             :         }
      57             : 
      58           0 :         uint8_t cr1 = 
      59             :                 LPS_CR1_ODR_25hz |      // 25hz update rate
      60             :                 // TODO: should bdu be set?
      61             :                 LPS_CR1_BDU;            // Output registers update only when read
      62             : 
      63           0 :         if (m_type == Type::Lps25) {
      64             :                 // Set to active mode
      65             :                 // this bit must be 0 on LPS22
      66           0 :                 cr1 |= LPS_CR1_PD;
      67             :         }
      68             : 
      69             :         // Set the control registers
      70           0 :         m_i2c.writeRegister(addr, regCr1(), cr1);
      71             : 
      72           0 :         m_hasInit = true;
      73           0 :         return true;
      74             : }
      75             : 
      76           0 : expected<float> Lps25::readPressureKpa() {
      77           0 :         if (!m_hasInit) {
      78           0 :                 return unexpected;
      79             :         }
      80             : 
      81           0 :         uint8_t buffer[4];
      82             :         // Sequential multi-byte reads need to set the high bit of the
      83             :         // register address to enable multi-byte read
      84           0 :         constexpr uint8_t readAddr = REG_Status | 0x80;
      85           0 :         m_i2c.writeRead(addr, &readAddr, 1, buffer, 4);
      86             : 
      87             :         // First check the status reg to check if there are data available
      88           0 :         bool hasPressure = buffer[0] & LPS_SR_P_DA;
      89             : 
      90           0 :         if (!hasPressure) {
      91           0 :                 return unexpected;
      92             :         }
      93             : 
      94             :         // Glue the 3 bytes back in to a 24 bit integer
      95           0 :         uint32_t counts = buffer[3] << 16 | buffer[2] << 8 | buffer[1];
      96             : 
      97             :         // 4096 counts per hectopascal
      98             :         // = 40960 counts per kilopascal
      99           0 :         constexpr float ratio = 1 / 40960.0f;
     100             :         
     101           0 :         float kilopascal = counts * ratio;
     102             : 
     103             :         // Sensor limits are 26-126 kPa
     104             :         // The highest ever barometric pressure measured was only 108.3 kPa
     105             :         // The pressure at the highest altitude road (Khardung La, India/Tibet) is at 5600 meters,
     106             :         // which should have a nominal barometric pressure of around 50 kPa
     107             :         // Anything outside that range is not a place we expect your engine to run, so we assume
     108             :         // some sensing problem (sealed ECU case and high temperature?)
     109           0 :         if (kilopascal > 120 || kilopascal < 50) {
     110           0 :                 return unexpected;
     111             :         }
     112             : 
     113           0 :         return kilopascal;
     114             : }
     115             : 
     116           0 : uint8_t Lps25::regCr1() const {
     117           0 :         switch (m_type)
     118             :         {
     119           0 :         case Type::Lps22:
     120           0 :                 return REG_Cr1_Lps22;
     121           0 :         case Type::Lps25:
     122             :         default:
     123           0 :                 return REG_Cr1_Lps25;
     124             :         }
     125             : }

Generated by: LCOV version 1.14