|
| 1 | +$script:CalibrationData = @{} |
| 2 | + |
| 3 | +function Get-BME280ChipID |
| 4 | +{ |
| 5 | + param |
| 6 | + ( |
| 7 | + [ValidateNotNullOrEmpty()] |
| 8 | + [Microsoft.PowerShell.IoT.I2CDevice] $Device |
| 9 | + ) |
| 10 | + |
| 11 | + Read-I2CRegister -Device $Device -Register 0xD0 |
| 12 | +} |
| 13 | + |
| 14 | +function Read-CalibrationData |
| 15 | +{ |
| 16 | + param |
| 17 | + ( |
| 18 | + [ValidateNotNullOrEmpty()] |
| 19 | + [Microsoft.PowerShell.IoT.I2CDevice] $Device |
| 20 | + ) |
| 21 | + |
| 22 | + # read calibration data from sensor |
| 23 | + $cd1 = Read-I2CRegister -Device $Device -Register 0x88 -Length 25 |
| 24 | + $cd2 = Read-I2CRegister -Device $Device -Register 0xE1 -Length 7 |
| 25 | + |
| 26 | + [uint16] $T1 = $cd1[1] |
| 27 | + $T1 = ($T1 -shl 8) -bor $cd1[0] |
| 28 | + |
| 29 | + [int16] $T2 = $cd1[3] |
| 30 | + $T2 = ($T2 -shl 8) -bor $cd1[2] |
| 31 | + |
| 32 | + [int16] $T3 = $cd1[5] |
| 33 | + $T3 = ($T3 -shl 8) -bor $cd1[4] |
| 34 | + |
| 35 | + [uint16] $P1 = $cd1[7] |
| 36 | + $P1 = ($P1 -shl 8) -bor $cd1[6] |
| 37 | + |
| 38 | + [int16] $P2 = $cd1[9] |
| 39 | + $P2 = ($P2 -shl 8) -bor $cd1[8] |
| 40 | + |
| 41 | + [int16] $P3 = $cd1[11] |
| 42 | + $P3 = ($P3 -shl 8) -bor $cd1[10] |
| 43 | + |
| 44 | + [int16] $P4 = $cd1[13] |
| 45 | + $P4 = ($P4 -shl 8) -bor $cd1[12] |
| 46 | + |
| 47 | + [int16] $P5 = $cd1[15] |
| 48 | + $P5 = ($P5 -shl 8) -bor $cd1[14] |
| 49 | + |
| 50 | + [int16] $P6 = $cd1[17] |
| 51 | + $P6 = ($P6 -shl 8) -bor $cd1[16] |
| 52 | + |
| 53 | + [int16] $P7 = $cd1[19] |
| 54 | + $P7 = ($P7 -shl 8) -bor $cd1[18] |
| 55 | + |
| 56 | + [int16] $P8 = $cd1[21] |
| 57 | + $P8 = ($P8 -shl 8) -bor $cd1[20] |
| 58 | + |
| 59 | + [int16] $P9 = $cd1[23] |
| 60 | + $P9 = ($P9 -shl 8) -bor $cd1[22] |
| 61 | + |
| 62 | + [byte] $H1 = $cd1[24] |
| 63 | + |
| 64 | + [int16] $H2 = $cd2[1] |
| 65 | + $H2 = ($H2 -shl 8) -bor $cd2[0] |
| 66 | + |
| 67 | + [byte] $H3 = $cd2[2] |
| 68 | + |
| 69 | + [int16] $H4 = $cd2[3] |
| 70 | + $H4 = ($H4 -shl 4) -bor ($cd2[4] -band 0x00FF) |
| 71 | + |
| 72 | + [int16] $H5 = $cd2[5] |
| 73 | + $H5 = ($H5 -shl 4) -bor ($cd2[4] -band 0xFF00) |
| 74 | + |
| 75 | + [sbyte] $H6 = $cd2[6] |
| 76 | + |
| 77 | + $cd_final = [pscustomobject]@{ |
| 78 | + T1=$T1; |
| 79 | + T2=$T2; |
| 80 | + T3=$T3; |
| 81 | + |
| 82 | + P1=$P1; |
| 83 | + P2=$P2; |
| 84 | + P3=$P3; |
| 85 | + P4=$P4; |
| 86 | + P5=$P5; |
| 87 | + P6=$P6; |
| 88 | + P7=$P7; |
| 89 | + P8=$P8; |
| 90 | + P9=$P9; |
| 91 | + |
| 92 | + H1=$H1; |
| 93 | + H2=$H2; |
| 94 | + H3=$H3; |
| 95 | + H4=$H4; |
| 96 | + H5=$H5; |
| 97 | + H6=$H6} |
| 98 | + |
| 99 | + $script:CalibrationData[$Device] = $cd_final |
| 100 | +} |
| 101 | + |
| 102 | +function Set-BME280Config |
| 103 | +{ |
| 104 | + param |
| 105 | + ( |
| 106 | + [Parameter(Mandatory=$true, ValueFromPipeline=$true)] |
| 107 | + [ValidateNotNullOrEmpty()] |
| 108 | + [Microsoft.PowerShell.IoT.I2CDevice] $Device, |
| 109 | + |
| 110 | + [Parameter(Mandatory=$false)] |
| 111 | + [ValidateNotNullOrEmpty()] |
| 112 | + [string] $Mode, |
| 113 | + |
| 114 | + [Parameter(Mandatory=$false)] |
| 115 | + [ValidateNotNullOrEmpty()] |
| 116 | + [string] $Oversampling |
| 117 | + ) |
| 118 | + |
| 119 | + # set oversampling of humidity data to ×2 |
| 120 | + [byte] $reg_ctrl_hum = 0xF2 |
| 121 | + [byte] $reg_ctrl_hum_value = [Convert]::ToByte("00000010",2) |
| 122 | + |
| 123 | + # set forced mode, set oversampling for temperature and pressure data to x2 |
| 124 | + [byte] $reg_ctrl_meas = 0xF4 |
| 125 | + [byte] $reg_ctrl_meas_value = [Convert]::ToByte("01001001",2) |
| 126 | + |
| 127 | + Write-I2CRegister -Device $Device -Register $reg_ctrl_hum -Value $reg_ctrl_hum_value |
| 128 | + Write-I2CRegister -Device $Device -Register $reg_ctrl_meas -Value $reg_ctrl_meas_value |
| 129 | +} |
| 130 | + |
| 131 | + |
| 132 | + |
| 133 | +# Calculate variable TFine (signed 32 bit) that carries a fine resolution temperature value over to the pressure and humidity compensation formula |
| 134 | +function Calc-T-Fine |
| 135 | +{ |
| 136 | + param |
| 137 | + ( |
| 138 | + [ValidateNotNullOrEmpty()] |
| 139 | + [int] $adc_T, |
| 140 | + |
| 141 | + [ValidateNotNullOrEmpty()] |
| 142 | + [pscustomobject] $cd |
| 143 | + ) |
| 144 | + |
| 145 | + [int] $var1 = (((($adc_T -shr 3) - ([int]$cd.T1 -shl 1))) * ([int]$cd.T2)) -shr 11 |
| 146 | + [int] $var2 = ((((($adc_T -shr 4) - ([int]$cd.T1)) * (($adc_T -shr 4) - ([int]$cd.T1))) -shr 12) * ([int]$cd.T3)) -shr 14 |
| 147 | + [int] $TFine = $var1 + $var2 |
| 148 | + $TFine |
| 149 | +} |
| 150 | + |
| 151 | +# Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits). |
| 152 | +# Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa |
| 153 | +function Compensate_P |
| 154 | +{ |
| 155 | + param |
| 156 | + ( |
| 157 | + [ValidateNotNullOrEmpty()] |
| 158 | + [int] $adc_P, |
| 159 | + |
| 160 | + [ValidateNotNullOrEmpty()] |
| 161 | + [pscustomobject] $cd, |
| 162 | + |
| 163 | + [ValidateNotNullOrEmpty()] |
| 164 | + [int] $t_fine |
| 165 | + ) |
| 166 | + |
| 167 | + [int64] $var1 = ([int64]$t_fine) - 128000; |
| 168 | + [int64] $var2 = $var1 * $var1 * [int64]$cd.P6; |
| 169 | + $var2 = $var2 + (($var1*[int64]$cd.P5) -shl 17); |
| 170 | + $var2 = $var2 + (([int64]$cd.P4) -shl 35); |
| 171 | + $var1 = (($var1 * $var1 * [int64]$cd.P3) -shr 8) + (($var1 * [int64]$cd.P2) -shl 12); |
| 172 | + $var1 = (((([int64]1) -shl 47)+$var1))*([int64]$cd.P1) -shr 33; |
| 173 | + if ($var1 -eq 0) |
| 174 | + { |
| 175 | + return 0 # avoid exception caused by division by zero |
| 176 | + } |
| 177 | + [int64] $p = 1048576 - $adc_P; |
| 178 | + $p = ((($p -shl 31)-$var2)*3125)/$var1; |
| 179 | + $var1 = (([int64]$cd.P9) * ($p -shr 13) * ($p -shr 13)) -shr 25; |
| 180 | + $var2 = (([int64]$cd.P8) * $p) -shr 19; |
| 181 | + $p = (($p + $var1 + $var2) -shr 8) + (([int64]$cd.P7) -shl 4); |
| 182 | + $p = [uint32]$p/256; |
| 183 | + $p |
| 184 | +} |
| 185 | + |
| 186 | +# Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits). |
| 187 | +# Output value of “47445” represents 47445/1024 = 46.333 %RH |
| 188 | +function Compensate_H |
| 189 | +{ |
| 190 | + param |
| 191 | + ( |
| 192 | + [ValidateNotNullOrEmpty()] |
| 193 | + [int] $adc_H, |
| 194 | + |
| 195 | + [ValidateNotNullOrEmpty()] |
| 196 | + [pscustomobject] $cd, |
| 197 | + |
| 198 | + [ValidateNotNullOrEmpty()] |
| 199 | + [int] $t_fine |
| 200 | + ) |
| 201 | + |
| 202 | + [int32] $v_x1_u32r = ($t_fine - ([int32]76800)) |
| 203 | + $v_x1_u32r = ((((($adc_H -shl 14) - (([int32]$cd.H4) -shl 20) - (([int32]$cd.H5) * $v_x1_u32r)) + |
| 204 | + ([int32]16384)) -shr 15) * ((((((($v_x1_u32r * ([int32]$cd.H6)) -shr 10) * ((($v_x1_u32r * |
| 205 | + ([int32]$cd.H3)) -shr 11) + ([int32]32768))) -shr 10) + ([int32]2097152)) * |
| 206 | + ([int32]$cd.H2) + 8192) -shr 14)) |
| 207 | + $v_x1_u32r = ($v_x1_u32r - ((((($v_x1_u32r -shr 15) * ($v_x1_u32r -shr 15)) -shr 7) * ([int32]$cd.H1)) -shr 4)) |
| 208 | + if ($v_x1_u32r -lt 0) { $v_x1_u32r = 0 } |
| 209 | + if ($v_x1_u32r -gt 419430400) {$v_x1_u32r = 419430400} |
| 210 | + $v_x1_u32r = ($v_x1_u32r -shr 12)*100 / 1024 |
| 211 | + $v_x1_u32r |
| 212 | +} |
| 213 | + |
| 214 | +# Units of returned data: temperature in degrees Celsius, pressure in hPa, relative humidity in % |
| 215 | +function Get-BME280Data |
| 216 | +{ |
| 217 | + param |
| 218 | + ( |
| 219 | + [Parameter(Mandatory=$true, ValueFromPipeline=$true)] |
| 220 | + [ValidateNotNullOrEmpty()] |
| 221 | + [Microsoft.PowerShell.IoT.I2CDevice] $Device, |
| 222 | + |
| 223 | + [Parameter(Mandatory=$false)] |
| 224 | + [ValidateNotNullOrEmpty()] |
| 225 | + [string] $Mode, |
| 226 | + |
| 227 | + [Parameter(Mandatory=$false)] |
| 228 | + [ValidateNotNullOrEmpty()] |
| 229 | + [string] $Oversampling |
| 230 | + ) |
| 231 | + |
| 232 | + Read-CalibrationData $Device |
| 233 | + Set-BME280Config $Device $Mode $Oversampling |
| 234 | + |
| 235 | + # read raw temperature, humidity and pressure measurement output data |
| 236 | + $adc = Read-I2CRegister -Device $Device -Register 0xF7 -Length 8 |
| 237 | + |
| 238 | + [int] $adc_P = $adc[0] |
| 239 | + $adc_P = ($adc_P -shl 8) -bor $adc[1] |
| 240 | + $adc_P = ($adc_P -shl 4) -bor ($adc[2] -shr 4) |
| 241 | + |
| 242 | + [int] $adc_T = $adc[3] |
| 243 | + $adc_T = ($adc_T -shl 8) -bor $adc[4] |
| 244 | + $adc_T = ($adc_T -shl 4) -bor ($adc[5] -shr 4) |
| 245 | + |
| 246 | + [int] $adc_H = $adc[6] |
| 247 | + $adc_H = ($adc_H -shl 8) -bor $adc[7] |
| 248 | + |
| 249 | + [int] $TFine = Calc-T-Fine $adc_T $script:CalibrationData[$Device] |
| 250 | + [float] $Temperature = (($TFine * 5 + 128) -shr 8) / [float]100; |
| 251 | + |
| 252 | + [float] $Pressure = Compensate_P $adc_P $script:CalibrationData[$Device] $TFine |
| 253 | + $Pressure = $Pressure / 100 |
| 254 | + |
| 255 | + [float] $Humidity = Compensate_H $adc_H $script:CalibrationData[$Device] $TFine |
| 256 | + $Humidity = $Humidity / 100 |
| 257 | + |
| 258 | + $result = [pscustomobject]@{ |
| 259 | + Temperature=$Temperature; |
| 260 | + Pressure=$Pressure; |
| 261 | + Humidity=$Humidity} |
| 262 | + |
| 263 | + $result |
| 264 | +} |
| 265 | + |
| 266 | + |
0 commit comments