pamoja.sensors
Idiomatic sensor-driver facade.
These are the decode half of eleven parts a field node is likely to have wired to
it, turning the register bytes a bus driver read into the physical reading the
manufacturer's datasheet says they mean. The BME280 also has a driver, which runs
the datasheet's whole conversation over an I2cBus from pamoja.hal, and a
simulated part that answers it with nothing plugged in.
1"""Idiomatic sensor-driver facade. 2 3These are the decode half of eleven parts a field node is likely to have wired to 4it, turning the register bytes a bus driver read into the physical reading the 5manufacturer's datasheet says they mean. The BME280 also has a driver, which runs 6the datasheet's whole conversation over an `I2cBus` from :mod:`pamoja.hal`, and a 7simulated part that answers it with nothing plugged in. 8""" 9 10from __future__ import annotations 11 12import enum 13from typing import List, Optional 14 15from pamoja.hal import CommandPart, I2cBus, I2cPart, WordPart 16 17from pamoja._native import Ads1115Config, Bme280Calibration, Bme280Measurement, Ds18b20Reading 18from pamoja._native import Bme280 as _NativeBme280 19from pamoja._native import Bme280Config, Bme280CtrlMeas 20from pamoja._native import bme280_config_bits as _bme280_config_bits 21from pamoja._native import bme280_config_from_bits as _bme280_config_from_bits 22from pamoja._native import bme280_ctrl_hum_bits as _bme280_ctrl_hum_bits 23from pamoja._native import bme280_ctrl_hum_from_bits as _bme280_ctrl_hum_from_bits 24from pamoja._native import bme280_ctrl_meas_bits as _bme280_ctrl_meas_bits 25from pamoja._native import bme280_ctrl_meas_from_bits as _bme280_ctrl_meas_from_bits 26from pamoja._native import bme280_filter_coefficient as _bme280_filter_coefficient 27from pamoja._native import bme280_image_updating as _bme280_image_updating 28from pamoja._native import bme280_max_measurement_micros as _bme280_max_measurement_micros 29from pamoja._native import bme280_measuring as _bme280_measuring 30from pamoja._native import bme280_oversampling_factor as _bme280_oversampling_factor 31from pamoja._native import bme280_sim_burst as _bme280_sim_burst 32from pamoja._native import bme280_sim_burst_for as _bme280_sim_burst_for 33from pamoja._native import bme280_sim_calibration as _bme280_sim_calibration 34from pamoja._native import ( 35 bme280_sim_calibration_humidity as _bme280_sim_calibration_humidity, 36) 37from pamoja._native import bme280_sim_part as _bme280_sim_part 38from pamoja._native import bme280_sim_reporting as _bme280_sim_reporting 39from pamoja._native import bme280_standby_micros as _bme280_standby_micros 40from pamoja._native import ( 41 bme280_typical_measurement_micros as _bme280_typical_measurement_micros, 42) 43from pamoja._native import ads1115_config_bits as _ads1115_config_bits 44from pamoja._native import ads1115_config_from_bits as _ads1115_config_from_bits 45from pamoja._native import ads1115_full_scale_microvolts as _ads1115_full_scale_microvolts 46from pamoja._native import ads1115_samples_per_second as _ads1115_samples_per_second 47from pamoja._native import ads1115_to_nanovolts as _ads1115_to_nanovolts 48from pamoja._native import ads1115_to_volts as _ads1115_to_volts 49from pamoja._native import ds18b20_build_scratchpad as _ds18b20_build_scratchpad 50from pamoja._native import ds18b20_celsius as _ds18b20_celsius 51from pamoja._native import ds18b20_config_byte as _ds18b20_config_byte 52from pamoja._native import ds18b20_crc8 as _ds18b20_crc8 53from pamoja._native import ds18b20_max_conversion_micros as _ds18b20_max_conversion_micros 54from pamoja._native import ds18b20_micro_celsius as _ds18b20_micro_celsius 55from pamoja._native import ds18b20_parse_scratchpad as _ds18b20_parse_scratchpad 56from pamoja._native import ds18b20_resolution_bits as _ds18b20_resolution_bits 57from pamoja._native import ds18b20_step_micro_celsius as _ds18b20_step_micro_celsius 58from pamoja._native import ina219_bus_register as _ina219_bus_register 59from pamoja._native import ina219_current_register as _ina219_current_register 60from pamoja._native import ina219_power_register as _ina219_power_register 61from pamoja._native import ina219_shunt_register as _ina219_shunt_register 62from pamoja._native import ina219_bus_millivolts as _ina219_bus_millivolts 63from pamoja._native import ina219_calibration as _ina219_calibration 64from pamoja._native import ina219_conversion_ready as _ina219_conversion_ready 65from pamoja._native import ina219_current_microamps as _ina219_current_microamps 66from pamoja._native import ina219_math_overflow as _ina219_math_overflow 67from pamoja._native import ( 68 ina219_minimum_current_lsb_microamps as _ina219_minimum_current_lsb_microamps, 69) 70from pamoja._native import ina219_power_microwatts as _ina219_power_microwatts 71from pamoja._native import ina219_shunt_microvolts as _ina219_shunt_microvolts 72from pamoja._native import ( 73 Bmp280Calibration, 74 Bmp280Coefficients, 75 Bmp280Config, 76 Bmp280CtrlMeas, 77 Bmp280RawMeasurement, 78 Bmp280Reading, 79 Hdc1080Config, 80 Hdc1080Measurement, 81 Ina226Config, 82 Ina226DieId, 83 Ina226MaskEnable, 84 Opt3001Config, 85 Scd4xMeasurement, 86 Sht3xMeasurement, 87 Sht3xStatus, 88 Tmp117Config, 89) 90from pamoja._native import bmp280_config_bits as _bmp280_config_bits 91from pamoja._native import bmp280_config_from_bits as _bmp280_config_from_bits 92from pamoja._native import bmp280_ctrl_meas_bits as _bmp280_ctrl_meas_bits 93from pamoja._native import bmp280_ctrl_meas_from_bits as _bmp280_ctrl_meas_from_bits 94from pamoja._native import bmp280_image_updating as _bmp280_image_updating 95from pamoja._native import bmp280_measurement_bytes as _bmp280_measurement_bytes 96from pamoja._native import bmp280_measuring as _bmp280_measuring 97from pamoja._native import bmp280_oversampling_factor as _bmp280_oversampling_factor 98from pamoja._native import bmp280_parse_measurement as _bmp280_parse_measurement 99from pamoja._native import bmp280_pressure_skipped as _bmp280_pressure_skipped 100from pamoja._native import bmp280_standby_micros as _bmp280_standby_micros 101from pamoja._native import bmp280_temperature_skipped as _bmp280_temperature_skipped 102from pamoja._native import hdc1080_celsius as _hdc1080_celsius 103from pamoja._native import hdc1080_config_from_register as _hdc1080_config_from_register 104from pamoja._native import hdc1080_config_to_register as _hdc1080_config_to_register 105from pamoja._native import hdc1080_conversion_time_micros as _hdc1080_conversion_time_micros 106from pamoja._native import ( 107 hdc1080_humidity_conversion_micros as _hdc1080_humidity_conversion_micros, 108) 109from pamoja._native import hdc1080_humidity_register as _hdc1080_humidity_register 110from pamoja._native import hdc1080_measurement_bytes as _hdc1080_measurement_bytes 111from pamoja._native import hdc1080_measurement_from_physical as _hdc1080_measurement_from_physical 112from pamoja._native import hdc1080_milli_celsius as _hdc1080_milli_celsius 113from pamoja._native import hdc1080_milli_percent as _hdc1080_milli_percent 114from pamoja._native import hdc1080_parse_measurement as _hdc1080_parse_measurement 115from pamoja._native import hdc1080_relative_humidity as _hdc1080_relative_humidity 116from pamoja._native import hdc1080_serial_id as _hdc1080_serial_id 117from pamoja._native import hdc1080_serial_id_registers as _hdc1080_serial_id_registers 118from pamoja._native import ( 119 hdc1080_temperature_conversion_micros as _hdc1080_temperature_conversion_micros, 120) 121from pamoja._native import hdc1080_temperature_register as _hdc1080_temperature_register 122from pamoja._native import ina226_active_alert_function as _ina226_active_alert_function 123from pamoja._native import ina226_address as _ina226_address 124from pamoja._native import ina226_averaging_samples as _ina226_averaging_samples 125from pamoja._native import ina226_bus_microvolts as _ina226_bus_microvolts 126from pamoja._native import ina226_bus_register as _ina226_bus_register 127from pamoja._native import ina226_bus_volts as _ina226_bus_volts 128from pamoja._native import ina226_calibration as _ina226_calibration 129from pamoja._native import ina226_config_from_register as _ina226_config_from_register 130from pamoja._native import ina226_config_to_register as _ina226_config_to_register 131from pamoja._native import ina226_conversion_micros as _ina226_conversion_micros 132from pamoja._native import ina226_current_amps as _ina226_current_amps 133from pamoja._native import ina226_current_microamps as _ina226_current_microamps 134from pamoja._native import ina226_current_register as _ina226_current_register 135from pamoja._native import ( 136 ina226_current_register_from_shunt as _ina226_current_register_from_shunt, 137) 138from pamoja._native import ina226_die_id as _ina226_die_id 139from pamoja._native import ina226_identify as _ina226_identify 140from pamoja._native import ina226_is_continuous as _ina226_is_continuous 141from pamoja._native import ina226_mask_enable_from_register as _ina226_mask_enable_from_register 142from pamoja._native import ina226_mask_enable_to_register as _ina226_mask_enable_to_register 143from pamoja._native import ina226_measures_bus as _ina226_measures_bus 144from pamoja._native import ina226_measures_shunt as _ina226_measures_shunt 145from pamoja._native import ( 146 ina226_minimum_current_lsb_microamps as _ina226_minimum_current_lsb_microamps, 147) 148from pamoja._native import ina226_power_microwatts as _ina226_power_microwatts 149from pamoja._native import ina226_power_register as _ina226_power_register 150from pamoja._native import ( 151 ina226_power_register_from_current as _ina226_power_register_from_current, 152) 153from pamoja._native import ina226_power_watts as _ina226_power_watts 154from pamoja._native import ina226_shunt_millivolts as _ina226_shunt_millivolts 155from pamoja._native import ina226_shunt_nanovolts as _ina226_shunt_nanovolts 156from pamoja._native import ina226_shunt_register as _ina226_shunt_register 157from pamoja._native import ina226_update_micros as _ina226_update_micros 158from pamoja._native import opt3001_config_bits as _opt3001_config_bits 159from pamoja._native import opt3001_config_from_bits as _opt3001_config_from_bits 160from pamoja._native import opt3001_conversion_millis as _opt3001_conversion_millis 161from pamoja._native import opt3001_fault_count as _opt3001_fault_count 162from pamoja._native import opt3001_full_scale_milli_lux as _opt3001_full_scale_milli_lux 163from pamoja._native import opt3001_is_automatic_range as _opt3001_is_automatic_range 164from pamoja._native import opt3001_lsb_milli_lux as _opt3001_lsb_milli_lux 165from pamoja._native import opt3001_lux as _opt3001_lux 166from pamoja._native import opt3001_milli_lux as _opt3001_milli_lux 167from pamoja._native import opt3001_raw_from_milli_lux as _opt3001_raw_from_milli_lux 168from pamoja._native import opt3001_word_from_bytes as _opt3001_word_from_bytes 169from pamoja._native import opt3001_word_to_bytes as _opt3001_word_to_bytes 170from pamoja._native import scd4x_allowed_during_measurement as _scd4x_allowed_during_measurement 171from pamoja._native import scd4x_ambient_pressure_pascals as _scd4x_ambient_pressure_pascals 172from pamoja._native import scd4x_ambient_pressure_word as _scd4x_ambient_pressure_word 173from pamoja._native import ( 174 scd4x_automatic_self_calibration_enabled as _scd4x_automatic_self_calibration_enabled, 175) 176from pamoja._native import ( 177 scd4x_automatic_self_calibration_word as _scd4x_automatic_self_calibration_word, 178) 179from pamoja._native import scd4x_celsius as _scd4x_celsius 180from pamoja._native import scd4x_command_frame as _scd4x_command_frame 181from pamoja._native import scd4x_crc as _scd4x_crc 182from pamoja._native import scd4x_data_ready as _scd4x_data_ready 183from pamoja._native import ( 184 scd4x_forced_recalibration_correction_ppm as _scd4x_forced_recalibration_correction_ppm, 185) 186from pamoja._native import scd4x_forced_recalibration_word as _scd4x_forced_recalibration_word 187from pamoja._native import scd4x_humidity_milli_percent as _scd4x_humidity_milli_percent 188from pamoja._native import scd4x_humidity_raw as _scd4x_humidity_raw 189from pamoja._native import scd4x_max_duration_ms as _scd4x_max_duration_ms 190from pamoja._native import scd4x_measurement_bytes as _scd4x_measurement_bytes 191from pamoja._native import scd4x_measurement_from_physical as _scd4x_measurement_from_physical 192from pamoja._native import scd4x_milli_celsius as _scd4x_milli_celsius 193from pamoja._native import scd4x_parse_measurement as _scd4x_parse_measurement 194from pamoja._native import scd4x_relative_humidity_percent as _scd4x_relative_humidity_percent 195from pamoja._native import scd4x_self_test_passed as _scd4x_self_test_passed 196from pamoja._native import scd4x_serial_number as _scd4x_serial_number 197from pamoja._native import scd4x_serial_number_frame as _scd4x_serial_number_frame 198from pamoja._native import ( 199 scd4x_temperature_offset_milli_celsius as _scd4x_temperature_offset_milli_celsius, 200) 201from pamoja._native import scd4x_temperature_offset_word as _scd4x_temperature_offset_word 202from pamoja._native import scd4x_temperature_raw as _scd4x_temperature_raw 203from pamoja._native import scd4x_word as _scd4x_word 204from pamoja._native import scd4x_word_frame as _scd4x_word_frame 205from pamoja._native import scd4x_write_frame as _scd4x_write_frame 206from pamoja._native import sht3x_celsius as _sht3x_celsius 207from pamoja._native import sht3x_crc as _sht3x_crc 208from pamoja._native import sht3x_fahrenheit as _sht3x_fahrenheit 209from pamoja._native import ( 210 sht3x_humidity_raw_from_milli_percent as _sht3x_humidity_raw_from_milli_percent, 211) 212from pamoja._native import ( 213 sht3x_humidity_raw_from_relative_humidity as _sht3x_humidity_raw_from_relative_humidity, 214) 215from pamoja._native import sht3x_interval_micros as _sht3x_interval_micros 216from pamoja._native import sht3x_max_measurement_micros as _sht3x_max_measurement_micros 217from pamoja._native import sht3x_measurement_bytes as _sht3x_measurement_bytes 218from pamoja._native import sht3x_milli_celsius as _sht3x_milli_celsius 219from pamoja._native import sht3x_milli_fahrenheit as _sht3x_milli_fahrenheit 220from pamoja._native import sht3x_milli_percent as _sht3x_milli_percent 221from pamoja._native import sht3x_parse_measurement as _sht3x_parse_measurement 222from pamoja._native import sht3x_parse_status as _sht3x_parse_status 223from pamoja._native import sht3x_periodic as _sht3x_periodic 224from pamoja._native import sht3x_relative_humidity as _sht3x_relative_humidity 225from pamoja._native import sht3x_single_shot as _sht3x_single_shot 226from pamoja._native import sht3x_status_bytes as _sht3x_status_bytes 227from pamoja._native import sht3x_status_from_bits as _sht3x_status_from_bits 228from pamoja._native import ( 229 sht3x_temperature_raw_from_celsius as _sht3x_temperature_raw_from_celsius, 230) 231from pamoja._native import ( 232 sht3x_temperature_raw_from_milli_celsius as _sht3x_temperature_raw_from_milli_celsius, 233) 234from pamoja._native import ( 235 sht3x_temperature_raw_from_milli_fahrenheit as _sht3x_temperature_raw_from_milli_fahrenheit, 236) 237from pamoja._native import sht3x_typical_measurement_micros as _sht3x_typical_measurement_micros 238from pamoja._native import sht3x_word as _sht3x_word 239from pamoja._native import sht3x_word_bytes as _sht3x_word_bytes 240from pamoja._native import tmp117_averaging_conversions as _tmp117_averaging_conversions 241from pamoja._native import tmp117_averaging_micros as _tmp117_averaging_micros 242from pamoja._native import tmp117_celsius as _tmp117_celsius 243from pamoja._native import tmp117_config_bits as _tmp117_config_bits 244from pamoja._native import tmp117_config_from_bits as _tmp117_config_from_bits 245from pamoja._native import tmp117_cycle_micros as _tmp117_cycle_micros 246from pamoja._native import tmp117_cycle_nominal_micros as _tmp117_cycle_nominal_micros 247from pamoja._native import tmp117_data_ready as _tmp117_data_ready 248from pamoja._native import tmp117_device_id as _tmp117_device_id 249from pamoja._native import tmp117_eeprom_busy as _tmp117_eeprom_busy 250from pamoja._native import tmp117_eeprom_unlock_busy as _tmp117_eeprom_unlock_busy 251from pamoja._native import tmp117_high_alert as _tmp117_high_alert 252from pamoja._native import tmp117_low_alert as _tmp117_low_alert 253from pamoja._native import tmp117_micro_celsius as _tmp117_micro_celsius 254from pamoja._native import tmp117_nano_celsius as _tmp117_nano_celsius 255from pamoja._native import tmp117_raw_from_celsius as _tmp117_raw_from_celsius 256from pamoja._native import tmp117_raw_from_micro_celsius as _tmp117_raw_from_micro_celsius 257from pamoja._native import tmp117_revision as _tmp117_revision 258from pamoja._native import tmp117_temperature_bytes as _tmp117_temperature_bytes 259from pamoja._native import tmp117_temperature_from_bytes as _tmp117_temperature_from_bytes 260from pamoja._native import Ads1115 as _NativeAds1115 261from pamoja._native import Ads1115Sample, Ina219Config, Ina219Reading, Ina226Reading 262from pamoja._native import Bmp280 as _NativeBmp280 263from pamoja._native import Ds18b20Thermometer as _NativeDs18b20Thermometer 264from pamoja._native import Hdc1080 as _NativeHdc1080 265from pamoja._native import Ina219 as _NativeIna219 266from pamoja._native import Ina226 as _NativeIna226 267from pamoja._native import Opt3001 as _NativeOpt3001 268from pamoja._native import Opt3001Reading, Tmp117Alerts, Tmp117Reading 269from pamoja._native import Scd4x as _NativeScd4x 270from pamoja._native import Sht3x as _NativeSht3x 271from pamoja._native import Tmp117 as _NativeTmp117 272from pamoja._native import ads1115_conversion_micros as _ads1115_conversion_micros 273from pamoja._native import ads1115_sim_part as _ads1115_sim_part 274from pamoja._native import ads1115_sim_reporting as _ads1115_sim_reporting 275from pamoja._native import bmp280_sim_burst as _bmp280_sim_burst 276from pamoja._native import bmp280_sim_burst_for as _bmp280_sim_burst_for 277from pamoja._native import bmp280_sim_calibration as _bmp280_sim_calibration 278from pamoja._native import bmp280_sim_part as _bmp280_sim_part 279from pamoja._native import bmp280_sim_reporting as _bmp280_sim_reporting 280from pamoja._native import ds18b20_parse_w1_slave as _ds18b20_parse_w1_slave 281from pamoja._native import ds18b20_w1_slave_text as _ds18b20_w1_slave_text 282from pamoja._native import hdc1080_sim_part as _hdc1080_sim_part 283from pamoja._native import hdc1080_sim_reporting as _hdc1080_sim_reporting 284from pamoja._native import ina219_adc_conversion_micros as _ina219_adc_conversion_micros 285from pamoja._native import ina219_address as _ina219_address 286from pamoja._native import ina219_config_bits as _ina219_config_bits 287from pamoja._native import ina219_config_from_bits as _ina219_config_from_bits 288from pamoja._native import ina219_conversion_micros as _ina219_conversion_micros 289from pamoja._native import ina219_gain_range_millivolts as _ina219_gain_range_millivolts 290from pamoja._native import ina219_sim_part as _ina219_sim_part 291from pamoja._native import ina219_sim_reporting as _ina219_sim_reporting 292from pamoja._native import ina226_sim_part as _ina226_sim_part 293from pamoja._native import ina226_sim_reporting as _ina226_sim_reporting 294from pamoja._native import opt3001_sim_part as _opt3001_sim_part 295from pamoja._native import opt3001_sim_reporting as _opt3001_sim_reporting 296from pamoja._native import scd4x_sim_part as _scd4x_sim_part 297from pamoja._native import scd4x_sim_reporting as _scd4x_sim_reporting 298from pamoja._native import sht3x_sim_part as _sht3x_sim_part 299from pamoja._native import sht3x_sim_reporting as _sht3x_sim_reporting 300from pamoja._native import tmp117_sim_part as _tmp117_sim_part 301from pamoja._native import tmp117_sim_reporting as _tmp117_sim_reporting 302 303__all__ = [ 304 "Ads1115", 305 "Ads1115Config", 306 "Ads1115DataRate", 307 "Ads1115Mux", 308 "Ads1115Pga", 309 "Ads1115Sample", 310 "Bme280", 311 "Bme280Calibration", 312 "Bme280Config", 313 "Bme280CtrlMeas", 314 "Bme280Filter", 315 "Bme280Measurement", 316 "Bme280Mode", 317 "Bme280Oversampling", 318 "Bme280Standby", 319 "Bmp280", 320 "Bmp280Calibration", 321 "Bmp280Coefficients", 322 "Bmp280Config", 323 "Bmp280CtrlMeas", 324 "Bmp280Oversampling", 325 "Bmp280RawMeasurement", 326 "Bmp280Reading", 327 "Ds18b20Reading", 328 "Ds18b20Thermometer", 329 "Hdc1080", 330 "Hdc1080Config", 331 "Hdc1080HumidityResolution", 332 "Hdc1080Measurement", 333 "Hdc1080TemperatureResolution", 334 "Ina219", 335 "Ina219Adc", 336 "Ina219BusRange", 337 "Ina219Config", 338 "Ina219Gain", 339 "Ina219Mode", 340 "Ina219Reading", 341 "Ina226", 342 "Ina226AlertFunction", 343 "Ina226Averaging", 344 "Ina226Config", 345 "Ina226ConversionTime", 346 "Ina226DieId", 347 "Ina226Mode", 348 "Ina226MaskEnable", 349 "Ina226Reading", 350 "Opt3001", 351 "Opt3001Config", 352 "Opt3001ConversionTime", 353 "Opt3001Reading", 354 "Scd4x", 355 "Scd4xMeasurement", 356 "Sht3x", 357 "Sht3xMeasurement", 358 "Sht3xRate", 359 "Sht3xRepeatability", 360 "Sht3xStatus", 361 "Tmp117", 362 "Tmp117Alerts", 363 "Tmp117Averaging", 364 "Tmp117Config", 365 "Tmp117Reading", 366 "ads1115", 367 "bme280", 368 "bmp280", 369 "ds18b20", 370 "hdc1080", 371 "ina219", 372 "ina226", 373 "opt3001", 374 "scd4x", 375 "sht3x", 376 "tmp117", 377] 378 379 380class Bme280Oversampling(enum.IntEnum): 381 """How many samples a BME280 measurement averages, as its register code.""" 382 383 #: The measurement is skipped. 384 SKIPPED = 0 385 #: One sample. 386 X1 = 1 387 #: Two samples. 388 X2 = 2 389 #: Four samples. 390 X4 = 3 391 #: Eight samples. 392 X8 = 4 393 #: Sixteen samples. 394 X16 = 5 395 396 397class Bme280Mode(enum.IntEnum): 398 """A BME280 power mode, as its register code.""" 399 400 #: No measurements; the power-on default. 401 SLEEP = 0 402 #: One measurement, then back to sleep. 403 FORCED = 1 404 #: Measurements on a cycle, a standby period apart. 405 NORMAL = 3 406 407 408class Bme280Filter(enum.IntEnum): 409 """The IIR filter that smooths a BME280's pressure and temperature, as its code.""" 410 411 #: No filtering. 412 OFF = 0 413 #: Coefficient 2. 414 X2 = 1 415 #: Coefficient 4. 416 X4 = 2 417 #: Coefficient 8. 418 X8 = 3 419 #: Coefficient 16. 420 X16 = 4 421 422 423class Bme280Standby(enum.IntEnum): 424 """The period a BME280 in normal mode rests between measurements, as its code.""" 425 426 #: 0.5 ms. 427 MS_0_5 = 0 428 #: 62.5 ms. 429 MS_62_5 = 1 430 #: 125 ms. 431 MS_125 = 2 432 #: 250 ms. 433 MS_250 = 3 434 #: 500 ms. 435 MS_500 = 4 436 #: 1000 ms. 437 MS_1000 = 5 438 #: 10 ms. 439 MS_10 = 6 440 #: 20 ms. 441 MS_20 = 7 442 443 444class Bmp280Oversampling(enum.IntEnum): 445 """How many samples a BMP280 measurement averages, as its register code.""" 446 447 #: The measurement is skipped. 448 SKIPPED = 0 449 #: One sample. 450 X1 = 1 451 #: Two samples. 452 X2 = 2 453 #: Four samples. 454 X4 = 3 455 #: Eight samples. 456 X8 = 4 457 #: Sixteen samples. 458 X16 = 5 459 460 461class Tmp117Averaging(enum.IntEnum): 462 """How many conversions a TMP117 averages into one result, as its register code.""" 463 464 #: No averaging: each result is one 15.5 ms conversion. 465 NONE = 0 466 #: Eight conversions, the factory setting. 467 X8 = 1 468 #: Thirty-two conversions. 469 X32 = 2 470 #: Sixty-four conversions. 471 X64 = 3 472 473 474class Opt3001ConversionTime(enum.IntEnum): 475 """How long an OPT3001 conversion integrates, in milliseconds.""" 476 477 #: 100 ms, for speed. 478 MS_100 = 100 479 #: 800 ms, for resolution; the part's reset setting. 480 MS_800 = 800 481 482 483class Hdc1080TemperatureResolution(enum.IntEnum): 484 """An HDC1080 temperature resolution, as its bit count.""" 485 486 #: 11 bits, 3.65 ms. 487 BITS_11 = 11 488 #: 14 bits, 6.35 ms. 489 BITS_14 = 14 490 491 492class Hdc1080HumidityResolution(enum.IntEnum): 493 """An HDC1080 humidity resolution, as its bit count.""" 494 495 #: 8 bits, 2.5 ms. 496 BITS_8 = 8 497 #: 11 bits, 3.85 ms. 498 BITS_11 = 11 499 #: 14 bits, 6.5 ms. 500 BITS_14 = 14 501 502 503class Ina219BusRange(enum.IntEnum): 504 """An INA219 bus-voltage range, as its register code.""" 505 506 #: 0 to 16 V. 507 V16 = 0 508 #: 0 to 32 V, the reset setting. 509 V32 = 1 510 511 512class Ina219Gain(enum.IntEnum): 513 """An INA219 shunt gain, by the shunt-voltage range it gives, as its register code.""" 514 515 #: Gain 1, 40 mV either side of zero. 516 DIV1 = 0 517 #: Gain 1/2, 80 mV. 518 DIV2 = 1 519 #: Gain 1/4, 160 mV. 520 DIV4 = 2 521 #: Gain 1/8, 320 mV, the reset setting. 522 DIV8 = 3 523 524 525class Ina219Adc(enum.IntEnum): 526 """An INA219 converter setting: a resolution, or samples averaged at 12 bits.""" 527 528 #: 9 bits, 84 us. 529 BITS_9 = 0b0000 530 #: 10 bits, 148 us. 531 BITS_10 = 0b0001 532 #: 11 bits, 276 us. 533 BITS_11 = 0b0010 534 #: 12 bits, 532 us, the reset setting. 535 BITS_12 = 0b0011 536 #: 2 samples averaged, 1.06 ms. 537 SAMPLES_2 = 0b1001 538 #: 4 samples averaged, 2.13 ms. 539 SAMPLES_4 = 0b1010 540 #: 8 samples averaged, 4.26 ms. 541 SAMPLES_8 = 0b1011 542 #: 16 samples averaged, 8.51 ms. 543 SAMPLES_16 = 0b1100 544 #: 32 samples averaged, 17.02 ms. 545 SAMPLES_32 = 0b1101 546 #: 64 samples averaged, 34.05 ms. 547 SAMPLES_64 = 0b1110 548 #: 128 samples averaged, 68.10 ms. 549 SAMPLES_128 = 0b1111 550 551 552class Ina219Mode(enum.IntEnum): 553 """An INA219 operating mode, as its register code.""" 554 555 #: No conversions, lowest power. 556 POWER_DOWN = 0 557 #: One shunt conversion. 558 SHUNT_TRIGGERED = 1 559 #: One bus conversion. 560 BUS_TRIGGERED = 2 561 #: One shunt and one bus conversion. 562 SHUNT_AND_BUS_TRIGGERED = 3 563 #: The converter disabled. 564 ADC_OFF = 4 565 #: Shunt conversions back to back. 566 SHUNT_CONTINUOUS = 5 567 #: Bus conversions back to back. 568 BUS_CONTINUOUS = 6 569 #: Shunt and bus conversions back to back, the reset setting. 570 SHUNT_AND_BUS_CONTINUOUS = 7 571 572 573class Ina226Averaging(enum.IntEnum): 574 """How many samples an INA226 folds into each result, as its register code.""" 575 576 #: Every conversion reported, the reset setting. 577 SAMPLES_1 = 0 578 #: 4 samples. 579 SAMPLES_4 = 1 580 #: 16 samples. 581 SAMPLES_16 = 2 582 #: 64 samples. 583 SAMPLES_64 = 3 584 #: 128 samples. 585 SAMPLES_128 = 4 586 #: 256 samples. 587 SAMPLES_256 = 5 588 #: 512 samples. 589 SAMPLES_512 = 6 590 #: 1024 samples. 591 SAMPLES_1024 = 7 592 593 594class Ina226ConversionTime(enum.IntEnum): 595 """An INA226 conversion time, for the bus or the shunt voltage, as its register code.""" 596 597 #: 140 us. 598 US_140 = 0 599 #: 204 us. 600 US_204 = 1 601 #: 332 us. 602 US_332 = 2 603 #: 588 us. 604 US_588 = 3 605 #: 1.1 ms, the reset setting. 606 US_1100 = 4 607 #: 2.116 ms. 608 US_2116 = 5 609 #: 4.156 ms. 610 US_4156 = 6 611 #: 8.244 ms. 612 US_8244 = 7 613 614 615class Ina226Mode(enum.IntEnum): 616 """An INA226 operating mode, as its register code.""" 617 618 #: No conversions; the registers stay readable and writable. 619 POWER_DOWN = 0 620 #: One shunt conversion. 621 SHUNT_TRIGGERED = 1 622 #: One bus conversion. 623 BUS_TRIGGERED = 2 624 #: One shunt and one bus conversion. 625 SHUNT_AND_BUS_TRIGGERED = 3 626 #: Shunt conversions back to back. 627 SHUNT_CONTINUOUS = 5 628 #: Bus conversions back to back. 629 BUS_CONTINUOUS = 6 630 #: Shunt and bus conversions back to back, the reset setting. 631 SHUNT_AND_BUS_CONTINUOUS = 7 632 633 634class Ads1115Mux(enum.IntEnum): 635 """An ADS1115 input multiplexer setting, as its register code.""" 636 637 #: AIN0 against AIN1, the reset setting. 638 AIN0_AIN1 = 0 639 #: AIN0 against AIN3. 640 AIN0_AIN3 = 1 641 #: AIN1 against AIN3. 642 AIN1_AIN3 = 2 643 #: AIN2 against AIN3. 644 AIN2_AIN3 = 3 645 #: AIN0 against ground. 646 AIN0_GND = 4 647 #: AIN1 against ground. 648 AIN1_GND = 5 649 #: AIN2 against ground. 650 AIN2_GND = 6 651 #: AIN3 against ground. 652 AIN3_GND = 7 653 654 655class Ads1115Pga(enum.IntEnum): 656 """An ADS1115 full-scale range, as its register code.""" 657 658 #: 6.144 V either side of zero. 659 FSR_6_144 = 0 660 #: 4.096 V. 661 FSR_4_096 = 1 662 #: 2.048 V, the reset setting. 663 FSR_2_048 = 2 664 #: 1.024 V. 665 FSR_1_024 = 3 666 #: 0.512 V. 667 FSR_0_512 = 4 668 #: 0.256 V. 669 FSR_0_256 = 5 670 671 672class Ads1115DataRate(enum.IntEnum): 673 """An ADS1115 data rate, as its register code.""" 674 675 #: 8 samples per second. 676 SPS_8 = 0 677 #: 16 samples per second. 678 SPS_16 = 1 679 #: 32 samples per second. 680 SPS_32 = 2 681 #: 64 samples per second. 682 SPS_64 = 3 683 #: 128 samples per second, the reset setting. 684 SPS_128 = 4 685 #: 250 samples per second. 686 SPS_250 = 5 687 #: 475 samples per second. 688 SPS_475 = 6 689 #: 860 samples per second. 690 SPS_860 = 7 691 692 693class Bme280: 694 """A Bosch BME280 driven over an :class:`~pamoja.hal.I2cBus`, measuring on demand in 695 forced mode. 696 697 Nothing is sent until :meth:`init` or the first :meth:`measure`. The driver holds its 698 own share of the bus, and releases the interpreter while the part answers. 699 700 >>> from pamoja.hal import I2cBus 701 >>> bus = I2cBus.simulated([bme280.sim.part(bme280.ADDRESS_PRIMARY)]) 702 >>> sensor = Bme280(bus, bme280.ADDRESS_PRIMARY) 703 >>> f"{sensor.measure().celsius:.2f}" 704 '20.44' 705 """ 706 707 __slots__ = ("_native",) 708 709 def __init__( 710 self, 711 bus: I2cBus, 712 address: int, 713 *, 714 temperature: Bme280Oversampling = Bme280Oversampling.X1, 715 pressure: Bme280Oversampling = Bme280Oversampling.X1, 716 humidity: Bme280Oversampling = Bme280Oversampling.X1, 717 filter: Bme280Filter = Bme280Filter.OFF, 718 ) -> None: 719 """Make a driver for the part at ``address`` on ``bus``. 720 721 :param bus: The bus the part is on. 722 :param address: ``bme280.ADDRESS_PRIMARY`` with SDO low, or 723 ``bme280.ADDRESS_SECONDARY`` with SDO high. 724 :param temperature: The temperature oversampling. 725 :param pressure: The pressure oversampling. 726 :param humidity: The humidity oversampling. 727 :param filter: The IIR filter. 728 """ 729 self._native = _NativeBme280( 730 bus._native, 731 address, 732 int(temperature), 733 int(pressure), 734 int(humidity), 735 int(filter), 736 ) 737 738 def init(self) -> None: 739 """Reset the part, check it is a BME280, read its calibration, and write the 740 settings in the order the datasheet requires, leaving the part asleep. 741 742 :raises PamojaError: If nothing answers at the address, another part does, or 743 the calibration never finishes loading. 744 """ 745 self._native.init() 746 747 def measure(self) -> Bme280Measurement: 748 """Run one forced measurement and compensate it, initializing the part first if 749 :meth:`init` has not run. 750 751 :returns: The reading. 752 :raises PamojaError: As :meth:`init`, and when the part is still measuring after 753 the datasheet's time. 754 """ 755 return self._native.measure() 756 757 758class _Bme280Sim: 759 """A BME280 that is not there, for a bus with nothing plugged in.""" 760 761 __slots__ = () 762 763 #: The status a simulated part reports when it is neither measuring nor loading. 764 STATUS_IDLE = 0x00 765 766 def part(self, address: int) -> I2cPart: 767 """Make a part holding a real BME280's calibration and one measurement it took, 768 which compensate to 20.44 C, 848.05 hPa, and 44.65 %. 769 770 :param address: The address it answers to. 771 :returns: The part, to put on a simulated bus. 772 """ 773 return I2cPart._wrap(_bme280_sim_part(address)) 774 775 def reporting( 776 self, address: int, celsius: float, hectopascals: float, relative_humidity: float 777 ) -> I2cPart: 778 """Make a part that reads what it is asked to, to within what its converter can 779 represent. 780 781 :param address: The address it answers to. 782 :param celsius: The temperature it reports. 783 :param hectopascals: The pressure it reports. 784 :param relative_humidity: The humidity it reports, as a percentage. 785 :returns: The part, to put on a simulated bus. 786 """ 787 return I2cPart._wrap( 788 _bme280_sim_reporting(address, celsius, hectopascals, relative_humidity) 789 ) 790 791 def calibration(self) -> bytes: 792 """The 26-byte temperature and pressure calibration block a simulated part holds.""" 793 return bytes(_bme280_sim_calibration()) 794 795 def calibration_humidity(self) -> bytes: 796 """The 7-byte humidity calibration block a simulated part holds.""" 797 return bytes(_bme280_sim_calibration_humidity()) 798 799 def burst(self) -> bytes: 800 """The eight data registers a simulated part holds: one measurement a real part 801 took.""" 802 return bytes(_bme280_sim_burst()) 803 804 def burst_for(self, celsius: float, hectopascals: float, relative_humidity: float) -> bytes: 805 """Build the eight data registers that compensate to a reading against the 806 simulated calibration. 807 808 :param celsius: The temperature. 809 :param hectopascals: The pressure. 810 :param relative_humidity: The humidity, as a percentage. 811 :returns: The bytes a burst read would return. 812 """ 813 return bytes(_bme280_sim_burst_for(celsius, hectopascals, relative_humidity)) 814 815 816class _Bme280: 817 """A Bosch BME280 temperature, pressure, and humidity sensor.""" 818 819 __slots__ = () 820 821 #: The address a BME280 answers on with its SDO pin low. 822 ADDRESS_PRIMARY = 0x76 823 #: The address it answers on with SDO high. 824 ADDRESS_SECONDARY = 0x77 825 #: The value its chip-ID register reads, which tells it from a BMP280. 826 CHIP_ID = 0x60 827 #: The word written to the reset register to restart the part. 828 RESET_WORD = 0xB6 829 #: How long the part takes to start after a reset, in microseconds. 830 STARTUP_MICROS = 2_000 831 #: How many bytes the temperature and pressure calibration block holds. 832 CALIBRATION_TEMP_PRESS_LENGTH = 26 833 #: How many bytes the humidity calibration block holds. 834 CALIBRATION_HUMIDITY_LENGTH = 7 835 #: How many bytes one measurement burst holds. 836 DATA_LENGTH = 8 837 #: The chip-ID register. 838 REGISTER_CHIP_ID = 0xD0 839 #: The reset register. 840 REGISTER_RESET = 0xE0 841 #: The first of the 26 temperature and pressure calibration bytes. 842 REGISTER_CALIB_TEMP_PRESS = 0x88 843 #: The first of the 7 humidity calibration bytes. 844 REGISTER_CALIB_HUMIDITY = 0xE1 845 #: The humidity control register, ``ctrl_hum``. 846 REGISTER_CTRL_HUM = 0xF2 847 #: The status register. 848 REGISTER_STATUS = 0xF3 849 #: The measurement control register, ``ctrl_meas``. 850 REGISTER_CTRL_MEAS = 0xF4 851 #: The configuration register, ``config``. 852 REGISTER_CONFIG = 0xF5 853 #: The first of the 8 data bytes a burst read covers. 854 REGISTER_DATA = 0xF7 855 856 #: The oversampling codes. 857 Oversampling = Bme280Oversampling 858 #: The power mode codes. 859 Mode = Bme280Mode 860 #: The IIR filter codes. 861 Filter = Bme280Filter 862 #: The normal-mode standby codes. 863 Standby = Bme280Standby 864 865 #: A BME280 that is not there, for a bus with nothing plugged in. 866 sim = _Bme280Sim() 867 868 def calibration(self, temp_press: bytes, humidity: bytes) -> Bme280Calibration: 869 """Read the factory calibration out of the registers, once at start-up. 870 871 :param temp_press: The 26-byte temperature and pressure calibration block. 872 :param humidity: The 7-byte humidity calibration block. 873 :returns: The calibration, to reuse for every measurement. 874 :raises ValueError: If either block is the wrong length. 875 """ 876 return Bme280Calibration(bytes(temp_press), bytes(humidity)) 877 878 def measuring(self, status: int) -> bool: 879 """Report whether a status register says a conversion is running. 880 881 :param status: The status register. 882 :returns: Whether a measurement is in progress. 883 """ 884 return _bme280_measuring(status) 885 886 def image_updating(self, status: int) -> bool: 887 """Report whether a status register says the calibration image is loading. 888 889 :param status: The status register. 890 :returns: Whether the calibration is still being copied. 891 """ 892 return _bme280_image_updating(status) 893 894 def ctrl_meas_bits(self, ctrl: Bme280CtrlMeas) -> int: 895 """Pack a ``ctrl_meas`` register value. 896 897 :param ctrl: The oversampling codes and the power mode. 898 :returns: The register value to write. 899 """ 900 return _bme280_ctrl_meas_bits(ctrl) 901 902 def ctrl_meas_from_bits(self, bits: int) -> Bme280CtrlMeas: 903 """Parse a ``ctrl_meas`` register value. 904 905 :param bits: The register value, as read from the part. 906 :returns: The oversampling codes and the power mode. 907 """ 908 return _bme280_ctrl_meas_from_bits(bits) 909 910 def ctrl_hum_bits(self, humidity: int) -> int: 911 """Pack a ``ctrl_hum`` register value, which takes effect only after the next 912 ``ctrl_meas`` write. 913 914 :param humidity: The humidity oversampling code. 915 :returns: The register value to write. 916 """ 917 return _bme280_ctrl_hum_bits(int(humidity)) 918 919 def ctrl_hum_from_bits(self, bits: int) -> Bme280Oversampling: 920 """Parse a ``ctrl_hum`` register value. 921 922 :param bits: The register value, as read from the part. 923 :returns: The humidity oversampling. 924 """ 925 return Bme280Oversampling(_bme280_ctrl_hum_from_bits(bits)) 926 927 def config_bits(self, config: Bme280Config) -> int: 928 """Pack a ``config`` register value. 929 930 :param config: The standby period, filter, and interface settings. 931 :returns: The register value to write. 932 """ 933 return _bme280_config_bits(config) 934 935 def config_from_bits(self, bits: int) -> Bme280Config: 936 """Parse a ``config`` register value. 937 938 :param bits: The register value, as read from the part. 939 :returns: The standby period, filter, and interface settings. 940 """ 941 return _bme280_config_from_bits(bits) 942 943 def oversampling_factor(self, code: int) -> int: 944 """Return how many samples an oversampling code averages. 945 946 :param code: The oversampling code. 947 :returns: The factor, or 0 when the code skips the measurement. 948 """ 949 return _bme280_oversampling_factor(int(code)) 950 951 def standby_micros(self, code: int) -> int: 952 """Return the standby period a code selects in normal mode. 953 954 :param code: The standby code. 955 :returns: The period in microseconds. 956 """ 957 return _bme280_standby_micros(int(code)) 958 959 def filter_coefficient(self, code: int) -> int: 960 """Return the IIR coefficient a filter code selects. 961 962 :param code: The filter code. 963 :returns: The coefficient, or 0 when the filter is off. 964 """ 965 return _bme280_filter_coefficient(int(code)) 966 967 def max_measurement_micros(self, temperature: int, pressure: int, humidity: int) -> int: 968 """Return the longest one measurement can take, which is how long a driver waits 969 after forcing one. 970 971 :param temperature: The temperature oversampling code. 972 :param pressure: The pressure oversampling code. 973 :param humidity: The humidity oversampling code. 974 :returns: The datasheet's maximum in microseconds. 975 """ 976 return _bme280_max_measurement_micros(int(temperature), int(pressure), int(humidity)) 977 978 def typical_measurement_micros(self, temperature: int, pressure: int, humidity: int) -> int: 979 """Return the typical time one measurement takes. 980 981 :param temperature: The temperature oversampling code. 982 :param pressure: The pressure oversampling code. 983 :param humidity: The humidity oversampling code. 984 :returns: The datasheet's typical time in microseconds. 985 """ 986 return _bme280_typical_measurement_micros( 987 int(temperature), int(pressure), int(humidity) 988 ) 989 990 991class _Ds18b20: 992 """A Maxim DS18B20 1-Wire thermometer.""" 993 994 __slots__ = () 995 996 #: The 1-Wire family code that identifies a DS18B20 on the bus. 997 FAMILY_CODE = 0x28 998 999 def parse_scratchpad(self, data: bytes) -> Ds18b20Reading: 1000 """Parse and CRC-check a nine-byte scratchpad. 1001 1002 :param data: The scratchpad as the device sent it, the ninth byte its CRC. 1003 :returns: The decoded reading. 1004 :raises PamojaError: If the CRC does not match, which means the read was 1005 corrupted on the bus and should be repeated. 1006 """ 1007 return _ds18b20_parse_scratchpad(bytes(data)) 1008 1009 def build_scratchpad( 1010 self, celsius: float, resolution_bits: int, alarm_high: int, alarm_low: int 1011 ) -> bytes: 1012 """Build the nine bytes a part in the given state puts on the bus. 1013 1014 This is the inverse of :meth:`parse_scratchpad`, so a node can be written and 1015 tested against what a thermometer sends without one attached. 1016 1017 :param celsius: The temperature the part is reading. 1018 :param resolution_bits: The resolution it is configured for, 9 to 12. 1019 :param alarm_high: The high alarm threshold in whole degrees Celsius. 1020 :param alarm_low: The low alarm threshold in whole degrees Celsius. 1021 :returns: The nine scratchpad bytes in transmission order, CRC last. 1022 :raises PamojaError: If the resolution is not 9, 10, 11, or 12 bits. 1023 """ 1024 return bytes( 1025 _ds18b20_build_scratchpad(celsius, resolution_bits, alarm_high, alarm_low) 1026 ) 1027 1028 def crc8(self, data: bytes) -> int: 1029 """Compute the Maxim CRC-8 a 1-Wire device checks its own bytes with. 1030 1031 :param data: The bytes the checksum covers. 1032 :returns: The checksum. 1033 """ 1034 return _ds18b20_crc8(bytes(data)) 1035 1036 def micro_celsius(self, raw: int) -> int: 1037 """Convert a raw temperature register to micro-degrees Celsius. 1038 1039 :param raw: The 16-bit two's-complement register. 1040 :returns: The temperature, exact in integer arithmetic. 1041 """ 1042 return _ds18b20_micro_celsius(raw) 1043 1044 def celsius(self, raw: int) -> float: 1045 """Convert a raw temperature register to degrees Celsius. 1046 1047 :param raw: The 16-bit two's-complement register. 1048 :returns: The temperature. 1049 """ 1050 return _ds18b20_celsius(raw) 1051 1052 def config_byte(self, bits: int) -> int: 1053 """Return the configuration byte that selects a resolution. 1054 1055 :param bits: The resolution in bits: 9, 10, 11, or 12. 1056 :returns: The byte to write to the configuration register. 1057 :raises ValueError: If the resolution is not one the part offers. 1058 """ 1059 return _ds18b20_config_byte(bits) 1060 1061 def resolution_bits(self, config_byte: int) -> int: 1062 """Return the resolution a configuration byte selects. 1063 1064 :param config_byte: The byte read from the configuration register. 1065 :returns: The resolution in bits. 1066 """ 1067 return _ds18b20_resolution_bits(config_byte) 1068 1069 def step_micro_celsius(self, bits: int) -> int: 1070 """Return the temperature step a resolution resolves. 1071 1072 :param bits: The resolution in bits. 1073 :returns: The step in micro-degrees Celsius. 1074 :raises ValueError: If the resolution is not one the part offers. 1075 """ 1076 return _ds18b20_step_micro_celsius(bits) 1077 1078 def max_conversion_micros(self, bits: int) -> int: 1079 """Return how long a conversion may take at a resolution. 1080 1081 :param bits: The resolution in bits. 1082 :returns: The datasheet's worst case, in microseconds. 1083 :raises ValueError: If the resolution is not one the part offers. 1084 """ 1085 return _ds18b20_max_conversion_micros(bits) 1086 1087 def parse_w1_slave(self, text: str) -> Ds18b20Reading: 1088 """Decode the text the Linux kernel's ``w1_therm`` driver serves for a thermometer: 1089 the scratchpad in hex with the kernel's checksum verdict, then the temperature. 1090 1091 :param text: The ``w1_slave`` file's contents. 1092 :returns: The reading, its CRC checked here as well. 1093 :raises PamojaError: If the kernel or this decoder rejects the CRC, or the text is 1094 not in the driver's format. 1095 """ 1096 return _ds18b20_parse_w1_slave(text) 1097 1098 def w1_slave_text(self, data: bytes) -> str: 1099 """Render the text the Linux kernel's ``w1_therm`` driver serves for a scratchpad 1100 it read cleanly, the inverse of :meth:`parse_w1_slave`: the bytes with the CRC the 1101 kernel computed and ``YES``, then the bytes again with ``t=`` and the temperature 1102 in millidegrees. 1103 1104 :param data: The nine scratchpad bytes, the ninth their CRC. 1105 :returns: The ``w1_slave`` file's two lines. 1106 :raises ValueError: If the bytes are not nine. 1107 :raises PamojaError: If the CRC does not match. 1108 """ 1109 return _ds18b20_w1_slave_text(bytes(data)) 1110 1111 1112class _Ina219Sim: 1113 """An INA219 that is not there, for a bus with nothing plugged in. 1114 1115 A monitor's current and power registers count in steps the calibration sets, so 1116 :meth:`reporting` takes the same shunt and largest current a driver is given. 1117 """ 1118 1119 __slots__ = () 1120 1121 #: The shunt :meth:`part` sits across, in milliohms: the common breakout's. 1122 SHUNT_MILLIOHMS = 100 1123 #: The largest current :meth:`part` is sized for, in microamps. 1124 MAX_MICROAMPS = 3_200_000 1125 #: The bus voltage :meth:`part` reports, in millivolts. 1126 BUS_MILLIVOLTS = 12_000 1127 #: The current :meth:`part` reports, in microamps. 1128 MICROAMPS = 500_000 1129 1130 def part(self, address: int) -> WordPart: 1131 """Make a part carrying 500 mA at 12 V through the shunt a driver starts with. 1132 1133 :param address: The address it answers to. 1134 :returns: The part, to put on a simulated bus. 1135 """ 1136 return WordPart._wrap(_ina219_sim_part(address)) 1137 1138 def reporting( 1139 self, 1140 address: int, 1141 shunt_milliohms: int, 1142 max_microamps: int, 1143 bus_millivolts: int, 1144 microamps: int, 1145 ) -> WordPart: 1146 """Make a part that reads what it is asked to, on the steps its registers count 1147 in: 4 mV of bus, 10 uV of shunt, and the calibration's current step. 1148 1149 :param address: The address it answers to. 1150 :param shunt_milliohms: The shunt, as the driver is given it. 1151 :param max_microamps: The largest current, as the driver is given it. 1152 :param bus_millivolts: The bus voltage it reports. 1153 :param microamps: The current it reports; negative flows the other way. 1154 :returns: The part, to put on a simulated bus. 1155 """ 1156 return WordPart._wrap( 1157 _ina219_sim_reporting( 1158 address, shunt_milliohms, max_microamps, bus_millivolts, microamps 1159 ) 1160 ) 1161 1162 1163class _Ina219: 1164 """A TI INA219 current, voltage, and power monitor.""" 1165 1166 __slots__ = () 1167 1168 #: The address with A1 and A0 tied to ground; the pins add to it. 1169 BASE_ADDRESS = 0x40 1170 #: An address pin tied to GND, as the code :meth:`address` takes. 1171 PIN_GROUND = 0 1172 #: An address pin tied to VS+. 1173 PIN_SUPPLY = 1 1174 #: An address pin tied to SDA. 1175 PIN_SDA = 2 1176 #: An address pin tied to SCL. 1177 PIN_SCL = 3 1178 #: The configuration register's power-on value. 1179 CONFIG_RESET = 0x399F 1180 #: The configuration register: range, gain, converter settings, and mode. 1181 REGISTER_CONFIGURATION = 0x00 1182 #: The shunt voltage, 10 uV per count. 1183 REGISTER_SHUNT_VOLTAGE = 0x01 1184 #: The bus voltage in bits 15:3, 4 mV per count, with two flags below. 1185 REGISTER_BUS_VOLTAGE = 0x02 1186 #: The power, scaled by the calibration. 1187 REGISTER_POWER = 0x03 1188 #: The current, scaled by the calibration. 1189 REGISTER_CURRENT = 0x04 1190 #: The calibration, which sets the current and power scale. 1191 REGISTER_CALIBRATION = 0x05 1192 1193 #: The bus-voltage range codes. 1194 BusRange = Ina219BusRange 1195 #: The shunt gain codes. 1196 Gain = Ina219Gain 1197 #: The converter codes. 1198 Adc = Ina219Adc 1199 #: The operating-mode codes. 1200 Mode = Ina219Mode 1201 #: An INA219 that is not there, for a bus with nothing plugged in. 1202 sim = _Ina219Sim() 1203 1204 def address(self, a1: int, a0: int) -> int: 1205 """Return the 7-bit address the A1 and A0 pins select, from Table 1 of the 1206 datasheet. 1207 1208 :param a1: What the A1 pin is tied to, one of the ``PIN_`` codes. 1209 :param a0: What the A0 pin is tied to. 1210 :returns: The address, 0x40 to 0x4F. 1211 :raises ValueError: If either pin code is not 0, 1, 2, or 3. 1212 """ 1213 return _ina219_address(a1, a0) 1214 1215 def config_bits(self, config: Ina219Config) -> int: 1216 """Assemble the configuration register value. 1217 1218 :param config: The range, gain, converter, and mode codes. 1219 :returns: The register value to write. 1220 """ 1221 return _ina219_config_bits(config) 1222 1223 def config_from_bits(self, bits: int) -> Ina219Config: 1224 """Parse a configuration register value. 1225 1226 :param bits: The register value, as read from the part. 1227 :returns: The settings. Every value decodes. 1228 """ 1229 return _ina219_config_from_bits(bits) 1230 1231 def conversion_micros(self, config: Ina219Config) -> int: 1232 """Return how long one conversion cycle takes: the shunt and bus conversions the 1233 mode runs, one after the other. 1234 1235 :param config: The settings. 1236 :returns: The time in microseconds. 1237 """ 1238 return _ina219_conversion_micros(config) 1239 1240 def adc_conversion_micros(self, adc: Ina219Adc) -> int: 1241 """Return how long one conversion takes at a converter setting. 1242 1243 :param adc: The setting. 1244 :returns: The time in microseconds, from the datasheet's table. 1245 """ 1246 return _ina219_adc_conversion_micros(int(adc)) 1247 1248 def gain_range_millivolts(self, gain: Ina219Gain) -> int: 1249 """Return the shunt-voltage range a gain selects. 1250 1251 :param gain: The gain. 1252 :returns: The range in millivolts either side of zero. 1253 """ 1254 return _ina219_gain_range_millivolts(int(gain)) 1255 1256 def calibration(self, current_lsb_microamps: int, shunt_milliohms: int) -> int: 1257 """Compute the calibration register for a shunt and current resolution. 1258 1259 :param current_lsb_microamps: The microamps per count the current register 1260 should carry. 1261 :param shunt_milliohms: The shunt resistor value. 1262 :returns: The register value to write. 1263 """ 1264 return _ina219_calibration(current_lsb_microamps, shunt_milliohms) 1265 1266 def minimum_current_lsb_microamps(self, max_expected_microamps: int) -> int: 1267 """Return the smallest current resolution that still covers a maximum. 1268 1269 :param max_expected_microamps: The largest current the application measures. 1270 :returns: The minimum current LSB in microamps. 1271 """ 1272 return _ina219_minimum_current_lsb_microamps(max_expected_microamps) 1273 1274 def shunt_register(self, microvolts: int) -> int: 1275 """Build the shunt-voltage register a monitor reports for a shunt voltage. 1276 1277 The inverse of :meth:`shunt_microvolts`, so a node can be written and tested 1278 against what a monitor sends without one attached. 1279 1280 :param microvolts: The shunt voltage in microvolts. 1281 :returns: The signed register value, at 10 uV per count. 1282 """ 1283 return _ina219_shunt_register(microvolts) 1284 1285 def bus_register(self, millivolts: int) -> int: 1286 """Build the bus-voltage register a monitor reports for a bus voltage. 1287 1288 :param millivolts: The bus voltage in millivolts. 1289 :returns: The register value, with the conversion-ready flag set. 1290 """ 1291 return _ina219_bus_register(millivolts) 1292 1293 def current_register(self, microamps: int, current_lsb_microamps: int) -> int: 1294 """Build the current register a monitor reports for a current. 1295 1296 :param microamps: The current in microamps. 1297 :param current_lsb_microamps: The current LSB the calibration was set for. 1298 :returns: The signed register value. 1299 """ 1300 return _ina219_current_register(microamps, current_lsb_microamps) 1301 1302 def power_register(self, microwatts: int, current_lsb_microamps: int) -> int: 1303 """Build the power register a monitor reports for a power. 1304 1305 :param microwatts: The power in microwatts. 1306 :param current_lsb_microamps: The current LSB the calibration was set for. 1307 :returns: The register value. 1308 """ 1309 return _ina219_power_register(microwatts, current_lsb_microamps) 1310 1311 def shunt_microvolts(self, raw: int) -> int: 1312 """Convert a raw shunt-voltage register to microvolts. 1313 1314 :param raw: The signed register value. 1315 :returns: The shunt voltage. 1316 """ 1317 return _ina219_shunt_microvolts(raw) 1318 1319 def bus_millivolts(self, raw: int) -> int: 1320 """Convert a raw bus-voltage register to millivolts. 1321 1322 :param raw: The register value. 1323 :returns: The bus voltage. 1324 """ 1325 return _ina219_bus_millivolts(raw) 1326 1327 def conversion_ready(self, raw: int) -> bool: 1328 """Report whether a bus-voltage register says a conversion is ready. 1329 1330 :param raw: The register value. 1331 :returns: Whether the conversion-ready flag is set. 1332 """ 1333 return _ina219_conversion_ready(raw) 1334 1335 def math_overflow(self, raw: int) -> bool: 1336 """Report whether a bus-voltage register flags a math overflow. 1337 1338 :param raw: The register value. 1339 :returns: Whether the current and power readings are meaningless, which 1340 means the calibration needs revisiting. 1341 """ 1342 return _ina219_math_overflow(raw) 1343 1344 def current_microamps(self, raw: int, current_lsb_microamps: int) -> int: 1345 """Convert a raw current register to microamps. 1346 1347 :param raw: The signed register value. 1348 :param current_lsb_microamps: The resolution the calibration selected. 1349 :returns: The current. 1350 """ 1351 return _ina219_current_microamps(raw, current_lsb_microamps) 1352 1353 def power_microwatts(self, raw: int, current_lsb_microamps: int) -> int: 1354 """Convert a raw power register to microwatts. 1355 1356 :param raw: The register value. 1357 :param current_lsb_microamps: The resolution the calibration selected. 1358 :returns: The power. The power LSB is fixed at twenty times the current LSB. 1359 """ 1360 return _ina219_power_microwatts(raw, current_lsb_microamps) 1361 1362 1363class _Ads1115Sim: 1364 """An ADS1115 that is not there, for a bus with nothing plugged in. 1365 1366 A conversion comes back as a count of the range the gain selects, so :meth:`reporting` 1367 takes the same gain a driver is given. 1368 """ 1369 1370 __slots__ = () 1371 1372 #: The voltage :meth:`part` reports: half a 3.3 V supply. 1373 VOLTS = 1.65 1374 1375 def part(self, address: int) -> WordPart: 1376 """Make a part reading :attr:`VOLTS` at the range a driver starts with. 1377 1378 :param address: The address it answers to. 1379 :returns: The part, to put on a simulated bus. 1380 """ 1381 return WordPart._wrap(_ads1115_sim_part(address)) 1382 1383 def reporting(self, address: int, pga: Ads1115Pga, volts: float) -> WordPart: 1384 """Make a part that reads what it is asked to, on the nearest of the 32768 steps 1385 either side of zero the range divides into. 1386 1387 :param address: The address it answers to. 1388 :param pga: The range the driver converts at. 1389 :param volts: The voltage it reports, held to the range. 1390 :returns: The part, to put on a simulated bus. 1391 """ 1392 return WordPart._wrap(_ads1115_sim_reporting(address, int(pga), volts)) 1393 1394 1395class _Ads1115: 1396 """A TI ADS1115 16-bit analog-to-digital converter.""" 1397 1398 __slots__ = () 1399 1400 #: The address with ADDR tied to ground. 1401 ADDRESS_GND = 0x48 1402 #: The address with ADDR tied to VDD. 1403 ADDRESS_VDD = 0x49 1404 #: The address with ADDR tied to SDA. 1405 ADDRESS_SDA = 0x4A 1406 #: The address with ADDR tied to SCL. 1407 ADDRESS_SCL = 0x4B 1408 #: The conversion register. 1409 REGISTER_CONVERSION = 0x00 1410 #: The configuration register. 1411 REGISTER_CONFIG = 0x01 1412 #: The comparator's low threshold register. 1413 REGISTER_LO_THRESH = 0x02 1414 #: The comparator's high threshold register. 1415 REGISTER_HI_THRESH = 0x03 1416 1417 #: The input multiplexer codes. 1418 Mux = Ads1115Mux 1419 #: The full-scale range codes. 1420 Pga = Ads1115Pga 1421 #: The data-rate codes. 1422 DataRate = Ads1115DataRate 1423 #: An ADS1115 that is not there, for a bus with nothing plugged in. 1424 sim = _Ads1115Sim() 1425 1426 def conversion_micros(self, data_rate: Ads1115DataRate) -> int: 1427 """Return how long a conversion takes at a data rate: one period plus the 1428 datasheet's ten percent rate variation. 1429 1430 :param data_rate: The data rate. 1431 :returns: The time in microseconds. 1432 """ 1433 return _ads1115_conversion_micros(int(data_rate)) 1434 1435 #: The value the configuration register reads after a reset. 1436 CONFIG_RESET = 0x8583 1437 1438 def config_bits(self, config: Ads1115Config) -> int: 1439 """Assemble the 16-bit configuration register value. 1440 1441 :param config: The settings to encode. 1442 :returns: The register value to write, most significant bit first. 1443 """ 1444 return _ads1115_config_bits(config) 1445 1446 def config_from_bits(self, bits: int) -> Ads1115Config: 1447 """Parse a 16-bit configuration register value. 1448 1449 :param bits: The register value, as read from the device. 1450 :returns: The decoded settings. Every value decodes, so this never raises. 1451 """ 1452 return _ads1115_config_from_bits(bits) 1453 1454 def full_scale_microvolts(self, pga: int) -> int: 1455 """Return the full-scale range a gain code selects. 1456 1457 :param pga: The gain code, 0 to 7. 1458 :returns: The full scale in microvolts. 1459 """ 1460 return _ads1115_full_scale_microvolts(pga) 1461 1462 def samples_per_second(self, data_rate: int) -> int: 1463 """Return the sample rate a data-rate code selects. 1464 1465 :param data_rate: The data-rate code, 0 to 7. 1466 :returns: The rate in samples per second. 1467 """ 1468 return _ads1115_samples_per_second(data_rate) 1469 1470 def to_nanovolts(self, pga: int, raw: int) -> int: 1471 """Convert a raw conversion result to nanovolts. 1472 1473 :param pga: The gain the conversion was taken at. 1474 :param raw: The signed conversion register value. 1475 :returns: The measured voltage, exact at every gain setting. 1476 """ 1477 return _ads1115_to_nanovolts(pga, raw) 1478 1479 def to_volts(self, pga: int, raw: int) -> float: 1480 """Convert a raw conversion result to volts. 1481 1482 :param pga: The gain the conversion was taken at. 1483 :param raw: The signed conversion register value. 1484 :returns: The measured voltage. 1485 """ 1486 return _ads1115_to_volts(pga, raw) 1487 1488 1489class Sht3xRepeatability(str, enum.Enum): 1490 """How hard an SHT3x works at one measurement, traded against time and power.""" 1491 1492 #: The fastest and least precise setting. 1493 LOW = "Low" 1494 #: The middle setting. 1495 MEDIUM = "Medium" 1496 #: The slowest and most precise setting. 1497 HIGH = "High" 1498 1499 1500class Sht3xRate(str, enum.Enum): 1501 """How often an SHT3x in periodic mode takes a measurement.""" 1502 1503 #: One measurement every two seconds. 1504 HALF_MPS = "HalfMps" 1505 #: One measurement per second. 1506 ONE_MPS = "OneMps" 1507 #: Two measurements per second. 1508 TWO_MPS = "TwoMps" 1509 #: Four measurements per second. 1510 FOUR_MPS = "FourMps" 1511 #: Ten measurements per second. 1512 TEN_MPS = "TenMps" 1513 1514 1515class Ina226AlertFunction(str, enum.Enum): 1516 """The limit comparison an INA226 alert pin responds to.""" 1517 1518 #: The shunt voltage rose above the alert limit. 1519 SHUNT_OVER_LIMIT = "ShuntOverLimit" 1520 #: The shunt voltage fell below the alert limit. 1521 SHUNT_UNDER_LIMIT = "ShuntUnderLimit" 1522 #: The bus voltage rose above the alert limit. 1523 BUS_OVER_LIMIT = "BusOverLimit" 1524 #: The bus voltage fell below the alert limit. 1525 BUS_UNDER_LIMIT = "BusUnderLimit" 1526 #: The power rose above the alert limit. 1527 POWER_OVER_LIMIT = "PowerOverLimit" 1528 1529 1530class _Bmp280Sim: 1531 """A BMP280 that is not there, for a bus with nothing plugged in. 1532 1533 A BMP280 is a BME280 without humidity, so :meth:`part` holds the temperature and 1534 pressure half of a real part and reads 20.44 C and 848.05 hPa. 1535 """ 1536 1537 __slots__ = () 1538 1539 #: The status a simulated part reports when it is neither measuring nor loading. 1540 STATUS_IDLE = 0x00 1541 1542 def part(self, address: int) -> I2cPart: 1543 """Make a part holding a real part's trimming and one measurement it took. 1544 1545 :param address: The address it answers to. 1546 :returns: The part, to put on a simulated bus. 1547 """ 1548 return I2cPart._wrap(_bmp280_sim_part(address)) 1549 1550 def reporting(self, address: int, celsius: float, hectopascals: float) -> I2cPart: 1551 """Make a part that reads what it is asked to, within a hundredth of a degree and 1552 of a hectopascal. 1553 1554 :param address: The address it answers to. 1555 :param celsius: The temperature it reports. 1556 :param hectopascals: The pressure it reports. 1557 :returns: The part, to put on a simulated bus. 1558 """ 1559 return I2cPart._wrap(_bmp280_sim_reporting(address, celsius, hectopascals)) 1560 1561 def calibration(self) -> bytes: 1562 """The 24 trimming bytes a simulated part holds.""" 1563 return bytes(_bmp280_sim_calibration()) 1564 1565 def burst(self) -> bytes: 1566 """The six data registers a simulated part holds: one measurement a real part 1567 took.""" 1568 return bytes(_bmp280_sim_burst()) 1569 1570 def burst_for(self, celsius: float, hectopascals: float) -> bytes: 1571 """Build the six data registers that compensate to a reading against the simulated 1572 trimming. 1573 1574 :param celsius: The temperature. 1575 :param hectopascals: The pressure. 1576 :returns: The bytes a burst read would return. 1577 """ 1578 return bytes(_bmp280_sim_burst_for(celsius, hectopascals)) 1579 1580 1581class _Bmp280: 1582 """A Bosch BMP280 pressure and temperature sensor, the BME280 without humidity.""" 1583 1584 __slots__ = () 1585 1586 #: The oversampling codes. 1587 Oversampling = Bmp280Oversampling 1588 #: A BMP280 that is not there, for a bus with nothing plugged in. 1589 sim = _Bmp280Sim() 1590 1591 #: The address a BMP280 answers on with its SDO pin low. 1592 ADDRESS_PRIMARY = 0x76 1593 #: The address it answers on with SDO high. 1594 ADDRESS_SECONDARY = 0x77 1595 #: The value its chip-ID register reads, which confirms the part. 1596 CHIP_ID = 0x58 1597 #: The word written to the reset register to restart the part. 1598 RESET_WORD = 0xB6 1599 #: The raw output a channel reports when its measurement is switched off. 1600 SKIPPED_OUTPUT = 0x80000 1601 #: How many bytes the calibration block holds. 1602 CALIBRATION_LENGTH = 24 1603 #: How many bytes one measurement burst holds. 1604 DATA_LENGTH = 6 1605 #: The first of the 24 calibration bytes. 1606 REGISTER_CALIBRATION = 0x88 1607 #: The chip-ID register. 1608 REGISTER_CHIP_ID = 0xD0 1609 #: The reset register. 1610 REGISTER_RESET = 0xE0 1611 #: The status register. 1612 REGISTER_STATUS = 0xF3 1613 #: The measurement-control register. 1614 REGISTER_CTRL_MEAS = 0xF4 1615 #: The configuration register. 1616 REGISTER_CONFIG = 0xF5 1617 #: The first of the six data bytes. 1618 REGISTER_DATA = 0xF7 1619 1620 def calibration(self, data: bytes) -> Bmp280Calibration: 1621 """Read the factory calibration out of the registers, once at start-up. 1622 1623 :param data: The 24-byte calibration block. 1624 :returns: The calibration, to reuse for every measurement. 1625 :raises ValueError: If the block is the wrong length. 1626 """ 1627 return Bmp280Calibration(bytes(data)) 1628 1629 def parse_measurement(self, data: bytes) -> Bmp280RawMeasurement: 1630 """Split a six-byte data read into its two uncompensated outputs. 1631 1632 :param data: The six data registers in read order. 1633 :returns: The raw pressure and temperature, before compensation. 1634 :raises ValueError: If the read is the wrong length. 1635 """ 1636 return _bmp280_parse_measurement(bytes(data)) 1637 1638 def measurement_bytes(self, pressure: int, temperature: int) -> bytes: 1639 """Build the six data-register bytes a part reports for two raw outputs. 1640 1641 The inverse of :meth:`parse_measurement`, so a node can be written and tested 1642 against what a sensor sends without one attached. 1643 1644 :param pressure: The 20-bit uncompensated pressure. 1645 :param temperature: The 20-bit uncompensated temperature. 1646 :returns: The six bytes in read order. 1647 """ 1648 return bytes(_bmp280_measurement_bytes(pressure, temperature)) 1649 1650 def pressure_skipped(self, pressure: int) -> bool: 1651 """Report whether a raw pressure says the measurement is switched off. 1652 1653 :param pressure: The 20-bit uncompensated pressure. 1654 :returns: Whether the channel's oversampling is set to skip. 1655 """ 1656 return _bmp280_pressure_skipped(pressure) 1657 1658 def temperature_skipped(self, temperature: int) -> bool: 1659 """Report whether a raw temperature says the measurement is switched off. 1660 1661 :param temperature: The 20-bit uncompensated temperature. 1662 :returns: Whether the channel's oversampling is set to skip. 1663 """ 1664 return _bmp280_temperature_skipped(temperature) 1665 1666 def measuring(self, status: int) -> bool: 1667 """Report whether a status register says a conversion is running. 1668 1669 :param status: The status register. 1670 :returns: Whether a measurement is in progress. 1671 """ 1672 return _bmp280_measuring(status) 1673 1674 def image_updating(self, status: int) -> bool: 1675 """Report whether a status register says the calibration image is loading. 1676 1677 :param status: The status register. 1678 :returns: Whether the coefficients are still being copied from NVM. 1679 """ 1680 return _bmp280_image_updating(status) 1681 1682 def ctrl_meas_bits(self, ctrl: Bmp280CtrlMeas) -> int: 1683 """Pack a measurement-control register value. 1684 1685 :param ctrl: The oversampling settings and power mode. 1686 :returns: The byte to write. 1687 """ 1688 return _bmp280_ctrl_meas_bits(ctrl) 1689 1690 def ctrl_meas_from_bits(self, bits: int) -> Bmp280CtrlMeas: 1691 """Parse a measurement-control register value. 1692 1693 :param bits: The byte read from the device. 1694 :returns: The decoded settings. 1695 """ 1696 return _bmp280_ctrl_meas_from_bits(bits) 1697 1698 def config_bits(self, config: Bmp280Config) -> int: 1699 """Pack a configuration register value. 1700 1701 :param config: The standby, filter, and interface settings. 1702 :returns: The byte to write. 1703 """ 1704 return _bmp280_config_bits(config) 1705 1706 def config_from_bits(self, bits: int) -> Bmp280Config: 1707 """Parse a configuration register value. 1708 1709 :param bits: The byte read from the device. 1710 :returns: The decoded settings. 1711 """ 1712 return _bmp280_config_from_bits(bits) 1713 1714 def oversampling_factor(self, code: int) -> int: 1715 """Return how many samples an oversampling code averages. 1716 1717 :param code: The oversampling code, 0 to 5. 1718 :returns: The sample count, or 0 when the measurement is skipped. 1719 """ 1720 return _bmp280_oversampling_factor(code) 1721 1722 def standby_micros(self, code: int) -> int: 1723 """Return the normal-mode standby period a code selects. 1724 1725 :param code: The standby code, 0 to 7. 1726 :returns: The period in microseconds. 1727 """ 1728 return _bmp280_standby_micros(code) 1729 1730 1731class _Sht3xSim: 1732 """An SHT3x that is not there, for a bus with nothing plugged in. 1733 1734 It answers every single-shot command and a periodic fetch with the reading and its 1735 checksums, and the status command with the status a part reports after a reset. 1736 """ 1737 1738 __slots__ = () 1739 1740 #: The temperature :meth:`part` reports. 1741 CELSIUS = 22.5 1742 #: The relative humidity :meth:`part` reports, as a percentage. 1743 RELATIVE_HUMIDITY = 45.0 1744 1745 def part(self, address: int) -> CommandPart: 1746 """Make a part reading :attr:`CELSIUS` and :attr:`RELATIVE_HUMIDITY`. 1747 1748 :param address: The address it answers to. 1749 :returns: The part, to put on a simulated bus. 1750 """ 1751 return CommandPart._wrap(_sht3x_sim_part(address)) 1752 1753 def reporting(self, address: int, celsius: float, relative_humidity: float) -> CommandPart: 1754 """Make a part that reads what it is asked to, within three thousandths of a degree 1755 and two thousandths of a percent. 1756 1757 :param address: The address it answers to. 1758 :param celsius: The temperature it reports. 1759 :param relative_humidity: The humidity it reports, as a percentage. 1760 :returns: The part, to put on a simulated bus. 1761 """ 1762 return CommandPart._wrap(_sht3x_sim_reporting(address, celsius, relative_humidity)) 1763 1764 1765class _Sht3x: 1766 """A Sensirion SHT30, SHT31, or SHT35 temperature and humidity sensor.""" 1767 1768 __slots__ = () 1769 1770 #: An SHT3x that is not there, for a bus with nothing plugged in. 1771 sim = _Sht3xSim() 1772 1773 #: The address the part answers on with its ADDR pin low. 1774 ADDRESS_A = 0x44 1775 #: The address it answers on with ADDR high. 1776 ADDRESS_B = 0x45 1777 #: The shortest gap the datasheet allows between two commands, in microseconds. 1778 MIN_COMMAND_GAP_MICROS = 1_000 1779 #: The status word the part powers up with. 1780 STATUS_DEFAULT = 0x8010 1781 #: Single shot, high repeatability, holding the clock until the result is ready. 1782 COMMAND_SINGLE_SHOT_HIGH_STRETCH = 0x2C06 1783 #: Single shot, medium repeatability, with clock stretching. 1784 COMMAND_SINGLE_SHOT_MEDIUM_STRETCH = 0x2C0D 1785 #: Single shot, low repeatability, with clock stretching. 1786 COMMAND_SINGLE_SHOT_LOW_STRETCH = 0x2C10 1787 #: Single shot, high repeatability, polled rather than stretched. 1788 COMMAND_SINGLE_SHOT_HIGH = 0x2400 1789 #: Single shot, medium repeatability, polled. 1790 COMMAND_SINGLE_SHOT_MEDIUM = 0x240B 1791 #: Single shot, low repeatability, polled. 1792 COMMAND_SINGLE_SHOT_LOW = 0x2416 1793 #: Periodic at one measurement every two seconds, high repeatability. 1794 COMMAND_PERIODIC_HALF_MPS_HIGH = 0x2032 1795 #: Periodic at one measurement every two seconds, medium repeatability. 1796 COMMAND_PERIODIC_HALF_MPS_MEDIUM = 0x2024 1797 #: Periodic at one measurement every two seconds, low repeatability. 1798 COMMAND_PERIODIC_HALF_MPS_LOW = 0x202F 1799 #: Periodic at one measurement per second, high repeatability. 1800 COMMAND_PERIODIC_ONE_MPS_HIGH = 0x2130 1801 #: Periodic at one measurement per second, medium repeatability. 1802 COMMAND_PERIODIC_ONE_MPS_MEDIUM = 0x2126 1803 #: Periodic at one measurement per second, low repeatability. 1804 COMMAND_PERIODIC_ONE_MPS_LOW = 0x212D 1805 #: Periodic at two measurements per second, high repeatability. 1806 COMMAND_PERIODIC_TWO_MPS_HIGH = 0x2236 1807 #: Periodic at two measurements per second, medium repeatability. 1808 COMMAND_PERIODIC_TWO_MPS_MEDIUM = 0x2220 1809 #: Periodic at two measurements per second, low repeatability. 1810 COMMAND_PERIODIC_TWO_MPS_LOW = 0x222B 1811 #: Periodic at four measurements per second, high repeatability. 1812 COMMAND_PERIODIC_FOUR_MPS_HIGH = 0x2334 1813 #: Periodic at four measurements per second, medium repeatability. 1814 COMMAND_PERIODIC_FOUR_MPS_MEDIUM = 0x2322 1815 #: Periodic at four measurements per second, low repeatability. 1816 COMMAND_PERIODIC_FOUR_MPS_LOW = 0x2329 1817 #: Periodic at ten measurements per second, high repeatability. 1818 COMMAND_PERIODIC_TEN_MPS_HIGH = 0x2737 1819 #: Periodic at ten measurements per second, medium repeatability. 1820 COMMAND_PERIODIC_TEN_MPS_MEDIUM = 0x2721 1821 #: Periodic at ten measurements per second, low repeatability. 1822 COMMAND_PERIODIC_TEN_MPS_LOW = 0x272A 1823 #: Accelerated response time, four measurements per second. 1824 COMMAND_PERIODIC_ART = 0x2B32 1825 #: Fetch the latest periodic result. 1826 COMMAND_FETCH_DATA = 0xE000 1827 #: Leave periodic mode. 1828 COMMAND_BREAK = 0x3093 1829 #: Soft reset. 1830 COMMAND_SOFT_RESET = 0x30A2 1831 #: The general-call reset, addressed to 0x00. 1832 COMMAND_GENERAL_CALL_RESET = 0x0006 1833 #: Turn the on-die heater on. 1834 COMMAND_HEATER_ENABLE = 0x306D 1835 #: Turn the on-die heater off. 1836 COMMAND_HEATER_DISABLE = 0x3066 1837 #: Read the status register. 1838 COMMAND_READ_STATUS = 0xF32D 1839 #: Clear the status register. 1840 COMMAND_CLEAR_STATUS = 0x3041 1841 1842 def crc(self, data: bytes) -> int: 1843 """Compute the Sensirion CRC-8 the part appends to every word. 1844 1845 :param data: The bytes the checksum covers. 1846 :returns: The checksum. 1847 """ 1848 return _sht3x_crc(bytes(data)) 1849 1850 def word(self, frame: bytes) -> int: 1851 """Read a CRC-checked three-byte word frame. 1852 1853 :param frame: The two data bytes and their checksum. 1854 :returns: The 16-bit word. 1855 :raises ValueError: If the frame is not three bytes. 1856 :raises PamojaError: If the checksum does not match, which means the read 1857 was corrupted on the bus and should be repeated. 1858 """ 1859 return _sht3x_word(bytes(frame)) 1860 1861 def word_bytes(self, value: int) -> bytes: 1862 """Build the three bytes the part sends for a word: the word then its CRC. 1863 1864 :param value: The 16-bit word. 1865 :returns: The frame in transmission order. 1866 """ 1867 return bytes(_sht3x_word_bytes(value)) 1868 1869 def parse_measurement(self, frame: bytes) -> Sht3xMeasurement: 1870 """Parse and CRC-check a six-byte measurement frame. 1871 1872 :param frame: The temperature word, humidity word, and their checksums. 1873 :returns: The decoded reading, in raw words and physical units. 1874 :raises ValueError: If the frame is not six bytes. 1875 :raises PamojaError: If either checksum does not match. 1876 """ 1877 return _sht3x_parse_measurement(bytes(frame)) 1878 1879 def measurement_bytes(self, temperature_raw: int, humidity_raw: int) -> bytes: 1880 """Build the six bytes the part sends for a pair of raw words. 1881 1882 The inverse of :meth:`parse_measurement`, so a node can be written and tested 1883 against what a sensor sends without one attached. 1884 1885 :param temperature_raw: The raw temperature word. 1886 :param humidity_raw: The raw humidity word. 1887 :returns: The frame in transmission order, each word followed by its CRC. 1888 """ 1889 return bytes(_sht3x_measurement_bytes(temperature_raw, humidity_raw)) 1890 1891 def parse_status(self, frame: bytes) -> Sht3xStatus: 1892 """Parse and CRC-check a three-byte status frame. 1893 1894 :param frame: The status word and its checksum. 1895 :returns: The decoded status word and its flags. 1896 :raises ValueError: If the frame is not three bytes. 1897 :raises PamojaError: If the checksum does not match. 1898 """ 1899 return _sht3x_parse_status(bytes(frame)) 1900 1901 def status_from_bits(self, bits: int) -> Sht3xStatus: 1902 """Split a status word into its flags. 1903 1904 :param bits: The 16-bit status register. 1905 :returns: The decoded flags. Every value decodes, so this never raises. 1906 """ 1907 return _sht3x_status_from_bits(bits) 1908 1909 def status_bytes(self, bits: int) -> bytes: 1910 """Build the three bytes the part sends for a status word, CRC last. 1911 1912 :param bits: The 16-bit status register. 1913 :returns: The frame in transmission order. 1914 """ 1915 return bytes(_sht3x_status_bytes(bits)) 1916 1917 def milli_celsius(self, raw: int) -> int: 1918 """Convert a raw temperature word to milli-degrees Celsius. 1919 1920 :param raw: The 16-bit temperature word. 1921 :returns: The temperature, exact in integer arithmetic. 1922 """ 1923 return _sht3x_milli_celsius(raw) 1924 1925 def celsius(self, raw: int) -> float: 1926 """Convert a raw temperature word to degrees Celsius. 1927 1928 :param raw: The 16-bit temperature word. 1929 :returns: The temperature. 1930 """ 1931 return _sht3x_celsius(raw) 1932 1933 def milli_fahrenheit(self, raw: int) -> int: 1934 """Convert a raw temperature word to milli-degrees Fahrenheit. 1935 1936 :param raw: The 16-bit temperature word. 1937 :returns: The temperature, from the datasheet's own Fahrenheit formula. 1938 """ 1939 return _sht3x_milli_fahrenheit(raw) 1940 1941 def fahrenheit(self, raw: int) -> float: 1942 """Convert a raw temperature word to degrees Fahrenheit. 1943 1944 :param raw: The 16-bit temperature word. 1945 :returns: The temperature. 1946 """ 1947 return _sht3x_fahrenheit(raw) 1948 1949 def milli_percent(self, raw: int) -> int: 1950 """Convert a raw humidity word to milli-percent. 1951 1952 :param raw: The 16-bit humidity word. 1953 :returns: The relative humidity, exact in integer arithmetic. 1954 """ 1955 return _sht3x_milli_percent(raw) 1956 1957 def relative_humidity(self, raw: int) -> float: 1958 """Convert a raw humidity word to a relative humidity percentage. 1959 1960 :param raw: The 16-bit humidity word. 1961 :returns: The relative humidity. 1962 """ 1963 return _sht3x_relative_humidity(raw) 1964 1965 def temperature_raw_from_milli_celsius(self, milli_celsius: int) -> int: 1966 """Build the temperature word that decodes to a temperature. 1967 1968 :param milli_celsius: The temperature in milli-degrees Celsius. 1969 :returns: The 16-bit word, clamped to the part's range. 1970 """ 1971 return _sht3x_temperature_raw_from_milli_celsius(milli_celsius) 1972 1973 def temperature_raw_from_celsius(self, celsius: float) -> int: 1974 """Build the temperature word that decodes to a temperature in Celsius. 1975 1976 :param celsius: The temperature. 1977 :returns: The 16-bit word, clamped to the part's range. 1978 """ 1979 return _sht3x_temperature_raw_from_celsius(celsius) 1980 1981 def temperature_raw_from_milli_fahrenheit(self, milli_fahrenheit: int) -> int: 1982 """Build the temperature word that decodes to a temperature in Fahrenheit. 1983 1984 :param milli_fahrenheit: The temperature in milli-degrees Fahrenheit. 1985 :returns: The 16-bit word, clamped to the part's range. 1986 """ 1987 return _sht3x_temperature_raw_from_milli_fahrenheit(milli_fahrenheit) 1988 1989 def humidity_raw_from_milli_percent(self, milli_percent: int) -> int: 1990 """Build the humidity word that decodes to a relative humidity. 1991 1992 :param milli_percent: The relative humidity in milli-percent. 1993 :returns: The 16-bit word, clamped to full scale. 1994 """ 1995 return _sht3x_humidity_raw_from_milli_percent(milli_percent) 1996 1997 def humidity_raw_from_relative_humidity(self, percent: float) -> int: 1998 """Build the humidity word that decodes to a relative humidity percentage. 1999 2000 :param percent: The relative humidity. 2001 :returns: The 16-bit word, clamped to full scale. 2002 """ 2003 return _sht3x_humidity_raw_from_relative_humidity(percent) 2004 2005 def single_shot(self, repeatability: Sht3xRepeatability, clock_stretching: bool) -> int: 2006 """Return the single-shot command for a repeatability and clock mode. 2007 2008 :param repeatability: How hard the part works at the measurement. 2009 :param clock_stretching: Whether the part holds the clock until the result 2010 is ready, rather than making the driver poll for it. 2011 :returns: The 16-bit command word. 2012 :raises ValueError: If the repeatability is not one the part offers. 2013 """ 2014 return _sht3x_single_shot(Sht3xRepeatability(repeatability).value, clock_stretching) 2015 2016 def periodic(self, repeatability: Sht3xRepeatability, rate: Sht3xRate) -> int: 2017 """Return the periodic-mode command for a repeatability and rate. 2018 2019 :param repeatability: How hard the part works at each measurement. 2020 :param rate: How often it measures. 2021 :returns: The 16-bit command word. 2022 :raises ValueError: If either setting is not one the part offers. 2023 """ 2024 return _sht3x_periodic( 2025 Sht3xRepeatability(repeatability).value, Sht3xRate(rate).value 2026 ) 2027 2028 def max_measurement_micros(self, repeatability: Sht3xRepeatability) -> int: 2029 """Return how long a measurement may take. 2030 2031 :param repeatability: The setting the measurement is taken at. 2032 :returns: The datasheet's worst case, in microseconds. 2033 :raises ValueError: If the repeatability is not one the part offers. 2034 """ 2035 return _sht3x_max_measurement_micros(Sht3xRepeatability(repeatability).value) 2036 2037 def typical_measurement_micros(self, repeatability: Sht3xRepeatability) -> int: 2038 """Return how long a measurement typically takes. 2039 2040 :param repeatability: The setting the measurement is taken at. 2041 :returns: The datasheet's typical figure, in microseconds. 2042 :raises ValueError: If the repeatability is not one the part offers. 2043 """ 2044 return _sht3x_typical_measurement_micros(Sht3xRepeatability(repeatability).value) 2045 2046 def interval_micros(self, rate: Sht3xRate) -> int: 2047 """Return the gap between periodic measurements. 2048 2049 :param rate: The periodic rate. 2050 :returns: The interval in microseconds. 2051 :raises ValueError: If the rate is not one the part offers. 2052 """ 2053 return _sht3x_interval_micros(Sht3xRate(rate).value) 2054 2055class _Scd4xSim: 2056 """An SCD4x that is not there, for a bus with nothing plugged in. 2057 2058 It answers the serial number, data-ready, and measurement commands, each word with its 2059 checksum, and always has a result waiting. 2060 """ 2061 2062 __slots__ = () 2063 2064 #: The carbon dioxide :meth:`part` reports, in parts per million. 2065 CO2_PPM = 800 2066 #: The temperature :meth:`part` reports. 2067 CELSIUS = 22.5 2068 #: The relative humidity :meth:`part` reports, as a percentage. 2069 RELATIVE_HUMIDITY = 45.0 2070 #: The serial number every simulated part reports. 2071 SERIAL = 0x0000_5A4D_0C1E_2B3F 2072 2073 def part(self) -> CommandPart: 2074 """Make a part reading :attr:`CO2_PPM`, :attr:`CELSIUS`, and 2075 :attr:`RELATIVE_HUMIDITY`. 2076 2077 :returns: The part, to put on a simulated bus. 2078 """ 2079 return CommandPart._wrap(_scd4x_sim_part()) 2080 2081 def reporting(self, co2_ppm: int, celsius: float, relative_humidity: float) -> CommandPart: 2082 """Make a part that reads what it is asked to. 2083 2084 :param co2_ppm: The carbon dioxide it reports, in parts per million. 2085 :param celsius: The temperature it reports. 2086 :param relative_humidity: The humidity it reports, as a percentage. 2087 :returns: The part, to put on a simulated bus. 2088 """ 2089 return CommandPart._wrap(_scd4x_sim_reporting(co2_ppm, celsius, relative_humidity)) 2090 2091 2092class _Scd4x: 2093 """A Sensirion SCD40 or SCD41 carbon dioxide, temperature, and humidity sensor.""" 2094 2095 __slots__ = () 2096 2097 #: An SCD4x that is not there, for a bus with nothing plugged in. 2098 sim = _Scd4xSim() 2099 2100 #: The only address the part answers on. 2101 ADDRESS = 0x62 2102 #: The highest concentration the part reports, in parts per million. 2103 CO2_MAX_PPM = 40_000 2104 #: The temperature offset the part powers up with, in milli-degrees Celsius. 2105 DEFAULT_TEMPERATURE_OFFSET_MILLI_CELSIUS = 4_000 2106 #: How often periodic measurement produces a result, in milliseconds. 2107 PERIODIC_MEASUREMENT_INTERVAL_MS = 5_000 2108 #: How often low-power periodic measurement produces a result, in milliseconds. 2109 LOW_POWER_PERIODIC_MEASUREMENT_INTERVAL_MS = 30_000 2110 #: How long the part takes to become ready after power-up, in milliseconds. 2111 POWER_UP_TIME_MS = 1_000 2112 #: The word a forced recalibration returns when it did not take. 2113 FORCED_RECALIBRATION_FAILED = 0xFFFF 2114 #: Start periodic measurement. 2115 COMMAND_START_PERIODIC_MEASUREMENT = 0x21B1 2116 #: Read the latest result. 2117 COMMAND_READ_MEASUREMENT = 0xEC05 2118 #: Leave periodic measurement. 2119 COMMAND_STOP_PERIODIC_MEASUREMENT = 0x3F86 2120 #: Write the temperature offset. 2121 COMMAND_SET_TEMPERATURE_OFFSET = 0x241D 2122 #: Read the temperature offset. 2123 COMMAND_GET_TEMPERATURE_OFFSET = 0x2318 2124 #: Write the installation altitude. 2125 COMMAND_SET_SENSOR_ALTITUDE = 0x2427 2126 #: Read the installation altitude. 2127 COMMAND_GET_SENSOR_ALTITUDE = 0x2322 2128 #: Write the ambient pressure, which overrides the altitude. 2129 COMMAND_SET_AMBIENT_PRESSURE = 0xE000 2130 #: Run a forced recalibration against a known concentration. 2131 COMMAND_PERFORM_FORCED_RECALIBRATION = 0x362F 2132 #: Turn automatic self-calibration on or off. 2133 COMMAND_SET_AUTOMATIC_SELF_CALIBRATION_ENABLED = 0x2416 2134 #: Read whether automatic self-calibration is on. 2135 COMMAND_GET_AUTOMATIC_SELF_CALIBRATION_ENABLED = 0x2313 2136 #: Start low-power periodic measurement. 2137 COMMAND_START_LOW_POWER_PERIODIC_MEASUREMENT = 0x21AC 2138 #: Ask whether a result is waiting. 2139 COMMAND_GET_DATA_READY_STATUS = 0xE4B8 2140 #: Copy the settings to non-volatile memory. 2141 COMMAND_PERSIST_SETTINGS = 0x3615 2142 #: Read the serial number. 2143 COMMAND_GET_SERIAL_NUMBER = 0x3682 2144 #: Run the self test. 2145 COMMAND_PERFORM_SELF_TEST = 0x3639 2146 #: Restore the factory settings. 2147 COMMAND_PERFORM_FACTORY_RESET = 0x3632 2148 #: Reinitialize from the stored settings. 2149 COMMAND_REINIT = 0x3646 2150 #: Take one measurement and return to idle. 2151 COMMAND_MEASURE_SINGLE_SHOT = 0x219D 2152 #: Take one humidity and temperature measurement, without carbon dioxide. 2153 COMMAND_MEASURE_SINGLE_SHOT_RHT_ONLY = 0x2196 2154 #: Enter sleep, SCD41 only. 2155 COMMAND_POWER_DOWN = 0x36E0 2156 #: Leave sleep, SCD41 only. 2157 COMMAND_WAKE_UP = 0x36F6 2158 2159 def crc(self, data: bytes) -> int: 2160 """Compute the Sensirion CRC-8 the part appends to every word. 2161 2162 :param data: The bytes the checksum covers. 2163 :returns: The checksum. 2164 """ 2165 return _scd4x_crc(bytes(data)) 2166 2167 def word(self, frame: bytes) -> int: 2168 """Read a CRC-checked three-byte word frame. 2169 2170 :param frame: The two data bytes and their checksum. 2171 :returns: The 16-bit word. 2172 :raises ValueError: If the frame is not three bytes. 2173 :raises PamojaError: If the checksum does not match, which means the read 2174 was corrupted on the bus and should be repeated. 2175 """ 2176 return _scd4x_word(bytes(frame)) 2177 2178 def word_frame(self, value: int) -> bytes: 2179 """Build the three bytes the part sends for a word: the word then its CRC. 2180 2181 :param value: The 16-bit word. 2182 :returns: The frame in transmission order. 2183 """ 2184 return bytes(_scd4x_word_frame(value)) 2185 2186 def command_frame(self, command: int) -> bytes: 2187 """Build the two bytes that send a bare command. 2188 2189 :param command: The 16-bit command word. 2190 :returns: The bytes to write, most significant first. 2191 """ 2192 return bytes(_scd4x_command_frame(command)) 2193 2194 def write_frame(self, command: int, value: int) -> bytes: 2195 """Build the five bytes that send a command with an argument. 2196 2197 :param command: The 16-bit command word. 2198 :param value: The argument the command takes. 2199 :returns: The command, the argument, and the argument's CRC. 2200 """ 2201 return bytes(_scd4x_write_frame(command, value)) 2202 2203 def max_duration_ms(self, command: int) -> int | None: 2204 """Return how long a command may take. 2205 2206 :param command: The 16-bit command word. 2207 :returns: The datasheet's execution time in milliseconds, or ``None`` for a 2208 command that completes without one. 2209 """ 2210 return _scd4x_max_duration_ms(command) 2211 2212 def allowed_during_measurement(self, command: int) -> bool: 2213 """Report whether the part accepts a command while it is measuring. 2214 2215 :param command: The 16-bit command word. 2216 :returns: Whether the command can be sent without stopping measurement first. 2217 """ 2218 return _scd4x_allowed_during_measurement(command) 2219 2220 def parse_measurement(self, frame: bytes) -> Scd4xMeasurement: 2221 """Parse and CRC-check a nine-byte measurement frame. 2222 2223 :param frame: The three words and their checksums, as the device sent them. 2224 :returns: The decoded reading, in raw words and physical units. 2225 :raises ValueError: If the frame is not nine bytes. 2226 :raises PamojaError: If any checksum does not match. 2227 """ 2228 return _scd4x_parse_measurement(bytes(frame)) 2229 2230 def measurement_from_physical( 2231 self, co2_ppm: int, milli_celsius: int, humidity_milli_percent: int 2232 ) -> Scd4xMeasurement: 2233 """Build the measurement a sensor reporting these values would send. 2234 2235 :param co2_ppm: The carbon dioxide concentration in parts per million. 2236 :param milli_celsius: The temperature in milli-degrees Celsius. 2237 :param humidity_milli_percent: The relative humidity in milli-percent. 2238 :returns: The measurement, with the raw words the part would have reported. 2239 """ 2240 return _scd4x_measurement_from_physical( 2241 co2_ppm, milli_celsius, humidity_milli_percent 2242 ) 2243 2244 def measurement_bytes( 2245 self, co2_ppm: int, temperature_raw: int, humidity_raw: int 2246 ) -> bytes: 2247 """Build the nine bytes the part sends for a set of raw words. 2248 2249 The inverse of :meth:`parse_measurement`, so a node can be written and tested 2250 against what a sensor sends without one attached. 2251 2252 :param co2_ppm: The carbon dioxide concentration in parts per million. 2253 :param temperature_raw: The raw temperature word. 2254 :param humidity_raw: The raw humidity word. 2255 :returns: The frame in transmission order, each word followed by its CRC. 2256 """ 2257 return bytes(_scd4x_measurement_bytes(co2_ppm, temperature_raw, humidity_raw)) 2258 2259 def milli_celsius(self, raw: int) -> int: 2260 """Convert a raw temperature word to milli-degrees Celsius. 2261 2262 :param raw: The 16-bit temperature word. 2263 :returns: The temperature, exact in integer arithmetic. 2264 """ 2265 return _scd4x_milli_celsius(raw) 2266 2267 def celsius(self, raw: int) -> float: 2268 """Convert a raw temperature word to degrees Celsius. 2269 2270 :param raw: The 16-bit temperature word. 2271 :returns: The temperature. 2272 """ 2273 return _scd4x_celsius(raw) 2274 2275 def temperature_raw(self, milli_celsius: int) -> int: 2276 """Build the temperature word that decodes to a temperature. 2277 2278 :param milli_celsius: The temperature in milli-degrees Celsius. 2279 :returns: The 16-bit word, clamped to the part's range. 2280 """ 2281 return _scd4x_temperature_raw(milli_celsius) 2282 2283 def humidity_milli_percent(self, raw: int) -> int: 2284 """Convert a raw humidity word to milli-percent. 2285 2286 :param raw: The 16-bit humidity word. 2287 :returns: The relative humidity, exact in integer arithmetic. 2288 """ 2289 return _scd4x_humidity_milli_percent(raw) 2290 2291 def relative_humidity_percent(self, raw: int) -> float: 2292 """Convert a raw humidity word to a relative humidity percentage. 2293 2294 :param raw: The 16-bit humidity word. 2295 :returns: The relative humidity. 2296 """ 2297 return _scd4x_relative_humidity_percent(raw) 2298 2299 def humidity_raw(self, milli_percent: int) -> int: 2300 """Build the humidity word that decodes to a relative humidity. 2301 2302 :param milli_percent: The relative humidity in milli-percent. 2303 :returns: The 16-bit word, clamped to full scale. 2304 """ 2305 return _scd4x_humidity_raw(milli_percent) 2306 2307 def data_ready(self, word: int) -> bool: 2308 """Report whether a data-ready word says a measurement is waiting. 2309 2310 :param word: The word the data-ready command returned. 2311 :returns: Whether a result can be read. 2312 """ 2313 return _scd4x_data_ready(word) 2314 2315 def temperature_offset_word(self, milli_celsius: int) -> int: 2316 """Build the word that programs a temperature offset. 2317 2318 The offset scales by 2^16, not by the 2^16 - 1 a measurement uses. 2319 2320 :param milli_celsius: The offset in milli-degrees Celsius. 2321 :returns: The word to write. 2322 """ 2323 return _scd4x_temperature_offset_word(milli_celsius) 2324 2325 def temperature_offset_milli_celsius(self, word: int) -> int: 2326 """Convert a temperature-offset word back to milli-degrees Celsius. 2327 2328 :param word: The word the part returned. 2329 :returns: The offset in milli-degrees Celsius. 2330 """ 2331 return _scd4x_temperature_offset_milli_celsius(word) 2332 2333 def ambient_pressure_word(self, pascals: int) -> int: 2334 """Build the word that programs an ambient pressure. 2335 2336 :param pascals: The ambient pressure. 2337 :returns: The word to write, in hundreds of pascals. 2338 """ 2339 return _scd4x_ambient_pressure_word(pascals) 2340 2341 def ambient_pressure_pascals(self, word: int) -> int: 2342 """Convert an ambient-pressure word back to pascals. 2343 2344 :param word: The word the part holds. 2345 :returns: The ambient pressure. 2346 """ 2347 return _scd4x_ambient_pressure_pascals(word) 2348 2349 def forced_recalibration_correction_ppm(self, word: int) -> int | None: 2350 """Read the correction the part reports after a forced recalibration. 2351 2352 :param word: The word the recalibration command returned. 2353 :returns: The correction in parts per million, or ``None`` if the 2354 recalibration did not take. 2355 """ 2356 return _scd4x_forced_recalibration_correction_ppm(word) 2357 2358 def forced_recalibration_word(self, correction_ppm: int | None = None) -> int: 2359 """Build the word the part returns for a forced-recalibration outcome. 2360 2361 :param correction_ppm: The correction in parts per million, or ``None`` for 2362 a recalibration that did not take. 2363 :returns: The word. 2364 """ 2365 return _scd4x_forced_recalibration_word(correction_ppm) 2366 2367 def automatic_self_calibration_enabled(self, word: int) -> bool: 2368 """Report whether a word says automatic self-calibration is on. 2369 2370 :param word: The word the part returned. 2371 :returns: Whether the part recalibrates itself against clean air. 2372 """ 2373 return _scd4x_automatic_self_calibration_enabled(word) 2374 2375 def automatic_self_calibration_word(self, enabled: bool) -> int: 2376 """Build the word that turns automatic self-calibration on or off. 2377 2378 :param enabled: Whether to leave self-calibration running. 2379 :returns: The word to write. 2380 """ 2381 return _scd4x_automatic_self_calibration_word(enabled) 2382 2383 def self_test_passed(self, word: int) -> bool: 2384 """Report whether a self-test word says the part passed. 2385 2386 :param word: The word the self-test command returned. 2387 :returns: Whether the part reported no malfunction. 2388 """ 2389 return _scd4x_self_test_passed(word) 2390 2391 def serial_number(self, frame: bytes) -> int: 2392 """Read a CRC-checked nine-byte serial-number frame. 2393 2394 :param frame: The three words and their checksums. 2395 :returns: The 48-bit serial number. 2396 :raises ValueError: If the frame is not nine bytes. 2397 :raises PamojaError: If any checksum does not match. 2398 """ 2399 return _scd4x_serial_number(bytes(frame)) 2400 2401 def serial_number_frame(self, serial: int) -> bytes: 2402 """Build the nine bytes the part sends for a serial number. 2403 2404 :param serial: The 48-bit serial number. 2405 :returns: The frame in transmission order, each word followed by its CRC. 2406 """ 2407 return bytes(_scd4x_serial_number_frame(serial)) 2408 2409 2410class _Tmp117Sim: 2411 """A TMP117 that is not there, for a bus with nothing plugged in. 2412 2413 Its configuration register keeps the flags the part sets for itself whatever a driver 2414 writes, with the data-ready flag set, so every conversion reads as finished. 2415 """ 2416 2417 __slots__ = () 2418 2419 #: The temperature :meth:`part` reports. 2420 CELSIUS = 21.25 2421 2422 def part(self, address: int) -> WordPart: 2423 """Make a part reading :attr:`CELSIUS`. 2424 2425 :param address: The address it answers to. 2426 :returns: The part, to put on a simulated bus. 2427 """ 2428 return WordPart._wrap(_tmp117_sim_part(address)) 2429 2430 def reporting(self, address: int, celsius: float) -> WordPart: 2431 """Make a part that reads what it is asked to, to the nearest 7.8125 millidegrees. 2432 2433 :param address: The address it answers to. 2434 :param celsius: The temperature it reports. 2435 :returns: The part, to put on a simulated bus. 2436 """ 2437 return WordPart._wrap(_tmp117_sim_reporting(address, celsius)) 2438 2439 2440class _Tmp117: 2441 """A TI TMP117 precision thermometer.""" 2442 2443 __slots__ = () 2444 2445 #: The averaging codes. 2446 Averaging = Tmp117Averaging 2447 #: A TMP117 that is not there, for a bus with nothing plugged in. 2448 sim = _Tmp117Sim() 2449 2450 #: The value the device-ID register reads, which confirms the part. 2451 DEVICE_ID = 0x0117 2452 #: The value the configuration register reads after a reset. 2453 CONFIG_RESET = 0x0220 2454 #: The value the high-limit register holds after a reset. 2455 HIGH_LIMIT_RESET = 0x6000 2456 #: The value the low-limit register holds after a reset. 2457 LOW_LIMIT_RESET = 0x8000 2458 #: The value the result register holds before the first conversion. 2459 TEMP_RESULT_RESET = 0x8000 2460 #: The byte a general-call reset sends to address 0x00. 2461 GENERAL_CALL_RESET = 0x06 2462 #: The word written to the EEPROM-unlock register to allow a write. 2463 EEPROM_UNLOCK = 0x8000 2464 #: The address with ADD0 tied to GND. 2465 ADDRESS_ADD0_GND = 0x48 2466 #: The address with ADD0 tied to V+. 2467 ADDRESS_ADD0_VPLUS = 0x49 2468 #: The address with ADD0 tied to SDA. 2469 ADDRESS_ADD0_SDA = 0x4A 2470 #: The address with ADD0 tied to SCL. 2471 ADDRESS_ADD0_SCL = 0x4B 2472 #: The temperature result. 2473 REGISTER_TEMP_RESULT = 0x00 2474 #: The configuration register. 2475 REGISTER_CONFIGURATION = 0x01 2476 #: The high alert limit. 2477 REGISTER_THIGH_LIMIT = 0x02 2478 #: The low alert limit. 2479 REGISTER_TLOW_LIMIT = 0x03 2480 #: The EEPROM unlock register. 2481 REGISTER_EEPROM_UL = 0x04 2482 #: The first general-purpose EEPROM word. 2483 REGISTER_EEPROM1 = 0x05 2484 #: The second general-purpose EEPROM word. 2485 REGISTER_EEPROM2 = 0x06 2486 #: The temperature offset applied to every result. 2487 REGISTER_TEMP_OFFSET = 0x07 2488 #: The third general-purpose EEPROM word. 2489 REGISTER_EEPROM3 = 0x08 2490 #: The device-ID register. 2491 REGISTER_DEVICE_ID = 0x0F 2492 2493 def nano_celsius(self, raw: int) -> int: 2494 """Convert a raw temperature register to nano-degrees Celsius. 2495 2496 :param raw: The signed 16-bit register. 2497 :returns: The temperature, exact at the part's 7.8125 m°C resolution. 2498 """ 2499 return _tmp117_nano_celsius(raw) 2500 2501 def micro_celsius(self, raw: int) -> int: 2502 """Convert a raw temperature register to micro-degrees Celsius. 2503 2504 :param raw: The signed 16-bit register. 2505 :returns: The temperature, truncated toward zero. 2506 """ 2507 return _tmp117_micro_celsius(raw) 2508 2509 def celsius(self, raw: int) -> float: 2510 """Convert a raw temperature register to degrees Celsius. 2511 2512 :param raw: The signed 16-bit register. 2513 :returns: The temperature. 2514 """ 2515 return _tmp117_celsius(raw) 2516 2517 def raw_from_micro_celsius(self, micro_celsius: int) -> int: 2518 """Build the temperature register that decodes to a temperature. 2519 2520 :param micro_celsius: The temperature in micro-degrees Celsius. 2521 :returns: The signed register, rounded to nearest and saturating at the 2522 part's range. 2523 """ 2524 return _tmp117_raw_from_micro_celsius(micro_celsius) 2525 2526 def raw_from_celsius(self, celsius: float) -> int: 2527 """Build the temperature register that decodes to a temperature in Celsius. 2528 2529 :param celsius: The temperature. 2530 :returns: The signed register, saturating at the part's range. 2531 """ 2532 return _tmp117_raw_from_celsius(celsius) 2533 2534 def temperature_bytes(self, raw: int) -> bytes: 2535 """Build the two bytes the part sends for a temperature register. 2536 2537 :param raw: The signed 16-bit register. 2538 :returns: The bytes, most significant first. 2539 """ 2540 return bytes(_tmp117_temperature_bytes(raw)) 2541 2542 def temperature_from_bytes(self, data: bytes) -> int: 2543 """Read the two bytes the part sends for a temperature register. 2544 2545 :param data: The two register bytes, most significant first. 2546 :returns: The signed register value. 2547 :raises ValueError: If the read is not two bytes. 2548 """ 2549 return _tmp117_temperature_from_bytes(bytes(data)) 2550 2551 def device_id(self, raw: int) -> int: 2552 """Read the device identifier out of a device-ID register. 2553 2554 :param raw: The device-ID register. 2555 :returns: The 12-bit identifier, :attr:`DEVICE_ID` for a TMP117. 2556 """ 2557 return _tmp117_device_id(raw) 2558 2559 def revision(self, raw: int) -> int: 2560 """Read the die revision out of a device-ID register. 2561 2562 :param raw: The device-ID register. 2563 :returns: The 4-bit revision. 2564 """ 2565 return _tmp117_revision(raw) 2566 2567 def high_alert(self, config: int) -> bool: 2568 """Report whether a configuration register flags a high alert. 2569 2570 :param config: The configuration register. 2571 :returns: Whether a result went above the high limit. 2572 """ 2573 return _tmp117_high_alert(config) 2574 2575 def low_alert(self, config: int) -> bool: 2576 """Report whether a configuration register flags a low alert. 2577 2578 :param config: The configuration register. 2579 :returns: Whether a result went below the low limit. 2580 """ 2581 return _tmp117_low_alert(config) 2582 2583 def data_ready(self, config: int) -> bool: 2584 """Report whether a configuration register says a result is ready. 2585 2586 :param config: The configuration register. 2587 :returns: Whether a conversion completed since the register was last read. 2588 """ 2589 return _tmp117_data_ready(config) 2590 2591 def eeprom_busy(self, config: int) -> bool: 2592 """Report whether a configuration register says an EEPROM write is running. 2593 2594 :param config: The configuration register. 2595 :returns: Whether a programming cycle is still in progress. 2596 """ 2597 return _tmp117_eeprom_busy(config) 2598 2599 def eeprom_unlock_busy(self, unlock: int) -> bool: 2600 """Report whether an EEPROM unlock register says a write is running. 2601 2602 :param unlock: The EEPROM unlock register. 2603 :returns: Whether a programming cycle is still in progress. 2604 """ 2605 return _tmp117_eeprom_unlock_busy(unlock) 2606 2607 def config_bits(self, config: Tmp117Config) -> int: 2608 """Assemble the 16-bit configuration register value. 2609 2610 :param config: The settings to encode. 2611 :returns: The register value to write. 2612 """ 2613 return _tmp117_config_bits(config) 2614 2615 def config_from_bits(self, bits: int) -> Tmp117Config: 2616 """Parse a 16-bit configuration register value. 2617 2618 :param bits: The register value, as read from the device. 2619 :returns: The decoded settings. Every value decodes, so this never raises. 2620 """ 2621 return _tmp117_config_from_bits(bits) 2622 2623 def conversions(self, averaging: int) -> int: 2624 """Return how many conversions an averaging code folds into one result. 2625 2626 :param averaging: The averaging code, 0 to 3. 2627 :returns: The conversion count: 1, 8, 32, or 64. 2628 """ 2629 return _tmp117_averaging_conversions(averaging) 2630 2631 def conversion_micros(self, averaging: int) -> int: 2632 """Return how long an averaging code takes to convert. 2633 2634 :param averaging: The averaging code, 0 to 3. 2635 :returns: The conversion time in microseconds. 2636 """ 2637 return _tmp117_averaging_micros(averaging) 2638 2639 def nominal_micros(self, cycle: int) -> int: 2640 """Return the nominal cycle a conversion-cycle code selects. 2641 2642 :param cycle: The conversion-cycle code, 0 to 7. 2643 :returns: The nominal cycle in microseconds. 2644 """ 2645 return _tmp117_cycle_nominal_micros(cycle) 2646 2647 def cycle_micros(self, cycle: int, averaging: int) -> int: 2648 """Return the result-update interval for a cycle and averaging code. 2649 2650 A cycle shorter than the conversion it asks for stretches to the conversion. 2651 2652 :param cycle: The conversion-cycle code, 0 to 7. 2653 :param averaging: The averaging code, 0 to 3. 2654 :returns: The interval in microseconds. 2655 """ 2656 return _tmp117_cycle_micros(cycle, averaging) 2657 2658class _Hdc1080Sim: 2659 """An HDC1080 that is not there, for a bus with nothing plugged in.""" 2660 2661 __slots__ = () 2662 2663 #: The temperature :meth:`part` reports. 2664 CELSIUS = 22.5 2665 #: The relative humidity :meth:`part` reports, as a percentage. 2666 RELATIVE_HUMIDITY = 45.0 2667 2668 def part(self) -> WordPart: 2669 """Make a part reading :attr:`CELSIUS` and :attr:`RELATIVE_HUMIDITY`, at the one 2670 address an HDC1080 has. 2671 2672 :returns: The part, to put on a simulated bus. 2673 """ 2674 return WordPart._wrap(_hdc1080_sim_part()) 2675 2676 def reporting(self, celsius: float, relative_humidity: float) -> WordPart: 2677 """Make a part that reads what it is asked to, within three thousandths of a degree 2678 and two thousandths of a percent. 2679 2680 :param celsius: The temperature it reports. 2681 :param relative_humidity: The humidity it reports, as a percentage. 2682 :returns: The part, to put on a simulated bus. 2683 """ 2684 return WordPart._wrap(_hdc1080_sim_reporting(celsius, relative_humidity)) 2685 2686 2687class _Hdc1080: 2688 """A TI HDC1080 temperature and humidity sensor.""" 2689 2690 __slots__ = () 2691 2692 #: The temperature resolutions. 2693 TemperatureResolution = Hdc1080TemperatureResolution 2694 #: The humidity resolutions. 2695 HumidityResolution = Hdc1080HumidityResolution 2696 #: An HDC1080 that is not there, for a bus with nothing plugged in. 2697 sim = _Hdc1080Sim() 2698 2699 #: The only address the part answers on. 2700 ADDRESS = 0x40 2701 #: The value the manufacturer-ID register reads. 2702 MANUFACTURER_ID = 0x5449 2703 #: The value the device-ID register reads, which confirms the part. 2704 DEVICE_ID = 0x1050 2705 #: The value the configuration register reads after a reset. 2706 CONFIGURATION_RESET = 0x1000 2707 #: The temperature result. 2708 REGISTER_TEMPERATURE = 0x00 2709 #: The humidity result. 2710 REGISTER_HUMIDITY = 0x01 2711 #: The configuration register. 2712 REGISTER_CONFIGURATION = 0x02 2713 #: The top word of the serial number. 2714 REGISTER_SERIAL_ID_HIGH = 0xFB 2715 #: The middle word of the serial number. 2716 REGISTER_SERIAL_ID_MID = 0xFC 2717 #: The bottom word of the serial number. 2718 REGISTER_SERIAL_ID_LOW = 0xFD 2719 #: The manufacturer-ID register. 2720 REGISTER_MANUFACTURER_ID = 0xFE 2721 #: The device-ID register. 2722 REGISTER_DEVICE_ID = 0xFF 2723 2724 def milli_celsius(self, raw: int) -> int: 2725 """Convert a raw temperature register to milli-degrees Celsius. 2726 2727 :param raw: The 16-bit register. 2728 :returns: The temperature, exact in integer arithmetic. 2729 """ 2730 return _hdc1080_milli_celsius(raw) 2731 2732 def celsius(self, raw: int) -> float: 2733 """Convert a raw temperature register to degrees Celsius. 2734 2735 :param raw: The 16-bit register. 2736 :returns: The temperature. 2737 """ 2738 return _hdc1080_celsius(raw) 2739 2740 def milli_percent(self, raw: int) -> int: 2741 """Convert a raw humidity register to milli-percent. 2742 2743 :param raw: The 16-bit register. 2744 :returns: The relative humidity, exact in integer arithmetic. 2745 """ 2746 return _hdc1080_milli_percent(raw) 2747 2748 def relative_humidity(self, raw: int) -> float: 2749 """Convert a raw humidity register to a relative humidity percentage. 2750 2751 :param raw: The 16-bit register. 2752 :returns: The relative humidity. 2753 """ 2754 return _hdc1080_relative_humidity(raw) 2755 2756 def temperature_register(self, milli_celsius: int) -> int: 2757 """Build the temperature register that decodes to a temperature. 2758 2759 :param milli_celsius: The temperature in milli-degrees Celsius. 2760 :returns: The 14-bit code in bits 15:2, clamped to the part's range. 2761 """ 2762 return _hdc1080_temperature_register(milli_celsius) 2763 2764 def humidity_register(self, milli_percent: int) -> int: 2765 """Build the humidity register that decodes to a relative humidity. 2766 2767 :param milli_percent: The relative humidity in milli-percent. 2768 :returns: The 14-bit code in bits 15:2, clamped to full scale. 2769 """ 2770 return _hdc1080_humidity_register(milli_percent) 2771 2772 def serial_id(self, high: int, mid: int, low: int) -> int: 2773 """Join the three serial-ID registers into the serial number. 2774 2775 :param high: The top serial-ID register. 2776 :param mid: The middle serial-ID register. 2777 :param low: The bottom serial-ID register. 2778 :returns: The 40-bit serial number. 2779 """ 2780 return _hdc1080_serial_id(high, mid, low) 2781 2782 def serial_id_registers(self, serial: int) -> tuple[int, int, int]: 2783 """Split a serial number back into the three serial-ID registers. 2784 2785 :param serial: The 40-bit serial number. 2786 :returns: The high, middle, and low registers. 2787 """ 2788 high, mid, low = _hdc1080_serial_id_registers(serial) 2789 return high, mid, low 2790 2791 def parse_measurement(self, data: bytes) -> Hdc1080Measurement: 2792 """Parse the four bytes a sequential read returns. 2793 2794 The part appends no checksum, so every read decodes. 2795 2796 :param data: The temperature and humidity registers, most significant first. 2797 :returns: The decoded reading, in raw registers and physical units. 2798 :raises ValueError: If the read is not four bytes. 2799 """ 2800 return _hdc1080_parse_measurement(bytes(data)) 2801 2802 def measurement_from_physical( 2803 self, milli_celsius: int, milli_percent: int 2804 ) -> Hdc1080Measurement: 2805 """Build the measurement a sensor reporting these values would send. 2806 2807 :param milli_celsius: The temperature in milli-degrees Celsius. 2808 :param milli_percent: The relative humidity in milli-percent. 2809 :returns: The measurement, with the raw registers the part would have held. 2810 """ 2811 return _hdc1080_measurement_from_physical(milli_celsius, milli_percent) 2812 2813 def measurement_bytes(self, temperature_raw: int, humidity_raw: int) -> bytes: 2814 """Build the four bytes the part sends for a pair of raw registers. 2815 2816 The inverse of :meth:`parse_measurement`, so a node can be written and tested 2817 against what a sensor sends without one attached. 2818 2819 :param temperature_raw: The raw temperature register. 2820 :param humidity_raw: The raw humidity register. 2821 :returns: The four bytes in read order. 2822 """ 2823 return bytes(_hdc1080_measurement_bytes(temperature_raw, humidity_raw)) 2824 2825 def config_from_register(self, raw: int) -> Hdc1080Config: 2826 """Parse a configuration register value. 2827 2828 :param raw: The register value, as read from the device. 2829 :returns: The decoded settings. 2830 :raises PamojaError: If the humidity-resolution field holds the code the 2831 datasheet leaves undefined, which no working part reports. 2832 """ 2833 return _hdc1080_config_from_register(raw) 2834 2835 def config_to_register(self, config: Hdc1080Config) -> int: 2836 """Assemble a configuration register value. 2837 2838 :param config: The settings to encode. 2839 :returns: The register value to write. 2840 :raises ValueError: If either resolution is not one the part offers. 2841 """ 2842 return _hdc1080_config_to_register(config) 2843 2844 def conversion_time_micros(self, config: Hdc1080Config) -> int: 2845 """Return how long to wait after triggering the part in this configuration. 2846 2847 :param config: The settings the part is running. 2848 :returns: The conversion time in microseconds, both channels in sequential 2849 mode. 2850 :raises ValueError: If either resolution is not one the part offers. 2851 """ 2852 return _hdc1080_conversion_time_micros(config) 2853 2854 def temperature_conversion_micros(self, bits: int) -> int: 2855 """Return how long a temperature conversion takes. 2856 2857 :param bits: The temperature resolution in bits: 14 or 11. 2858 :returns: The conversion time in microseconds. 2859 :raises ValueError: If the resolution is not one the part offers. 2860 """ 2861 return _hdc1080_temperature_conversion_micros(bits) 2862 2863 def humidity_conversion_micros(self, bits: int) -> int: 2864 """Return how long a humidity conversion takes. 2865 2866 :param bits: The humidity resolution in bits: 14, 11, or 8. 2867 :returns: The conversion time in microseconds. 2868 :raises ValueError: If the resolution is not one the part offers. 2869 """ 2870 return _hdc1080_humidity_conversion_micros(bits) 2871 2872 2873class _Opt3001Sim: 2874 """An OPT3001 that is not there, for a bus with nothing plugged in. 2875 2876 Its configuration register keeps the flags the part sets for itself whatever a driver 2877 writes, with the conversion-ready flag set, so every conversion reads as finished. 2878 """ 2879 2880 __slots__ = () 2881 2882 #: The illuminance :meth:`part` reports. 2883 LUX = 380.0 2884 2885 def part(self, address: int) -> WordPart: 2886 """Make a part reading :attr:`LUX`. 2887 2888 :param address: The address it answers to. 2889 :returns: The part, to put on a simulated bus. 2890 """ 2891 return WordPart._wrap(_opt3001_sim_part(address)) 2892 2893 def reporting(self, address: int, lux: float) -> WordPart: 2894 """Make a part that reads what it is asked to, to the nearest step its exponent and 2895 mantissa represent. 2896 2897 :param address: The address it answers to. 2898 :param lux: The illuminance it reports. 2899 :returns: The part, to put on a simulated bus. 2900 """ 2901 return WordPart._wrap(_opt3001_sim_reporting(address, lux)) 2902 2903 2904class _Opt3001: 2905 """A TI OPT3001 ambient light sensor.""" 2906 2907 __slots__ = () 2908 2909 #: The conversion times. 2910 ConversionTime = Opt3001ConversionTime 2911 #: An OPT3001 that is not there, for a bus with nothing plugged in. 2912 sim = _Opt3001Sim() 2913 2914 #: The address the part answers on with ADDR tied to GND. 2915 ADDRESS_GND = 0x44 2916 #: The address it answers on with ADDR tied to VDD. 2917 ADDRESS_VDD = 0x45 2918 #: The address it answers on with ADDR tied to SDA. 2919 ADDRESS_SDA = 0x46 2920 #: The address it answers on with ADDR tied to SCL. 2921 ADDRESS_SCL = 0x47 2922 #: The value the manufacturer-ID register reads. 2923 MANUFACTURER_ID = 0x5449 2924 #: The value the device-ID register reads, which confirms the part. 2925 DEVICE_ID = 0x3001 2926 #: The value the configuration register reads after a reset. 2927 CONFIGURATION_RESET = 0xC810 2928 #: The value the low-limit register holds after a reset. 2929 LOW_LIMIT_RESET = 0x0000 2930 #: The value the high-limit register holds after a reset. 2931 HIGH_LIMIT_RESET = 0xBFFF 2932 #: The low-limit value that turns the INT pin into an end-of-conversion signal. 2933 LOW_LIMIT_END_OF_CONVERSION = 0xC000 2934 #: The range number that lets the part choose its own full scale. 2935 RANGE_AUTOMATIC = 0b1100 2936 #: The highest fixed range number. 2937 RANGE_MAX = 11 2938 #: The result register. 2939 REGISTER_RESULT = 0x00 2940 #: The configuration register. 2941 REGISTER_CONFIGURATION = 0x01 2942 #: The low limit. 2943 REGISTER_LOW_LIMIT = 0x02 2944 #: The high limit. 2945 REGISTER_HIGH_LIMIT = 0x03 2946 #: The manufacturer-ID register. 2947 REGISTER_MANUFACTURER_ID = 0x7E 2948 #: The device-ID register. 2949 REGISTER_DEVICE_ID = 0x7F 2950 2951 def lsb_milli_lux(self, exponent: int) -> int | None: 2952 """Return the illuminance one count carries at an exponent. 2953 2954 :param exponent: The result's exponent field, 0 to 11. 2955 :returns: The step in milli-lux, or ``None`` for a reserved exponent. 2956 """ 2957 return _opt3001_lsb_milli_lux(exponent) 2958 2959 def full_scale_milli_lux(self, range_number: int) -> int | None: 2960 """Return the full scale a range number covers. 2961 2962 :param range_number: The range number, 0 to 11. 2963 :returns: The full scale in milli-lux, or ``None`` for a reserved range, 2964 which includes the automatic-range code. 2965 """ 2966 return _opt3001_full_scale_milli_lux(range_number) 2967 2968 def milli_lux(self, raw: int) -> int: 2969 """Convert a raw result register to milli-lux. 2970 2971 :param raw: The register value, an exponent and a 12-bit mantissa. 2972 :returns: The illuminance, exact in integer arithmetic. 2973 """ 2974 return _opt3001_milli_lux(raw) 2975 2976 def lux(self, raw: int) -> float: 2977 """Convert a raw result register to lux. 2978 2979 :param raw: The register value. 2980 :returns: The illuminance. 2981 """ 2982 return _opt3001_lux(raw) 2983 2984 def raw_from_milli_lux(self, milli_lux: int) -> int: 2985 """Build the result register that decodes to an illuminance. 2986 2987 The smallest exponent that holds the value is used, so the mantissa keeps 2988 as much resolution as the format allows. 2989 2990 :param milli_lux: The illuminance in milli-lux. 2991 :returns: The register value, saturating at full scale. 2992 """ 2993 return _opt3001_raw_from_milli_lux(milli_lux) 2994 2995 def word_from_bytes(self, data: bytes) -> int: 2996 """Read the two bytes the part sends for a register. 2997 2998 :param data: The register bytes, most significant first. 2999 :returns: The register value. 3000 :raises ValueError: If the read is not two bytes. 3001 """ 3002 return _opt3001_word_from_bytes(bytes(data)) 3003 3004 def word_to_bytes(self, word: int) -> bytes: 3005 """Build the two bytes the part sends for a register. 3006 3007 :param word: The register value. 3008 :returns: The bytes, most significant first. 3009 """ 3010 return bytes(_opt3001_word_to_bytes(word)) 3011 3012 def config_bits(self, config: Opt3001Config) -> int: 3013 """Assemble the 16-bit configuration register value. 3014 3015 The read-only status bits are written as zero. 3016 3017 :param config: The settings to encode. 3018 :returns: The register value to write. 3019 """ 3020 return _opt3001_config_bits(config) 3021 3022 def config_from_bits(self, bits: int) -> Opt3001Config: 3023 """Parse a 16-bit configuration register value. 3024 3025 :param bits: The register value, as read from the device. 3026 :returns: The decoded settings. Every value decodes, so this never raises. 3027 """ 3028 return _opt3001_config_from_bits(bits) 3029 3030 def conversion_millis(self, long_conversion: bool) -> int: 3031 """Return the conversion time a setting selects. 3032 3033 :param long_conversion: Whether the 800 ms conversion is selected rather 3034 than the 100 ms one. 3035 :returns: The conversion time in milliseconds. 3036 """ 3037 return _opt3001_conversion_millis(long_conversion) 3038 3039 def fault_count(self, code: int) -> int: 3040 """Return how many consecutive faults a fault-count code requires. 3041 3042 :param code: The fault-count code, 0 to 3. 3043 :returns: The fault count: 1, 2, 4, or 8. 3044 """ 3045 return _opt3001_fault_count(code) 3046 3047 def is_automatic_range(self, range_number: int) -> bool: 3048 """Report whether a range number sets the full scale automatically. 3049 3050 :param range_number: The range number from a configuration register. 3051 :returns: Whether the part chooses its own full scale. 3052 """ 3053 return _opt3001_is_automatic_range(range_number) 3054 3055 3056class _Ina226Sim: 3057 """An INA226 that is not there, for a bus with nothing plugged in. 3058 3059 It carries TI's manufacturer id and the INA226 die id, its conversion-ready flag is set, 3060 and :meth:`reporting` takes the same shunt and largest current a driver is given. 3061 """ 3062 3063 __slots__ = () 3064 3065 #: The shunt :meth:`part` sits across, in milliohms. 3066 SHUNT_MILLIOHMS = 100 3067 #: The largest current :meth:`part` is sized for, in microamps. 3068 MAX_MICROAMPS = 3_200_000 3069 #: The bus voltage :meth:`part` reports, in microvolts. 3070 BUS_MICROVOLTS = 12_000_000 3071 #: The current :meth:`part` reports, in microamps. 3072 MICROAMPS = 500_000 3073 3074 def part(self, address: int) -> WordPart: 3075 """Make a part carrying 500 mA at 12 V through the shunt a driver starts with. 3076 3077 :param address: The address it answers to. 3078 :returns: The part, to put on a simulated bus. 3079 """ 3080 return WordPart._wrap(_ina226_sim_part(address)) 3081 3082 def reporting( 3083 self, 3084 address: int, 3085 shunt_milliohms: int, 3086 max_microamps: int, 3087 bus_microvolts: int, 3088 microamps: int, 3089 ) -> WordPart: 3090 """Make a part that reads what it is asked to, on the steps its registers count 3091 in: 1.25 mV of bus, 2.5 uV of shunt, and the calibration's current step. 3092 3093 :param address: The address it answers to. 3094 :param shunt_milliohms: The shunt, as the driver is given it. 3095 :param max_microamps: The largest current, as the driver is given it. 3096 :param bus_microvolts: The bus voltage it reports. 3097 :param microamps: The current it reports; negative flows the other way. 3098 :returns: The part, to put on a simulated bus. 3099 """ 3100 return WordPart._wrap( 3101 _ina226_sim_reporting( 3102 address, shunt_milliohms, max_microamps, bus_microvolts, microamps 3103 ) 3104 ) 3105 3106 3107class _Ina226: 3108 """A TI INA226 current, voltage, and power monitor.""" 3109 3110 __slots__ = () 3111 3112 #: An INA226 that is not there, for a bus with nothing plugged in. 3113 sim = _Ina226Sim() 3114 3115 #: The address with both A1 and A0 tied to GND. 3116 BASE_ADDRESS = 0x40 3117 #: The value the manufacturer-ID register reads. 3118 MANUFACTURER_ID = 0x5449 3119 #: The device identifier the die-ID register carries for an INA226. 3120 DEVICE_ID = 0x226 3121 #: The value the configuration register reads after a reset. 3122 CONFIG_RESET = 0x4127 3123 #: The shunt voltage one count carries, in nanovolts. 3124 SHUNT_LSB_NANOVOLTS = 2_500 3125 #: The bus voltage one count carries, in microvolts. 3126 BUS_LSB_MICROVOLTS = 1_250 3127 #: How many times the power LSB is the current LSB. 3128 POWER_LSB_RATIO = 25 3129 #: An address pin tied to GND. 3130 PIN_GROUND = 0 3131 #: An address pin tied to VS. 3132 PIN_SUPPLY = 1 3133 #: An address pin tied to SDA. 3134 PIN_SDA = 2 3135 #: An address pin tied to SCL. 3136 PIN_SCL = 3 3137 #: The configuration register. 3138 REGISTER_CONFIGURATION = 0x00 3139 #: The shunt voltage result. 3140 REGISTER_SHUNT_VOLTAGE = 0x01 3141 #: The bus voltage result. 3142 REGISTER_BUS_VOLTAGE = 0x02 3143 #: The power result. 3144 REGISTER_POWER = 0x03 3145 #: The current result. 3146 REGISTER_CURRENT = 0x04 3147 #: The calibration register. 3148 REGISTER_CALIBRATION = 0x05 3149 #: The Mask/Enable register. 3150 REGISTER_MASK_ENABLE = 0x06 3151 #: The alert limit. 3152 REGISTER_ALERT_LIMIT = 0x07 3153 #: The manufacturer-ID register. 3154 REGISTER_MANUFACTURER_ID = 0xFE 3155 #: The die-ID register. 3156 REGISTER_DIE_ID = 0xFF 3157 3158 def address(self, a1: int, a0: int) -> int: 3159 """Return the 7-bit address the A1 and A0 pins select. 3160 3161 :param a1: What the A1 pin is tied to, one of the ``PIN_`` codes. 3162 :param a0: What the A0 pin is tied to. 3163 :returns: The address, 0x40 to 0x4F. 3164 :raises ValueError: If either pin code is not 0, 1, 2, or 3. 3165 """ 3166 return _ina226_address(a1, a0) 3167 3168 def averaging_samples(self, averaging: int) -> int: 3169 """Return how many samples an averaging code folds into one result. 3170 3171 :param averaging: The averaging code, 0 to 7. 3172 :returns: The sample count, from 1 to 1024. 3173 """ 3174 return _ina226_averaging_samples(averaging) 3175 3176 def conversion_micros(self, conversion_time: int) -> int: 3177 """Return the conversion time a code selects. 3178 3179 :param conversion_time: The conversion-time code, 0 to 7. 3180 :returns: The typical conversion time in microseconds. 3181 """ 3182 return _ina226_conversion_micros(conversion_time) 3183 3184 def measures_shunt(self, mode: int) -> bool: 3185 """Report whether a mode code converts the shunt voltage. 3186 3187 :param mode: The operating-mode code, 0 to 7. 3188 :returns: Whether the shunt input is converted. 3189 """ 3190 return _ina226_measures_shunt(mode) 3191 3192 def measures_bus(self, mode: int) -> bool: 3193 """Report whether a mode code converts the bus voltage. 3194 3195 :param mode: The operating-mode code, 0 to 7. 3196 :returns: Whether the bus input is converted. 3197 """ 3198 return _ina226_measures_bus(mode) 3199 3200 def is_continuous(self, mode: int) -> bool: 3201 """Report whether a mode code keeps converting after the first result. 3202 3203 :param mode: The operating-mode code, 0 to 7. 3204 :returns: Whether conversions run back to back. 3205 """ 3206 return _ina226_is_continuous(mode) 3207 3208 def config_from_register(self, raw: int) -> Ina226Config: 3209 """Parse a configuration register value. 3210 3211 :param raw: The register value, as read from the device. 3212 :returns: The decoded settings. Every value decodes, so this never raises. 3213 """ 3214 return _ina226_config_from_register(raw) 3215 3216 def config_to_register(self, config: Ina226Config) -> int: 3217 """Assemble a configuration register value. 3218 3219 :param config: The settings to encode. 3220 :returns: The register value to write, with reserved bit 14 set as at reset. 3221 """ 3222 return _ina226_config_to_register(config) 3223 3224 def update_micros(self, config: Ina226Config) -> int: 3225 """Return how often the part in this configuration updates its results. 3226 3227 :param config: The settings the part is running. 3228 :returns: The update interval in microseconds, or 0 in power-down. 3229 """ 3230 return _ina226_update_micros(config) 3231 3232 def mask_enable_from_register(self, raw: int) -> Ina226MaskEnable: 3233 """Parse a Mask/Enable register value. 3234 3235 :param raw: The register value, as read from the device. 3236 :returns: The decoded enables and flags. 3237 """ 3238 return _ina226_mask_enable_from_register(raw) 3239 3240 def mask_enable_to_register(self, mask: Ina226MaskEnable) -> int: 3241 """Assemble a Mask/Enable register value. 3242 3243 :param mask: The enables and flags to encode. 3244 :returns: The register value to write. 3245 """ 3246 return _ina226_mask_enable_to_register(mask) 3247 3248 def active_alert_function( 3249 self, mask: Ina226MaskEnable 3250 ) -> Ina226AlertFunction | None: 3251 """Return the alert function the pin actually responds to. 3252 3253 Only one limit function drives the pin at a time; when several are enabled 3254 the part honors the most significant bit. 3255 3256 :param mask: The enables and flags the part is running. 3257 :returns: The function the pin follows, or ``None`` if no limit function is 3258 enabled. 3259 """ 3260 function = _ina226_active_alert_function(mask) 3261 return None if function is None else Ina226AlertFunction(function) 3262 3263 def die_id(self, raw: int) -> Ina226DieId: 3264 """Split a die-ID register into its device and revision fields. 3265 3266 :param raw: The die-ID register. 3267 :returns: The device identifier and die revision. 3268 """ 3269 return _ina226_die_id(raw) 3270 3271 def identify(self, manufacturer_id: int, die_id: int) -> Ina226DieId: 3272 """Check that a pair of identification registers belongs to an INA226. 3273 3274 :param manufacturer_id: The manufacturer-ID register. 3275 :param die_id: The die-ID register. 3276 :returns: The device identifier and die revision. 3277 :raises PamojaError: If either register does not carry the value the 3278 datasheet fixes, which means a different part answered at that address 3279 and its readings must not be trusted. 3280 """ 3281 return _ina226_identify(manufacturer_id, die_id) 3282 3283 def calibration(self, current_lsb_microamps: int, shunt_milliohms: int) -> int: 3284 """Compute the calibration register for a shunt and current resolution. 3285 3286 :param current_lsb_microamps: The microamps per count the current register 3287 should carry. 3288 :param shunt_milliohms: The shunt resistor value. 3289 :returns: The register value to write. 3290 """ 3291 return _ina226_calibration(current_lsb_microamps, shunt_milliohms) 3292 3293 def minimum_current_lsb_microamps(self, max_expected_microamps: int) -> int: 3294 """Return the smallest current resolution that still covers a maximum. 3295 3296 :param max_expected_microamps: The largest current the application measures. 3297 :returns: The minimum current LSB in microamps. 3298 """ 3299 return _ina226_minimum_current_lsb_microamps(max_expected_microamps) 3300 3301 def shunt_nanovolts(self, raw: int) -> int: 3302 """Convert a raw shunt-voltage register to nanovolts. 3303 3304 :param raw: The signed register value. 3305 :returns: The shunt voltage, at 2.5 uV per count. 3306 """ 3307 return _ina226_shunt_nanovolts(raw) 3308 3309 def shunt_millivolts(self, raw: int) -> float: 3310 """Convert a raw shunt-voltage register to millivolts. 3311 3312 :param raw: The signed register value. 3313 :returns: The shunt voltage. 3314 """ 3315 return _ina226_shunt_millivolts(raw) 3316 3317 def bus_microvolts(self, raw: int) -> int: 3318 """Convert a raw bus-voltage register to microvolts. 3319 3320 :param raw: The register value. 3321 :returns: The bus voltage, at 1.25 mV per count. 3322 """ 3323 return _ina226_bus_microvolts(raw) 3324 3325 def bus_volts(self, raw: int) -> float: 3326 """Convert a raw bus-voltage register to volts. 3327 3328 :param raw: The register value. 3329 :returns: The bus voltage. 3330 """ 3331 return _ina226_bus_volts(raw) 3332 3333 def current_microamps(self, raw: int, current_lsb_microamps: int) -> int: 3334 """Convert a raw current register to microamps. 3335 3336 :param raw: The signed register value. 3337 :param current_lsb_microamps: The resolution the calibration selected. 3338 :returns: The current. 3339 """ 3340 return _ina226_current_microamps(raw, current_lsb_microamps) 3341 3342 def current_amps(self, raw: int, current_lsb_microamps: int) -> float: 3343 """Convert a raw current register to amps. 3344 3345 :param raw: The signed register value. 3346 :param current_lsb_microamps: The resolution the calibration selected. 3347 :returns: The current. 3348 """ 3349 return _ina226_current_amps(raw, current_lsb_microamps) 3350 3351 def power_microwatts(self, raw: int, current_lsb_microamps: int) -> int: 3352 """Convert a raw power register to microwatts. 3353 3354 :param raw: The register value. 3355 :param current_lsb_microamps: The resolution the calibration selected. 3356 :returns: The power. The power LSB is fixed at 25 times the current LSB. 3357 """ 3358 return _ina226_power_microwatts(raw, current_lsb_microamps) 3359 3360 def power_watts(self, raw: int, current_lsb_microamps: int) -> float: 3361 """Convert a raw power register to watts. 3362 3363 :param raw: The register value. 3364 :param current_lsb_microamps: The resolution the calibration selected. 3365 :returns: The power. 3366 """ 3367 return _ina226_power_watts(raw, current_lsb_microamps) 3368 3369 def shunt_register(self, nanovolts: int) -> int: 3370 """Build the shunt-voltage register a monitor reports for a shunt voltage. 3371 3372 The inverse of :meth:`shunt_nanovolts`, so a node can be written and tested 3373 against what a monitor sends without one attached. 3374 3375 :param nanovolts: The shunt voltage in nanovolts. 3376 :returns: The signed register value. 3377 """ 3378 return _ina226_shunt_register(nanovolts) 3379 3380 def bus_register(self, microvolts: int) -> int: 3381 """Build the bus-voltage register a monitor reports for a bus voltage. 3382 3383 :param microvolts: The bus voltage in microvolts. 3384 :returns: The register value. 3385 """ 3386 return _ina226_bus_register(microvolts) 3387 3388 def current_register(self, microamps: int, current_lsb_microamps: int) -> int: 3389 """Build the current register a monitor reports for a current. 3390 3391 :param microamps: The current in microamps. 3392 :param current_lsb_microamps: The current LSB the calibration was set for. 3393 :returns: The signed register value. 3394 """ 3395 return _ina226_current_register(microamps, current_lsb_microamps) 3396 3397 def power_register(self, microwatts: int, current_lsb_microamps: int) -> int: 3398 """Build the power register a monitor reports for a power. 3399 3400 :param microwatts: The power in microwatts. 3401 :param current_lsb_microamps: The current LSB the calibration was set for. 3402 :returns: The register value. 3403 """ 3404 return _ina226_power_register(microwatts, current_lsb_microamps) 3405 3406 def current_register_from_shunt(self, shunt: int, calibration: int) -> int: 3407 """Compute the current register the chip derives from a shunt reading. 3408 3409 :param shunt: The signed shunt-voltage register. 3410 :param calibration: The calibration register the part is running. 3411 :returns: The signed current register. 3412 """ 3413 return _ina226_current_register_from_shunt(shunt, calibration) 3414 3415 def power_register_from_current(self, current: int, bus: int) -> int: 3416 """Compute the power register the chip derives from a current reading. 3417 3418 :param current: The signed current register. 3419 :param bus: The bus-voltage register. 3420 :returns: The power register. 3421 """ 3422 return _ina226_power_register_from_current(current, bus) 3423 3424 3425class Bmp280: 3426 """A Bosch BMP280 driven over an :class:`~pamoja.hal.I2cBus`, measuring on demand in 3427 forced mode. 3428 3429 Nothing is sent until :meth:`init` or the first :meth:`measure`. The driver holds its 3430 own share of the bus, and releases the interpreter while the part answers. 3431 3432 >>> from pamoja.hal import I2cBus 3433 >>> bus = I2cBus.simulated([bmp280.sim.part(bmp280.ADDRESS_PRIMARY)]) 3434 >>> f"{Bmp280(bus, bmp280.ADDRESS_PRIMARY).measure().celsius:.2f}" 3435 '20.44' 3436 """ 3437 3438 __slots__ = ("_native",) 3439 3440 def __init__( 3441 self, 3442 bus: I2cBus, 3443 address: int, 3444 *, 3445 temperature: Bmp280Oversampling = Bmp280Oversampling.X1, 3446 pressure: Bmp280Oversampling = Bmp280Oversampling.X1, 3447 filter: int = 0, 3448 ) -> None: 3449 """Make a driver for the part at ``address`` on ``bus``. 3450 3451 :param bus: The bus the part is on. 3452 :param address: ``bmp280.ADDRESS_PRIMARY`` with SDO low, or 3453 ``bmp280.ADDRESS_SECONDARY`` with SDO high. 3454 :param temperature: The temperature oversampling. 3455 :param pressure: The pressure oversampling. 3456 :param filter: The IIR filter's three-bit code, ``0`` for the filter off, written 3457 as given. 3458 """ 3459 self._native = _NativeBmp280( 3460 bus._native, address, int(temperature), int(pressure), int(filter) 3461 ) 3462 3463 def init(self) -> None: 3464 """Reset the part, check it is a BMP280, read its trimming, and write the settings, 3465 leaving the part asleep. 3466 3467 :raises PamojaError: If nothing answers at the address, another part does, or the 3468 trimming never finishes loading. 3469 """ 3470 self._native.init() 3471 3472 def measure(self) -> Bmp280Reading: 3473 """Run one forced measurement and compensate it, initializing the part first if 3474 :meth:`init` has not run. 3475 3476 :returns: The reading. 3477 :raises PamojaError: As :meth:`init`, and when the part is still measuring after 3478 the datasheet's time. 3479 """ 3480 return self._native.measure() 3481 3482 @property 3483 def coefficients(self) -> Optional[Bmp280Coefficients]: 3484 """The trimming coefficients read at initialization, or ``None`` before it.""" 3485 return self._native.coefficients 3486 3487 3488class Tmp117: 3489 """A Texas Instruments TMP117 driven over an :class:`~pamoja.hal.I2cBus`, converting on 3490 demand in one-shot mode and powered down between conversions. 3491 3492 >>> from pamoja.hal import I2cBus 3493 >>> bus = I2cBus.simulated([tmp117.sim.reporting(tmp117.ADDRESS_ADD0_GND, -18.5)]) 3494 >>> Tmp117(bus, tmp117.ADDRESS_ADD0_GND).measure().celsius 3495 -18.5 3496 """ 3497 3498 __slots__ = ("_native",) 3499 3500 def __init__( 3501 self, bus: I2cBus, address: int, *, averaging: Tmp117Averaging = Tmp117Averaging.X8 3502 ) -> None: 3503 """Make a driver for the part at ``address`` on ``bus``. 3504 3505 :param bus: The bus the part is on. 3506 :param address: One of the ``tmp117.ADDRESS_ADD0_*`` constants, by where ADD0 is 3507 tied. 3508 :param averaging: How many conversions are averaged into each result. 3509 """ 3510 self._native = _NativeTmp117(bus._native, address, int(averaging)) 3511 3512 def init(self) -> None: 3513 """Check the part is a TMP117, wait for its EEPROM, and write the settings with the 3514 part in shutdown. 3515 3516 :raises PamojaError: If nothing answers, the device id is not a TMP117's, or the 3517 EEPROM never reports ready. 3518 """ 3519 self._native.init() 3520 3521 def measure(self) -> Tmp117Reading: 3522 """Run one conversion and read the temperature, initializing the part first if 3523 :meth:`init` has not run. 3524 3525 :returns: The temperature. 3526 :raises PamojaError: As :meth:`init`, and when the conversion never finishes. 3527 """ 3528 return self._native.measure() 3529 3530 def set_alert_limits(self, high_celsius: float, low_celsius: float) -> None: 3531 """Write the high and low limits the part compares each result against. 3532 3533 :param high_celsius: The high limit; the factory value is 192 C. 3534 :param low_celsius: The low limit; the factory value is -256 C. 3535 :raises PamojaError: If the transfer fails. 3536 """ 3537 self._native.set_alert_limits(high_celsius, low_celsius) 3538 3539 def alerts(self) -> Tmp117Alerts: 3540 """Read the alert flags, including results the driver's own reads saw since the 3541 last call. 3542 3543 :returns: Whether a result was above the high limit or below the low limit. 3544 :raises PamojaError: If the transfer fails. 3545 """ 3546 return self._native.alerts() 3547 3548 @property 3549 def silicon_revision(self) -> Optional[int]: 3550 """The silicon revision read at initialization, or ``None`` before it.""" 3551 return self._native.silicon_revision 3552 3553 3554class Opt3001: 3555 """A Texas Instruments OPT3001 driven over an :class:`~pamoja.hal.I2cBus`, measuring 3556 illuminance on demand in single-shot mode. 3557 3558 >>> from pamoja.hal import I2cBus 3559 >>> bus = I2cBus.simulated([opt3001.sim.reporting(opt3001.ADDRESS_GND, 1200.0)]) 3560 >>> Opt3001(bus, opt3001.ADDRESS_GND).measure().lux 3561 1200.0 3562 """ 3563 3564 __slots__ = ("_native",) 3565 3566 def __init__( 3567 self, 3568 bus: I2cBus, 3569 address: int, 3570 *, 3571 conversion_time: Opt3001ConversionTime = Opt3001ConversionTime.MS_800, 3572 range_number: int = 12, 3573 ) -> None: 3574 """Make a driver for the part at ``address`` on ``bus``. 3575 3576 :param bus: The bus the part is on. 3577 :param address: One of the ``opt3001.ADDRESS_*`` constants, by where ADDR is tied. 3578 :param conversion_time: How long each conversion integrates. 3579 :param range_number: A fixed full-scale range, ``0`` to ``11``, or ``12`` to let 3580 the part choose. 3581 """ 3582 self._native = _NativeOpt3001( 3583 bus._native, 3584 address, 3585 Opt3001ConversionTime(conversion_time) == Opt3001ConversionTime.MS_800, 3586 range_number, 3587 ) 3588 3589 def init(self) -> None: 3590 """Check the part is an OPT3001 and write the settings with the part in shutdown. 3591 3592 :raises PamojaError: If nothing answers, or either id register is not an OPT3001's. 3593 """ 3594 self._native.init() 3595 3596 def measure(self) -> Opt3001Reading: 3597 """Run one conversion and read the illuminance, initializing the part first if 3598 :meth:`init` has not run. 3599 3600 :returns: The illuminance. 3601 :raises PamojaError: As :meth:`init`, and when the conversion never finishes. 3602 """ 3603 return self._native.measure() 3604 3605 def set_limits(self, low_milli_lux: int, high_milli_lux: int) -> None: 3606 """Write the low and high limits the part's interrupt pin compares each result 3607 against. 3608 3609 :param low_milli_lux: The low limit, in millilux. 3610 :param high_milli_lux: The high limit, in millilux. 3611 :raises PamojaError: If the transfer fails. 3612 """ 3613 self._native.set_limits(low_milli_lux, high_milli_lux) 3614 3615 @property 3616 def configuration(self) -> Opt3001Config: 3617 """The configuration the driver writes, with the part in shutdown.""" 3618 return self._native.configuration 3619 3620 3621class Hdc1080: 3622 """A Texas Instruments HDC1080 driven over an :class:`~pamoja.hal.I2cBus`, measuring 3623 temperature then humidity from one trigger at its one address. 3624 3625 >>> from pamoja.hal import I2cBus 3626 >>> bus = I2cBus.simulated([hdc1080.sim.reporting(4.0, 91.0)]) 3627 >>> round(Hdc1080(bus).measure().relative_humidity, 2) 3628 91.0 3629 """ 3630 3631 __slots__ = ("_native",) 3632 3633 def __init__( 3634 self, 3635 bus: I2cBus, 3636 *, 3637 temperature_resolution: Hdc1080TemperatureResolution = ( 3638 Hdc1080TemperatureResolution.BITS_14 3639 ), 3640 humidity_resolution: Hdc1080HumidityResolution = Hdc1080HumidityResolution.BITS_14, 3641 ) -> None: 3642 """Make a driver for the part on ``bus``. 3643 3644 :param bus: The bus the part is on. 3645 :param temperature_resolution: The temperature resolution, which sets its time. 3646 :param humidity_resolution: The humidity resolution, which sets its time. 3647 :raises ValueError: For a resolution the part does not have. 3648 """ 3649 self._native = _NativeHdc1080( 3650 bus._native, int(temperature_resolution), int(humidity_resolution) 3651 ) 3652 3653 def init(self) -> None: 3654 """Check the part is an HDC1080 and write the configuration. 3655 3656 :raises PamojaError: If nothing answers, or either id register is not an HDC1080's. 3657 """ 3658 self._native.init() 3659 3660 def measure(self) -> Hdc1080Measurement: 3661 """Trigger one acquisition of both channels and read them, initializing the part 3662 first if :meth:`init` has not run. 3663 3664 :returns: The temperature and humidity. 3665 :raises PamojaError: As :meth:`init`, and when the part does not acknowledge the 3666 read, which it refuses until its results are ready. 3667 """ 3668 return self._native.measure() 3669 3670 def heater(self, on: bool) -> None: 3671 """Switch the on-die heater, which runs only during acquisitions, on or off. 3672 3673 :param on: Whether the heater runs. 3674 :raises PamojaError: If the transfer fails. 3675 """ 3676 self._native.heater(on) 3677 3678 @property 3679 def configuration(self) -> Hdc1080Config: 3680 """The configuration the driver writes.""" 3681 return self._native.configuration 3682 3683 3684class Ina219: 3685 """A Texas Instruments INA219 driven over an :class:`~pamoja.hal.I2cBus`: shunt and bus 3686 voltage, current, and power on demand. 3687 3688 >>> from pamoja.hal import I2cBus 3689 >>> bus = I2cBus.simulated([ina219.sim.part(ina219.BASE_ADDRESS)]) 3690 >>> Ina219(bus, ina219.BASE_ADDRESS).measure().bus_millivolts 3691 12000 3692 """ 3693 3694 __slots__ = ("_native",) 3695 3696 def __init__( 3697 self, 3698 bus: I2cBus, 3699 address: int, 3700 *, 3701 shunt_milliohms: int = 100, 3702 max_microamps: int = 3_200_000, 3703 current_lsb_microamps: Optional[int] = None, 3704 config: Optional[Ina219Config] = None, 3705 ) -> None: 3706 """Make a driver for the part at ``address`` on ``bus``. 3707 3708 :param bus: The bus the part is on. 3709 :param address: ``ina219.BASE_ADDRESS`` plus what A1 and A0 add. 3710 :param shunt_milliohms: The shunt resistance; the common breakout's is 100. 3711 :param max_microamps: The largest current the shunt will carry, which sets the 3712 finest current step. 3713 :param current_lsb_microamps: A current step to use instead, such as a round 100. 3714 :param config: The range, gain, and converter settings; the power-on ones unless 3715 given. 3716 """ 3717 self._native = _NativeIna219( 3718 bus._native, 3719 address, 3720 shunt_milliohms, 3721 max_microamps, 3722 current_lsb_microamps, 3723 config, 3724 ) 3725 3726 def init(self) -> None: 3727 """Reset the part, write the configuration and the calibration, and read the 3728 calibration back, the identity check a part with no id register allows. 3729 3730 :raises PamojaError: If nothing answers, or the calibration does not hold. 3731 """ 3732 self._native.init() 3733 3734 def measure(self) -> Ina219Reading: 3735 """Trigger one shunt and bus conversion and read every result, initializing the 3736 part first if :meth:`init` has not run. 3737 3738 :returns: The registers as read, and what they mean. 3739 :raises PamojaError: As :meth:`init`, and when the conversion-ready flag never sets. 3740 """ 3741 return self._native.measure() 3742 3743 @property 3744 def current_lsb_microamps(self) -> int: 3745 """The current step the driver programs, in microamps per count.""" 3746 return self._native.current_lsb_microamps 3747 3748 @property 3749 def calibration_word(self) -> int: 3750 """The calibration word the driver programs.""" 3751 return self._native.calibration_word 3752 3753 3754class Ina226: 3755 """A Texas Instruments INA226 driven over an :class:`~pamoja.hal.I2cBus`: shunt and bus 3756 voltage, current, and power on demand. 3757 3758 >>> from pamoja.hal import I2cBus 3759 >>> bus = I2cBus.simulated([ina226.sim.part(ina226.BASE_ADDRESS)]) 3760 >>> Ina226(bus, ina226.BASE_ADDRESS).measure().bus_microvolts 3761 12000000 3762 """ 3763 3764 __slots__ = ("_native",) 3765 3766 def __init__( 3767 self, 3768 bus: I2cBus, 3769 address: int, 3770 *, 3771 shunt_milliohms: int = 100, 3772 max_microamps: int = 3_200_000, 3773 current_lsb_microamps: Optional[int] = None, 3774 config: Optional[Ina226Config] = None, 3775 ) -> None: 3776 """Make a driver for the part at ``address`` on ``bus``. 3777 3778 :param bus: The bus the part is on. 3779 :param address: The address A1 and A0 select, which ``ina226.address`` works out. 3780 :param shunt_milliohms: The shunt resistance. 3781 :param max_microamps: The largest current the shunt will carry, which sets the 3782 finest current step. 3783 :param current_lsb_microamps: A current step to use instead. 3784 :param config: The averaging and conversion times; the power-on ones unless given. 3785 """ 3786 self._native = _NativeIna226( 3787 bus._native, 3788 address, 3789 shunt_milliohms, 3790 max_microamps, 3791 current_lsb_microamps, 3792 config, 3793 ) 3794 3795 def init(self) -> None: 3796 """Reset the part, check it is an INA226, and program the configuration and 3797 calibration. 3798 3799 :raises PamojaError: If nothing answers, the id registers are not an INA226's, or 3800 the calibration does not read back. 3801 """ 3802 self._native.init() 3803 3804 def measure(self) -> Ina226Reading: 3805 """Trigger one shunt and bus conversion and read every result, initializing the 3806 part first if :meth:`init` has not run. 3807 3808 :returns: The registers as read, and what they mean. 3809 :raises PamojaError: As :meth:`init`, and when the conversion-ready flag never sets. 3810 """ 3811 return self._native.measure() 3812 3813 def set_alert(self, mask: Ina226MaskEnable, limit: int) -> None: 3814 """Program the alert pin: which limit it watches, and the limit. 3815 3816 :param mask: The mask/enable settings, one alert function at a time. 3817 :param limit: The alert-limit register, in the units of the register the function 3818 watches. 3819 :raises PamojaError: If the transfer fails. 3820 """ 3821 self._native.set_alert(mask, limit) 3822 3823 @property 3824 def current_lsb_microamps(self) -> int: 3825 """The current step the driver programs, in microamps per count.""" 3826 return self._native.current_lsb_microamps 3827 3828 @property 3829 def calibration_word(self) -> int: 3830 """The calibration word the driver programs.""" 3831 return self._native.calibration_word 3832 3833 @property 3834 def identity(self) -> Optional[Ina226DieId]: 3835 """The die id read at initialization, or ``None`` before it.""" 3836 return self._native.identity 3837 3838 3839class Ads1115: 3840 """A Texas Instruments ADS1115 driven over an :class:`~pamoja.hal.I2cBus`, converting 3841 one input on demand. 3842 3843 >>> from pamoja.hal import I2cBus 3844 >>> bus = I2cBus.simulated([ads1115.sim.part(ads1115.ADDRESS_GND)]) 3845 >>> round(Ads1115(bus, ads1115.ADDRESS_GND).sample().volts, 3) 3846 1.65 3847 """ 3848 3849 __slots__ = ("_native",) 3850 3851 def __init__( 3852 self, 3853 bus: I2cBus, 3854 address: int, 3855 *, 3856 mux: Ads1115Mux = Ads1115Mux.AIN0_AIN1, 3857 pga: Ads1115Pga = Ads1115Pga.FSR_2_048, 3858 data_rate: Ads1115DataRate = Ads1115DataRate.SPS_128, 3859 ) -> None: 3860 """Make a driver for the part at ``address`` on ``bus``. 3861 3862 :param bus: The bus the part is on. 3863 :param address: One of the ``ads1115.ADDRESS_*`` constants, by where ADDR is tied. 3864 :param mux: The input the part converts. 3865 :param pga: The full-scale range, and with it the size of one count. 3866 :param data_rate: The data rate, and with it the conversion time and the noise. 3867 """ 3868 self._native = _NativeAds1115( 3869 bus._native, address, int(mux), int(pga), int(data_rate) 3870 ) 3871 3872 def init(self) -> None: 3873 """Write the input, range, and data rate, and read the configuration back, the 3874 identity check a part with no id register allows. 3875 3876 :raises PamojaError: If nothing answers, or the configuration reads back 3877 differently. 3878 """ 3879 self._native.init() 3880 3881 def sample(self) -> Ads1115Sample: 3882 """Run one conversion of the configured input, initializing the part first if 3883 :meth:`init` has not run. 3884 3885 :returns: The conversion, with the range it ran at. 3886 :raises PamojaError: As :meth:`init`, and when the conversion never finishes. 3887 """ 3888 return self._native.sample() 3889 3890 def sample_input(self, mux: Ads1115Mux) -> Ads1115Sample: 3891 """Convert another input once, leaving the configured input as it was. 3892 3893 :param mux: The input for this one conversion. 3894 :returns: The conversion. 3895 :raises PamojaError: As :meth:`sample`. 3896 """ 3897 return self._native.sample_input(int(mux)) 3898 3899 @property 3900 def config(self) -> Ads1115Config: 3901 """The configuration the driver writes.""" 3902 return self._native.config 3903 3904 3905class Sht3x: 3906 """A Sensirion SHT3x driven over an :class:`~pamoja.hal.I2cBus`, measuring on demand in 3907 single-shot mode. 3908 3909 >>> from pamoja.hal import I2cBus 3910 >>> bus = I2cBus.simulated([sht3x.sim.reporting(sht3x.ADDRESS_A, 30.0, 70.0)]) 3911 >>> round(Sht3x(bus, sht3x.ADDRESS_A).measure().celsius, 1) 3912 30.0 3913 """ 3914 3915 __slots__ = ("_native",) 3916 3917 def __init__( 3918 self, 3919 bus: I2cBus, 3920 address: int, 3921 *, 3922 repeatability: Sht3xRepeatability = Sht3xRepeatability.HIGH, 3923 ) -> None: 3924 """Make a driver for the part at ``address`` on ``bus``. 3925 3926 :param bus: The bus the part is on. 3927 :param address: ``sht3x.ADDRESS_A`` with ADDR low, ``sht3x.ADDRESS_B`` with it 3928 high. 3929 :param repeatability: How repeatable each measurement is, against how long it 3930 takes. 3931 """ 3932 self._native = _NativeSht3x( 3933 bus._native, address, Sht3xRepeatability(repeatability).value 3934 ) 3935 3936 def init(self) -> None: 3937 """Soft-reset the part and read its status; a status word whose checksum holds is 3938 what confirms an SHT3x answers, as the part has no id register. 3939 3940 :raises PamojaError: If nothing answers, or the status word fails its checksum. 3941 """ 3942 self._native.init() 3943 3944 def measure(self) -> Sht3xMeasurement: 3945 """Run one single-shot measurement, initializing the part first if :meth:`init` 3946 has not run. 3947 3948 :returns: The checksum-checked temperature and humidity. 3949 :raises PamojaError: As :meth:`init`, and when a data word fails its checksum. 3950 """ 3951 return self._native.measure() 3952 3953 def read_status(self) -> Sht3xStatus: 3954 """Read the status register, which :attr:`last_status` keeps as well. 3955 3956 :returns: The status. 3957 :raises PamojaError: If the transfer fails or the word fails its checksum. 3958 """ 3959 return self._native.read_status() 3960 3961 def heater_on(self) -> None: 3962 """Switch the plausibility-check heater on, initializing the part first if needed. 3963 3964 :raises PamojaError: As :meth:`init`. 3965 """ 3966 self._native.heater_on() 3967 3968 def heater_off(self) -> None: 3969 """Switch the heater off, which is its state after any reset. 3970 3971 :raises PamojaError: As :meth:`init`. 3972 """ 3973 self._native.heater_off() 3974 3975 @property 3976 def last_status(self) -> Optional[Sht3xStatus]: 3977 """The status register as it was last read, or ``None`` before it has been.""" 3978 return self._native.last_status 3979 3980 3981class Scd4x: 3982 """A Sensirion SCD40 or SCD41 driven over an :class:`~pamoja.hal.I2cBus` in periodic 3983 measurement, a result every five seconds. 3984 3985 >>> from pamoja.hal import I2cBus 3986 >>> bus = I2cBus.simulated([scd4x.sim.reporting(1450, 24.0, 55.0)]) 3987 >>> Scd4x(bus).measure().co2_ppm 3988 1450 3989 """ 3990 3991 __slots__ = ("_native",) 3992 3993 def __init__(self, bus: I2cBus) -> None: 3994 """Make a driver for the part on ``bus``, which has one address. 3995 3996 :param bus: The bus the part is on. 3997 """ 3998 self._native = _NativeScd4x(bus._native) 3999 4000 def init(self) -> None: 4001 """Stop any running measurement, read the serial number, and start periodic 4002 measurement. 4003 4004 :raises PamojaError: If nothing answers, or the serial number fails its checksum. 4005 """ 4006 self._native.init() 4007 4008 def measure(self) -> Scd4xMeasurement: 4009 """Wait for the next periodic result and read it, initializing the part first if 4010 :meth:`init` has not run. 4011 4012 :returns: The carbon dioxide, temperature, and humidity. 4013 :raises PamojaError: As :meth:`init`, when no result becomes ready, and when a word 4014 fails its checksum. 4015 """ 4016 return self._native.measure() 4017 4018 def measure_single_shot(self) -> Scd4xMeasurement: 4019 """Run one on-demand measurement on an SCD41, which takes five seconds. The part 4020 must not be measuring periodically: call :meth:`stop` first, or use this in place 4021 of :meth:`init`. 4022 4023 :returns: The measurement. 4024 :raises PamojaError: As :meth:`measure`. 4025 """ 4026 return self._native.measure_single_shot() 4027 4028 def data_ready(self) -> bool: 4029 """Ask the part whether a periodic result is waiting. 4030 4031 :returns: Whether :meth:`measure` would read without waiting. 4032 :raises PamojaError: If the transfer fails or the word fails its checksum. 4033 """ 4034 return self._native.data_ready() 4035 4036 def stop(self) -> None: 4037 """Stop periodic measurement, after which the part takes its settings commands. 4038 4039 :raises PamojaError: If the transfer fails. 4040 """ 4041 self._native.stop() 4042 4043 def start(self) -> None: 4044 """Start periodic measurement. 4045 4046 :raises PamojaError: If the transfer fails. 4047 """ 4048 self._native.start() 4049 4050 def set_temperature_offset(self, milli_celsius: int) -> None: 4051 """Set the temperature offset that compensates the part's own warmth, until power 4052 is lost. 4053 4054 :param milli_celsius: The offset to subtract, in millidegrees. 4055 :raises PamojaError: If the transfer fails. 4056 """ 4057 self._native.set_temperature_offset(milli_celsius) 4058 4059 def set_sensor_altitude(self, meters: int) -> None: 4060 """Set the altitude the part corrects its carbon dioxide reading for. 4061 4062 :param meters: The altitude above sea level. 4063 :raises PamojaError: If the transfer fails. 4064 """ 4065 self._native.set_sensor_altitude(meters) 4066 4067 @property 4068 def serial(self) -> Optional[int]: 4069 """The 48-bit serial number read at initialization, or ``None`` before it.""" 4070 return self._native.serial 4071 4072 4073class Ds18b20Thermometer: 4074 """A DS18B20 the Linux kernel serves as a ``w1_slave`` file. 4075 4076 On a Raspberry Pi the ``w1-gpio`` overlay (``dtoverlay=w1-gpio`` in ``config.txt``) 4077 puts a 1-Wire bus on GPIO 4, and the kernel lists every DS18B20 it finds under 4078 ``/sys/bus/w1/devices`` as a directory named by its family code and serial. Reading the 4079 directory's ``w1_slave`` file makes the kernel run a conversion and print the 4080 scratchpad, which :meth:`read` decodes. The file is only text, so a test can write one 4081 anywhere and read it with :meth:`at`. 4082 """ 4083 4084 __slots__ = ("_native",) 4085 4086 def __init__(self, native: _NativeDs18b20Thermometer) -> None: 4087 """Wrap a native thermometer. Use :meth:`for_serial`, :meth:`at`, or 4088 :meth:`discover`.""" 4089 self._native = native 4090 4091 @classmethod 4092 def for_serial(cls, serial: str) -> Ds18b20Thermometer: 4093 """Name a thermometer by the serial in its directory name. 4094 4095 :param serial: The twelve hex digits after ``28-``. 4096 :returns: The thermometer, reading ``/sys/bus/w1/devices/28-<serial>/w1_slave``. 4097 """ 4098 return cls(_NativeDs18b20Thermometer.for_serial(serial)) 4099 4100 @classmethod 4101 def at(cls, path: str) -> Ds18b20Thermometer: 4102 """Name a thermometer by the path of its ``w1_slave`` file. 4103 4104 :param path: The file to read. 4105 :returns: The thermometer. 4106 """ 4107 return cls(_NativeDs18b20Thermometer.at(str(path))) 4108 4109 @classmethod 4110 def discover(cls, devices: Optional[str] = None) -> List[Ds18b20Thermometer]: 4111 """List every DS18B20 the kernel has found, one per ``28-`` directory. 4112 4113 :param devices: The directory the kernel lists its 1-Wire devices in, or ``None`` 4114 for ``/sys/bus/w1/devices``. 4115 :returns: The thermometers, sorted by directory name. 4116 :raises PamojaError: If the directory cannot be listed, which usually means the 4117 1-Wire overlay is off. 4118 """ 4119 found = _NativeDs18b20Thermometer.discover(None if devices is None else str(devices)) 4120 return [cls(native) for native in found] 4121 4122 @property 4123 def path(self) -> str: 4124 """The path of the file the thermometer reads.""" 4125 return self._native.path 4126 4127 @property 4128 def serial(self) -> Optional[str]: 4129 """The serial the kernel named the thermometer's directory after. 4130 4131 The twelve hex digits after ``28-``, which tell one probe from another and stay with 4132 the part for life, or ``None`` when the file does not sit in a DS18B20's directory, as 4133 one named by :meth:`at` may not. 4134 4135 >>> Ds18b20Thermometer.for_serial("000005e2fdc3").serial 4136 '000005e2fdc3' 4137 >>> Ds18b20Thermometer.at("/tmp/w1_slave").serial is None 4138 True 4139 """ 4140 return self._native.serial 4141 4142 def read(self) -> Ds18b20Reading: 4143 """Read the file, which makes the kernel run a conversion, and decode it. 4144 4145 :returns: The checksum-checked reading. 4146 :raises PamojaError: If the file cannot be read, because the overlay is off, the 4147 probe is gone, or the process may not read it; or if the kernel or this decoder 4148 rejects the checksum. 4149 """ 4150 return self._native.read() 4151 4152 4153#: A Bosch BME280 temperature, pressure, and humidity sensor. 4154bme280 = _Bme280() 4155 4156#: A Maxim DS18B20 1-Wire thermometer. 4157ds18b20 = _Ds18b20() 4158 4159#: A TI INA219 current, voltage, and power monitor. 4160ina219 = _Ina219() 4161 4162#: A TI ADS1115 16-bit analog-to-digital converter. 4163ads1115 = _Ads1115() 4164 4165#: A Bosch BMP280 pressure and temperature sensor. 4166bmp280 = _Bmp280() 4167 4168#: A Sensirion SHT30, SHT31, or SHT35 temperature and humidity sensor. 4169sht3x = _Sht3x() 4170 4171#: A Sensirion SCD40 or SCD41 carbon dioxide, temperature, and humidity sensor. 4172scd4x = _Scd4x() 4173 4174#: A TI TMP117 precision thermometer. 4175tmp117 = _Tmp117() 4176 4177#: A TI HDC1080 temperature and humidity sensor. 4178hdc1080 = _Hdc1080() 4179 4180#: A TI OPT3001 ambient light sensor. 4181opt3001 = _Opt3001() 4182 4183#: A TI INA226 current, voltage, and power monitor. 4184ina226 = _Ina226()
3840class Ads1115: 3841 """A Texas Instruments ADS1115 driven over an :class:`~pamoja.hal.I2cBus`, converting 3842 one input on demand. 3843 3844 >>> from pamoja.hal import I2cBus 3845 >>> bus = I2cBus.simulated([ads1115.sim.part(ads1115.ADDRESS_GND)]) 3846 >>> round(Ads1115(bus, ads1115.ADDRESS_GND).sample().volts, 3) 3847 1.65 3848 """ 3849 3850 __slots__ = ("_native",) 3851 3852 def __init__( 3853 self, 3854 bus: I2cBus, 3855 address: int, 3856 *, 3857 mux: Ads1115Mux = Ads1115Mux.AIN0_AIN1, 3858 pga: Ads1115Pga = Ads1115Pga.FSR_2_048, 3859 data_rate: Ads1115DataRate = Ads1115DataRate.SPS_128, 3860 ) -> None: 3861 """Make a driver for the part at ``address`` on ``bus``. 3862 3863 :param bus: The bus the part is on. 3864 :param address: One of the ``ads1115.ADDRESS_*`` constants, by where ADDR is tied. 3865 :param mux: The input the part converts. 3866 :param pga: The full-scale range, and with it the size of one count. 3867 :param data_rate: The data rate, and with it the conversion time and the noise. 3868 """ 3869 self._native = _NativeAds1115( 3870 bus._native, address, int(mux), int(pga), int(data_rate) 3871 ) 3872 3873 def init(self) -> None: 3874 """Write the input, range, and data rate, and read the configuration back, the 3875 identity check a part with no id register allows. 3876 3877 :raises PamojaError: If nothing answers, or the configuration reads back 3878 differently. 3879 """ 3880 self._native.init() 3881 3882 def sample(self) -> Ads1115Sample: 3883 """Run one conversion of the configured input, initializing the part first if 3884 :meth:`init` has not run. 3885 3886 :returns: The conversion, with the range it ran at. 3887 :raises PamojaError: As :meth:`init`, and when the conversion never finishes. 3888 """ 3889 return self._native.sample() 3890 3891 def sample_input(self, mux: Ads1115Mux) -> Ads1115Sample: 3892 """Convert another input once, leaving the configured input as it was. 3893 3894 :param mux: The input for this one conversion. 3895 :returns: The conversion. 3896 :raises PamojaError: As :meth:`sample`. 3897 """ 3898 return self._native.sample_input(int(mux)) 3899 3900 @property 3901 def config(self) -> Ads1115Config: 3902 """The configuration the driver writes.""" 3903 return self._native.config
A Texas Instruments ADS1115 driven over an ~pamoja.hal.I2cBus, converting
one input on demand.
>>> from pamoja.hal import I2cBus
>>> bus = I2cBus.simulated([ads1115.sim.part(ads1115.ADDRESS_GND)])
>>> round(Ads1115(bus, ads1115.ADDRESS_GND).sample().volts, 3)
1.65
3852 def __init__( 3853 self, 3854 bus: I2cBus, 3855 address: int, 3856 *, 3857 mux: Ads1115Mux = Ads1115Mux.AIN0_AIN1, 3858 pga: Ads1115Pga = Ads1115Pga.FSR_2_048, 3859 data_rate: Ads1115DataRate = Ads1115DataRate.SPS_128, 3860 ) -> None: 3861 """Make a driver for the part at ``address`` on ``bus``. 3862 3863 :param bus: The bus the part is on. 3864 :param address: One of the ``ads1115.ADDRESS_*`` constants, by where ADDR is tied. 3865 :param mux: The input the part converts. 3866 :param pga: The full-scale range, and with it the size of one count. 3867 :param data_rate: The data rate, and with it the conversion time and the noise. 3868 """ 3869 self._native = _NativeAds1115( 3870 bus._native, address, int(mux), int(pga), int(data_rate) 3871 )
Make a driver for the part at address on bus.
Parameters
- bus: The bus the part is on.
- address: One of the
ads1115.ADDRESS_*constants, by where ADDR is tied. - mux: The input the part converts.
- pga: The full-scale range, and with it the size of one count.
- data_rate: The data rate, and with it the conversion time and the noise.
3873 def init(self) -> None: 3874 """Write the input, range, and data rate, and read the configuration back, the 3875 identity check a part with no id register allows. 3876 3877 :raises PamojaError: If nothing answers, or the configuration reads back 3878 differently. 3879 """ 3880 self._native.init()
Write the input, range, and data rate, and read the configuration back, the identity check a part with no id register allows.
Raises
- PamojaError: If nothing answers, or the configuration reads back differently.
3882 def sample(self) -> Ads1115Sample: 3883 """Run one conversion of the configured input, initializing the part first if 3884 :meth:`init` has not run. 3885 3886 :returns: The conversion, with the range it ran at. 3887 :raises PamojaError: As :meth:`init`, and when the conversion never finishes. 3888 """ 3889 return self._native.sample()
3891 def sample_input(self, mux: Ads1115Mux) -> Ads1115Sample: 3892 """Convert another input once, leaving the configured input as it was. 3893 3894 :param mux: The input for this one conversion. 3895 :returns: The conversion. 3896 :raises PamojaError: As :meth:`sample`. 3897 """ 3898 return self._native.sample_input(int(mux))
Convert another input once, leaving the configured input as it was.
Parameters
- mux: The input for this one conversion. :returns: The conversion.
Raises
- PamojaError: As
sample().
An ADS1115 configuration register, field by field.
673class Ads1115DataRate(enum.IntEnum): 674 """An ADS1115 data rate, as its register code.""" 675 676 #: 8 samples per second. 677 SPS_8 = 0 678 #: 16 samples per second. 679 SPS_16 = 1 680 #: 32 samples per second. 681 SPS_32 = 2 682 #: 64 samples per second. 683 SPS_64 = 3 684 #: 128 samples per second, the reset setting. 685 SPS_128 = 4 686 #: 250 samples per second. 687 SPS_250 = 5 688 #: 475 samples per second. 689 SPS_475 = 6 690 #: 860 samples per second. 691 SPS_860 = 7
An ADS1115 data rate, as its register code.
635class Ads1115Mux(enum.IntEnum): 636 """An ADS1115 input multiplexer setting, as its register code.""" 637 638 #: AIN0 against AIN1, the reset setting. 639 AIN0_AIN1 = 0 640 #: AIN0 against AIN3. 641 AIN0_AIN3 = 1 642 #: AIN1 against AIN3. 643 AIN1_AIN3 = 2 644 #: AIN2 against AIN3. 645 AIN2_AIN3 = 3 646 #: AIN0 against ground. 647 AIN0_GND = 4 648 #: AIN1 against ground. 649 AIN1_GND = 5 650 #: AIN2 against ground. 651 AIN2_GND = 6 652 #: AIN3 against ground. 653 AIN3_GND = 7
An ADS1115 input multiplexer setting, as its register code.
656class Ads1115Pga(enum.IntEnum): 657 """An ADS1115 full-scale range, as its register code.""" 658 659 #: 6.144 V either side of zero. 660 FSR_6_144 = 0 661 #: 4.096 V. 662 FSR_4_096 = 1 663 #: 2.048 V, the reset setting. 664 FSR_2_048 = 2 665 #: 1.024 V. 666 FSR_1_024 = 3 667 #: 0.512 V. 668 FSR_0_512 = 4 669 #: 0.256 V. 670 FSR_0_256 = 5
An ADS1115 full-scale range, as its register code.
One ADS1115 conversion.
694class Bme280: 695 """A Bosch BME280 driven over an :class:`~pamoja.hal.I2cBus`, measuring on demand in 696 forced mode. 697 698 Nothing is sent until :meth:`init` or the first :meth:`measure`. The driver holds its 699 own share of the bus, and releases the interpreter while the part answers. 700 701 >>> from pamoja.hal import I2cBus 702 >>> bus = I2cBus.simulated([bme280.sim.part(bme280.ADDRESS_PRIMARY)]) 703 >>> sensor = Bme280(bus, bme280.ADDRESS_PRIMARY) 704 >>> f"{sensor.measure().celsius:.2f}" 705 '20.44' 706 """ 707 708 __slots__ = ("_native",) 709 710 def __init__( 711 self, 712 bus: I2cBus, 713 address: int, 714 *, 715 temperature: Bme280Oversampling = Bme280Oversampling.X1, 716 pressure: Bme280Oversampling = Bme280Oversampling.X1, 717 humidity: Bme280Oversampling = Bme280Oversampling.X1, 718 filter: Bme280Filter = Bme280Filter.OFF, 719 ) -> None: 720 """Make a driver for the part at ``address`` on ``bus``. 721 722 :param bus: The bus the part is on. 723 :param address: ``bme280.ADDRESS_PRIMARY`` with SDO low, or 724 ``bme280.ADDRESS_SECONDARY`` with SDO high. 725 :param temperature: The temperature oversampling. 726 :param pressure: The pressure oversampling. 727 :param humidity: The humidity oversampling. 728 :param filter: The IIR filter. 729 """ 730 self._native = _NativeBme280( 731 bus._native, 732 address, 733 int(temperature), 734 int(pressure), 735 int(humidity), 736 int(filter), 737 ) 738 739 def init(self) -> None: 740 """Reset the part, check it is a BME280, read its calibration, and write the 741 settings in the order the datasheet requires, leaving the part asleep. 742 743 :raises PamojaError: If nothing answers at the address, another part does, or 744 the calibration never finishes loading. 745 """ 746 self._native.init() 747 748 def measure(self) -> Bme280Measurement: 749 """Run one forced measurement and compensate it, initializing the part first if 750 :meth:`init` has not run. 751 752 :returns: The reading. 753 :raises PamojaError: As :meth:`init`, and when the part is still measuring after 754 the datasheet's time. 755 """ 756 return self._native.measure()
A Bosch BME280 driven over an ~pamoja.hal.I2cBus, measuring on demand in
forced mode.
Nothing is sent until init() or the first measure(). The driver holds its
own share of the bus, and releases the interpreter while the part answers.
>>> from pamoja.hal import I2cBus
>>> bus = I2cBus.simulated([bme280.sim.part(bme280.ADDRESS_PRIMARY)])
>>> sensor = Bme280(bus, bme280.ADDRESS_PRIMARY)
>>> f"{sensor.measure().celsius:.2f}"
'20.44'
710 def __init__( 711 self, 712 bus: I2cBus, 713 address: int, 714 *, 715 temperature: Bme280Oversampling = Bme280Oversampling.X1, 716 pressure: Bme280Oversampling = Bme280Oversampling.X1, 717 humidity: Bme280Oversampling = Bme280Oversampling.X1, 718 filter: Bme280Filter = Bme280Filter.OFF, 719 ) -> None: 720 """Make a driver for the part at ``address`` on ``bus``. 721 722 :param bus: The bus the part is on. 723 :param address: ``bme280.ADDRESS_PRIMARY`` with SDO low, or 724 ``bme280.ADDRESS_SECONDARY`` with SDO high. 725 :param temperature: The temperature oversampling. 726 :param pressure: The pressure oversampling. 727 :param humidity: The humidity oversampling. 728 :param filter: The IIR filter. 729 """ 730 self._native = _NativeBme280( 731 bus._native, 732 address, 733 int(temperature), 734 int(pressure), 735 int(humidity), 736 int(filter), 737 )
Make a driver for the part at address on bus.
Parameters
- bus: The bus the part is on.
- address:
bme280.ADDRESS_PRIMARYwith SDO low, orbme280.ADDRESS_SECONDARYwith SDO high. - temperature: The temperature oversampling.
- pressure: The pressure oversampling.
- humidity: The humidity oversampling.
- filter: The IIR filter.
739 def init(self) -> None: 740 """Reset the part, check it is a BME280, read its calibration, and write the 741 settings in the order the datasheet requires, leaving the part asleep. 742 743 :raises PamojaError: If nothing answers at the address, another part does, or 744 the calibration never finishes loading. 745 """ 746 self._native.init()
Reset the part, check it is a BME280, read its calibration, and write the settings in the order the datasheet requires, leaving the part asleep.
Raises
- PamojaError: If nothing answers at the address, another part does, or the calibration never finishes loading.
748 def measure(self) -> Bme280Measurement: 749 """Run one forced measurement and compensate it, initializing the part first if 750 :meth:`init` has not run. 751 752 :returns: The reading. 753 :raises PamojaError: As :meth:`init`, and when the part is still measuring after 754 the datasheet's time. 755 """ 756 return self._native.measure()
A BME280's factory calibration, read once and reused for every measurement.
A BME280 config register, field by field.
A BME280 ctrl_meas register, field by field.
409class Bme280Filter(enum.IntEnum): 410 """The IIR filter that smooths a BME280's pressure and temperature, as its code.""" 411 412 #: No filtering. 413 OFF = 0 414 #: Coefficient 2. 415 X2 = 1 416 #: Coefficient 4. 417 X4 = 2 418 #: Coefficient 8. 419 X8 = 3 420 #: Coefficient 16. 421 X16 = 4
The IIR filter that smooths a BME280's pressure and temperature, as its code.
A compensated BME280 reading.
398class Bme280Mode(enum.IntEnum): 399 """A BME280 power mode, as its register code.""" 400 401 #: No measurements; the power-on default. 402 SLEEP = 0 403 #: One measurement, then back to sleep. 404 FORCED = 1 405 #: Measurements on a cycle, a standby period apart. 406 NORMAL = 3
A BME280 power mode, as its register code.
381class Bme280Oversampling(enum.IntEnum): 382 """How many samples a BME280 measurement averages, as its register code.""" 383 384 #: The measurement is skipped. 385 SKIPPED = 0 386 #: One sample. 387 X1 = 1 388 #: Two samples. 389 X2 = 2 390 #: Four samples. 391 X4 = 3 392 #: Eight samples. 393 X8 = 4 394 #: Sixteen samples. 395 X16 = 5
How many samples a BME280 measurement averages, as its register code.
424class Bme280Standby(enum.IntEnum): 425 """The period a BME280 in normal mode rests between measurements, as its code.""" 426 427 #: 0.5 ms. 428 MS_0_5 = 0 429 #: 62.5 ms. 430 MS_62_5 = 1 431 #: 125 ms. 432 MS_125 = 2 433 #: 250 ms. 434 MS_250 = 3 435 #: 500 ms. 436 MS_500 = 4 437 #: 1000 ms. 438 MS_1000 = 5 439 #: 10 ms. 440 MS_10 = 6 441 #: 20 ms. 442 MS_20 = 7
The period a BME280 in normal mode rests between measurements, as its code.
3426class Bmp280: 3427 """A Bosch BMP280 driven over an :class:`~pamoja.hal.I2cBus`, measuring on demand in 3428 forced mode. 3429 3430 Nothing is sent until :meth:`init` or the first :meth:`measure`. The driver holds its 3431 own share of the bus, and releases the interpreter while the part answers. 3432 3433 >>> from pamoja.hal import I2cBus 3434 >>> bus = I2cBus.simulated([bmp280.sim.part(bmp280.ADDRESS_PRIMARY)]) 3435 >>> f"{Bmp280(bus, bmp280.ADDRESS_PRIMARY).measure().celsius:.2f}" 3436 '20.44' 3437 """ 3438 3439 __slots__ = ("_native",) 3440 3441 def __init__( 3442 self, 3443 bus: I2cBus, 3444 address: int, 3445 *, 3446 temperature: Bmp280Oversampling = Bmp280Oversampling.X1, 3447 pressure: Bmp280Oversampling = Bmp280Oversampling.X1, 3448 filter: int = 0, 3449 ) -> None: 3450 """Make a driver for the part at ``address`` on ``bus``. 3451 3452 :param bus: The bus the part is on. 3453 :param address: ``bmp280.ADDRESS_PRIMARY`` with SDO low, or 3454 ``bmp280.ADDRESS_SECONDARY`` with SDO high. 3455 :param temperature: The temperature oversampling. 3456 :param pressure: The pressure oversampling. 3457 :param filter: The IIR filter's three-bit code, ``0`` for the filter off, written 3458 as given. 3459 """ 3460 self._native = _NativeBmp280( 3461 bus._native, address, int(temperature), int(pressure), int(filter) 3462 ) 3463 3464 def init(self) -> None: 3465 """Reset the part, check it is a BMP280, read its trimming, and write the settings, 3466 leaving the part asleep. 3467 3468 :raises PamojaError: If nothing answers at the address, another part does, or the 3469 trimming never finishes loading. 3470 """ 3471 self._native.init() 3472 3473 def measure(self) -> Bmp280Reading: 3474 """Run one forced measurement and compensate it, initializing the part first if 3475 :meth:`init` has not run. 3476 3477 :returns: The reading. 3478 :raises PamojaError: As :meth:`init`, and when the part is still measuring after 3479 the datasheet's time. 3480 """ 3481 return self._native.measure() 3482 3483 @property 3484 def coefficients(self) -> Optional[Bmp280Coefficients]: 3485 """The trimming coefficients read at initialization, or ``None`` before it.""" 3486 return self._native.coefficients
A Bosch BMP280 driven over an ~pamoja.hal.I2cBus, measuring on demand in
forced mode.
Nothing is sent until init() or the first measure(). The driver holds its
own share of the bus, and releases the interpreter while the part answers.
>>> from pamoja.hal import I2cBus
>>> bus = I2cBus.simulated([bmp280.sim.part(bmp280.ADDRESS_PRIMARY)])
>>> f"{Bmp280(bus, bmp280.ADDRESS_PRIMARY).measure().celsius:.2f}"
'20.44'
3441 def __init__( 3442 self, 3443 bus: I2cBus, 3444 address: int, 3445 *, 3446 temperature: Bmp280Oversampling = Bmp280Oversampling.X1, 3447 pressure: Bmp280Oversampling = Bmp280Oversampling.X1, 3448 filter: int = 0, 3449 ) -> None: 3450 """Make a driver for the part at ``address`` on ``bus``. 3451 3452 :param bus: The bus the part is on. 3453 :param address: ``bmp280.ADDRESS_PRIMARY`` with SDO low, or 3454 ``bmp280.ADDRESS_SECONDARY`` with SDO high. 3455 :param temperature: The temperature oversampling. 3456 :param pressure: The pressure oversampling. 3457 :param filter: The IIR filter's three-bit code, ``0`` for the filter off, written 3458 as given. 3459 """ 3460 self._native = _NativeBmp280( 3461 bus._native, address, int(temperature), int(pressure), int(filter) 3462 )
Make a driver for the part at address on bus.
Parameters
- bus: The bus the part is on.
- address:
bmp280.ADDRESS_PRIMARYwith SDO low, orbmp280.ADDRESS_SECONDARYwith SDO high. - temperature: The temperature oversampling.
- pressure: The pressure oversampling.
- filter: The IIR filter's three-bit code,
0for the filter off, written as given.
3464 def init(self) -> None: 3465 """Reset the part, check it is a BMP280, read its trimming, and write the settings, 3466 leaving the part asleep. 3467 3468 :raises PamojaError: If nothing answers at the address, another part does, or the 3469 trimming never finishes loading. 3470 """ 3471 self._native.init()
Reset the part, check it is a BMP280, read its trimming, and write the settings, leaving the part asleep.
Raises
- PamojaError: If nothing answers at the address, another part does, or the trimming never finishes loading.
3473 def measure(self) -> Bmp280Reading: 3474 """Run one forced measurement and compensate it, initializing the part first if 3475 :meth:`init` has not run. 3476 3477 :returns: The reading. 3478 :raises PamojaError: As :meth:`init`, and when the part is still measuring after 3479 the datasheet's time. 3480 """ 3481 return self._native.measure()
3483 @property 3484 def coefficients(self) -> Optional[Bmp280Coefficients]: 3485 """The trimming coefficients read at initialization, or ``None`` before it.""" 3486 return self._native.coefficients
The trimming coefficients read at initialization, or None before it.
A BMP280's factory calibration, read once and reused for every measurement.
A BMP280's per-chip trimming coefficients, as they sit in its registers.
A BMP280 config register, field by field.
A BMP280 ctrl_meas register, field by field.
445class Bmp280Oversampling(enum.IntEnum): 446 """How many samples a BMP280 measurement averages, as its register code.""" 447 448 #: The measurement is skipped. 449 SKIPPED = 0 450 #: One sample. 451 X1 = 1 452 #: Two samples. 453 X2 = 2 454 #: Four samples. 455 X4 = 3 456 #: Eight samples. 457 X8 = 4 458 #: Sixteen samples. 459 X16 = 5
How many samples a BMP280 measurement averages, as its register code.
The uncompensated codes a BMP280 burst read carries.
A compensated BMP280 reading.
A decoded DS18B20 scratchpad.
4074class Ds18b20Thermometer: 4075 """A DS18B20 the Linux kernel serves as a ``w1_slave`` file. 4076 4077 On a Raspberry Pi the ``w1-gpio`` overlay (``dtoverlay=w1-gpio`` in ``config.txt``) 4078 puts a 1-Wire bus on GPIO 4, and the kernel lists every DS18B20 it finds under 4079 ``/sys/bus/w1/devices`` as a directory named by its family code and serial. Reading the 4080 directory's ``w1_slave`` file makes the kernel run a conversion and print the 4081 scratchpad, which :meth:`read` decodes. The file is only text, so a test can write one 4082 anywhere and read it with :meth:`at`. 4083 """ 4084 4085 __slots__ = ("_native",) 4086 4087 def __init__(self, native: _NativeDs18b20Thermometer) -> None: 4088 """Wrap a native thermometer. Use :meth:`for_serial`, :meth:`at`, or 4089 :meth:`discover`.""" 4090 self._native = native 4091 4092 @classmethod 4093 def for_serial(cls, serial: str) -> Ds18b20Thermometer: 4094 """Name a thermometer by the serial in its directory name. 4095 4096 :param serial: The twelve hex digits after ``28-``. 4097 :returns: The thermometer, reading ``/sys/bus/w1/devices/28-<serial>/w1_slave``. 4098 """ 4099 return cls(_NativeDs18b20Thermometer.for_serial(serial)) 4100 4101 @classmethod 4102 def at(cls, path: str) -> Ds18b20Thermometer: 4103 """Name a thermometer by the path of its ``w1_slave`` file. 4104 4105 :param path: The file to read. 4106 :returns: The thermometer. 4107 """ 4108 return cls(_NativeDs18b20Thermometer.at(str(path))) 4109 4110 @classmethod 4111 def discover(cls, devices: Optional[str] = None) -> List[Ds18b20Thermometer]: 4112 """List every DS18B20 the kernel has found, one per ``28-`` directory. 4113 4114 :param devices: The directory the kernel lists its 1-Wire devices in, or ``None`` 4115 for ``/sys/bus/w1/devices``. 4116 :returns: The thermometers, sorted by directory name. 4117 :raises PamojaError: If the directory cannot be listed, which usually means the 4118 1-Wire overlay is off. 4119 """ 4120 found = _NativeDs18b20Thermometer.discover(None if devices is None else str(devices)) 4121 return [cls(native) for native in found] 4122 4123 @property 4124 def path(self) -> str: 4125 """The path of the file the thermometer reads.""" 4126 return self._native.path 4127 4128 @property 4129 def serial(self) -> Optional[str]: 4130 """The serial the kernel named the thermometer's directory after. 4131 4132 The twelve hex digits after ``28-``, which tell one probe from another and stay with 4133 the part for life, or ``None`` when the file does not sit in a DS18B20's directory, as 4134 one named by :meth:`at` may not. 4135 4136 >>> Ds18b20Thermometer.for_serial("000005e2fdc3").serial 4137 '000005e2fdc3' 4138 >>> Ds18b20Thermometer.at("/tmp/w1_slave").serial is None 4139 True 4140 """ 4141 return self._native.serial 4142 4143 def read(self) -> Ds18b20Reading: 4144 """Read the file, which makes the kernel run a conversion, and decode it. 4145 4146 :returns: The checksum-checked reading. 4147 :raises PamojaError: If the file cannot be read, because the overlay is off, the 4148 probe is gone, or the process may not read it; or if the kernel or this decoder 4149 rejects the checksum. 4150 """ 4151 return self._native.read()
A DS18B20 the Linux kernel serves as a w1_slave file.
On a Raspberry Pi the w1-gpio overlay (dtoverlay=w1-gpio in config.txt)
puts a 1-Wire bus on GPIO 4, and the kernel lists every DS18B20 it finds under
/sys/bus/w1/devices as a directory named by its family code and serial. Reading the
directory's w1_slave file makes the kernel run a conversion and print the
scratchpad, which read() decodes. The file is only text, so a test can write one
anywhere and read it with at().
4087 def __init__(self, native: _NativeDs18b20Thermometer) -> None: 4088 """Wrap a native thermometer. Use :meth:`for_serial`, :meth:`at`, or 4089 :meth:`discover`.""" 4090 self._native = native
Wrap a native thermometer. Use for_serial(), at(), or
discover().
4092 @classmethod 4093 def for_serial(cls, serial: str) -> Ds18b20Thermometer: 4094 """Name a thermometer by the serial in its directory name. 4095 4096 :param serial: The twelve hex digits after ``28-``. 4097 :returns: The thermometer, reading ``/sys/bus/w1/devices/28-<serial>/w1_slave``. 4098 """ 4099 return cls(_NativeDs18b20Thermometer.for_serial(serial))
Name a thermometer by the serial in its directory name.
Parameters
- serial: The twelve hex digits after
28-. :returns: The thermometer, reading/sys/bus/w1/devices/28-<serial>/w1_slave.
4101 @classmethod 4102 def at(cls, path: str) -> Ds18b20Thermometer: 4103 """Name a thermometer by the path of its ``w1_slave`` file. 4104 4105 :param path: The file to read. 4106 :returns: The thermometer. 4107 """ 4108 return cls(_NativeDs18b20Thermometer.at(str(path)))
Name a thermometer by the path of its w1_slave file.
Parameters
- path: The file to read. :returns: The thermometer.
4110 @classmethod 4111 def discover(cls, devices: Optional[str] = None) -> List[Ds18b20Thermometer]: 4112 """List every DS18B20 the kernel has found, one per ``28-`` directory. 4113 4114 :param devices: The directory the kernel lists its 1-Wire devices in, or ``None`` 4115 for ``/sys/bus/w1/devices``. 4116 :returns: The thermometers, sorted by directory name. 4117 :raises PamojaError: If the directory cannot be listed, which usually means the 4118 1-Wire overlay is off. 4119 """ 4120 found = _NativeDs18b20Thermometer.discover(None if devices is None else str(devices)) 4121 return [cls(native) for native in found]
List every DS18B20 the kernel has found, one per 28- directory.
Parameters
- devices: The directory the kernel lists its 1-Wire devices in, or
Nonefor/sys/bus/w1/devices. :returns: The thermometers, sorted by directory name.
Raises
- PamojaError: If the directory cannot be listed, which usually means the 1-Wire overlay is off.
4123 @property 4124 def path(self) -> str: 4125 """The path of the file the thermometer reads.""" 4126 return self._native.path
The path of the file the thermometer reads.
4128 @property 4129 def serial(self) -> Optional[str]: 4130 """The serial the kernel named the thermometer's directory after. 4131 4132 The twelve hex digits after ``28-``, which tell one probe from another and stay with 4133 the part for life, or ``None`` when the file does not sit in a DS18B20's directory, as 4134 one named by :meth:`at` may not. 4135 4136 >>> Ds18b20Thermometer.for_serial("000005e2fdc3").serial 4137 '000005e2fdc3' 4138 >>> Ds18b20Thermometer.at("/tmp/w1_slave").serial is None 4139 True 4140 """ 4141 return self._native.serial
The serial the kernel named the thermometer's directory after.
The twelve hex digits after 28-, which tell one probe from another and stay with
the part for life, or None when the file does not sit in a DS18B20's directory, as
one named by at() may not.
>>> Ds18b20Thermometer.for_serial("000005e2fdc3").serial
'000005e2fdc3'
>>> Ds18b20Thermometer.at("/tmp/w1_slave").serial is None
True
4143 def read(self) -> Ds18b20Reading: 4144 """Read the file, which makes the kernel run a conversion, and decode it. 4145 4146 :returns: The checksum-checked reading. 4147 :raises PamojaError: If the file cannot be read, because the overlay is off, the 4148 probe is gone, or the process may not read it; or if the kernel or this decoder 4149 rejects the checksum. 4150 """ 4151 return self._native.read()
Read the file, which makes the kernel run a conversion, and decode it.
:returns: The checksum-checked reading.
Raises
- PamojaError: If the file cannot be read, because the overlay is off, the probe is gone, or the process may not read it; or if the kernel or this decoder rejects the checksum.
3622class Hdc1080: 3623 """A Texas Instruments HDC1080 driven over an :class:`~pamoja.hal.I2cBus`, measuring 3624 temperature then humidity from one trigger at its one address. 3625 3626 >>> from pamoja.hal import I2cBus 3627 >>> bus = I2cBus.simulated([hdc1080.sim.reporting(4.0, 91.0)]) 3628 >>> round(Hdc1080(bus).measure().relative_humidity, 2) 3629 91.0 3630 """ 3631 3632 __slots__ = ("_native",) 3633 3634 def __init__( 3635 self, 3636 bus: I2cBus, 3637 *, 3638 temperature_resolution: Hdc1080TemperatureResolution = ( 3639 Hdc1080TemperatureResolution.BITS_14 3640 ), 3641 humidity_resolution: Hdc1080HumidityResolution = Hdc1080HumidityResolution.BITS_14, 3642 ) -> None: 3643 """Make a driver for the part on ``bus``. 3644 3645 :param bus: The bus the part is on. 3646 :param temperature_resolution: The temperature resolution, which sets its time. 3647 :param humidity_resolution: The humidity resolution, which sets its time. 3648 :raises ValueError: For a resolution the part does not have. 3649 """ 3650 self._native = _NativeHdc1080( 3651 bus._native, int(temperature_resolution), int(humidity_resolution) 3652 ) 3653 3654 def init(self) -> None: 3655 """Check the part is an HDC1080 and write the configuration. 3656 3657 :raises PamojaError: If nothing answers, or either id register is not an HDC1080's. 3658 """ 3659 self._native.init() 3660 3661 def measure(self) -> Hdc1080Measurement: 3662 """Trigger one acquisition of both channels and read them, initializing the part 3663 first if :meth:`init` has not run. 3664 3665 :returns: The temperature and humidity. 3666 :raises PamojaError: As :meth:`init`, and when the part does not acknowledge the 3667 read, which it refuses until its results are ready. 3668 """ 3669 return self._native.measure() 3670 3671 def heater(self, on: bool) -> None: 3672 """Switch the on-die heater, which runs only during acquisitions, on or off. 3673 3674 :param on: Whether the heater runs. 3675 :raises PamojaError: If the transfer fails. 3676 """ 3677 self._native.heater(on) 3678 3679 @property 3680 def configuration(self) -> Hdc1080Config: 3681 """The configuration the driver writes.""" 3682 return self._native.configuration
A Texas Instruments HDC1080 driven over an ~pamoja.hal.I2cBus, measuring
temperature then humidity from one trigger at its one address.
>>> from pamoja.hal import I2cBus
>>> bus = I2cBus.simulated([hdc1080.sim.reporting(4.0, 91.0)])
>>> round(Hdc1080(bus).measure().relative_humidity, 2)
91.0
3634 def __init__( 3635 self, 3636 bus: I2cBus, 3637 *, 3638 temperature_resolution: Hdc1080TemperatureResolution = ( 3639 Hdc1080TemperatureResolution.BITS_14 3640 ), 3641 humidity_resolution: Hdc1080HumidityResolution = Hdc1080HumidityResolution.BITS_14, 3642 ) -> None: 3643 """Make a driver for the part on ``bus``. 3644 3645 :param bus: The bus the part is on. 3646 :param temperature_resolution: The temperature resolution, which sets its time. 3647 :param humidity_resolution: The humidity resolution, which sets its time. 3648 :raises ValueError: For a resolution the part does not have. 3649 """ 3650 self._native = _NativeHdc1080( 3651 bus._native, int(temperature_resolution), int(humidity_resolution) 3652 )
Make a driver for the part on bus.
Parameters
- bus: The bus the part is on.
- temperature_resolution: The temperature resolution, which sets its time.
- humidity_resolution: The humidity resolution, which sets its time.
Raises
- ValueError: For a resolution the part does not have.
3654 def init(self) -> None: 3655 """Check the part is an HDC1080 and write the configuration. 3656 3657 :raises PamojaError: If nothing answers, or either id register is not an HDC1080's. 3658 """ 3659 self._native.init()
Check the part is an HDC1080 and write the configuration.
Raises
- PamojaError: If nothing answers, or either id register is not an HDC1080's.
3661 def measure(self) -> Hdc1080Measurement: 3662 """Trigger one acquisition of both channels and read them, initializing the part 3663 first if :meth:`init` has not run. 3664 3665 :returns: The temperature and humidity. 3666 :raises PamojaError: As :meth:`init`, and when the part does not acknowledge the 3667 read, which it refuses until its results are ready. 3668 """ 3669 return self._native.measure()
3671 def heater(self, on: bool) -> None: 3672 """Switch the on-die heater, which runs only during acquisitions, on or off. 3673 3674 :param on: Whether the heater runs. 3675 :raises PamojaError: If the transfer fails. 3676 """ 3677 self._native.heater(on)
Switch the on-die heater, which runs only during acquisitions, on or off.
Parameters
- on: Whether the heater runs.
Raises
- PamojaError: If the transfer fails.
An HDC1080 configuration register, field by field.
493class Hdc1080HumidityResolution(enum.IntEnum): 494 """An HDC1080 humidity resolution, as its bit count.""" 495 496 #: 8 bits, 2.5 ms. 497 BITS_8 = 8 498 #: 11 bits, 3.85 ms. 499 BITS_11 = 11 500 #: 14 bits, 6.5 ms. 501 BITS_14 = 14
An HDC1080 humidity resolution, as its bit count.
A decoded HDC1080 temperature and humidity pair.
484class Hdc1080TemperatureResolution(enum.IntEnum): 485 """An HDC1080 temperature resolution, as its bit count.""" 486 487 #: 11 bits, 3.65 ms. 488 BITS_11 = 11 489 #: 14 bits, 6.35 ms. 490 BITS_14 = 14
An HDC1080 temperature resolution, as its bit count.
3685class Ina219: 3686 """A Texas Instruments INA219 driven over an :class:`~pamoja.hal.I2cBus`: shunt and bus 3687 voltage, current, and power on demand. 3688 3689 >>> from pamoja.hal import I2cBus 3690 >>> bus = I2cBus.simulated([ina219.sim.part(ina219.BASE_ADDRESS)]) 3691 >>> Ina219(bus, ina219.BASE_ADDRESS).measure().bus_millivolts 3692 12000 3693 """ 3694 3695 __slots__ = ("_native",) 3696 3697 def __init__( 3698 self, 3699 bus: I2cBus, 3700 address: int, 3701 *, 3702 shunt_milliohms: int = 100, 3703 max_microamps: int = 3_200_000, 3704 current_lsb_microamps: Optional[int] = None, 3705 config: Optional[Ina219Config] = None, 3706 ) -> None: 3707 """Make a driver for the part at ``address`` on ``bus``. 3708 3709 :param bus: The bus the part is on. 3710 :param address: ``ina219.BASE_ADDRESS`` plus what A1 and A0 add. 3711 :param shunt_milliohms: The shunt resistance; the common breakout's is 100. 3712 :param max_microamps: The largest current the shunt will carry, which sets the 3713 finest current step. 3714 :param current_lsb_microamps: A current step to use instead, such as a round 100. 3715 :param config: The range, gain, and converter settings; the power-on ones unless 3716 given. 3717 """ 3718 self._native = _NativeIna219( 3719 bus._native, 3720 address, 3721 shunt_milliohms, 3722 max_microamps, 3723 current_lsb_microamps, 3724 config, 3725 ) 3726 3727 def init(self) -> None: 3728 """Reset the part, write the configuration and the calibration, and read the 3729 calibration back, the identity check a part with no id register allows. 3730 3731 :raises PamojaError: If nothing answers, or the calibration does not hold. 3732 """ 3733 self._native.init() 3734 3735 def measure(self) -> Ina219Reading: 3736 """Trigger one shunt and bus conversion and read every result, initializing the 3737 part first if :meth:`init` has not run. 3738 3739 :returns: The registers as read, and what they mean. 3740 :raises PamojaError: As :meth:`init`, and when the conversion-ready flag never sets. 3741 """ 3742 return self._native.measure() 3743 3744 @property 3745 def current_lsb_microamps(self) -> int: 3746 """The current step the driver programs, in microamps per count.""" 3747 return self._native.current_lsb_microamps 3748 3749 @property 3750 def calibration_word(self) -> int: 3751 """The calibration word the driver programs.""" 3752 return self._native.calibration_word
A Texas Instruments INA219 driven over an ~pamoja.hal.I2cBus: shunt and bus
voltage, current, and power on demand.
>>> from pamoja.hal import I2cBus
>>> bus = I2cBus.simulated([ina219.sim.part(ina219.BASE_ADDRESS)])
>>> Ina219(bus, ina219.BASE_ADDRESS).measure().bus_millivolts
12000
3697 def __init__( 3698 self, 3699 bus: I2cBus, 3700 address: int, 3701 *, 3702 shunt_milliohms: int = 100, 3703 max_microamps: int = 3_200_000, 3704 current_lsb_microamps: Optional[int] = None, 3705 config: Optional[Ina219Config] = None, 3706 ) -> None: 3707 """Make a driver for the part at ``address`` on ``bus``. 3708 3709 :param bus: The bus the part is on. 3710 :param address: ``ina219.BASE_ADDRESS`` plus what A1 and A0 add. 3711 :param shunt_milliohms: The shunt resistance; the common breakout's is 100. 3712 :param max_microamps: The largest current the shunt will carry, which sets the 3713 finest current step. 3714 :param current_lsb_microamps: A current step to use instead, such as a round 100. 3715 :param config: The range, gain, and converter settings; the power-on ones unless 3716 given. 3717 """ 3718 self._native = _NativeIna219( 3719 bus._native, 3720 address, 3721 shunt_milliohms, 3722 max_microamps, 3723 current_lsb_microamps, 3724 config, 3725 )
Make a driver for the part at address on bus.
Parameters
- bus: The bus the part is on.
- address:
ina219.BASE_ADDRESSplus what A1 and A0 add. - shunt_milliohms: The shunt resistance; the common breakout's is 100.
- max_microamps: The largest current the shunt will carry, which sets the finest current step.
- current_lsb_microamps: A current step to use instead, such as a round 100.
- config: The range, gain, and converter settings; the power-on ones unless given.
3727 def init(self) -> None: 3728 """Reset the part, write the configuration and the calibration, and read the 3729 calibration back, the identity check a part with no id register allows. 3730 3731 :raises PamojaError: If nothing answers, or the calibration does not hold. 3732 """ 3733 self._native.init()
Reset the part, write the configuration and the calibration, and read the calibration back, the identity check a part with no id register allows.
Raises
- PamojaError: If nothing answers, or the calibration does not hold.
3735 def measure(self) -> Ina219Reading: 3736 """Trigger one shunt and bus conversion and read every result, initializing the 3737 part first if :meth:`init` has not run. 3738 3739 :returns: The registers as read, and what they mean. 3740 :raises PamojaError: As :meth:`init`, and when the conversion-ready flag never sets. 3741 """ 3742 return self._native.measure()
526class Ina219Adc(enum.IntEnum): 527 """An INA219 converter setting: a resolution, or samples averaged at 12 bits.""" 528 529 #: 9 bits, 84 us. 530 BITS_9 = 0b0000 531 #: 10 bits, 148 us. 532 BITS_10 = 0b0001 533 #: 11 bits, 276 us. 534 BITS_11 = 0b0010 535 #: 12 bits, 532 us, the reset setting. 536 BITS_12 = 0b0011 537 #: 2 samples averaged, 1.06 ms. 538 SAMPLES_2 = 0b1001 539 #: 4 samples averaged, 2.13 ms. 540 SAMPLES_4 = 0b1010 541 #: 8 samples averaged, 4.26 ms. 542 SAMPLES_8 = 0b1011 543 #: 16 samples averaged, 8.51 ms. 544 SAMPLES_16 = 0b1100 545 #: 32 samples averaged, 17.02 ms. 546 SAMPLES_32 = 0b1101 547 #: 64 samples averaged, 34.05 ms. 548 SAMPLES_64 = 0b1110 549 #: 128 samples averaged, 68.10 ms. 550 SAMPLES_128 = 0b1111
An INA219 converter setting: a resolution, or samples averaged at 12 bits.
504class Ina219BusRange(enum.IntEnum): 505 """An INA219 bus-voltage range, as its register code.""" 506 507 #: 0 to 16 V. 508 V16 = 0 509 #: 0 to 32 V, the reset setting. 510 V32 = 1
An INA219 bus-voltage range, as its register code.
An INA219 configuration register, field by field, each setting as the code the datasheet prints.
513class Ina219Gain(enum.IntEnum): 514 """An INA219 shunt gain, by the shunt-voltage range it gives, as its register code.""" 515 516 #: Gain 1, 40 mV either side of zero. 517 DIV1 = 0 518 #: Gain 1/2, 80 mV. 519 DIV2 = 1 520 #: Gain 1/4, 160 mV. 521 DIV4 = 2 522 #: Gain 1/8, 320 mV, the reset setting. 523 DIV8 = 3
An INA219 shunt gain, by the shunt-voltage range it gives, as its register code.
553class Ina219Mode(enum.IntEnum): 554 """An INA219 operating mode, as its register code.""" 555 556 #: No conversions, lowest power. 557 POWER_DOWN = 0 558 #: One shunt conversion. 559 SHUNT_TRIGGERED = 1 560 #: One bus conversion. 561 BUS_TRIGGERED = 2 562 #: One shunt and one bus conversion. 563 SHUNT_AND_BUS_TRIGGERED = 3 564 #: The converter disabled. 565 ADC_OFF = 4 566 #: Shunt conversions back to back. 567 SHUNT_CONTINUOUS = 5 568 #: Bus conversions back to back. 569 BUS_CONTINUOUS = 6 570 #: Shunt and bus conversions back to back, the reset setting. 571 SHUNT_AND_BUS_CONTINUOUS = 7
An INA219 operating mode, as its register code.
One INA219 conversion: the four result registers as read, and what they mean.
3755class Ina226: 3756 """A Texas Instruments INA226 driven over an :class:`~pamoja.hal.I2cBus`: shunt and bus 3757 voltage, current, and power on demand. 3758 3759 >>> from pamoja.hal import I2cBus 3760 >>> bus = I2cBus.simulated([ina226.sim.part(ina226.BASE_ADDRESS)]) 3761 >>> Ina226(bus, ina226.BASE_ADDRESS).measure().bus_microvolts 3762 12000000 3763 """ 3764 3765 __slots__ = ("_native",) 3766 3767 def __init__( 3768 self, 3769 bus: I2cBus, 3770 address: int, 3771 *, 3772 shunt_milliohms: int = 100, 3773 max_microamps: int = 3_200_000, 3774 current_lsb_microamps: Optional[int] = None, 3775 config: Optional[Ina226Config] = None, 3776 ) -> None: 3777 """Make a driver for the part at ``address`` on ``bus``. 3778 3779 :param bus: The bus the part is on. 3780 :param address: The address A1 and A0 select, which ``ina226.address`` works out. 3781 :param shunt_milliohms: The shunt resistance. 3782 :param max_microamps: The largest current the shunt will carry, which sets the 3783 finest current step. 3784 :param current_lsb_microamps: A current step to use instead. 3785 :param config: The averaging and conversion times; the power-on ones unless given. 3786 """ 3787 self._native = _NativeIna226( 3788 bus._native, 3789 address, 3790 shunt_milliohms, 3791 max_microamps, 3792 current_lsb_microamps, 3793 config, 3794 ) 3795 3796 def init(self) -> None: 3797 """Reset the part, check it is an INA226, and program the configuration and 3798 calibration. 3799 3800 :raises PamojaError: If nothing answers, the id registers are not an INA226's, or 3801 the calibration does not read back. 3802 """ 3803 self._native.init() 3804 3805 def measure(self) -> Ina226Reading: 3806 """Trigger one shunt and bus conversion and read every result, initializing the 3807 part first if :meth:`init` has not run. 3808 3809 :returns: The registers as read, and what they mean. 3810 :raises PamojaError: As :meth:`init`, and when the conversion-ready flag never sets. 3811 """ 3812 return self._native.measure() 3813 3814 def set_alert(self, mask: Ina226MaskEnable, limit: int) -> None: 3815 """Program the alert pin: which limit it watches, and the limit. 3816 3817 :param mask: The mask/enable settings, one alert function at a time. 3818 :param limit: The alert-limit register, in the units of the register the function 3819 watches. 3820 :raises PamojaError: If the transfer fails. 3821 """ 3822 self._native.set_alert(mask, limit) 3823 3824 @property 3825 def current_lsb_microamps(self) -> int: 3826 """The current step the driver programs, in microamps per count.""" 3827 return self._native.current_lsb_microamps 3828 3829 @property 3830 def calibration_word(self) -> int: 3831 """The calibration word the driver programs.""" 3832 return self._native.calibration_word 3833 3834 @property 3835 def identity(self) -> Optional[Ina226DieId]: 3836 """The die id read at initialization, or ``None`` before it.""" 3837 return self._native.identity
A Texas Instruments INA226 driven over an ~pamoja.hal.I2cBus: shunt and bus
voltage, current, and power on demand.
>>> from pamoja.hal import I2cBus
>>> bus = I2cBus.simulated([ina226.sim.part(ina226.BASE_ADDRESS)])
>>> Ina226(bus, ina226.BASE_ADDRESS).measure().bus_microvolts
12000000
3767 def __init__( 3768 self, 3769 bus: I2cBus, 3770 address: int, 3771 *, 3772 shunt_milliohms: int = 100, 3773 max_microamps: int = 3_200_000, 3774 current_lsb_microamps: Optional[int] = None, 3775 config: Optional[Ina226Config] = None, 3776 ) -> None: 3777 """Make a driver for the part at ``address`` on ``bus``. 3778 3779 :param bus: The bus the part is on. 3780 :param address: The address A1 and A0 select, which ``ina226.address`` works out. 3781 :param shunt_milliohms: The shunt resistance. 3782 :param max_microamps: The largest current the shunt will carry, which sets the 3783 finest current step. 3784 :param current_lsb_microamps: A current step to use instead. 3785 :param config: The averaging and conversion times; the power-on ones unless given. 3786 """ 3787 self._native = _NativeIna226( 3788 bus._native, 3789 address, 3790 shunt_milliohms, 3791 max_microamps, 3792 current_lsb_microamps, 3793 config, 3794 )
Make a driver for the part at address on bus.
Parameters
- bus: The bus the part is on.
- address: The address A1 and A0 select, which
ina226.addressworks out. - shunt_milliohms: The shunt resistance.
- max_microamps: The largest current the shunt will carry, which sets the finest current step.
- current_lsb_microamps: A current step to use instead.
- config: The averaging and conversion times; the power-on ones unless given.
3796 def init(self) -> None: 3797 """Reset the part, check it is an INA226, and program the configuration and 3798 calibration. 3799 3800 :raises PamojaError: If nothing answers, the id registers are not an INA226's, or 3801 the calibration does not read back. 3802 """ 3803 self._native.init()
Reset the part, check it is an INA226, and program the configuration and calibration.
Raises
- PamojaError: If nothing answers, the id registers are not an INA226's, or the calibration does not read back.
3805 def measure(self) -> Ina226Reading: 3806 """Trigger one shunt and bus conversion and read every result, initializing the 3807 part first if :meth:`init` has not run. 3808 3809 :returns: The registers as read, and what they mean. 3810 :raises PamojaError: As :meth:`init`, and when the conversion-ready flag never sets. 3811 """ 3812 return self._native.measure()
3814 def set_alert(self, mask: Ina226MaskEnable, limit: int) -> None: 3815 """Program the alert pin: which limit it watches, and the limit. 3816 3817 :param mask: The mask/enable settings, one alert function at a time. 3818 :param limit: The alert-limit register, in the units of the register the function 3819 watches. 3820 :raises PamojaError: If the transfer fails. 3821 """ 3822 self._native.set_alert(mask, limit)
Program the alert pin: which limit it watches, and the limit.
Parameters
- mask: The mask/enable settings, one alert function at a time.
- limit: The alert-limit register, in the units of the register the function watches.
Raises
- PamojaError: If the transfer fails.
3824 @property 3825 def current_lsb_microamps(self) -> int: 3826 """The current step the driver programs, in microamps per count.""" 3827 return self._native.current_lsb_microamps
The current step the driver programs, in microamps per count.
1516class Ina226AlertFunction(str, enum.Enum): 1517 """The limit comparison an INA226 alert pin responds to.""" 1518 1519 #: The shunt voltage rose above the alert limit. 1520 SHUNT_OVER_LIMIT = "ShuntOverLimit" 1521 #: The shunt voltage fell below the alert limit. 1522 SHUNT_UNDER_LIMIT = "ShuntUnderLimit" 1523 #: The bus voltage rose above the alert limit. 1524 BUS_OVER_LIMIT = "BusOverLimit" 1525 #: The bus voltage fell below the alert limit. 1526 BUS_UNDER_LIMIT = "BusUnderLimit" 1527 #: The power rose above the alert limit. 1528 POWER_OVER_LIMIT = "PowerOverLimit"
The limit comparison an INA226 alert pin responds to.
574class Ina226Averaging(enum.IntEnum): 575 """How many samples an INA226 folds into each result, as its register code.""" 576 577 #: Every conversion reported, the reset setting. 578 SAMPLES_1 = 0 579 #: 4 samples. 580 SAMPLES_4 = 1 581 #: 16 samples. 582 SAMPLES_16 = 2 583 #: 64 samples. 584 SAMPLES_64 = 3 585 #: 128 samples. 586 SAMPLES_128 = 4 587 #: 256 samples. 588 SAMPLES_256 = 5 589 #: 512 samples. 590 SAMPLES_512 = 6 591 #: 1024 samples. 592 SAMPLES_1024 = 7
How many samples an INA226 folds into each result, as its register code.
An INA226 configuration register, field by field.
595class Ina226ConversionTime(enum.IntEnum): 596 """An INA226 conversion time, for the bus or the shunt voltage, as its register code.""" 597 598 #: 140 us. 599 US_140 = 0 600 #: 204 us. 601 US_204 = 1 602 #: 332 us. 603 US_332 = 2 604 #: 588 us. 605 US_588 = 3 606 #: 1.1 ms, the reset setting. 607 US_1100 = 4 608 #: 2.116 ms. 609 US_2116 = 5 610 #: 4.156 ms. 611 US_4156 = 6 612 #: 8.244 ms. 613 US_8244 = 7
An INA226 conversion time, for the bus or the shunt voltage, as its register code.
A decoded INA226 die-ID register.
616class Ina226Mode(enum.IntEnum): 617 """An INA226 operating mode, as its register code.""" 618 619 #: No conversions; the registers stay readable and writable. 620 POWER_DOWN = 0 621 #: One shunt conversion. 622 SHUNT_TRIGGERED = 1 623 #: One bus conversion. 624 BUS_TRIGGERED = 2 625 #: One shunt and one bus conversion. 626 SHUNT_AND_BUS_TRIGGERED = 3 627 #: Shunt conversions back to back. 628 SHUNT_CONTINUOUS = 5 629 #: Bus conversions back to back. 630 BUS_CONTINUOUS = 6 631 #: Shunt and bus conversions back to back, the reset setting. 632 SHUNT_AND_BUS_CONTINUOUS = 7
An INA226 operating mode, as its register code.
An INA226 Mask/Enable register, field by field.
One INA226 conversion: the four result registers as read, and what they mean.
3555class Opt3001: 3556 """A Texas Instruments OPT3001 driven over an :class:`~pamoja.hal.I2cBus`, measuring 3557 illuminance on demand in single-shot mode. 3558 3559 >>> from pamoja.hal import I2cBus 3560 >>> bus = I2cBus.simulated([opt3001.sim.reporting(opt3001.ADDRESS_GND, 1200.0)]) 3561 >>> Opt3001(bus, opt3001.ADDRESS_GND).measure().lux 3562 1200.0 3563 """ 3564 3565 __slots__ = ("_native",) 3566 3567 def __init__( 3568 self, 3569 bus: I2cBus, 3570 address: int, 3571 *, 3572 conversion_time: Opt3001ConversionTime = Opt3001ConversionTime.MS_800, 3573 range_number: int = 12, 3574 ) -> None: 3575 """Make a driver for the part at ``address`` on ``bus``. 3576 3577 :param bus: The bus the part is on. 3578 :param address: One of the ``opt3001.ADDRESS_*`` constants, by where ADDR is tied. 3579 :param conversion_time: How long each conversion integrates. 3580 :param range_number: A fixed full-scale range, ``0`` to ``11``, or ``12`` to let 3581 the part choose. 3582 """ 3583 self._native = _NativeOpt3001( 3584 bus._native, 3585 address, 3586 Opt3001ConversionTime(conversion_time) == Opt3001ConversionTime.MS_800, 3587 range_number, 3588 ) 3589 3590 def init(self) -> None: 3591 """Check the part is an OPT3001 and write the settings with the part in shutdown. 3592 3593 :raises PamojaError: If nothing answers, or either id register is not an OPT3001's. 3594 """ 3595 self._native.init() 3596 3597 def measure(self) -> Opt3001Reading: 3598 """Run one conversion and read the illuminance, initializing the part first if 3599 :meth:`init` has not run. 3600 3601 :returns: The illuminance. 3602 :raises PamojaError: As :meth:`init`, and when the conversion never finishes. 3603 """ 3604 return self._native.measure() 3605 3606 def set_limits(self, low_milli_lux: int, high_milli_lux: int) -> None: 3607 """Write the low and high limits the part's interrupt pin compares each result 3608 against. 3609 3610 :param low_milli_lux: The low limit, in millilux. 3611 :param high_milli_lux: The high limit, in millilux. 3612 :raises PamojaError: If the transfer fails. 3613 """ 3614 self._native.set_limits(low_milli_lux, high_milli_lux) 3615 3616 @property 3617 def configuration(self) -> Opt3001Config: 3618 """The configuration the driver writes, with the part in shutdown.""" 3619 return self._native.configuration
A Texas Instruments OPT3001 driven over an ~pamoja.hal.I2cBus, measuring
illuminance on demand in single-shot mode.
>>> from pamoja.hal import I2cBus
>>> bus = I2cBus.simulated([opt3001.sim.reporting(opt3001.ADDRESS_GND, 1200.0)])
>>> Opt3001(bus, opt3001.ADDRESS_GND).measure().lux
1200.0
3567 def __init__( 3568 self, 3569 bus: I2cBus, 3570 address: int, 3571 *, 3572 conversion_time: Opt3001ConversionTime = Opt3001ConversionTime.MS_800, 3573 range_number: int = 12, 3574 ) -> None: 3575 """Make a driver for the part at ``address`` on ``bus``. 3576 3577 :param bus: The bus the part is on. 3578 :param address: One of the ``opt3001.ADDRESS_*`` constants, by where ADDR is tied. 3579 :param conversion_time: How long each conversion integrates. 3580 :param range_number: A fixed full-scale range, ``0`` to ``11``, or ``12`` to let 3581 the part choose. 3582 """ 3583 self._native = _NativeOpt3001( 3584 bus._native, 3585 address, 3586 Opt3001ConversionTime(conversion_time) == Opt3001ConversionTime.MS_800, 3587 range_number, 3588 )
Make a driver for the part at address on bus.
Parameters
- bus: The bus the part is on.
- address: One of the
opt3001.ADDRESS_*constants, by where ADDR is tied. - conversion_time: How long each conversion integrates.
- range_number: A fixed full-scale range,
0to11, or12to let the part choose.
3590 def init(self) -> None: 3591 """Check the part is an OPT3001 and write the settings with the part in shutdown. 3592 3593 :raises PamojaError: If nothing answers, or either id register is not an OPT3001's. 3594 """ 3595 self._native.init()
Check the part is an OPT3001 and write the settings with the part in shutdown.
Raises
- PamojaError: If nothing answers, or either id register is not an OPT3001's.
3597 def measure(self) -> Opt3001Reading: 3598 """Run one conversion and read the illuminance, initializing the part first if 3599 :meth:`init` has not run. 3600 3601 :returns: The illuminance. 3602 :raises PamojaError: As :meth:`init`, and when the conversion never finishes. 3603 """ 3604 return self._native.measure()
3606 def set_limits(self, low_milli_lux: int, high_milli_lux: int) -> None: 3607 """Write the low and high limits the part's interrupt pin compares each result 3608 against. 3609 3610 :param low_milli_lux: The low limit, in millilux. 3611 :param high_milli_lux: The high limit, in millilux. 3612 :raises PamojaError: If the transfer fails. 3613 """ 3614 self._native.set_limits(low_milli_lux, high_milli_lux)
Write the low and high limits the part's interrupt pin compares each result against.
Parameters
- low_milli_lux: The low limit, in millilux.
- high_milli_lux: The high limit, in millilux.
Raises
- PamojaError: If the transfer fails.
An OPT3001 configuration register, field by field.
475class Opt3001ConversionTime(enum.IntEnum): 476 """How long an OPT3001 conversion integrates, in milliseconds.""" 477 478 #: 100 ms, for speed. 479 MS_100 = 100 480 #: 800 ms, for resolution; the part's reset setting. 481 MS_800 = 800
How long an OPT3001 conversion integrates, in milliseconds.
An OPT3001 illuminance result.
3982class Scd4x: 3983 """A Sensirion SCD40 or SCD41 driven over an :class:`~pamoja.hal.I2cBus` in periodic 3984 measurement, a result every five seconds. 3985 3986 >>> from pamoja.hal import I2cBus 3987 >>> bus = I2cBus.simulated([scd4x.sim.reporting(1450, 24.0, 55.0)]) 3988 >>> Scd4x(bus).measure().co2_ppm 3989 1450 3990 """ 3991 3992 __slots__ = ("_native",) 3993 3994 def __init__(self, bus: I2cBus) -> None: 3995 """Make a driver for the part on ``bus``, which has one address. 3996 3997 :param bus: The bus the part is on. 3998 """ 3999 self._native = _NativeScd4x(bus._native) 4000 4001 def init(self) -> None: 4002 """Stop any running measurement, read the serial number, and start periodic 4003 measurement. 4004 4005 :raises PamojaError: If nothing answers, or the serial number fails its checksum. 4006 """ 4007 self._native.init() 4008 4009 def measure(self) -> Scd4xMeasurement: 4010 """Wait for the next periodic result and read it, initializing the part first if 4011 :meth:`init` has not run. 4012 4013 :returns: The carbon dioxide, temperature, and humidity. 4014 :raises PamojaError: As :meth:`init`, when no result becomes ready, and when a word 4015 fails its checksum. 4016 """ 4017 return self._native.measure() 4018 4019 def measure_single_shot(self) -> Scd4xMeasurement: 4020 """Run one on-demand measurement on an SCD41, which takes five seconds. The part 4021 must not be measuring periodically: call :meth:`stop` first, or use this in place 4022 of :meth:`init`. 4023 4024 :returns: The measurement. 4025 :raises PamojaError: As :meth:`measure`. 4026 """ 4027 return self._native.measure_single_shot() 4028 4029 def data_ready(self) -> bool: 4030 """Ask the part whether a periodic result is waiting. 4031 4032 :returns: Whether :meth:`measure` would read without waiting. 4033 :raises PamojaError: If the transfer fails or the word fails its checksum. 4034 """ 4035 return self._native.data_ready() 4036 4037 def stop(self) -> None: 4038 """Stop periodic measurement, after which the part takes its settings commands. 4039 4040 :raises PamojaError: If the transfer fails. 4041 """ 4042 self._native.stop() 4043 4044 def start(self) -> None: 4045 """Start periodic measurement. 4046 4047 :raises PamojaError: If the transfer fails. 4048 """ 4049 self._native.start() 4050 4051 def set_temperature_offset(self, milli_celsius: int) -> None: 4052 """Set the temperature offset that compensates the part's own warmth, until power 4053 is lost. 4054 4055 :param milli_celsius: The offset to subtract, in millidegrees. 4056 :raises PamojaError: If the transfer fails. 4057 """ 4058 self._native.set_temperature_offset(milli_celsius) 4059 4060 def set_sensor_altitude(self, meters: int) -> None: 4061 """Set the altitude the part corrects its carbon dioxide reading for. 4062 4063 :param meters: The altitude above sea level. 4064 :raises PamojaError: If the transfer fails. 4065 """ 4066 self._native.set_sensor_altitude(meters) 4067 4068 @property 4069 def serial(self) -> Optional[int]: 4070 """The 48-bit serial number read at initialization, or ``None`` before it.""" 4071 return self._native.serial
A Sensirion SCD40 or SCD41 driven over an ~pamoja.hal.I2cBus in periodic
measurement, a result every five seconds.
>>> from pamoja.hal import I2cBus
>>> bus = I2cBus.simulated([scd4x.sim.reporting(1450, 24.0, 55.0)])
>>> Scd4x(bus).measure().co2_ppm
1450
3994 def __init__(self, bus: I2cBus) -> None: 3995 """Make a driver for the part on ``bus``, which has one address. 3996 3997 :param bus: The bus the part is on. 3998 """ 3999 self._native = _NativeScd4x(bus._native)
Make a driver for the part on bus, which has one address.
Parameters
- bus: The bus the part is on.
4001 def init(self) -> None: 4002 """Stop any running measurement, read the serial number, and start periodic 4003 measurement. 4004 4005 :raises PamojaError: If nothing answers, or the serial number fails its checksum. 4006 """ 4007 self._native.init()
Stop any running measurement, read the serial number, and start periodic measurement.
Raises
- PamojaError: If nothing answers, or the serial number fails its checksum.
4009 def measure(self) -> Scd4xMeasurement: 4010 """Wait for the next periodic result and read it, initializing the part first if 4011 :meth:`init` has not run. 4012 4013 :returns: The carbon dioxide, temperature, and humidity. 4014 :raises PamojaError: As :meth:`init`, when no result becomes ready, and when a word 4015 fails its checksum. 4016 """ 4017 return self._native.measure()
4019 def measure_single_shot(self) -> Scd4xMeasurement: 4020 """Run one on-demand measurement on an SCD41, which takes five seconds. The part 4021 must not be measuring periodically: call :meth:`stop` first, or use this in place 4022 of :meth:`init`. 4023 4024 :returns: The measurement. 4025 :raises PamojaError: As :meth:`measure`. 4026 """ 4027 return self._native.measure_single_shot()
4029 def data_ready(self) -> bool: 4030 """Ask the part whether a periodic result is waiting. 4031 4032 :returns: Whether :meth:`measure` would read without waiting. 4033 :raises PamojaError: If the transfer fails or the word fails its checksum. 4034 """ 4035 return self._native.data_ready()
Ask the part whether a periodic result is waiting.
:returns: Whether measure() would read without waiting.
Raises
- PamojaError: If the transfer fails or the word fails its checksum.
4037 def stop(self) -> None: 4038 """Stop periodic measurement, after which the part takes its settings commands. 4039 4040 :raises PamojaError: If the transfer fails. 4041 """ 4042 self._native.stop()
Stop periodic measurement, after which the part takes its settings commands.
Raises
- PamojaError: If the transfer fails.
4044 def start(self) -> None: 4045 """Start periodic measurement. 4046 4047 :raises PamojaError: If the transfer fails. 4048 """ 4049 self._native.start()
Start periodic measurement.
Raises
- PamojaError: If the transfer fails.
4051 def set_temperature_offset(self, milli_celsius: int) -> None: 4052 """Set the temperature offset that compensates the part's own warmth, until power 4053 is lost. 4054 4055 :param milli_celsius: The offset to subtract, in millidegrees. 4056 :raises PamojaError: If the transfer fails. 4057 """ 4058 self._native.set_temperature_offset(milli_celsius)
Set the temperature offset that compensates the part's own warmth, until power is lost.
Parameters
- milli_celsius: The offset to subtract, in millidegrees.
Raises
- PamojaError: If the transfer fails.
4060 def set_sensor_altitude(self, meters: int) -> None: 4061 """Set the altitude the part corrects its carbon dioxide reading for. 4062 4063 :param meters: The altitude above sea level. 4064 :raises PamojaError: If the transfer fails. 4065 """ 4066 self._native.set_sensor_altitude(meters)
Set the altitude the part corrects its carbon dioxide reading for.
Parameters
- meters: The altitude above sea level.
Raises
- PamojaError: If the transfer fails.
A decoded SCD4x measurement frame.
3906class Sht3x: 3907 """A Sensirion SHT3x driven over an :class:`~pamoja.hal.I2cBus`, measuring on demand in 3908 single-shot mode. 3909 3910 >>> from pamoja.hal import I2cBus 3911 >>> bus = I2cBus.simulated([sht3x.sim.reporting(sht3x.ADDRESS_A, 30.0, 70.0)]) 3912 >>> round(Sht3x(bus, sht3x.ADDRESS_A).measure().celsius, 1) 3913 30.0 3914 """ 3915 3916 __slots__ = ("_native",) 3917 3918 def __init__( 3919 self, 3920 bus: I2cBus, 3921 address: int, 3922 *, 3923 repeatability: Sht3xRepeatability = Sht3xRepeatability.HIGH, 3924 ) -> None: 3925 """Make a driver for the part at ``address`` on ``bus``. 3926 3927 :param bus: The bus the part is on. 3928 :param address: ``sht3x.ADDRESS_A`` with ADDR low, ``sht3x.ADDRESS_B`` with it 3929 high. 3930 :param repeatability: How repeatable each measurement is, against how long it 3931 takes. 3932 """ 3933 self._native = _NativeSht3x( 3934 bus._native, address, Sht3xRepeatability(repeatability).value 3935 ) 3936 3937 def init(self) -> None: 3938 """Soft-reset the part and read its status; a status word whose checksum holds is 3939 what confirms an SHT3x answers, as the part has no id register. 3940 3941 :raises PamojaError: If nothing answers, or the status word fails its checksum. 3942 """ 3943 self._native.init() 3944 3945 def measure(self) -> Sht3xMeasurement: 3946 """Run one single-shot measurement, initializing the part first if :meth:`init` 3947 has not run. 3948 3949 :returns: The checksum-checked temperature and humidity. 3950 :raises PamojaError: As :meth:`init`, and when a data word fails its checksum. 3951 """ 3952 return self._native.measure() 3953 3954 def read_status(self) -> Sht3xStatus: 3955 """Read the status register, which :attr:`last_status` keeps as well. 3956 3957 :returns: The status. 3958 :raises PamojaError: If the transfer fails or the word fails its checksum. 3959 """ 3960 return self._native.read_status() 3961 3962 def heater_on(self) -> None: 3963 """Switch the plausibility-check heater on, initializing the part first if needed. 3964 3965 :raises PamojaError: As :meth:`init`. 3966 """ 3967 self._native.heater_on() 3968 3969 def heater_off(self) -> None: 3970 """Switch the heater off, which is its state after any reset. 3971 3972 :raises PamojaError: As :meth:`init`. 3973 """ 3974 self._native.heater_off() 3975 3976 @property 3977 def last_status(self) -> Optional[Sht3xStatus]: 3978 """The status register as it was last read, or ``None`` before it has been.""" 3979 return self._native.last_status
A Sensirion SHT3x driven over an ~pamoja.hal.I2cBus, measuring on demand in
single-shot mode.
>>> from pamoja.hal import I2cBus
>>> bus = I2cBus.simulated([sht3x.sim.reporting(sht3x.ADDRESS_A, 30.0, 70.0)])
>>> round(Sht3x(bus, sht3x.ADDRESS_A).measure().celsius, 1)
30.0
3918 def __init__( 3919 self, 3920 bus: I2cBus, 3921 address: int, 3922 *, 3923 repeatability: Sht3xRepeatability = Sht3xRepeatability.HIGH, 3924 ) -> None: 3925 """Make a driver for the part at ``address`` on ``bus``. 3926 3927 :param bus: The bus the part is on. 3928 :param address: ``sht3x.ADDRESS_A`` with ADDR low, ``sht3x.ADDRESS_B`` with it 3929 high. 3930 :param repeatability: How repeatable each measurement is, against how long it 3931 takes. 3932 """ 3933 self._native = _NativeSht3x( 3934 bus._native, address, Sht3xRepeatability(repeatability).value 3935 )
Make a driver for the part at address on bus.
Parameters
- bus: The bus the part is on.
- address:
sht3x.ADDRESS_Awith ADDR low,sht3x.ADDRESS_Bwith it high. - repeatability: How repeatable each measurement is, against how long it takes.
3937 def init(self) -> None: 3938 """Soft-reset the part and read its status; a status word whose checksum holds is 3939 what confirms an SHT3x answers, as the part has no id register. 3940 3941 :raises PamojaError: If nothing answers, or the status word fails its checksum. 3942 """ 3943 self._native.init()
Soft-reset the part and read its status; a status word whose checksum holds is what confirms an SHT3x answers, as the part has no id register.
Raises
- PamojaError: If nothing answers, or the status word fails its checksum.
3945 def measure(self) -> Sht3xMeasurement: 3946 """Run one single-shot measurement, initializing the part first if :meth:`init` 3947 has not run. 3948 3949 :returns: The checksum-checked temperature and humidity. 3950 :raises PamojaError: As :meth:`init`, and when a data word fails its checksum. 3951 """ 3952 return self._native.measure()
3954 def read_status(self) -> Sht3xStatus: 3955 """Read the status register, which :attr:`last_status` keeps as well. 3956 3957 :returns: The status. 3958 :raises PamojaError: If the transfer fails or the word fails its checksum. 3959 """ 3960 return self._native.read_status()
Read the status register, which last_status keeps as well.
:returns: The status.
Raises
- PamojaError: If the transfer fails or the word fails its checksum.
3962 def heater_on(self) -> None: 3963 """Switch the plausibility-check heater on, initializing the part first if needed. 3964 3965 :raises PamojaError: As :meth:`init`. 3966 """ 3967 self._native.heater_on()
Switch the plausibility-check heater on, initializing the part first if needed.
Raises
- PamojaError: As
init().
A decoded SHT3x temperature and humidity pair.
1501class Sht3xRate(str, enum.Enum): 1502 """How often an SHT3x in periodic mode takes a measurement.""" 1503 1504 #: One measurement every two seconds. 1505 HALF_MPS = "HalfMps" 1506 #: One measurement per second. 1507 ONE_MPS = "OneMps" 1508 #: Two measurements per second. 1509 TWO_MPS = "TwoMps" 1510 #: Four measurements per second. 1511 FOUR_MPS = "FourMps" 1512 #: Ten measurements per second. 1513 TEN_MPS = "TenMps"
How often an SHT3x in periodic mode takes a measurement.
1490class Sht3xRepeatability(str, enum.Enum): 1491 """How hard an SHT3x works at one measurement, traded against time and power.""" 1492 1493 #: The fastest and least precise setting. 1494 LOW = "Low" 1495 #: The middle setting. 1496 MEDIUM = "Medium" 1497 #: The slowest and most precise setting. 1498 HIGH = "High"
How hard an SHT3x works at one measurement, traded against time and power.
A decoded SHT3x status register.
3489class Tmp117: 3490 """A Texas Instruments TMP117 driven over an :class:`~pamoja.hal.I2cBus`, converting on 3491 demand in one-shot mode and powered down between conversions. 3492 3493 >>> from pamoja.hal import I2cBus 3494 >>> bus = I2cBus.simulated([tmp117.sim.reporting(tmp117.ADDRESS_ADD0_GND, -18.5)]) 3495 >>> Tmp117(bus, tmp117.ADDRESS_ADD0_GND).measure().celsius 3496 -18.5 3497 """ 3498 3499 __slots__ = ("_native",) 3500 3501 def __init__( 3502 self, bus: I2cBus, address: int, *, averaging: Tmp117Averaging = Tmp117Averaging.X8 3503 ) -> None: 3504 """Make a driver for the part at ``address`` on ``bus``. 3505 3506 :param bus: The bus the part is on. 3507 :param address: One of the ``tmp117.ADDRESS_ADD0_*`` constants, by where ADD0 is 3508 tied. 3509 :param averaging: How many conversions are averaged into each result. 3510 """ 3511 self._native = _NativeTmp117(bus._native, address, int(averaging)) 3512 3513 def init(self) -> None: 3514 """Check the part is a TMP117, wait for its EEPROM, and write the settings with the 3515 part in shutdown. 3516 3517 :raises PamojaError: If nothing answers, the device id is not a TMP117's, or the 3518 EEPROM never reports ready. 3519 """ 3520 self._native.init() 3521 3522 def measure(self) -> Tmp117Reading: 3523 """Run one conversion and read the temperature, initializing the part first if 3524 :meth:`init` has not run. 3525 3526 :returns: The temperature. 3527 :raises PamojaError: As :meth:`init`, and when the conversion never finishes. 3528 """ 3529 return self._native.measure() 3530 3531 def set_alert_limits(self, high_celsius: float, low_celsius: float) -> None: 3532 """Write the high and low limits the part compares each result against. 3533 3534 :param high_celsius: The high limit; the factory value is 192 C. 3535 :param low_celsius: The low limit; the factory value is -256 C. 3536 :raises PamojaError: If the transfer fails. 3537 """ 3538 self._native.set_alert_limits(high_celsius, low_celsius) 3539 3540 def alerts(self) -> Tmp117Alerts: 3541 """Read the alert flags, including results the driver's own reads saw since the 3542 last call. 3543 3544 :returns: Whether a result was above the high limit or below the low limit. 3545 :raises PamojaError: If the transfer fails. 3546 """ 3547 return self._native.alerts() 3548 3549 @property 3550 def silicon_revision(self) -> Optional[int]: 3551 """The silicon revision read at initialization, or ``None`` before it.""" 3552 return self._native.silicon_revision
A Texas Instruments TMP117 driven over an ~pamoja.hal.I2cBus, converting on
demand in one-shot mode and powered down between conversions.
>>> from pamoja.hal import I2cBus
>>> bus = I2cBus.simulated([tmp117.sim.reporting(tmp117.ADDRESS_ADD0_GND, -18.5)])
>>> Tmp117(bus, tmp117.ADDRESS_ADD0_GND).measure().celsius
-18.5
3501 def __init__( 3502 self, bus: I2cBus, address: int, *, averaging: Tmp117Averaging = Tmp117Averaging.X8 3503 ) -> None: 3504 """Make a driver for the part at ``address`` on ``bus``. 3505 3506 :param bus: The bus the part is on. 3507 :param address: One of the ``tmp117.ADDRESS_ADD0_*`` constants, by where ADD0 is 3508 tied. 3509 :param averaging: How many conversions are averaged into each result. 3510 """ 3511 self._native = _NativeTmp117(bus._native, address, int(averaging))
Make a driver for the part at address on bus.
Parameters
- bus: The bus the part is on.
- address: One of the
tmp117.ADDRESS_ADD0_*constants, by where ADD0 is tied. - averaging: How many conversions are averaged into each result.
3513 def init(self) -> None: 3514 """Check the part is a TMP117, wait for its EEPROM, and write the settings with the 3515 part in shutdown. 3516 3517 :raises PamojaError: If nothing answers, the device id is not a TMP117's, or the 3518 EEPROM never reports ready. 3519 """ 3520 self._native.init()
Check the part is a TMP117, wait for its EEPROM, and write the settings with the part in shutdown.
Raises
- PamojaError: If nothing answers, the device id is not a TMP117's, or the EEPROM never reports ready.
3522 def measure(self) -> Tmp117Reading: 3523 """Run one conversion and read the temperature, initializing the part first if 3524 :meth:`init` has not run. 3525 3526 :returns: The temperature. 3527 :raises PamojaError: As :meth:`init`, and when the conversion never finishes. 3528 """ 3529 return self._native.measure()
3531 def set_alert_limits(self, high_celsius: float, low_celsius: float) -> None: 3532 """Write the high and low limits the part compares each result against. 3533 3534 :param high_celsius: The high limit; the factory value is 192 C. 3535 :param low_celsius: The low limit; the factory value is -256 C. 3536 :raises PamojaError: If the transfer fails. 3537 """ 3538 self._native.set_alert_limits(high_celsius, low_celsius)
Write the high and low limits the part compares each result against.
Parameters
- high_celsius: The high limit; the factory value is 192 C.
- low_celsius: The low limit; the factory value is -256 C.
Raises
- PamojaError: If the transfer fails.
3540 def alerts(self) -> Tmp117Alerts: 3541 """Read the alert flags, including results the driver's own reads saw since the 3542 last call. 3543 3544 :returns: Whether a result was above the high limit or below the low limit. 3545 :raises PamojaError: If the transfer fails. 3546 """ 3547 return self._native.alerts()
Read the alert flags, including results the driver's own reads saw since the last call.
:returns: Whether a result was above the high limit or below the low limit.
Raises
- PamojaError: If the transfer fails.
The TMP117's alert flags: whether a result since they were last read crossed a limit.
462class Tmp117Averaging(enum.IntEnum): 463 """How many conversions a TMP117 averages into one result, as its register code.""" 464 465 #: No averaging: each result is one 15.5 ms conversion. 466 NONE = 0 467 #: Eight conversions, the factory setting. 468 X8 = 1 469 #: Thirty-two conversions. 470 X32 = 2 471 #: Sixty-four conversions. 472 X64 = 3
How many conversions a TMP117 averages into one result, as its register code.
A TMP117 configuration register, field by field.
A TMP117 temperature result.