STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
SensorSelfTest.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <
Arduino.h
>
4
5
#include "STAR_ADS126X.h"
6
7
namespace
SensorSelfTest
{
8
9
// Thresholds (ADC codes, full-scale = 2^31)
10
// ADC TDAC test: VDD reference. TDACP = 0.6*AVDD, TDACN = 0.5*AVDD.
11
// Differential = 0.1*AVDD. Reference = AVDD. So code = 0.1 * 2^31.
12
// We allow ±1% of the expected code.
13
constexpr
int32_t
ADC_TDAC_EXPECTED_CODE
= 214748364;
// 0.1 * 2^31
14
constexpr
int32_t
ADC_TDAC_TOLERANCE
= 2147484;
// 1% of expected code
15
16
// Sensor bias test (SBMAG = 0b110 → 10MΩ pull resistor via MODE1):
17
// Open circuit → bias pulls pin to rail → code saturates at +FS (~2^31)
18
// Connected → sensor loads the bias → small-to-moderate code
19
// Two thresholds with an AMBIGUOUS band in between:
20
// |code| < 40% FS → CONNECTED
21
// |code| > 60% FS → DISCONNECTED
22
// between → AMBIGUOUS
23
constexpr
int32_t
SENSOR_BIAS_CLOSED_THRESHOLD
= 858993459;
// 40% of 2^31
24
constexpr
int32_t
SENSOR_BIAS_OPEN_THRESHOLD
= 1288490188;
// 60% of 2^31
25
26
// Analog settling delay (ms) after mux switch during bias test.
27
// The 10MΩ bias resistor × parasitic capacitance (traces, connectors)
28
// forms an RC that needs ~3τ to reach the rail on open pins.
29
// 50ms covers ~3τ for up to ~1.6nF parasitic capacitance.
30
constexpr
unsigned
long
BIAS_SETTLE_MS
= 50;
31
32
// Number of ADC samples to average per channel during the bias test.
33
constexpr
uint8_t
BIAS_AVG_SAMPLES
= 4;
34
35
enum class
BiasResult
: uint8_t {
36
CONNECTED
= 0,
// |code| < closed threshold — sensor is present
37
AMBIGUOUS
= 1,
// between thresholds — uncertain
38
DISCONNECTED
= 2,
// |code| > open threshold — no sensor
39
};
40
41
/**
42
* ADC self-test via internal TDAC.
43
* Sets TDACP to 0.6*VDD and TDACN to 0.5*VDD.
44
* Muxes TDAC vs TDAC, uses VDD reference (5V).
45
* Reads and checks that the code is near ADC_TDAC_EXPECTED_CODE.
46
* Restores original reference, mux, and turns off TDAC after test.
47
*/
48
struct
AdcSelfTestResult
{
49
bool
passed
;
50
int32_t
code
;
// raw ADC code read
51
bool
checksum_valid
;
52
};
53
54
inline
AdcSelfTestResult
run_adc_self_test
(
ADS126X
&
adc
, uint8_t drdy_pin,
55
uint8_t original_ref_neg,
56
uint8_t original_ref_pos) {
57
adc
.bypassPGA();
58
adc
.setInputMux(
ADS126X_TDAC
,
ADS126X_TDAC
);
59
60
adc
.setOutputTDACP(1);
61
adc
.setOutputTDACN(1);
62
adc
.setOutputmagnitudeTDACP(
ADS126X_TDAC_DIV_0_6
);
63
adc
.setOutputmagnitudeTDACN(
ADS126X_TDAC_DIV_0_5
);
64
65
adc
.setReference(
ADS126X_REF_NEG_VSS
,
ADS126X_REF_POS_VDD
);
66
67
// Flush 5 conversions so SINC5 filter settles after mux/ref change
68
for
(uint8_t i = 0; i < 5; i++) {
69
delayMicroseconds
(10);
70
while
(
digitalRead
(drdy_pin) !=
LOW
)
71
delayMicroseconds
(10);
72
adc
.readADC1();
73
}
74
75
// Real measurement
76
delayMicroseconds
(10);
77
while
(
digitalRead
(drdy_pin) !=
LOW
)
78
delayMicroseconds
(10);
79
80
const
auto
reading =
adc
.readADC1();
81
int32_t code = reading.value;
82
83
adc
.bypassPGA();
84
adc
.setOutputTDACP(0);
85
adc
.setOutputTDACN(0);
86
adc
.setReference(original_ref_neg, original_ref_pos);
87
88
if
(!reading.checksumValid) {
89
return
{
false
, code,
false
};
90
}
91
92
int32_t
diff
= code -
ADC_TDAC_EXPECTED_CODE
;
93
if
(
diff
< 0)
94
diff
= -
diff
;
95
96
return
{
diff
<=
ADC_TDAC_TOLERANCE
, code,
true
};
97
}
98
99
/** Call once before the connector loop. Configures sensor bias on ADC1 with
100
* 10MΩ pull-up, bypasses PGA (bias voltages can exceed PGA input range),
101
* and turns off IDACs. */
102
inline
void
sensor_bias_enable
(
ADS126X
&
adc
) {
103
adc
.bypassPGA();
104
adc
.setIDAC1Mag(
ADS126X_IDAC_MAG_0
);
105
adc
.setIDAC2Mag(
ADS126X_IDAC_MAG_0
);
106
adc
.setBiasADC(
ADS126X_BIAS_ADC1
);
107
adc
.setBiasPolarity(
ADS126X_BIAS_PULLUP
);
108
adc
.setBiasMagnitude(
ADS126X_BIAS_MAG_10M
);
109
delay
(
BIAS_SETTLE_MS
);
110
}
111
112
struct
BiasReadResult
{
113
BiasResult
result
;
114
int32_t
code
;
// raw signed ADC code
115
bool
checksum_valid
;
116
};
117
118
/**
119
* Read one connector with sensor bias already active.
120
* After switching the mux, flushes `settle_cycles` conversions so the
121
* digital filter (e.g. SINC5 needs 5) fully settles on the new channel
122
* before taking the real measurement.
123
*
124
* Returns CONNECTED if |code| < SENSOR_BIAS_CLOSED_THRESHOLD,
125
* DISCONNECTED if |code| >= SENSOR_BIAS_OPEN_THRESHOLD,
126
* AMBIGUOUS otherwise (or on checksum failure).
127
*/
128
inline
BiasReadResult
read_sensor_bias
(
ADS126X
&
adc
, uint8_t drdy_pin,
129
uint8_t adc_channel, uint8_t aincom,
130
uint8_t settle_cycles = 5) {
131
// Stop ADC so the filter doesn't fill with mid-transition data
132
adc
.stopADC1();
133
adc
.setInputMux(adc_channel, aincom);
134
135
// Let the 10MΩ bias resistor charge/discharge parasitic capacitance
136
delay
(
BIAS_SETTLE_MS
);
137
138
// Restart ADC — filter pipeline starts fresh on the settled signal
139
adc
.startADC1();
140
141
// Flush conversions so the digital filter (SINC5) fully settles
142
for
(uint8_t i = 0; i < settle_cycles; i++) {
143
delayMicroseconds
(10);
144
while
(
digitalRead
(drdy_pin) !=
LOW
)
145
delayMicroseconds
(10);
146
adc
.readADC1();
147
}
148
149
// Take multiple samples and average for noise rejection
150
int64_t sum = 0;
151
uint8_t good_count = 0;
152
for
(uint8_t s = 0; s <
BIAS_AVG_SAMPLES
; s++) {
153
delayMicroseconds
(10);
154
while
(
digitalRead
(drdy_pin) !=
LOW
)
155
delayMicroseconds
(10);
156
auto
reading =
adc
.readADC1();
157
if
(reading.checksumValid) {
158
sum += reading.value;
159
good_count++;
160
}
161
}
162
163
if
(good_count == 0)
164
return
{
BiasResult::AMBIGUOUS
, 0,
false
};
165
166
int32_t val =
static_cast<
int32_t
>
(sum / good_count);
167
int32_t abs_val = (val < 0) ? -val : val;
168
169
BiasResult
r
;
170
if
(abs_val <
SENSOR_BIAS_CLOSED_THRESHOLD
)
171
r
=
BiasResult::CONNECTED
;
172
else
if
(abs_val >=
SENSOR_BIAS_OPEN_THRESHOLD
)
173
r
=
BiasResult::DISCONNECTED
;
174
else
175
r
=
BiasResult::AMBIGUOUS
;
176
177
return
{
r
, val,
true
};
178
}
179
180
/** Call once after the connector loop. Restores SBMAG = 0. */
181
inline
void
sensor_bias_disable
(
ADS126X
&
adc
) {
182
adc
.setBiasMagnitude(
ADS126X_BIAS_MAG_0
);
183
}
184
185
}
// namespace SensorSelfTest
Arduino.h
digitalRead
int digitalRead(int)
Definition
Arduino.h:50
LOW
#define LOW
Definition
Arduino.h:20
delayMicroseconds
void delayMicroseconds(unsigned int)
Definition
Arduino.h:58
ADS126X_TDAC_DIV_0_5
#define ADS126X_TDAC_DIV_0_5
Definition
STAR_ADS126X.h:7
ADS126X_BIAS_PULLUP
#define ADS126X_BIAS_PULLUP
Definition
STAR_ADS126X.h:12
ADS126X_REF_POS_VDD
#define ADS126X_REF_POS_VDD
Definition
STAR_ADS126X.h:9
ADS126X_TDAC_DIV_0_6
#define ADS126X_TDAC_DIV_0_6
Definition
STAR_ADS126X.h:6
ADS126X_BIAS_MAG_0
#define ADS126X_BIAS_MAG_0
Definition
STAR_ADS126X.h:14
ADS126X_IDAC_MAG_0
#define ADS126X_IDAC_MAG_0
Definition
STAR_ADS126X.h:10
ADS126X_BIAS_ADC1
#define ADS126X_BIAS_ADC1
Definition
STAR_ADS126X.h:11
ADS126X_TDAC
#define ADS126X_TDAC
Definition
STAR_ADS126X.h:5
ADS126X_BIAS_MAG_10M
#define ADS126X_BIAS_MAG_10M
Definition
STAR_ADS126X.h:13
ADS126X_REF_NEG_VSS
#define ADS126X_REF_NEG_VSS
Definition
STAR_ADS126X.h:8
delay
void delay(int ms)
Definition
actuator_nc.cpp:30
ADS126X
Definition
STAR_ADS126X.h:25
adc
static STAR_MCP3201 adc(MCP3201_CS_PIN, &mcp_spi)
SensorSelfTest
Definition
SensorSelfTest.h:7
SensorSelfTest::sensor_bias_disable
void sensor_bias_disable(ADS126X &adc)
Call once after the connector loop.
Definition
SensorSelfTest.h:181
SensorSelfTest::SENSOR_BIAS_CLOSED_THRESHOLD
constexpr int32_t SENSOR_BIAS_CLOSED_THRESHOLD
Definition
SensorSelfTest.h:23
SensorSelfTest::read_sensor_bias
BiasReadResult read_sensor_bias(ADS126X &adc, uint8_t drdy_pin, uint8_t adc_channel, uint8_t aincom, uint8_t settle_cycles=5)
Read one connector with sensor bias already active.
Definition
SensorSelfTest.h:128
SensorSelfTest::SENSOR_BIAS_OPEN_THRESHOLD
constexpr int32_t SENSOR_BIAS_OPEN_THRESHOLD
Definition
SensorSelfTest.h:24
SensorSelfTest::sensor_bias_enable
void sensor_bias_enable(ADS126X &adc)
Call once before the connector loop.
Definition
SensorSelfTest.h:102
SensorSelfTest::BIAS_AVG_SAMPLES
constexpr uint8_t BIAS_AVG_SAMPLES
Definition
SensorSelfTest.h:33
SensorSelfTest::ADC_TDAC_EXPECTED_CODE
constexpr int32_t ADC_TDAC_EXPECTED_CODE
Definition
SensorSelfTest.h:13
SensorSelfTest::ADC_TDAC_TOLERANCE
constexpr int32_t ADC_TDAC_TOLERANCE
Definition
SensorSelfTest.h:14
SensorSelfTest::run_adc_self_test
AdcSelfTestResult run_adc_self_test(ADS126X &adc, uint8_t drdy_pin, uint8_t original_ref_neg, uint8_t original_ref_pos)
Definition
SensorSelfTest.h:54
SensorSelfTest::BIAS_SETTLE_MS
constexpr unsigned long BIAS_SETTLE_MS
Definition
SensorSelfTest.h:30
SensorSelfTest::BiasResult
BiasResult
Definition
SensorSelfTest.h:35
SensorSelfTest::BiasResult::AMBIGUOUS
@ AMBIGUOUS
Definition
SensorSelfTest.h:37
SensorSelfTest::BiasResult::DISCONNECTED
@ DISCONNECTED
Definition
SensorSelfTest.h:38
SensorSelfTest::BiasResult::CONNECTED
@ CONNECTED
Definition
SensorSelfTest.h:36
SensorSelfTest::AdcSelfTestResult
ADC self-test via internal TDAC.
Definition
SensorSelfTest.h:48
SensorSelfTest::AdcSelfTestResult::passed
bool passed
Definition
SensorSelfTest.h:49
SensorSelfTest::AdcSelfTestResult::code
int32_t code
Definition
SensorSelfTest.h:50
SensorSelfTest::AdcSelfTestResult::checksum_valid
bool checksum_valid
Definition
SensorSelfTest.h:51
SensorSelfTest::BiasReadResult
Definition
SensorSelfTest.h:112
SensorSelfTest::BiasReadResult::result
BiasResult result
Definition
SensorSelfTest.h:113
SensorSelfTest::BiasReadResult::checksum_valid
bool checksum_valid
Definition
SensorSelfTest.h:115
SensorSelfTest::BiasReadResult::code
int32_t code
Definition
SensorSelfTest.h:114
r
static boot_report_t r
Definition
test_boot_report.c:73
diff
static int32_t diff(uint32_t a, uint32_t b)
Definition
test_sensors_core.c:93
firmware
Hotfire_Code
common
SensorSelfTest.h
Generated by
1.15.0