rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
lps25.cpp
Go to the documentation of this file.
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
15static constexpr uint8_t addr = 0x5C;
16static constexpr uint8_t expectedWhoAmILps22 = 0xB1;
17static 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
38 if (!m_i2c.init(scl, sda)) {
39 return false;
40 }
41
42 // Read ident register
43 auto whoAmI = m_i2c.readRegister(addr, REG_WhoAmI);
44
45 switch (whoAmI)
46 {
49 break;
52 break;
53 default:
54 // chip not detected
55 return false;
56 }
57
58 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 if (m_type == Type::Lps25) {
64 // Set to active mode
65 // this bit must be 0 on LPS22
66 cr1 |= LPS_CR1_PD;
67 }
68
69 // Set the control registers
71
72 m_hasInit = true;
73 return true;
74}
75
76expected<float> Lps25::readPressureKpa() {
77 if (!m_hasInit) {
78 return unexpected;
79 }
80
81 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 constexpr uint8_t readAddr = REG_Status | 0x80;
85 m_i2c.writeRead(addr, &readAddr, 1, buffer, 4);
86
87 // First check the status reg to check if there are data available
88 bool hasPressure = buffer[0] & LPS_SR_P_DA;
89
90 if (!hasPressure) {
91 return unexpected;
92 }
93
94 // Glue the 3 bytes back in to a 24 bit integer
95 uint32_t counts = buffer[3] << 16 | buffer[2] << 8 | buffer[1];
96
97 // 4096 counts per hectopascal
98 // = 40960 counts per kilopascal
99 constexpr float ratio = 1 / 40960.0f;
100
101 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 if (kilopascal > 120 || kilopascal < 50) {
110 return unexpected;
111 }
112
113 return kilopascal;
114}
115
116uint8_t Lps25::regCr1() const {
117 switch (m_type)
118 {
119 case Type::Lps22:
120 return REG_Cr1_Lps22;
121 case Type::Lps25:
122 default:
123 return REG_Cr1_Lps25;
124 }
125}
constexpr uint8_t addr
Definition ads1015.cpp:14
void writeRegister(uint8_t addr, uint8_t reg, uint8_t val)
Definition i2c_bb.cpp:235
bool init(brain_pin_e scl, brain_pin_e sda)
Definition i2c_bb.cpp:37
uint8_t readRegister(uint8_t addr, uint8_t reg)
Definition i2c_bb.cpp:227
void writeRead(uint8_t addr, const uint8_t *writeData, size_t writeSize, uint8_t *readData, size_t readSize)
Definition i2c_bb.cpp:204
bool init(brain_pin_e scl, brain_pin_e sda)
Definition lps25.cpp:37
uint8_t regCr1() const
Definition lps25.cpp:116
expected< float > readPressureKpa()
Definition lps25.cpp:76
BitbangI2c m_i2c
Definition lps25.h:24
Type m_type
Definition lps25.h:31
bool m_hasInit
Definition lps25.h:33
static constexpr uint8_t expectedWhoAmILps25
Definition lps25.cpp:17
static constexpr uint8_t addr
Definition lps25.cpp:15
static constexpr uint8_t expectedWhoAmILps22
Definition lps25.cpp:16
Driver for the ST LPS22HB and LPS25HB pressure sensor.
static BigBufferHandle buffer