Skyward boardcore
Loading...
Searching...
No Matches
MS5803.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 "MS5803.h"
25
27
28namespace Boardcore
29{
30
31MS5803::MS5803(SPIBusInterface& spiBus, miosix::GpioPin cs,
32 SPIBusConfig spiConfig, uint16_t temperatureDivider)
33 : spiSlave(spiBus, cs, spiConfig), temperatureDivider(temperatureDivider)
34{
35 // Ensure that the write bit is disabled
37}
38
40{
41 SPITransaction transaction{spiSlave};
42
43 // Read calibration data
44 calibrationData.sens = transaction.readRegister16(REG_PROM_SENS_MASK);
45 calibrationData.off = transaction.readRegister16(REG_PROM_OFF_MASK);
46 calibrationData.tcs = transaction.readRegister16(REG_PROM_TCS_MASK);
47 calibrationData.tco = transaction.readRegister16(REG_PROM_TCO_MASK);
48 calibrationData.tref = transaction.readRegister16(REG_PROM_TREF_MASK);
49 calibrationData.tempsens =
50 transaction.readRegister16(REG_PROM_TEMPSENS_MASK);
51
53 logger,
54 "sens={:X}, off={:X}, tcs={:X}, tco={:X}, tref={:X}, tempsens={:X}",
55 calibrationData.sens, calibrationData.off, calibrationData.tcs,
56 calibrationData.tco, calibrationData.tref, calibrationData.tempsens);
57
58 return true;
59}
60
61bool MS5803::selfTest() { return true; }
62
64{
65 SPITransaction transaction{spiSlave};
66
67 switch (deviceState)
68 {
69 case STATE_INIT:
70 {
71 // Begin temperature sampling
72 transaction.write(static_cast<uint8_t>(REG_CONVERT_D2_4096));
73 deviceState = STATE_SAMPLED_TEMP;
74 break;
75 }
77 {
78 // Read back the sampled temperature
79 uint32_t tmpRawTemperature =
80 transaction.readRegister24(REG_ADC_READ);
81 lastTemperatureTimestamp = TimestampTimer::getTimestamp();
82
83 // Check if the value is valid
84 if (tmpRawTemperature != 0)
85 rawTemperature = tmpRawTemperature;
86 else
87 LOG_ERR(logger, "The read raw temperature isn't valid");
88
89 // Begin pressure sampling
90 transaction.write(static_cast<uint8_t>(REG_CONVERT_D1_4096));
91 deviceState = STATE_SAMPLED_PRESS;
92 break;
93 }
95 {
96 // Read back the sampled pressure
97 uint32_t tmpRawPressure = transaction.readRegister24(REG_ADC_READ);
98
99 // Check if the value is valid
100 if (tmpRawPressure != 0)
101 rawPressure = tmpRawPressure;
102 else
103 LOG_ERR(logger, "The read raw pressure isn't valid");
104
105 lastSample = updateData();
106 // Check whether to read the pressure or the temperature
107 tempCounter++;
108 if (tempCounter % temperatureDivider == 0)
109 {
110 // Begin temperature sampling
111 transaction.write(static_cast<uint8_t>(REG_CONVERT_D2_4096));
112 deviceState = STATE_SAMPLED_TEMP;
113 }
114 else
115 {
116 // Begin pressure sampling again
117 transaction.write(static_cast<uint8_t>(REG_CONVERT_D1_4096));
118 }
119 break;
120 }
121 default:
122 break;
123 }
124
125 return lastSample;
126}
127
128MS5803Data MS5803::updateData()
129{
130 // First order compensation
131 int32_t dt = rawTemperature - (((uint32_t)calibrationData.tref) << 8);
132 int32_t temp = 2000 + (((uint64_t)dt * calibrationData.tempsens) >> 23);
133
134 int64_t offs = ((int64_t)calibrationData.off << 16) +
135 (((int64_t)calibrationData.tco * dt) >> 7);
136 int64_t sens = ((int64_t)calibrationData.sens << 15) +
137 (((int64_t)calibrationData.tcs * dt) >> 8);
138
139 int64_t t2 = 0, off2 = 0, sens2 = 0;
140
141 // Second order temperature compensation
142 if (temp < 2000)
143 {
144 t2 = (((int64_t)dt) * dt) >> 31;
145 off2 = 3 * (temp - 2000) * (temp - 2000);
146 sens2 = (7 * (temp - 2000) * (temp - 2000)) >> 3;
147
148 if (temp < -1500)
149 sens2 = sens2 + 2 * (temp + 1500) * (temp + 1500);
150 }
151 else if (temp >= 4500)
152 {
153 sens2 = sens2 - (((temp - 4500) * (temp - 4500)) >> 3);
154 }
155
156 temp = temp - t2;
157 offs = offs - off2;
158 sens = sens - sens2;
159
160 float pressure =
161 (((((int64_t)rawPressure) * sens) / 2097152.0) - offs) / 32786.0;
162
163 // Pressure in Pascal
164 return MS5803Data(TimestampTimer::getTimestamp(), pressure,
165 lastTemperatureTimestamp, temp / 100.0f);
166}
167
168} // namespace Boardcore
#define LOG_INFO(logger,...)
#define LOG_ERR(logger,...)
MS5803(SPIBusInterface &spiBus, miosix::GpioPin cs, SPIBusConfig spiConfig={}, uint16_t temperatureDivider=1)
Definition MS5803.cpp:31
bool init() override
Initialize the sensor.
Definition MS5803.cpp:39
@ REG_PROM_TEMPSENS_MASK
Definition MS5803.h:70
MS5803Data sampleImpl() override
Definition MS5803.cpp:63
bool selfTest() override
Check if the sensor is working.
Definition MS5803.cpp:61
Interface for low level access of a SPI bus as a master.
Provides high-level access to the SPI Bus for a single transaction.
@ DISABLED
Do not set write bit in any way.
uint64_t getTimestamp()
Returns the current timer value in microseconds.
This file includes all the types the logdecoder script will decode.
SPI Bus configuration for a specific slave.
SPI::WriteBit writeBit
How long to wait before starting a tranmission after CS is set (us)