Gases and part families¶
Which gas tables each part carries, why the driver needs to know the part before it starts some gases, and how the SF06 and SFx6000 families differ.
Gas tables by variant¶
A thermal flow sensor is calibrated per gas. Measuring CO2 with the air table gives a reading that is
plausible and wrong. The driver therefore refuses a gas the known variant is not calibrated for, with
DriverError::UnsupportedGas.
| Variant | Range | Calibrated gases |
|---|---|---|
| SFM4300-20-B, -O, -P | 0 to 20 slm | O2, air, N2O, CO2, air/O2, N2O/O2, CO2/O2 |
| SFM4300-50-B, -O, -P | 0 to 50 slm | O2, air, air/O2 |
| SFM3003-300-CL, -CE | -30 (CE: -150) to 300 slm | O2, air, air/O2 |
| SFM3013-300-CL | -30 to 300 slm | O2, air, air/O2 |
| SFM3013-300-CLM | -30 to 300 slm | O2, air, air/O2, HeOx 80/20, HeOx/O2 |
| SFM3019 | -10 to 240 slm | O2, air, air/O2 |
| SFM3119-240-CL | -10 to 240 slm | O2, air, air/O2 |
| SFM6000D-50, -20, -5 | 50, 20, 5 slm (air, O2) | O2, air, N2O, CO2, Ar, air/O2 |
| Unknown | O2, air |
The SF06 rows come from each part's datasheet (sections 2.1, 4.3.1 and 4.5). On the SFM3013-300-CLM the codes
0x3615 and 0x3639 select HeOx and HeOx/O2 (Gas::HeOx, Gas::HeOxO2Mix), not N2O.
sfm::SupportsGas() encodes the table; sfm::FullScaleSlm() gives the air / O2 full scale of a known
variant.
Why the part has to be known¶
The two families share the framing and most command codes, but two start codes mean different gases:
| Start code | SF06 (SFM4300, SFM3xxx) | SFx6000 (SFM6000D) |
|---|---|---|
0x3603 |
O2 | O2 |
0x3608 |
Air | Air |
0x3615 |
N2O | CO2 |
0x361E |
CO2 | N2O |
So until the driver knows the family, it starts only O2 and air, the two codes that mean the same gas
on both. Any other gas returns DriverError::VariantUnknown. Learn the part in one of two ways:
ReadProductIdentifier(), in idle mode: it decodes the variant and sets the family.AssumeVariant(), when the identifier cannot be read (the sensor is already measuring) and the board fixes the part (Configuration).
The constructor's family argument only sets the assumption used before either of those.
Never pick a start code yourself: sfm::StartCommandFor(family, gas) returns the right one, and a
static_assert in the header pins the CO2 codes of both families.
SF06 and SFx6000 compared¶
| SF06 | SFx6000 | |
|---|---|---|
| Parts | SFM4300, SFM3003, SFM3013, SFM3019, SFM3119 | SFM6000D |
| Measurement frame | flow, temperature, status | flow, reserved, status |
| Temperature | In every frame | ReadTemperature(), through an output-buffer pointer |
| Sample period | 0.5 ms | 1 ms |
| Scaling read | Three words | Five words through pointer 0xE151: adds full-scale flow and the SEMI gas ID |
| Averaging, sleep | Yes | No: ConfigureAveraging(), EnterSleep(), ExitSleep() return NotSupported |
| Soft-reset wait | 20 ms | 30 ms |
| Default address | 0x2A (SFM4300) |
0x24 |
The SFx6000 values come from Sensirion's SFC6xxx / SFM6xxx I2C interface reference (v1.1), as implemented in
inc/sfm_commands.hpp. The SFM6000D product identifiers are preliminary in that
document; the driver decodes 0x060211xx, 0x060212xx and 0x060214xx.
Other SF06 parts¶
SFM3003, SFM3013, SFM3019 and SFM3119 speak the same command set at their own addresses (sfm::addr). Pass the
part's address to the constructor (for example sfm::addr::kSfm3019); ReadProductIdentifier() then decodes the
variant from the product numbers in each datasheet:
| Product number | Variant | sfm::Variant |
Address |
|---|---|---|---|
0x040201xx |
SFM3003-300-CL | Sfm3003_300_CL |
0x28 |
0x040207xx |
SFM3003-300-CE | Sfm3003_300_CE |
0x2D |
0x040205xx |
SFM3013-300-CL | Sfm3013_300_CL |
0x2F |
0x040202xx |
SFM3013-300-CLM | Sfm3013_300_CLM |
0x2F |
0x040206xx |
SFM3019 | Sfm3019_240 |
0x2E |
0x040401xx |
SFM3119-240-CL | Sfm3119_240_CL |
0x29 |
The scale factor (170 per slm on these parts, offset -24576) is read from the sensor as on the SFM4300.
Next: API guide.