Skyward boardcore
Loading...
Searching...
No Matches
MS5803I2C.cpp
Go to the documentation of this file.
1
2/* Copyright (c) 2021 Skyward Experimental Rocketry
3 * Author: Alberto Nidasio
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#include "MS5803I2C.h"
25
27
28namespace Boardcore
29{
30
31MS5803I2C::MS5803I2C(I2C& bus, uint16_t temperatureDivider)
32 : bus(bus), temperatureDivider(temperatureDivider)
33{
34}
35
37{
38 // Read calibration data
39 calibrationData.sens = readReg(REG_PROM_SENS_MASK);
40 calibrationData.off = readReg(REG_PROM_OFF_MASK);
41 calibrationData.tcs = readReg(REG_PROM_TCS_MASK);
42 calibrationData.tco = readReg(REG_PROM_TCO_MASK);
43 calibrationData.tref = readReg(REG_PROM_TREF_MASK);
44 calibrationData.tempsens = readReg(REG_PROM_TEMPSENS_MASK);
45
47 logger,
48 "sens={:X}, off={:X}, tcs={:X}, tco={:X}, tref={:X}, tempsens={:X}",
49 calibrationData.sens, calibrationData.off, calibrationData.tcs,
50 calibrationData.tco, calibrationData.tref, calibrationData.tempsens);
51
52 return true;
53}
54
55bool MS5803I2C::selfTest() { return true; }
56
58{
59 uint8_t buffer[3];
60
61 switch (deviceState)
62 {
63 case STATE_INIT:
64 {
65 // Begin temperature sampling
66 uint8_t val = static_cast<uint8_t>(REG_CONVERT_D2_4096);
67 if (!bus.write(slaveConfig, &val, 1))
68 {
70 return lastSample;
71 }
72 deviceState = STATE_SAMPLED_TEMP;
73 break;
74 }
76 {
77 // Read back the sampled temperature
78 if (!bus.readFromRegister(slaveConfig, REG_ADC_READ, buffer, 3))
79 {
81 return lastSample;
82 }
83
84 uint32_t tmpRawTemperature = (uint32_t)buffer[2] |
85 ((uint32_t)buffer[1] << 8) |
86 ((uint32_t)buffer[0] << 16);
87 lastTemperatureTimestamp = TimestampTimer::getTimestamp();
88
89 // Check if the value is valid
90 if (tmpRawTemperature != 0)
91 rawTemperature = tmpRawTemperature;
92 else
93 LOG_ERR(logger, "The read raw temperature isn't valid");
94
95 // Begin pressure sampling
96 uint8_t val = static_cast<uint8_t>(REG_CONVERT_D1_4096);
97 if (!bus.write(slaveConfig, &val, 1))
98 {
100 return lastSample;
101 }
102 deviceState = STATE_SAMPLED_PRESS;
103 break;
104 }
106 {
107 // Read back the sampled pressure
108 if (!bus.readFromRegister(slaveConfig, REG_ADC_READ, buffer, 3))
109 {
111 return lastSample;
112 }
113
114 uint32_t tmpRawPressure = (uint32_t)buffer[2] |
115 ((uint32_t)buffer[1] << 8) |
116 ((uint32_t)buffer[0] << 16);
117
118 // Check if the value is valid
119 if (tmpRawPressure != 0)
120 rawPressure = tmpRawPressure;
121 else
122 LOG_ERR(logger, "The read raw pressure isn't valid");
123
124 lastSample = updateData();
125 // Check whether to read the pressure or the temperature
126 tempCounter++;
127 if (tempCounter % temperatureDivider == 0)
128 {
129 // Begin temperature sampling
130 uint8_t val = static_cast<uint8_t>(REG_CONVERT_D2_4096);
131 if (!bus.write(slaveConfig, &val, 1))
132 {
134 return lastSample;
135 }
136 deviceState = STATE_SAMPLED_TEMP;
137 }
138 else
139 {
140 // Begin pressure sampling again
141 uint8_t val = static_cast<uint8_t>(REG_CONVERT_D1_4096);
142 if (!bus.write(slaveConfig, &val, 1))
143 {
145 return lastSample;
146 }
147 }
148 break;
149 }
150 default:
151 break;
152 }
153
154 return lastSample;
155}
156
157MS5803Data MS5803I2C::updateData()
158{
159 // First order compensation
160 int32_t dt = rawTemperature - (((uint32_t)calibrationData.tref) << 8);
161 int32_t temp = 2000 + (((uint64_t)dt * calibrationData.tempsens) >> 23);
162
163 int64_t offs = ((int64_t)calibrationData.off << 16) +
164 (((int64_t)calibrationData.tco * dt) >> 7);
165 int64_t sens = ((int64_t)calibrationData.sens << 15) +
166 (((int64_t)calibrationData.tcs * dt) >> 8);
167
168 int64_t t2 = 0, off2 = 0, sens2 = 0;
169
170 // Second order temperature compensation
171 if (temp < 2000)
172 {
173 t2 = (((int64_t)dt) * dt) >> 31;
174 off2 = 3 * (temp - 2000) * (temp - 2000);
175 sens2 = (7 * (temp - 2000) * (temp - 2000)) >> 3;
176
177 if (temp < -1500)
178 sens2 = sens2 + 2 * (temp + 1500) * (temp + 1500);
179 }
180 else if (temp >= 4500)
181 {
182 sens2 = sens2 - (((temp - 4500) * (temp - 4500)) >> 3);
183 }
184
185 temp = temp - t2;
186 offs = offs - off2;
187 sens = sens - sens2;
188
189 float pressure =
190 (((((int64_t)rawPressure) * sens) / 2097152.0) - offs) / 32786.0;
191
192 // Pressure in Pascal
193 return MS5803Data(TimestampTimer::getTimestamp(), pressure,
194 lastTemperatureTimestamp, temp / 100.0f);
195}
196
197uint16_t MS5803I2C::readReg(uint8_t reg)
198{
199 uint8_t rcv[2];
200
201 if (!bus.readFromRegister(slaveConfig, reg, rcv, 2))
202 {
204 return 0;
205 }
206
207 uint16_t data = (rcv[0] << 8) | rcv[1];
208 return data;
209}
210
211} // namespace Boardcore
#define LOG_INFO(logger,...)
#define LOG_ERR(logger,...)
SensorErrors lastError
Definition Sensor.h:54
High level driver for the I2C peripherals.
Definition I2C.h:40
bool readFromRegister(const I2CDriver::I2CSlaveConfig &slaveConfig, const uint8_t registerAddress, void *buffer, const size_t nBytes)
Non blocking operation to read n-bytes from register from a slave.
Definition I2C.cpp:189
bool write(const I2CDriver::I2CSlaveConfig &slaveConfig, const void *buffer, const size_t nBytes)
Non blocking write operation to write nBytes.
Definition I2C.cpp:41
bool init() override
Initialize the sensor.
Definition MS5803I2C.cpp:36
bool selfTest() override
Check if the sensor is working.
Definition MS5803I2C.cpp:55
MS5803I2C(I2C &bus, uint16_t temperatureDivider=1)
Definition MS5803I2C.cpp:31
MS5803Data sampleImpl() override
Definition MS5803I2C.cpp:57
uint64_t getTimestamp()
Returns the current timer value in microseconds.
This file includes all the types the logdecoder script will decode.