implement lps25 (#2301)

* bb

* implement

* tweaks

* s

* comment, format

* guard

* implement lps25

* headers and comment

* sensor works

* headers

* guard

Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
Matthew Kennedy 2021-02-06 21:59:44 -08:00 committed by GitHub
parent fe688471ca
commit 50a860a380
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 133 additions and 0 deletions

View File

@ -0,0 +1,103 @@
/**
* @file lps25.cpp
* @brief Driver for the ST LPS25HB pressure sensor
*
* @date February 6, 2020
* @author Matthew Kennedy, (c) 2020
*/
#if EFI_PROD_CODE
#include "lps25.h"
static constexpr uint8_t addr = 0x5C;
static constexpr uint8_t expectedWhoAmI = 0xBD;
// Control register 1
#define LPS_CR1_PD (1 << 7)
#define LPS_CR1_ODR_25hz (4 << 4)
#define LPS_CR1_BDU (1 << 2)
// Status register flags
#define LPS_SR_P_DA (1 << 1) // Pressure data available
#define REG_WhoAmI 0x0F
#define REG_Cr1 0x20
#define REG_Status 0x27
#define REG_PressureOutXl 0x28
#define REG_PressureOutL 0x29
#define REG_PressureOutH 0x2A
bool Lps25::init(brain_pin_e scl, brain_pin_e sda) {
m_i2c.init(scl, sda);
// Read ident register
auto whoAmI = m_i2c.readRegister(addr, REG_WhoAmI);
if (whoAmI != expectedWhoAmI) {
return false;
}
// Set the control registers
m_i2c.writeRegister(addr, REG_Cr1,
LPS_CR1_PD | // Set to active mode
LPS_CR1_ODR_25hz | // 25hz update rate
// TODO: should bdu be set?
LPS_CR1_BDU // Output registers update only when read
);
m_hasInit = true;
return true;
}
expected<float> Lps25::readPressureKpa() {
// First read the status reg to check if there are data available
uint8_t sr = m_i2c.readRegister(addr, REG_Status);
bool hasPressure = sr & LPS_SR_P_DA;
if (!hasPressure) {
return unexpected;
}
/*
TODO: why doesn't this work?
// Sequential multi-byte reads need to set the high bit of the
// register address to enable multi-byte read
constexpr uint8_t readAddr = REG_PressureOutXl | 0x80;
uint8_t buffer[3];
m_i2c.writeRead(addr, &readAddr, 1, buffer, 3);
// Glue the 3 bytes back in to a 24 bit integer
uint32_t counts = buffer[2] << 16 | buffer[1] << 8 | buffer[0];
*/
auto xl = m_i2c.readRegister(addr, REG_PressureOutXl);
auto l = m_i2c.readRegister(addr, REG_PressureOutL);
auto h = m_i2c.readRegister(addr, REG_PressureOutH);
// Glue the 3 bytes back in to a 24 bit integer
uint32_t counts = h << 16 | l << 8 | xl;
// 4096 counts per hectopascal
// = 40960 counts per kilopascal
constexpr float ratio = 1 / 40960.0f;
float kilopascal = counts * ratio;
// Sensor limits are 26-126 kPa
// The highest ever barometric pressure measured was only 108.3 kPa
// The pressure at the highest altitude road (Khardung La, India/Tibet) is at 5600 meters,
// which should have a nominal barometric pressure of around 50 kPa
// Anything outside that range is not a place we expect your engine to run, so we assume
// some sensing problem (sealed ECU case and high temperature?)
if (kilopascal > 120 || kilopascal < 50) {
return unexpected;
}
return kilopascal;
}
#endif // EFI_PROD_CODE

View File

@ -0,0 +1,29 @@
/**
* @file lps25.h
* @brief Driver for the ST LPS25HB pressure sensor
*
* @date February 6, 2020
* @author Matthew Kennedy, (c) 2020
*/
#pragma once
#if EFI_PROD_CODE
#include "i2c_bb.h"
#include "expected.h"
class Lps25 {
public:
// Returns true if the sensor was initialized successfully.
bool init(brain_pin_e scl, brain_pin_e sda);
expected<float> readPressureKpa();
private:
BitbangI2c m_i2c;
bool m_hasInit = false;
};
#endif // EFI_PROD_CODE

View File

@ -8,4 +8,5 @@ HW_SENSORS_SRC = \
$(HW_SENSORS_DIR)/yaw_rate_sensor.cpp \
$(HW_SENSORS_DIR)/accelerometer.cpp \
$(HW_SENSORS_DIR)/joystick.cpp \
$(HW_SENSORS_DIR)/lps25.cpp \