Skyward boardcore
Loading...
Searching...
No Matches
ND015A.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 "ND015A.h"
24
27#include <utils/Constants.h>
28
29#include <cmath>
30#include <string>
31
32namespace Boardcore
33{
34const char ND015A::MODEL_NAME[] = "ND015A";
35
37{
38 SPIBusConfig spiConfig{};
39 spiConfig.mode = SPI::Mode::MODE_1;
40 spiConfig.clockDivider = SPI::ClockDivider::DIV_256;
41
42 // Datasheet specifies 100us, but 50us is enough from testing
43 spiConfig.csSetupTimeUs = 50;
44
45 // The datasheet specifies a minimum CS hold time of 100us
46 // If this is ever an issue, implement it by waiting at the next sample
47 // instead of setting it in SPIBusConfig
48
49 return spiConfig;
50}
51
52ND015A::ND015A(SPIBusInterface& bus, miosix::GpioPin cs, SPIBusConfig spiConfig,
53 DMAStreamGuard* streamRx, DMAStreamGuard* streamTx,
54 std::chrono::nanoseconds timeout, IOWatchdogEnable iow,
55 BWLimitFilter bwl, NotchEnable ntc, uint8_t odr)
56 : slave(bus, cs, spiConfig), streamRx(streamRx), streamTx(streamTx),
57 timeoutDma(timeout), sensorSettings{odr, 0x7, iow, bwl, ntc}
58{
59}
60
61ND015A::ND015A(SPIBusInterface& bus, miosix::GpioPin cs, SPIBusConfig spiConfig,
63 uint8_t odr)
64 : slave(bus, cs, spiConfig), streamRx(nullptr), streamTx(nullptr),
65 timeoutDma(std::chrono::nanoseconds::zero()),
66 sensorSettings{odr, 0x7, iow, bwl, ntc}
67{
68}
69
71{
72 // setting the sensor settings to the correct values
73 SPITransaction spi(slave);
74 uint16_t spiDataOut;
75
76 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
77 spi.transfer16(spiDataOut);
78
79 // Using the sensor immediately after initialization results in incorrect
80 // readings. To avoid this, we introduce a delay. The minimum delay required
81 // to prevent errors is 400 microseconds, but for safety and reliability, we
82 // set it to 4 milliseconds.
83 miosix::Thread::sleep(4);
84
85 return true;
86}
87
88bool ND015A::selfTest() { return true; }
89
91{
92 ND015ADataExtended extendedData{};
93 uint8_t* data = reinterpret_cast<uint8_t*>(&extendedData);
94
95 // setting the first 2 bytes of the data to the correct sensor settings
96 memcpy(&extendedData, &sensorSettings, sizeof(sensorSettings));
97
98 SPITransaction spi(slave);
99 spi.transfer(data, sizeof(extendedData));
100
101 // this part checks if the model number returned by the sensor matches the
102 // correct model number
103 bool compareResult =
104 (memcmp(&extendedData.model, &MODEL_NAME, sizeof(MODEL_NAME) - 1) == 0);
105
106 if (!compareResult)
107 {
108 auto model =
109 std::string(extendedData.model, sizeof(extendedData.model));
110 // Replace all \0 with '.' for printing
111 std::replace(model.begin(), model.end(), '\0', '.');
112
113 LOG_ERR(logger,
114 "Sensor model mismatch: received {}, expected {} (. = \\0)",
115 model, MODEL_NAME);
116 return false;
117 }
118 return true;
119}
120
122{
123 sensorSettings.odr = odr;
124
125 SPITransaction spi(slave);
126 uint16_t spiDataOut;
127
128 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
129 spi.transfer16(spiDataOut);
130}
131
133{
134 sensorSettings.iow = iow;
135
136 SPITransaction spi(slave);
137 uint16_t spiDataOut;
138
139 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
140 spi.transfer16(spiDataOut);
141}
142
144{
145 sensorSettings.bwl = bwl;
146
147 SPITransaction spi(slave);
148 uint16_t spiDataOut;
149
150 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
151 spi.transfer16(spiDataOut);
152}
153
155{
156 sensorSettings.ntc = ntc;
157
158 SPITransaction spi(slave);
159 uint16_t spiDataOut;
160
161 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
162 spi.transfer16(spiDataOut);
163}
164
165void ND015A::setOffset(float offset) { pressureOffset = offset; };
166void ND015A::updateOffset(float offset) { pressureOffset += offset; };
167float ND015A::getOffset() { return pressureOffset; };
168
170{
171 ND015XData data;
172 uint16_t spiDataOut;
173
174 memcpy(&spiDataOut, &sensorSettings, sizeof(spiDataOut));
175
176 uint16_t spiDataIn = 0;
177 if (streamRx != nullptr && streamTx != nullptr)
178 {
179 // Use dma
180 SPITransactionDMA spi(slave, *streamRx, *streamTx);
181 spiDataIn = spi.transfer16(spiDataOut, timeoutDma);
182 }
183 else
184 {
185 SPITransaction spi(slave);
186 spiDataIn = spi.transfer16(spiDataOut);
187 }
188
189 float normalizedPressure =
190 (static_cast<float>(spiDataIn) - 0.05f * powf(2, 16)) /
191 (0.9f * powf(2, 16));
192
193 data.pressure =
194 normalizedPressure * ND015A::FULLSCALE * Constants::PSI_TO_PASCAL +
195 pressureOffset;
196
198
199 return data;
200}
201
202} // namespace Boardcore
#define LOG_ERR(logger,...)
Simple RAII class to handle DMA streams.
Definition DMA.h:557
bool init() override
Initializes the sensor.
Definition ND015A.cpp:70
void setBWLimitFilter(BWLimitFilter bwl)
Sets the bandwidth limit filter for the sensor.
Definition ND015A.cpp:143
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 ND015A.cpp:166
bool checkModelMatch()
Checks if the sensor model matches the expected model.
Definition ND015A.cpp:90
void setNotch(NotchEnable ntc)
Enables or disables the notch filter.
Definition ND015A.cpp:154
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 ND015A.cpp:165
NotchEnable ntc
Definition ND015A.h:208
bool selfTest() override
Not implemented.
Definition ND015A.cpp:88
static const char MODEL_NAME[]
Definition ND015A.h:38
static const int FULLSCALE
Definition ND015A.h:39
static SPIBusConfig getDefaultSPIConfig()
Constructs the default config for the SPI bus.
Definition ND015A.cpp:36
IOWatchdogEnable iow
Definition ND015A.h:206
ND015XData sampleImpl() override
Read a data sample from the sensor. In case of errors, the method should return the last available co...
Definition ND015A.cpp:169
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 ND015A.cpp:167
void setIOWatchdog(IOWatchdogEnable iow)
function to enable the IO watchdog
Definition ND015A.cpp:132
ND015A(SPIBusInterface &bus, miosix::GpioPin cs, SPIBusConfig spiConfig, DMAStreamGuard *streamRx, DMAStreamGuard *streamTx, std::chrono::nanoseconds timeoutDma, IOWatchdogEnable iow=IOWatchdogEnable::DISABLED, BWLimitFilter bwl=BWLimitFilter::BWL_200, NotchEnable ntc=NotchEnable::ENABLED, uint8_t odr=0x1C)
Constructor for the ND015A sensor.
Definition ND015A.cpp:52
BWLimitFilter bwl
Definition ND015A.h:207
void setOutputDataRate(uint8_t odr)
function to set the output data rate
Definition ND015A.cpp:121
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.