Class: Denko::Sensor::QMP6988
- Inherits:
-
Object
- Object
- Denko::Sensor::QMP6988
- Includes:
- Behaviors::Lifecycle, Behaviors::Poller, I2C::Peripheral, PressureHelper, TemperatureHelper
- Defined in:
- lib/denko/sensor/qmp6988.rb
Constant Summary collapse
- I2C_ADDRESS =
0x70- UPDATE_TIME =
0.020- RESET_REGISTER =
0xE0- RESET_COMMAND =
0xE6- CTRL_MEAS_REGISTER =
0xF4- STANDBY_TIME_REGISTER =
0xF5- IIR_REGISTER =
0xF1- CONFIG_LENGTH =
5- DATA_REGISTER =
0xF7- DATA_LENGTH =
6- CALIBRATION_REGISTER =
0xA0- CALIBRATION_LENGTH =
25- CHIP_ID_REGISTER =
0xD1- CHIP_ID_LENGTH =
1- FORCED_MODE =
0b01- NORMAL_MODE =
0b11- STANDBY_TIMES =
Standby Times for Normal (Continuous) Mode in milliseconds
{ 1 => 0b000, 5 => 0b001, 50 => 0b010, 250 => 0b011, 500 => 0b100, 1000 => 0b101, 2000 => 0b110, 4000 => 0b111, }
- OVERSAMPLE_FACTORS =
Oversample Setting Values Note: Each sensor has a separate oversample setting.
General formula:
2 ** (n-1), where n is the decimal value of the bits, up to 16x max oversampling. { # 0 => 0b000, # Sensor skipped. Value will be 0x800000. 1 => 0b001, 2 => 0b010, 4 => 0b011, 8 => 0b100, 16 => 0b101, 32 => 0b110, 64 => 0b111, }
- TEMPERATURE_SAMPLE_TIME =
Single sample times (in milliseconds) for each sensor, derived from datasheet examples.
0.9- PRESSURE_SAMPLE_TIME =
0.85- IIR_COEFFICIENTS =
IIR Filter Coefficients
{ 0 => 0b000, 2 => 0b001, 4 => 0b010, 8 => 0b011, 16 => 0b100, 32 => 0b101, # 0b110 and 0b111 are also valid for 16. }
- CONVERSION_FACTORS =
{ a1: { A: -6.3e-03, S: 4.3e-04 }, a2: { A: -1.9e-11, S: 1.2e-10 }, bt1: { A: 1.0e-01, S: 9.1e-02 }, bt2: { A: 1.2e-08, S: 1.2e-06 }, bp1: { A: 3.3e-02, S: 1.9e-02 }, b11: { A: 2.1e-07, S: 1.4e-07 }, bp2: { A: -6.3e-10, S: 3.5e-10 }, b12: { A: 2.9e-13, S: 7.6e-13 }, b21: { A: 2.1e-15, S: 1.2e-14 }, bp3: { A: 1.3e-16, S: 7.9e-17 }, a0: 16.0, b00: 16.0, }
Constants included from Behaviors::Reader
Behaviors::Reader::READ_WAIT_TIME
Constants included from Behaviors::Lifecycle
Behaviors::Lifecycle::CALLBACK_METHODS
Constants included from I2C::Peripheral
I2C::Peripheral::I2C_FREQUENCY, I2C::Peripheral::I2C_REPEATED_START
Instance Attribute Summary collapse
-
#calibration_data_loaded ⇒ Object
readonly
Calibration.
-
#iir_coefficient ⇒ Object
Returns the value of attribute iir_coefficient.
-
#pressure_samples ⇒ Object
Returns the value of attribute pressure_samples.
-
#registers ⇒ Object
readonly
Returns the value of attribute registers.
-
#standby_time ⇒ Object
Returns the value of attribute standby_time.
-
#temperature_samples ⇒ Object
Returns the value of attribute temperature_samples.
Attributes included from Behaviors::Threaded
Attributes included from I2C::Peripheral
#i2c_frequency, #i2c_repeated_start
Attributes included from Behaviors::Component
Instance Method Summary collapse
-
#_read ⇒ Object
Reading & Processing.
- #calculate_measurement_time ⇒ Object
- #chip_id ⇒ Object
- #continuous_mode ⇒ Object
- #forced_mode ⇒ Object
- #get_calibration_data ⇒ Object
- #get_config_registers ⇒ Object
- #pre_callback_filter(bytes) ⇒ Object
- #reading ⇒ Object
-
#reset ⇒ Object
Configuration Methods.
- #state ⇒ Object
- #update_state(reading) ⇒ Object
Methods included from PressureHelper
#pressure, #pressure_atm, #pressure_bar
Methods included from TemperatureHelper
#temperature, #temperature_f, #temperature_k
Methods included from Behaviors::Poller
Methods included from Behaviors::Threaded
#enable_interrupts, included, #mruby_thread_check, #stop, #stop_thread, #threaded, #threaded_loop
Methods included from Behaviors::Reader
#read, #read_busy?, #read_nb, #read_raw, #read_using, #update
Methods included from Behaviors::Callbacks
#add_callback, #callbacks, #remove_callback, #update
Methods included from Behaviors::Lifecycle
Methods included from I2C::Peripheral
#address, #i2c_default, #i2c_read, #i2c_read_raw, #i2c_write
Methods included from Behaviors::BusPeripheralAddressed
Methods included from Behaviors::BusPeripheral
Methods included from Behaviors::Component
Instance Attribute Details
#calibration_data_loaded ⇒ Object (readonly)
Calibration
233 234 235 |
# File 'lib/denko/sensor/qmp6988.rb', line 233 def calibration_data_loaded @calibration_data_loaded end |
#iir_coefficient ⇒ Object
Returns the value of attribute iir_coefficient.
113 114 115 |
# File 'lib/denko/sensor/qmp6988.rb', line 113 def iir_coefficient @iir_coefficient end |
#pressure_samples ⇒ Object
Returns the value of attribute pressure_samples.
142 143 144 |
# File 'lib/denko/sensor/qmp6988.rb', line 142 def pressure_samples @pressure_samples end |
#registers ⇒ Object (readonly)
Returns the value of attribute registers.
228 229 230 |
# File 'lib/denko/sensor/qmp6988.rb', line 228 def registers @registers end |
#standby_time ⇒ Object
Returns the value of attribute standby_time.
122 123 124 |
# File 'lib/denko/sensor/qmp6988.rb', line 122 def standby_time @standby_time end |
#temperature_samples ⇒ Object
Returns the value of attribute temperature_samples.
132 133 134 |
# File 'lib/denko/sensor/qmp6988.rb', line 132 def temperature_samples @temperature_samples end |
Instance Method Details
#_read ⇒ Object
Reading & Processing
175 176 177 178 179 180 181 182 183 184 |
# File 'lib/denko/sensor/qmp6988.rb', line 175 def _read if @forced_mode # Write CTRL_MEAS register to trigger reading, then wait for measurement. i2c_write [CTRL_MEAS_REGISTER, @ctrl_meas_register] sleep @measurement_time end # Read the data bytes. i2c_read(DATA_LENGTH, register: DATA_REGISTER) end |
#calculate_measurement_time ⇒ Object
144 145 146 147 148 149 |
# File 'lib/denko/sensor/qmp6988.rb', line 144 def calculate_measurement_time @measurement_time = (@temperature_samples.to_i * TEMPERATURE_SAMPLE_TIME) + (@pressure_samples.to_i * PRESSURE_SAMPLE_TIME) # Add 5ms for safety and convert to seconds. @measurement_time = (@measurement_time + 5) * 0.001 end |
#chip_id ⇒ Object
165 166 167 168 169 170 |
# File 'lib/denko/sensor/qmp6988.rb', line 165 def chip_id return @chip_id if @chip_id bytes = i2c_read_raw(1, register: CHIP_ID_REGISTER) @chip_id = bytes[0] if bytes @chip_id end |
#continuous_mode ⇒ Object
158 159 160 161 162 163 |
# File 'lib/denko/sensor/qmp6988.rb', line 158 def continuous_mode @ctrl_meas_register = (@ctrl_meas_register & 0b11111100) | NORMAL_MODE i2c_write [CTRL_MEAS_REGISTER, @ctrl_meas_register] @forced_mode = false sleep UPDATE_TIME end |
#forced_mode ⇒ Object
151 152 153 154 155 156 |
# File 'lib/denko/sensor/qmp6988.rb', line 151 def forced_mode @ctrl_meas_register = (@ctrl_meas_register & 0b11111100) | FORCED_MODE i2c_write [CTRL_MEAS_REGISTER, @ctrl_meas_register] @forced_mode = true sleep UPDATE_TIME end |
#get_calibration_data ⇒ Object
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/denko/sensor/qmp6988.rb', line 250 def get_calibration_data bytes = i2c_read_raw(CALIBRATION_LENGTH, register: CALIBRATION_REGISTER) if bytes # These 2 values are 20-bit instead of 16-bit, so can't combine them with #pack. a0_unsigned = (bytes[18] << 12) + (bytes[19] << 4) + (bytes[24] & 0b00001111) b00_unsigned = (bytes[0] << 12) + (bytes[1] << 4) + ((bytes[24] & 0b11110000) >> 4) # Cast the raw bytes as big-endian signed. @calibration_raw = { # Shift these to 32-bit before converting to signed, then reverse the shift after. a0: [(a0_unsigned << 12)].pack('L>').unpack('l>')[0] >> 12, b00: [(b00_unsigned << 12)].pack('L>').unpack('l>')[0] >> 12, a1: bytes[20..21].pack('C*').unpack('s>')[0], a2: bytes[22..23].pack('C*').unpack('s>')[0], b11: bytes[8..9].pack('C*').unpack('s>')[0], b12: bytes[12..13].pack('C*').unpack('s>')[0], b21: bytes[14..15].pack('C*').unpack('s>')[0], bp1: bytes[6..7].pack('C*').unpack('s>')[0], bp2: bytes[10..11].pack('C*').unpack('s>')[0], bp3: bytes[16..17].pack('C*').unpack('s>')[0], bt1: bytes[2..3].pack('C*').unpack('s>')[0], bt2: bytes[4..5].pack('C*').unpack('s>')[0], } # Use conversion formulae to calculate compensation coefficients, all as floats. @calibration = {} @calibration_raw.keys.each do |key| if CONVERSION_FACTORS[key].class == Float @calibration[key] = @calibration_raw[key] / CONVERSION_FACTORS[key] else @calibration[key] = CONVERSION_FACTORS[key][:A] + (CONVERSION_FACTORS[key][:S] * @calibration_raw[key] / 32767.0) end end @calibration_data_loaded = true end end |
#get_config_registers ⇒ Object
222 223 224 225 226 227 |
# File 'lib/denko/sensor/qmp6988.rb', line 222 def get_config_registers bytes = i2c_read_raw(CONFIG_LENGTH, register: IIR_REGISTER) if bytes @registers = { f1: bytes[0], f2: bytes[1], f3: bytes[2], f4: bytes[3], f5: bytes[4] } end end |
#pre_callback_filter(bytes) ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/denko/sensor/qmp6988.rb', line 186 def pre_callback_filter(bytes) return nil unless bytes.length == DATA_LENGTH # Temperature and pressure are 24-bits long each, and need 2^23 subtracted. dt = ((bytes[3] << 16) + (bytes[4] << 8) + bytes[5]) - (0b1 << 23) dp = ((bytes[0] << 16) + (bytes[1] << 8) + bytes[2]) - (0b1 << 23) # Compensated temperature calculated in 1/256 of a degree Celsius. tr = @calibration[:a0] + @calibration[:a1] * dt + @calibration[:a2] * (dt ** 2) reading[:temperature] = tr / 256.0 # Compensated pressure calculated in Pascals. reading[:pressure] = @calibration[:b00] + @calibration[:bt1] * tr + @calibration[:bp1] * dp + @calibration[:b11] * (tr * dp) + @calibration[:bt2] * (tr ** 2) + @calibration[:bp2] * (dp ** 2) + @calibration[:b12] * (dp * (tr ** 2)) + @calibration[:b21] * ((dp ** 2) * tr) + @calibration[:bp3] * (dp ** 3) # Return reading for callbacks. reading end |
#reading ⇒ Object
96 97 98 |
# File 'lib/denko/sensor/qmp6988.rb', line 96 def reading @reading ||= { temperature: nil, pressure: nil } end |
#reset ⇒ Object
Configuration Methods
103 104 105 106 |
# File 'lib/denko/sensor/qmp6988.rb', line 103 def reset i2c_write [RESET_REGISTER, RESET_COMMAND] sleep UPDATE_TIME end |
#state ⇒ Object
92 93 94 |
# File 'lib/denko/sensor/qmp6988.rb', line 92 def state @state ||= { temperature: nil, pressure: nil } end |
#update_state(reading) ⇒ Object
214 215 216 217 218 219 220 |
# File 'lib/denko/sensor/qmp6988.rb', line 214 def update_state(reading) @state_mutex.lock @state[:temperature] = reading[:temperature] @state[:pressure] = reading[:pressure] @state_mutex.unlock @state end |