STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
PTCalibration.hpp
Go to the documentation of this file.
1#ifndef PT_CALIBRATION_HPP
2#define PT_CALIBRATION_HPP
3
4#include <array>
5#include <cstdint>
6#include <map>
7#include <optional>
8#include <string>
9
10namespace fsw {
11namespace calibration {
12
13/**
14 * @brief PT Calibration Coefficients
15 *
16 * Cubic polynomial: psi = A * (adc^3) + B * (adc^2) + C * adc + D
17 */
19 double A; // Coefficient for adc^3
20 double B; // Coefficient for adc^2
21 double C; // Coefficient for adc
22 double D; // Constant term
23
24 PTCalibrationCoeffs() : A(0.0), B(0.0), C(0.0), D(0.0) {
25 }
26 PTCalibrationCoeffs(double a, double b, double c, double d) : A(a), B(b), C(c), D(d) {
27 }
28
29 /**
30 * @brief Calculate pressure (psi) from ADC code
31 * @param adc_code Raw ADC code (32-bit signed integer)
32 * @return Calibrated pressure in PSI
33 */
34 double calculate_pressure(int32_t adc_code) const {
35 double adc = static_cast<double>(adc_code);
36 return (A * adc * adc * adc) + (B * adc * adc) + (C * adc) + D;
37 }
38
39 /**
40 * @brief Invert psi = A*x^3 + B*x^2 + C*x + D to find ADC code for target PSI
41 * @param target_psi Target pressure in PSI
42 * @return ADC code, or nullopt if out of range
43 */
44 std::optional<int32_t> invert_to_adc(double target_psi) const;
45};
46
47/**
48 * PT board slot (1–10, from board_id % 10 with 0→10) + local connector (1–10) → factory/JSON
49 * logical channel index (slot 1 → 1..10, slot 2 → 11..20, …). Same rule as calibration_service.
50 */
51inline uint8_t pt_logical_calibration_channel(uint8_t board_slot_number, uint8_t local_connector) {
52 if (local_connector == 0 || local_connector > 10)
53 return local_connector;
54 const int idx =
55 (static_cast<int>(board_slot_number) - 1) * 10 + static_cast<int>(local_connector);
56 if (idx < 1 || idx > 255)
57 return local_connector;
58 return static_cast<uint8_t>(idx);
59}
60
61/**
62 * @brief PT Calibration Manager
63 *
64 * Loads and manages PT calibration coefficients from JSON or CSV files.
65 * Provides calibrated pressure values for sensor channels.
66 */
68public:
69 // auto_load=false constructs with NO calibration (used by the physics-or-nothing calibration
70 // service, which applies only operator cubics from the store / an explicit bench-cal import).
71 explicit PTCalibrationManager(bool auto_load = true);
73
74 /**
75 * @brief Load calibration from JSON file (from calibration GUI)
76 * @param json_path Path to JSON calibration file
77 * @param merge_missing_only If true, only add channels not already present after CSV; if false,
78 * every channel in JSON overwrites the same logical key (GUI per-connector calibration).
79 * @return true if at least one channel was loaded/merged
80 */
81 bool load_from_json(const std::string& json_path, bool merge_missing_only = false);
82
83 /**
84 * @brief Load calibration from CSV file (from DiabloAvionics)
85 * @param csv_path Path to CSV calibration file
86 * @return true if loaded successfully
87 */
88 bool load_from_csv(const std::string& csv_path);
89
90 /**
91 * @brief Auto-load calibration from default paths
92 * Default: factory CSV first, then newest GUI JSON overlays every channel it lists (fixes CSV
93 * PT6≠GN2 ch6). CAL_PT_JSON_MISSING_ONLY=1 — JSON only fills gaps (legacy). CAL_PT_JSON_FIRST=1
94 * — JSON only, then CSV.
95 * @return true if any calibration was loaded
96 */
97 bool load_calibration();
98
99 /**
100 * @brief Get calibration coefficients for a sensor channel
101 * @param channel_id Sensor channel ID (1-indexed)
102 * @return Calibration coefficients if available, nullptr otherwise
103 */
104 const PTCalibrationCoeffs* get_calibration(uint8_t channel_id) const;
105
106 /**
107 * @brief Check if a channel has calibration
108 * @param channel_id Sensor channel ID
109 * @return true if calibrated
110 */
111 bool is_calibrated(uint8_t channel_id) const;
112
113 /**
114 * @brief Calculate calibrated pressure for a channel
115 * @param channel_id Sensor channel ID
116 * @param adc_code Raw ADC code
117 * @return Calibrated pressure in PSI, or 0.0 if not calibrated
118 */
119 double calculate_pressure(uint8_t channel_id, int32_t adc_code) const;
120
121 /**
122 * @brief Get number of calibrated channels
123 */
124 size_t get_calibrated_count() const {
125 return calibrations_.size();
126 }
127
128 /**
129 * @brief Set/replace the cubic coefficients for a logical channel at runtime.
130 *
131 * Used by the calibration service when an operator builds a cubic live from captured reference
132 * points — the new fit takes effect immediately on the streaming path (which evaluates these
133 * coefficients per packet). @param channel_id is the logical calibration channel
134 * (pt_logical_calibration_channel), not a board-local connector.
135 */
136 void set_calibration(uint8_t channel_id, const PTCalibrationCoeffs& coeffs);
137
138 /**
139 * @brief Remove any cubic for a logical channel, so is_calibrated() returns false again.
140 *
141 * Used by the calibration service's "clear" so a cleared/uncalibrated cubic sensor streams
142 * nothing (0) rather than reverting to a factory/baseline curve.
143 */
144 void clear_calibration(uint8_t channel_id);
145
146 /**
147 * @brief Set default calibration file paths
148 */
149 static void set_default_paths(const std::string& json_dir, const std::string& csv_path);
150
151private:
152 // Map: channel_id -> calibration coefficients
153 std::map<uint8_t, PTCalibrationCoeffs> calibrations_;
154
155 // Default paths
156 static std::string default_json_dir_;
157 static std::string default_csv_path_;
158
159 // Helper methods
160 bool parse_json_file(const std::string& json_path);
161 bool parse_csv_file(const std::string& csv_path);
162 std::string find_latest_json_file(const std::string& json_dir) const;
163};
164
165} // namespace calibration
166} // namespace fsw
167
168#endif // PT_CALIBRATION_HPP
std::string find_latest_json_file(const std::string &json_dir) const
bool parse_csv_file(const std::string &csv_path)
bool load_calibration()
Auto-load calibration from default paths Default: factory CSV first, then newest GUI JSON overlays ev...
size_t get_calibrated_count() const
Get number of calibrated channels.
bool load_from_json(const std::string &json_path, bool merge_missing_only=false)
Load calibration from JSON file (from calibration GUI).
void set_calibration(uint8_t channel_id, const PTCalibrationCoeffs &coeffs)
Set/replace the cubic coefficients for a logical channel at runtime.
bool parse_json_file(const std::string &json_path)
std::map< uint8_t, PTCalibrationCoeffs > calibrations_
bool is_calibrated(uint8_t channel_id) const
Check if a channel has calibration.
double calculate_pressure(uint8_t channel_id, int32_t adc_code) const
Calculate calibrated pressure for a channel.
void clear_calibration(uint8_t channel_id)
Remove any cubic for a logical channel, so is_calibrated() returns false again.
bool load_from_csv(const std::string &csv_path)
Load calibration from CSV file (from DiabloAvionics).
const PTCalibrationCoeffs * get_calibration(uint8_t channel_id) const
Get calibration coefficients for a sensor channel.
static void set_default_paths(const std::string &json_dir, const std::string &csv_path)
Set default calibration file paths.
static STAR_MCP3201 adc(MCP3201_CS_PIN, &mcp_spi)
*brief create JSON pointer *sa reference_tokens const string_t const string_t & b
Definition json.hpp:13878
*brief create JSON pointer *sa reference_tokens const string_t & a
Definition json.hpp:13877
Output smoothing for calibrated PT pressure, per sensor uid (ESP32 and LabJack T7 alike).
uint8_t pt_logical_calibration_channel(uint8_t board_slot_number, uint8_t local_connector)
PT board slot (1–10, from board_id % 10 with 0→10) + local connector (1–10) → factory/JSON logical ch...
Motorized ball valve position: raw ADC counts -> % open.
PT Calibration Coefficients.
std::optional< int32_t > invert_to_adc(double target_psi) const
Invert psi = A*x^3 + B*x^2 + C*x + D to find ADC code for target PSI.
double calculate_pressure(int32_t adc_code) const
Calculate pressure (psi) from ADC code.
PTCalibrationCoeffs(double a, double b, double c, double d)