Alicat BASIS-2 Driver 1.0.0
API reference
Loading...
Searching...
No Matches
alicat_basis2_types.hpp
Go to the documentation of this file.
1
21#pragma once
22
23#include <array>
24#include <cstdint>
25#include <string_view>
26
27namespace alicat_basis2 {
28
29//==============================================================================
30// DRIVER RESULT TYPES
31//==============================================================================
32
54
56constexpr std::string_view ToString(DriverError e) noexcept {
57 switch (e) {
58 case DriverError::None: return "None";
59 case DriverError::NotInitialized: return "NotInitialized";
60 case DriverError::InvalidParameter: return "InvalidParameter";
61 case DriverError::InvalidAddress: return "InvalidAddress";
62 case DriverError::BufferTooSmall: return "BufferTooSmall";
63 case DriverError::SerialError: return "SerialError";
64 case DriverError::Timeout: return "Timeout";
65 case DriverError::BadCrc: return "BadCrc";
66 case DriverError::InvalidFrame: return "InvalidFrame";
67 case DriverError::ModbusException: return "ModbusException";
68 case DriverError::UnsupportedRequest: return "UnsupportedRequest";
69 case DriverError::ResponseMismatch: return "ResponseMismatch";
70 case DriverError::AsciiBadResponse: return "AsciiBadResponse";
71 }
72 return "?";
73}
74
82enum class ModbusExceptionCode : uint8_t {
83 None = 0x00,
84 IllegalFunction = 0x01,
85 IllegalDataAddress = 0x02,
86 IllegalDataValue = 0x03,
87 ServerDeviceFailure = 0x04,
88 Acknowledge = 0x05,
89 ServerDeviceBusy = 0x06,
90};
91
93constexpr std::string_view ToString(ModbusExceptionCode c) noexcept {
94 switch (c) {
96 return "None";
98 return "IllegalFunction";
100 return "IllegalDataAddress";
102 return "IllegalDataValue";
104 return "ServerDeviceFailure";
106 return "Acknowledge";
108 return "ServerDeviceBusy";
109 }
110 return "?";
111}
112
114template <typename T>
116 T value{};
118
119 constexpr bool ok() const noexcept { return error == DriverError::None; }
120 constexpr explicit operator bool() const noexcept { return ok(); }
121
122 static constexpr DriverResult success(T v) noexcept { return {v, DriverError::None}; }
123 static constexpr DriverResult failure(DriverError e) noexcept { return {T{}, e}; }
124};
125
126template <>
127struct DriverResult<void> {
129 constexpr bool ok() const noexcept { return error == DriverError::None; }
130 constexpr explicit operator bool() const noexcept { return ok(); }
131 static constexpr DriverResult success() noexcept { return {DriverError::None}; }
132 static constexpr DriverResult failure(DriverError e) noexcept { return {e}; }
133};
134
135//==============================================================================
136// CALIBRATED GASES (datasheet "Active Gas")
137//==============================================================================
138
145enum class Gas : uint8_t {
146 Air = 0,
147 Argon = 1,
148 CarbonDioxide = 2,
149 Nitrogen = 3,
150 Oxygen = 4,
151 NitrousOxide = 5,
152 Hydrogen = 6,
153 Helium = 7,
154 Methane = 8,
155};
156
157constexpr std::string_view GasShortName(Gas g) noexcept {
158 switch (g) {
159 case Gas::Air: return "Air";
160 case Gas::Argon: return "Ar";
161 case Gas::CarbonDioxide: return "CO2";
162 case Gas::Nitrogen: return "N2";
163 case Gas::Oxygen: return "O2";
164 case Gas::NitrousOxide: return "N2O";
165 case Gas::Hydrogen: return "H2";
166 case Gas::Helium: return "He";
167 case Gas::Methane: return "CH4";
168 }
169 return "?";
170}
171
172//==============================================================================
173// ENGINEERING UNITS (datasheet "Engineering Units")
174//==============================================================================
175
181enum class FlowUnits : uint8_t {
182 SCCM = 0, NCCM = 1, SLPM = 2, NLPM = 3,
183 SmL_s = 4, NmL_s = 5, SmL_m = 6, NmL_m = 7,
184 SL_h = 8, NL_h = 9,
185 SCCS = 10, NCCS = 11,
186 Sm3_h = 12, Nm3_h = 13,
187 Sm3_d = 14, Nm3_d = 15,
188 SCIM = 16, SCFM = 17, SCFH = 18, SCFD = 19,
189 Unknown = 0xFF,
190};
191
192constexpr std::string_view ToString(FlowUnits u) noexcept {
193 switch (u) {
194 case FlowUnits::SCCM: return "SCCM";
195 case FlowUnits::NCCM: return "NCCM";
196 case FlowUnits::SLPM: return "SLPM";
197 case FlowUnits::NLPM: return "NLPM";
198 case FlowUnits::SmL_s: return "SmL/s";
199 case FlowUnits::NmL_s: return "NmL/s";
200 case FlowUnits::SmL_m: return "SmL/m";
201 case FlowUnits::NmL_m: return "NmL/m";
202 case FlowUnits::SL_h: return "SL/h";
203 case FlowUnits::NL_h: return "NL/h";
204 case FlowUnits::SCCS: return "SCCS";
205 case FlowUnits::NCCS: return "NCCS";
206 case FlowUnits::Sm3_h: return "Sm3/h";
207 case FlowUnits::Nm3_h: return "Nm3/h";
208 case FlowUnits::Sm3_d: return "Sm3/d";
209 case FlowUnits::Nm3_d: return "Nm3/d";
210 case FlowUnits::SCIM: return "SCIM";
211 case FlowUnits::SCFM: return "SCFM";
212 case FlowUnits::SCFH: return "SCFH";
213 case FlowUnits::SCFD: return "SCFD";
214 case FlowUnits::Unknown: return "?";
215 }
216 return "?";
217}
218
219//==============================================================================
220// SERIAL CONFIGURATION
221//==============================================================================
222
230enum class BaudRate : uint8_t {
231 Bps_4800 = 0,
232 Bps_9600 = 1,
233 Bps_19200 = 2,
234 Bps_38400 = 3,
235 Bps_57600 = 4,
236 Bps_115200 = 5,
237};
238
239constexpr uint32_t BaudRateToBps(BaudRate b) noexcept {
240 switch (b) {
241 case BaudRate::Bps_4800: return 4800;
242 case BaudRate::Bps_9600: return 9600;
243 case BaudRate::Bps_19200: return 19200;
244 case BaudRate::Bps_38400: return 38400;
245 case BaudRate::Bps_57600: return 57600;
246 case BaudRate::Bps_115200: return 115200;
247 }
248 return 38400;
249}
250
263enum class SetpointSource : uint8_t {
264 Analog = 0,
265 DigitalSaved = 1,
266 DigitalUnsaved = 2,
267};
268
272enum class TotalizerLimitMode : uint8_t {
273 SaturateNoError = 0,
274 ResetNoError = 1,
275 SaturateWithOvr = 2,
276 ResetWithOvr = 3,
277};
278
285namespace MeasurementTrigger {
286constexpr uint16_t OnDigitalSetpointChange = 1U << 0;
287constexpr uint16_t OnHoldPercentChange = 1U << 1;
288constexpr uint16_t OnAverageFlowRead = 1U << 2;
289} // namespace MeasurementTrigger
290
291//==============================================================================
292// DECODED DATA FRAMES
293//==============================================================================
294
307 bool valve_held{false};
309 float temperature_c{0.0f};
310 float flow{0.0f};
311 float total_volume{0.0f};
312 float setpoint{0.0f};
313 float valve_drive_pct{0.0f};
314 float batch_remaining{0.0f};
315
317 int16_t raw_flow_2103{0};
318 int16_t raw_temp_2102{0};
321};
322
330 int16_t min_flow_raw{0};
331 int16_t max_flow_raw{0};
333 int16_t avg_flow_raw{0};
334 int32_t prev_avg_flow_raw{0};
335
336 float min_temperature_c{0.0f};
337 float max_temperature_c{0.0f};
338 float avg_temperature_c{0.0f};
339 float avg_flow{0.0f};
340
342};
343
356
369
370//==============================================================================
371// CONFIGURATION CONSTANTS
372//==============================================================================
373
374inline constexpr uint8_t kBroadcastAddress = 0;
375inline constexpr uint8_t kMaxModbusAddress = 247;
376inline constexpr uint16_t kMagicTare = 0xAA55; // register 39 / 53.
377inline constexpr uint16_t kMagicFactoryRestore = 0x5214; // register 80.
378
379inline constexpr uint16_t kDefaultTimeoutMs = 200;
383inline constexpr uint16_t kInterFrameDelayMs = 5;
386inline constexpr uint32_t kDefaultBusBaudBps = 38400;
387
388} // namespace alicat_basis2
constexpr uint16_t OnHoldPercentChange
Definition alicat_basis2_types.hpp:287
constexpr uint16_t OnDigitalSetpointChange
Definition alicat_basis2_types.hpp:286
constexpr uint16_t OnAverageFlowRead
Definition alicat_basis2_types.hpp:288
Definition alicat_basis2.hpp:52
constexpr uint8_t kBroadcastAddress
Definition alicat_basis2_types.hpp:374
constexpr uint8_t kMaxModbusAddress
Definition alicat_basis2_types.hpp:375
FlowUnits
Flow-unit identifier read from instrument register 49.
Definition alicat_basis2_types.hpp:181
BaudRate
Baud-rate codes for register 21 (datasheet "Changing the Baud Rate").
Definition alicat_basis2_types.hpp:230
@ Bps_38400
Factory default.
constexpr std::string_view GasShortName(Gas g) noexcept
Definition alicat_basis2_types.hpp:157
DriverError
Driver-level error codes.
Definition alicat_basis2_types.hpp:39
@ UnsupportedRequest
Slave does not implement this register/command.
@ InvalidFrame
Frame too short, wrong function code, etc.
@ SerialError
Serial transport-layer error (HW failure).
@ InvalidParameter
Out-of-range argument.
@ BadCrc
CRC-16 mismatch on received Modbus frame.
@ InvalidAddress
Modbus address outside 1..247.
@ None
Operation succeeded.
@ ResponseMismatch
Echo doesn't match request (function 6/16).
@ NotInitialized
Driver not initialized yet.
@ ModbusException
Slave returned a Modbus exception PDU.
@ BufferTooSmall
Provided buffer is too small for the response.
@ Timeout
No response within the configured timeout.
@ AsciiBadResponse
ASCII reply not parseable.
constexpr uint16_t kDefaultTimeoutMs
Definition alicat_basis2_types.hpp:379
constexpr uint16_t kMagicFactoryRestore
Definition alicat_basis2_types.hpp:377
SetpointSource
Setpoint source — register 516 (controllers only).
Definition alicat_basis2_types.hpp:263
constexpr uint16_t kMagicTare
Definition alicat_basis2_types.hpp:376
constexpr uint16_t kInterFrameDelayMs
Definition alicat_basis2_types.hpp:383
TotalizerLimitMode
Totalizer overflow behaviour — register 54.
Definition alicat_basis2_types.hpp:272
constexpr std::string_view ToString(DriverError e) noexcept
Convert a DriverError to a stable human-readable string (no allocation).
Definition alicat_basis2_types.hpp:56
constexpr uint32_t BaudRateToBps(BaudRate b) noexcept
Definition alicat_basis2_types.hpp:239
Gas
Index into the BASIS-2 calibrated gas table.
Definition alicat_basis2_types.hpp:145
constexpr uint32_t kDefaultBusBaudBps
Baud rate the driver assumes for the inter-frame gap until told otherwise (the instrument's factory d...
Definition alicat_basis2_types.hpp:386
ModbusExceptionCode
Exception code of a Modbus exception reply (function code | 0x80, one code byte).
Definition alicat_basis2_types.hpp:82
@ IllegalDataValue
Value not accepted.
@ ServerDeviceFailure
Unrecoverable error in the instrument.
@ None
The last transaction got no exception reply.
@ IllegalFunction
Function code not supported.
@ ServerDeviceBusy
Busy; retry later.
@ Acknowledge
Accepted, long-running.
@ IllegalDataAddress
Register not implemented ("Bad Address").
static constexpr DriverResult failure(DriverError e) noexcept
Definition alicat_basis2_types.hpp:132
static constexpr DriverResult success() noexcept
Definition alicat_basis2_types.hpp:131
constexpr bool ok() const noexcept
Definition alicat_basis2_types.hpp:129
Lightweight result wrapper. Aborts on value() if !ok().
Definition alicat_basis2_types.hpp:115
T value
Definition alicat_basis2_types.hpp:116
DriverError error
Definition alicat_basis2_types.hpp:117
static constexpr DriverResult success(T v) noexcept
Definition alicat_basis2_types.hpp:122
constexpr bool ok() const noexcept
Definition alicat_basis2_types.hpp:119
static constexpr DriverResult failure(DriverError e) noexcept
Definition alicat_basis2_types.hpp:123
Decoded snapshot of registers 2100..2109 (one Modbus burst).
Definition alicat_basis2_types.hpp:302
float temperature_c
Register 2102 / 100.
Definition alicat_basis2_types.hpp:309
bool valve_thermal_management
VTM.
Definition alicat_basis2_types.hpp:308
bool valve_held
HLD.
Definition alicat_basis2_types.hpp:307
int16_t raw_flow_2103
Definition alicat_basis2_types.hpp:317
bool temperature_overrange
TOV.
Definition alicat_basis2_types.hpp:305
float flow
Register 2103 (× scale below).
Definition alicat_basis2_types.hpp:310
int32_t raw_setpoint_2053_2054
Definition alicat_basis2_types.hpp:316
float setpoint
Register 2106 (× scale below).
Definition alicat_basis2_types.hpp:312
uint32_t raw_total_volume_2104_2105
Definition alicat_basis2_types.hpp:319
int16_t raw_temp_2102
Definition alicat_basis2_types.hpp:318
uint32_t raw_batch_remaining_2108_2109
Definition alicat_basis2_types.hpp:320
bool totalizer_overrange
OVR.
Definition alicat_basis2_types.hpp:306
float valve_drive_pct
Register 2107 / 100.
Definition alicat_basis2_types.hpp:313
bool mass_flow_overrange
MOV.
Definition alicat_basis2_types.hpp:304
float batch_remaining
Registers 2108-9 (× scale below).
Definition alicat_basis2_types.hpp:314
Gas gas
Definition alicat_basis2_types.hpp:303
float total_volume
Registers 2104-5 (× scale below).
Definition alicat_basis2_types.hpp:311
Static identification of an instrument (read once at init).
Definition alicat_basis2_types.hpp:347
char serial_number[13]
Registers 26-31 (12 chars + NUL).
Definition alicat_basis2_types.hpp:350
char ascii_unit_id
Register 46.
Definition alicat_basis2_types.hpp:352
uint8_t fw_minor
Definition alicat_basis2_types.hpp:349
FlowUnits flow_units
Definition alicat_basis2_types.hpp:353
uint16_t firmware_version_raw
Register 25 — pack(a,b,c) = 256a + 16b + c.
Definition alicat_basis2_types.hpp:348
uint32_t full_scale_flow_raw
Registers 47-48; flow_units / 1000.
Definition alicat_basis2_types.hpp:354
uint8_t fw_major
Definition alicat_basis2_types.hpp:349
uint8_t fw_patch
Definition alicat_basis2_types.hpp:349
uint8_t modbus_address
Register 45.
Definition alicat_basis2_types.hpp:351
Carries the global instrument health derived from InstantaneousData.
Definition alicat_basis2_types.hpp:358
bool mass_flow_overrange
Definition alicat_basis2_types.hpp:363
bool temperature_overrange
Definition alicat_basis2_types.hpp:364
bool any_error() const noexcept
Definition alicat_basis2_types.hpp:359
bool valve_thermal_management
Definition alicat_basis2_types.hpp:367
bool totalizer_overrange
Definition alicat_basis2_types.hpp:365
bool valve_held
Definition alicat_basis2_types.hpp:366
Decoded measurement-window result (registers 4201..4215).
Definition alicat_basis2_types.hpp:326
float avg_flow
avg_flow_raw / 10^flow_decimals.
Definition alicat_basis2_types.hpp:339
int16_t min_flow_raw
Definition alicat_basis2_types.hpp:330
int16_t max_temperature_raw
Definition alicat_basis2_types.hpp:329
uint16_t num_samples_requested
Register 4201: samples to take.
Definition alicat_basis2_types.hpp:341
int16_t avg_flow_raw
Definition alicat_basis2_types.hpp:333
int16_t min_temperature_raw
Definition alicat_basis2_types.hpp:328
int32_t prev_avg_flow_raw
Registers 4214-4215, signed 32-bit.
Definition alicat_basis2_types.hpp:334
int16_t avg_temperature_raw
Definition alicat_basis2_types.hpp:332
float min_temperature_c
Definition alicat_basis2_types.hpp:336
uint16_t num_samples_collected
Register 4206: samples averaged so far.
Definition alicat_basis2_types.hpp:327
float max_temperature_c
Definition alicat_basis2_types.hpp:337
float avg_temperature_c
Definition alicat_basis2_types.hpp:338
int16_t max_flow_raw
Definition alicat_basis2_types.hpp:331