Skyward boardcore
Loading...
Searching...
No Matches
ND015D.cpp
Go to the documentation of this file.
1/* Copyright (c) 2025 Skyward Experimental Rocketry
2 * Author: Pietro Bortolus
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "ND015D.h"
24
27#include <utils/Constants.h>
28#include <utils/Numeric.h>
29
30#include <cmath>
31#include <string>
32
33namespace Boardcore
34{
35const char ND015D::MODEL_NAME[] = "ND015D";
36
38{
39 SPIBusConfig spiConfig{};
40 spiConfig.mode = SPI::Mode::MODE_1;
41 spiConfig.clockDivider = SPI::ClockDivider::DIV_256;
42
43 // Datasheet specifies 100us, but 50us is enough from testing
44 spiConfig.csSetupTimeUs = 50;
45
46 // The datasheet specifies a minimum CS hold time of 100us
47 // If this is ever an issue, implement it by waiting at the next sample
48 // instead of setting it in SPIBusConfig
49
50 return spiConfig;
51}
52
53ND015D::ND015D(SPIBusInterface& bus, miosix::GpioPin cs, SPIBusConfig spiConfig,
54 DMAStreamGuard* streamRx, DMAStreamGuard* streamTx,
55 std::chrono::nanoseconds timeout, FullScaleRange fsr,
57 uint8_t odr)
58 : slave(bus, cs, spiConfig), range(rangeToPressure(fsr)),
59 streamRx(streamRx), streamTx(streamTx), timeoutDma(timeout),
60 sensorSettings{odr, fsr, iow, bwl, ntc}
61{
62}
63
64ND015D::ND015D(SPIBusInterface& bus, miosix::GpioPin cs, SPIBusConfig spiConfig,
66 NotchEnable ntc, uint8_t odr)
67 : slave(bus, cs, spiConfig), range(rangeToPressure(fsr)), streamRx(nullptr),
68 streamTx(nullptr), timeoutDma(std::chrono::nanoseconds::zero()),
69 sensorSettings{odr, fsr, iow, bwl, ntc}
70{
71}
72
74{
75 // setting the sensor settings to the correct values
76 SPITransaction spi(slave);
77 uint16_t spiDataOut;
78
79 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
80 spi.transfer16(spiDataOut);
81
82 // Using the sensor immediately after initialization results in incorrect
83 // readings. To avoid this, we introduce a delay. The minimum delay required
84 // to prevent errors is 400 microseconds, but for safety and reliability, we
85 // set it to 4 milliseconds.
86 miosix::Thread::sleep(4);
87
88 return true;
89}
90
91bool ND015D::selfTest() { return true; }
92
94{
95 ND015DDataExtended extendedData{};
96 uint8_t* data = reinterpret_cast<uint8_t*>(&extendedData);
97
98 // setting the first 2 bytes of the data to the correct sensor settings
99 memcpy(&extendedData, &sensorSettings, sizeof(sensorSettings));
100
101 SPITransaction spi(slave);
102 spi.transfer(data, sizeof(extendedData));
103
104 // this part checks if the model number returned by the sensor matches the
105 // correct model number
106 bool compareResult =
107 (memcmp(&extendedData.model, &MODEL_NAME, sizeof(MODEL_NAME) - 1) == 0);
108
109 if (!compareResult)
110 {
111 auto model =
112 std::string(extendedData.model, sizeof(extendedData.model));
113 // Replace all \0 with '.' for printing
114 std::replace(model.begin(), model.end(), '\0', '.');
115
116 LOG_ERR(logger,
117 "Sensor model mismatch: received {}, expected {} (. = \\0)",
118 model, MODEL_NAME);
119 return false;
120 }
121 return true;
122}
123
125{
126 sensorSettings.odr = odr;
127
128 SPITransaction spi(slave);
129 uint16_t spiDataOut;
130
131 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
132 spi.transfer16(spiDataOut);
133}
134
136{
137 sensorSettings.fsr = fsr;
138
139 range = rangeToPressure(fsr);
140
141 SPITransaction spi(slave);
142 uint16_t spiDataOut;
143
144 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
145 spi.transfer16(spiDataOut);
146}
147
149{
150 switch (fsr)
151 {
153 return 1;
155 return 2;
157 return 4;
159 return 5;
161 return 10;
163 return 15;
164 default:
165 return 0;
166 }
167}
168
170{
171 sensorSettings.iow = iow;
172
173 SPITransaction spi(slave);
174 uint16_t spiDataOut;
175
176 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
177 spi.transfer16(spiDataOut);
178}
179
181{
182 sensorSettings.bwl = bwl;
183
184 SPITransaction spi(slave);
185 uint16_t spiDataOut;
186
187 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
188 spi.transfer16(spiDataOut);
189}
190
192{
193 sensorSettings.ntc = ntc;
194
195 SPITransaction spi(slave);
196 uint16_t spiDataOut;
197
198 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
199 spi.transfer16(spiDataOut);
200}
201
202void ND015D::setOffset(float offset) { pressureOffset = offset; };
203void ND015D::updateOffset(float offset) { pressureOffset += offset; };
204float ND015D::getOffset() { return pressureOffset; };
205
207{
208 ND015XData data;
209 uint16_t spiDataOut;
210 uint16_t spiDataIn = 0;
211
212 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
213
214 if (streamRx != nullptr && streamTx != nullptr)
215 {
216 // Use dma
217 SPITransactionDMA spi(slave, *streamRx, *streamTx);
218 spiDataIn = spi.transfer16(spiDataOut, timeoutDma);
219 }
220 else
221 {
222 SPITransaction spi(slave);
223 spiDataIn = spi.transfer16(spiDataOut);
224 }
225
226 float normalizedPressure =
227 std::bit_cast<int16_t>(spiDataIn) / (0.9f * powf(2, 15));
228
229 data.pressure =
230 normalizedPressure * range * Constants::PSI_TO_PASCAL + pressureOffset;
231
233
234 return data;
235}
236
237} // namespace Boardcore
#define LOG_ERR(logger,...)
Simple RAII class to handle DMA streams.
Definition DMA.h:557
void setIOWatchdog(IOWatchdogEnable iow)
Enables or disables the IO watchdog.
Definition ND015D.cpp:169
void setFullScaleRange(FullScaleRange fsr)
Sets the full-scale range for the sensor.
Definition ND015D.cpp:135
void setOffset(float offset)
Set the offset of this sensor. The offset is stored as a int16_t and can be both postive or negative.
Definition ND015D.cpp:202
BWLimitFilter bwl
Definition ND015D.h:238
bool init() override
Initializes the sensor.
Definition ND015D.cpp:73
ND015D(SPIBusInterface &bus, miosix::GpioPin cs, SPIBusConfig spiConfig, DMAStreamGuard *streamRx, DMAStreamGuard *streamTx, std::chrono::nanoseconds timeoutDma, FullScaleRange fsr=FullScaleRange::FS_2, IOWatchdogEnable iow=IOWatchdogEnable::DISABLED, BWLimitFilter bwl=BWLimitFilter::BWL_200, NotchEnable ntc=NotchEnable::ENABLED, uint8_t odr=0x1C)
Constructor for the ND015D sensor.
Definition ND015D.cpp:53
FullScaleRange fsr
Definition ND015D.h:236
void setBWLimitFilter(BWLimitFilter bwl)
Sets the bandwidth limit filter for the sensor.
Definition ND015D.cpp:180
void setNotch(NotchEnable ntc)
Enables or disables the notch filter.
Definition ND015D.cpp:191
float getOffset()
Get the current offset of this sensor. The offset is stored as a int16_t and can be both postive or n...
Definition ND015D.cpp:204
void updateOffset(float offset)
Modify the offset of this sensor. The offset is stored as a int16_t and can be both postive or negati...
Definition ND015D.cpp:203
static SPIBusConfig getDefaultSPIConfig()
Constructs the default config for the SPI bus.
Definition ND015D.cpp:37
static float rangeToPressure(FullScaleRange fsr)
Converts the FullScale value to its corresponding range.
Definition ND015D.cpp:148
IOWatchdogEnable iow
Definition ND015D.h:237
NotchEnable ntc
Definition ND015D.h:239
static const char MODEL_NAME[]
Definition ND015D.h:38
bool checkModelMatch()
Checks if the sensor model matches the expected model.
Definition ND015D.cpp:93
void setOutputDataRate(uint8_t odr)
function to set the output data rate
Definition ND015D.cpp:124
ND015XData sampleImpl() override
Read a data sample from the sensor. In case of errors, the method should return the last available co...
Definition ND015D.cpp:206
bool selfTest() override
Not implemented.
Definition ND015D.cpp:91
Interface for low level access of a SPI bus as a master.
Provides high-level access to the SPI Bus for a single spi transaction with dma.
uint16_t transfer16(uint16_t data, std::chrono::nanoseconds timeout=std::chrono::nanoseconds::zero())
Full duplex transmission of 16 bits on the bus.
Provides high-level access to the SPI Bus for a single transaction.
uint16_t transfer16(uint16_t data)
Full duplex transmission of one half word on the bus.
uint8_t transfer(uint8_t data)
Full duplex transmission of one byte on the bus.
@ MODE_1
CPOL = 1, CPHA = 0 -> Clock high when idle, sample on first edge.
uint64_t getTimestamp()
Returns the current timer value in microseconds.
Driver for the VN100S IMU.
Definition WIZ5500.h:339
SPI Bus configuration for a specific slave.
SPI::Mode mode
MSBit or LSBit first.