$prog &HFF , &H62 , &HDF , &HFF 'ヒューズ設定。(工場出荷状態) ' ' ********************************************* ' * * ' * BME280 気圧・温度・湿度センサー * ' * 気圧・温度・湿度・高低差 計 プログラム * ' * * ' * Basic Compiler is BASCOM-AVR * ' * Copyright O-Family 2018.10.31 * ' ********************************************* ' ' Ver 1.01 LPS25H版 初回公開バージョン。 2016. 1.13 ' Ver 2.01 BME280版 初回公開バージョン。 2018.10.31 ' Const Prgver = " 2.01" 'プログラム・バージョン。 $regfile = "ATtiny85.DAT" '使用するAVRを設定。 $crystal = 1000000 'AVRクロックを設定。 ' $hwstack = 40 'ハードウェア・スタックの容量を設定。 $swstack = 10 'ソフトウェア・スタックの容量を設定。 $framesize = 24 'フレーム領域の容量を設定。 ' ' * 動作設定値の初期値 * ' Const Setcontrast = 32 'LCDのコントラスト値。(0〜63) Const Setatptime = 1 '自動電源OFFの設定時間。(0,1,2,3,4 Min) Const Setaltcoeff = 9 '気圧差から高低差を計算する係数。(1hPa = 8〜12m) ' ' * ポート名の定義 * ' Sw_1 Alias Pinb.2 'スイッチ[1]の接続ポート。 Sw_1pu Alias Portb.2 'スイッチ[1]の接続ポート(プルアップ用)。 Sw_2 Alias Pinb.1 'スイッチ[2]の接続ポート。 Sw_2pu Alias Portb.1 'スイッチ[2]の接続ポート(プルアップ用)。 Lcd_power Alias Portb.4 'LCDとセンサーの電源接続ポート。 ' ' * 変数の宣言 * ' Dim Average(32) As Long '移動平均用バッファー。 Dim Avgpoi As Byte '移動平均のポインター。 Dim Avgpoi2 As Byte '移動平均のポインター。(高速モード用) Dim Avgsum As Long '移動平均の合計値。 Dim Avgsum2 As Long '移動平均の合計値。(高速モード用) Dim Baropress As Long '気圧値。(xxxx.xx hPa ×100倍) Dim Temperature As Integer '温度値。(xxx.x ℃ ×10倍) Dim Humidity As Integer '湿度値。(xxx.x % ×10倍) Dim Sampmode As Byte '気圧のサンプリング・モード。(0:通常 , 1:高速モード) Dim Sampchf As Byte '気圧のサンプリング時間変更フラグ。 Dim Barobase As Long '高低差計算用の基準気圧値。(xxxx.xx hPa ×100倍) Dim Altcoeff As Byte '気圧差から高低差を計算する係数。(1hPa = 8〜12m) Dim Dispmode As Byte 'LCDの表示モード。(0:気圧+高低差表示, 1:温度+湿度表示) Dim T500msf As Byte '500mS経過フラグ。 Dim T1scount As Byte '1秒カウンター。 Dim T1sflag As Byte '1秒経過フラグ。 Dim Atptime As Byte '自動電源OFFの設定時間。 Dim Atpowcun As Byte '自動電源OFFカウンター。 Dim Swoffchf As Byte 'スイッチOFFチェックフラグ。 Dim Lpushcun As Byte 'スイッチ長押しカンター。 ' Dim T As Integer , H As Integer , P As Dword '温度値,湿度値,気圧値の変数。 Dim I2cbuff(30) As Byte 'I2C送受信バッファー。 ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Temp3 As Byte '汎用テンポラリ変数 Byte型 No.3 Dim Tempw1 As Word '汎用テンポラリ変数 Word型 No.1 Dim Tempi1 As Integer '汎用テンポラリ変数 Integer型 No.1 Dim Templ1 As Long '汎用テンポラリ変数 Long型 No.1 Dim Tempstr As String * 8 '汎用テンポラリ変数 String型 No.1 Dim Tempstr2 As String * 8 '汎用テンポラリ変数 String型 No.2 ' Dim Dummy As Eram Long 'EEPROM 4バイトのダミーエリア。 Dim Eepcontrast As Eram Byte 'EEPROM LCDのコントラスト値。(0〜63) Dim Eepatptime As Eram Byte 'EEPROM 自動電源OFFの設定時間。(0,1,2,3,4 Min) Dim Eepaltcoeff As Eram Byte 'EEPROM 気圧差から高低差を計算する係数。(1hPa = 8〜12m) ' ' * ハードウェアの初期設定 * ' Set Sw_1pu 'スイッチ[1]の接続ポートをプルアップする。 Set Sw_2pu 'スイッチ[2]の接続ポートをプルアップする。 Config Aci = Off 'アナログ比較器の電源を切る。 Config Lcd_power = Output 'LCDの電源接続ポートを出力に設定する。 Waitms 500 'AVR起動の安定待ち時間。 Set Lcd_power 'LCDの電源をONにする。 Waitms 100 'LCDの起動待ち時間。 ' Config Scl = Portb.0 'I2CバスのSCLラインを接続するポートピンを設定。 Config Sda = Portb.3 'I2CバスのSDAラインを接続するポートピンを設定。 Const Bme280_adr = &HEC 'BME280のI2Cアドレスを指定する。 ' Const Vmode = 3 '[AQM0802A]の電源電圧。(3.5V以下 = 3 , 3.5V以上 = 5) Config Lcd = 16x2 , Chipset = St7032 'LCD表示を16文字2行に設定。 $lib "Lcd_AQMxx02.LBX" 'I2C LCD用のライブラリを組み込む。 ' I2cinit 'I2Cバスを初期化する。 Gosub Lcdiniset 'LCDを初期化してカスタム文字を書き込む。 ' Pcmsk = &B0000_0100 'スイッチ[1]のピン変化割り込みを許可する。 On Pcint0 Intsw1 Nosave 'スイッチ[1]のピン変化割り込みルーチンを設定。 ' ' * タイマーの設定 * ' Tccr1 = &B0100_1100 'Timer1 = PWM , Prescale = 2048 (1,000,000 / 2048 = 488.28Hz) Ocr1c = 244 - 1 '488.28Hz / 244 = 2Hz (500mS) ' ' * BME280の接続を確認する * ' I2cbuff(1) = &HD0 '[ID]レジスター。 I2creceive Bme280_adr , I2cbuff(1) , 1 , 1 'I2Cバスで、1バイトのコマンドを送信し1バイトのデータを受信する。 If I2cbuff(1) <> &H60 Then 'If BME280のチップ識別番号が返ってこないか? Then Locate 1 , 1 Lcd "# BME280" Locate 2 , 1 Lcd "NotFound" Stop End If ' ' * プログラム・バージョンの表示 * ' If Sw_1 = 0 Then 'If スイッチ1が押されているか? Then Cls Locate 1 , 1 'プログラム・バージョンを表示。 Lcd "BME280" Locate 2 , 2 Lcd "V." ; Prgver Waitms 30 'チャタリングの待ち時間。 Bitwait Sw_1 , Set '[SW1]が離されるまで待つ。 Waitms 30 'チャタリングの待ち時間。 Cls End If ' ' * BME280の初期化 * ' Gosub Bme280setup 'BME280の初期設定と移動平均バッファーの初期化をする。 Barobase = Baropress '高低差計算用の基準気圧値を初期化する。 ' ' * EEPROMのデータを確認する * ' If Eepcontrast > 63 Then 'If EEPROMが初期値か? Then Eepcontrast = Setcontrast 'EEPROM LCDのコントラスト値。(0〜63) Eepatptime = Setatptime 'EEPROM 自動電源OFFの設定時間。(0,1,2,3,4 Min) Eepaltcoeff = Setaltcoeff 'EEPROM 気圧差から高低差を計算する係数。(1hPa = 8〜12m) End If _temp1 = Eepcontrast 'LCDのコントラスト値。(0〜63) !CALL _LCD_CONTRAST 'コントラスト設定ルーチン。 Temp1 = Eepatptime '自動電源OFFの設定時間。(0,1,2,3,4 Min) Atptime = Temp1 * 60 Altcoeff = Eepaltcoeff '気圧差から高低差を計算する係数。(1hPa = 8〜12m) ' Gosub Sw1on1 'LCDに測定値を表示する。 Enable Interrupts 'すべての割り込みを許可。 '-------------------------------------------------------------------------------------------------- ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: Gosub Tim500ms '500mSごとの処理。 Gosub Atpower '電源の自動管理処理。 Gosub Swcheck 'スイッチ入力処理。 Goto Main '================================================================================================== ' ' ******************* ' * 500mSごとの処理 * ' ******************* ' Tim500ms: If Tifr.tov1 = 0 Then Return 'If 500mS経過していないか? Then Set Tifr.tov1 'Timer1 オーバーフロー・フラグをクリアする。 T500msf = 1 '500mS経過フラグを立てる。 ' ' * 気圧値と温度・湿度値の取得 * ' Gosub Bme280read 'BME280から測定データを読み出して補償を行う。 ' ' * 気圧値を移動平均する * ' Avgsum = Avgsum - Average(avgpoi) '一番古いデータを減算する。 Average(avgpoi) = P '移動平均バッファーに格納する。 Avgsum = Avgsum + P '新しいデータを合算する。 ' Avgsum2 = Avgsum2 - Average(avgpoi2) '一番古いデータを減算する。(高速モード用) Avgsum2 = Avgsum2 + P '新しいデータを合算する。(高速モード用) ' Avgpoi = Avgpoi + 1 '移動平均ポインターを更新する。 If Avgpoi > 32 Then 'If ポインターが上限か? Then Avgpoi = 1 End If Avgpoi2 = Avgpoi2 + 1 '移動平均ポインターを更新する。(高速モード用) If Avgpoi2 > 32 Then 'If ポインターが上限か? Then Avgpoi2 = 1 End If ' If Sampmode = 0 Then 'If 圧力のサンプリング・モードが通常モードか? Then Baropress = Avgsum Shift Baropress , Right , 5 '32個の移動平均を取る。 Else '気圧のサンプリング・モードが高速モードの場合。 Baropress = Avgsum2 Shift Baropress , Right , 3 '8個の平均合計を取る。 End If ' If Dispmode = 0 Then 'If 気圧+高低差表示表示モードか? Then Gosub Barodisp '気圧値の移動平均データをLCDに表示する。 End If ' ' * 温度値または高低差値をLCDに表示する * ' T1scount = T1scount + 1 '1秒カウンターを更新する。 If T1scount >= 2 Then 'If 1秒経過したか? Then T1scount = 0 T1sflag = 1 '1秒経過フラグを立てる。 If Dispmode = 0 Then 'If 気圧+高低差表示表示モードか? Then Gosub Altdisp '高低差値をLCDに表示する。 Else '温度+湿度表示の場合。 Gosub Tempdisp '温度値をLCDに表示する。 Gosub Humidisp '湿度値をLCDに表示する End If End If Return '-------------------------------------------------------------------------------------------------- ' ' ********************** ' * 電源の自動管理処理 * ' ********************** ' Atpower: If T1sflag <> 0 Then '1秒経過したか? Then T1sflag = 0 If Atptime <> 0 Then '自動電源OFFが有効か? Then Atpowcun = Atpowcun + 1 '自動電源OFFカウンターを更新する。 If Atptime = Atpowcun Then 'If 自動電源OFF時間か? Then Atpower1: Reset Lcd_power 'LCDとBME280の電源をOFFにする。 Reset Gifr.pcif 'ピン変化割り込みフラグをリセットする。 Enable Pcint0 'ピン変化割り込みを許可する。 ' Power Powerdown 'AVRをパワーダウン・モードに移行する。([SW1]で再起動する) ' Disable Pcint0 'ピン変化割り込みを禁止する。 Set Lcd_power 'LCDの電源をONにする。 Waitms 50 'LCDの起動待ち時間。 Gosub Lcdiniset 'LCDを初期化してカスタム文字を書き込む。 ' Gosub Bme280setup 'BME280の初期設定と移動平均バッファーの初期化をする。 ' Gosub Sw1on1 'LCDに測定値を表示する。 ' Swoffchf = 1 'スイッチが離されるのを待つ。 Atpowcun = 0 '自動電源OFFカウンターをクリアする。 End If End If End If Return '-------------------------------------------------------------------------------------------------- ' ' ******************** ' * スイッチ入力処理 * ' ******************** ' Swcheck: If Swoffchf <> 0 Then Goto Swoffchk 'If スイッチが押されたままか? Then If Sw_1 = 0 Then Goto Sw1on 'If [SW1]が押されたか? Then If Sw_2 = 0 Then Goto Sw2on 'If [SW2]が押されたか? Then Return ' ' * [SW1]が押された場合 * ' Sw1on: Waitms 30 'チャタリング除去の待ち時間。 If Sw_2 = 0 Then Goto Sw12on 'If [SW1]と[SW2]が同時に押されたか? Then Toggle Dispmode.0 '表示モードを変更する。 If Dispmode = 0 Then '表示モードが[0]か? Then If Atptime = 0 Then Goto Sw1on2 '自動電源OFFが無効か? Then End If Swoffchf = 1 'スイッチが離されるのを待つ。 ' Sw1on1: Cls If Dispmode = 0 Then 'If 気圧+高低差表示表示モードか? Then Gosub Barodisp '気圧値の移動平均データをLCDに表示する。 Lcd Chr(1) '[hP]単位を表示する。 Gosub Altdisp '高低差値をLCDに表示する。 Lcd "m" '[m]単位を表示する。 Else '温度+湿度表示の場合。 Gosub Tempdisp '温度値をLCDに表示する。 Lcd " " ; Chr(2) '[℃]単位を表示する。 Gosub Humidisp '湿度値をLCDに表示する。 Lcd " %" '[%]単位を表示する。 End If Gosub Sampmdisp '圧力のサンプリング・モードを表示する。 Atpowcun = 0 '自動電源OFFカウンターをクリアする。 Return ' ' Sw1on2: '自動電源OFFが無効の場合。([SW1]で電源OFFする) Bitwait Sw_1 , Set 'スイッチ[1]が離されるまで待つ。 Waitms 30 'チャタリング除去の待ち時間。 Goto Atpower1 '電源OFFへ。 ' ' * [SW2]が押された場合 * ' Sw2on: Waitms 30 'チャタリング除去の待ち時間。 Swoffchf = 1 'スイッチが離されるのを待つ。 Lpushcun = 0 'スイッチ長押しカンターを初期化する。 T500msf = 0 '500mS経過フラグをクリアする。 Sampchf = 1 '気圧のサンプリング・モード変更フラグ。 Atpowcun = 0 '自動電源OFFカウンターをクリアする。 Return ' ' * スイッチが離されるのを待つ * ' Swoffchk: Temp1 = Sw_1 Or Sw_2 If Temp1 = 0 Then Goto Sw12on 'If [SW1]と[SW2]が同時に押されたか? Then ' Temp1 = Sw_1 And Sw_2 If Temp1 <> 0 Then 'If [SW1]と[SW2]が離されたか? Then Waitms 30 'チャタリング除去の待ち時間。 Swoffchf = 0 Lpushcun = 0 'スイッチ長押しカンターを初期化する。 ' If Sampchf <> 0 Then '気圧のサンプリング・モードを変更か? Then Sampchf = 0 Toggle Sampmode.0 '圧力のサンプリング・モードを変更する。 Gosub Sampmdisp '圧力のサンプリング・モードを表示する。 End If Else 'スイッチ長押しの検出。 If T500msf <> 0 Then 'If 500mS経過したか? Then T500msf = 0 If Sw_1 <> 0 Then 'If [SW1]が押されていないか? Then If Sw_2 = 0 Then 'If [SW2]が押されているか? Then If Dispmode = 0 Then 'If 気圧+高低差表示モードか? Then Select Case Lpushcun Case 0 : Lpushcun = Lpushcun + 1 'スイッチ長押しカンターを更新する。 Case Is < 7 : '3秒経過していない場合。 Lpushcun = Lpushcun + 1 'スイッチ長押しカンターを更新する。 Locate 2 , Lpushcun 'LCDに[*]マークを表示する。 Lcd "*" Sampchf = 0 '気圧のサンプリング時間変更フラグをリセットする。 Case 7 : '3秒押し続けた場合。 Locate 2 , 2 Lcd "Res0.0" Barobase = Baropress '高低差計算用の基準気圧値を現在の気圧値にリセットする。 Lpushcun = 100 End Select End If End If End If End If End If Atpowcun = 0 '自動電源OFFカウンターをクリアする。 Return '-------------------------------------------------------------------------------------------------- ' ' * [SW1]と[SW2]が同時に押された場合 (機能設定モード) * ' Sw12on: Cls Lcd "Contrast" Locate 2 , 1 Lcd "Set" ' Waitms 30 'チャタリングの待ち時間。 Do 'スイッチ[1,2]が離されるまで待つ。 Temp1 = Sw_1 And Sw_2 Loop Until Temp1 = 1 'If スイッチ[1,2]が離されたか? Then Waitms 30 'チャタリングの待ち時間。 Lcdcmd &B0000_1111 'LCDのカーソルをオン・点滅にする。 ' ' * コントラストの設定 * ' Temp1 = Eepcontrast Setmode11: Locate 2 , 7 Lcd Temp1 Locate 2 , 6 Setmode12: Debounce Sw_1 , 0 , Setmode14 'If スイッチ[1]が押されたか? Then Debounce Sw_2 , 0 , Setmode13 'If スイッチ[2]が押されたか? Then Goto Setmode12 ' Setmode13: Temp1 = Temp1 + 1 If Temp1 > 50 Then 'If 上限値か? Then Temp1 = 30 End If _temp1 = Temp1 'LCDのコントラスト値。(0〜63) !CALL _LCD_CONTRAST 'コントラスト設定ルーチン。 Goto Setmode11 ' Setmode14: Eepcontrast = Temp1 ' ' * 自動電源オフ時間の設定 * ' Cls Lcd "AutPower" Locate 2 , 1 Lcd "OFF min" Waitms 30 'チャタリングの待ち時間。 Bitwait Sw_1 , Set 'スイッチ[1]が離されるまで待つ。 Waitms 30 'チャタリングの待ち時間。 ' Temp1 = Eepatptime Setmode21: Locate 2 , 5 Lcd Temp1 Locate 2 , 4 Setmode22: Debounce Sw_1 , 0 , Setmode24 'If スイッチ[1]が押されたか? Then Debounce Sw_2 , 0 , Setmode23 'If スイッチ[2]が押されたか? Then Goto Setmode22 ' Setmode23: Temp1 = Temp1 + 1 If Temp1 > 4 Then 'If 上限値か? Then Temp1 = 0 End If Goto Setmode21 ' Setmode24: Eepatptime = Temp1 Atptime = Temp1 * 60 ' ' * 気圧差から高低差を計算する係数の設定 (1hPa = 8〜12m) * ' Cls Lcd "DiffElev" Locate 2 , 1 Lcd "1" ; Chr(1) ; " = m" Waitms 30 'チャタリングの待ち時間。 Bitwait Sw_1 , Set 'スイッチ[1]が離されるまで待つ。 Waitms 30 'チャタリングの待ち時間。 ' Temp1 = Eepaltcoeff Setmode31: Locate 2 , 6 Tempstr = Str(temp1) Lcd Format(tempstr , " 0") Locate 2 , 5 Setmode32: Debounce Sw_1 , 0 , Setmode34 'If スイッチ[1]が押されたか? Then Debounce Sw_2 , 0 , Setmode33 'If スイッチ[2]が押されたか? Then Goto Setmode32 ' Setmode33: Temp1 = Temp1 + 1 If Temp1 > 12 Then 'If 上限値か? Then Temp1 = 8 End If Goto Setmode31 ' Setmode34: Eepaltcoeff = Temp1 Altcoeff = Temp1 ' Lcdcmd &B0000_1100 'LCDのカーソルをオフ・点滅なしにする。 Cls Gosub Sw1on1 'LCDに測定値を表示する。 Waitms 30 'チャタリングの待ち時間。 Bitwait Sw_1 , Set 'スイッチ[1]が離されるまで待つ。 Waitms 30 'チャタリングの待ち時間。 Swoffchf = 1 'スイッチが離されるのを待つ。 Atpowcun = 0 '自動電源OFFカウンターをクリアする。 Sampchf = 0 '気圧のサンプリング時間変更フラグをリセットする。 Return '================================================================================================== ' ' ***************************************** ' * LCDを初期化してカスタム文字を書き込む * ' ***************************************** ' Lcdiniset: Initlcd 'LCDを初期化する。 ' Deflcdchar 1 , &H10 , &H18 , &H14 , &H14 , &H02 , &H05 , &H06 , &H04 'カスタム文字[hp]をLCDへ書き込む。 Deflcdchar 2 , &H08 , &H14 , &H08 , &H06 , &H09 , &H08 , &H09 , &H06 'カスタム文字[℃]をLCDへ書き込む。 Return ' ' ************************************************ ' * BME280の初期設定と移動平均バッファーの初期化 * ' ************************************************ ' Bme280setup: Gosub Bme280init 'BME280の初期設定。 Waitms 500 '初回の計測の待ち時間。 Gosub Bme280read 'BME280から測定データを読み出して補償を行う。 Baropress = P '平均気圧値の初期値。 ' For Avgpoi = 1 To 32 '移動平均バッファーを初期値で埋める。 Average(avgpoi) = Baropress Next Avgpoi Avgsum = Baropress '32個の平均合計を作る。 Shift Avgsum , Left , 5 Avgsum2 = Baropress '8個の平均合計を作る。 Shift Avgsum2 , Left , 3 Avgpoi = 8 '移動平均のポインターを初期化する。 Avgpoi2 = 1 '移動平均のポインター(高速用)を初期化する。 Return ' ' **************************************** ' * 圧力のサンプリング・モードを表示する * ' **************************************** ' Sampmdisp: Locate 2 , 1 If Sampmode = 0 Then 'If サンプリング・モードが[通常]か? Then Lcd " " Else Lcd "h" End If Return ' ' ************************* ' * 気圧値をLCDに表示する * ' ************************* ' Barodisp: Locate 1 , 1 Tempstr = Str(baropress) Lcd Format(tempstr , " 0.00") Return ' ' ************************* ' * 温度値をLCDに表示する * ' ************************* ' Tempdisp: Temperature = T / 10 '温度値の小数点以下を1桁にする。 ' Locate 1 , 2 Tempstr2 = Str(temperature) '文字列に変換する。 Tempstr = Format(tempstr2 , " 0.0") '小数点表記に変換する。 If Temperature < 0 Then 'If マイナスの温度か? Then Tempstr2 = Mid(tempstr , 2 , 5) Lcd Tempstr2 Else 'プラスの場合。 Lcd Tempstr End If Return ' ' ************************* ' * 湿度値をLCDに表示する * ' ************************* ' Humidisp: Humidity = H / 10 '湿度値の小数点以下を1桁にする。 ' Locate 2 , 2 Tempstr = Str(humidity) '文字列に変換する。 Lcd Format(tempstr , " 0.0") '小数点表記に変換する。 Return ' ' *************************** ' * 高低差値をLCDに表示する * ' *************************** ' Altdisp: If Lpushcun = 0 Then 'If スイッチの長押し検出をしていないか? Then Templ1 = Barobase - Baropress '気圧の基準点との差を計算する。 Templ1 = Templ1 * Altcoeff '気圧差から高低差を計算する係数。(1hPa = 8〜12m) Templ1 = Templ1 / 10 '単位を[m]に合わせる。 ' Locate 2 , 2 Tempstr2 = Str(templ1) '文字列に変換する。 Tempstr = Format(tempstr2 , " 0.0") '小数点表記に変換する。 Select Case Templ1 Case Is < -9999 : '-1000m 以下の場合。 Tempstr2 = Left(tempstr , 5) Lcd Tempstr2 ; " " Case Is < 0 : '-0.1〜-999.9 の場合。 Tempstr2 = Mid(tempstr , 2 , 6) Lcd Tempstr2 Case Else : 'プラスの場合。 Lcd Tempstr End Select End If Return '################################################################################################## ' ' ************************************ ' * スイッチ入力割り込み処理ルーチン * ' ************************************ ' Intsw1: Return '何も処理しない。 '################################################################################################## ' **************************************************** ' * BME280 温度・湿度・気圧センサー 制御サブルーチン * (オリジナルは「Mrshilov」氏) ' **************************************************** ' ' * BME280用の変数を宣言 * ' Dim Dig_t1 As Word , Dig_t2 As Integer , Dig_t3 As Integer Dim Dig_p1 As Word , Dig_p2 As Integer , Dig_p3 As Integer Dim Dig_p4 As Integer , Dig_p5 As Integer , Dig_p6 As Integer Dim Dig_p7 As Integer , Dig_p8 As Integer , Dig_p9 As Integer Dim Dig_h1 As Word , Dig_h2 As Integer , Dig_h3 As Word Dim Dig_h4 As Integer , Dig_h5 As Integer , Dig_h6 As Integer Dim Adc_t As Dword , Adc_p As Dword , Adc_h As Dword Dim Var1 As Long , Var2 As Long , Var3 As Long , Var4 As Word Dim T_fine As Long ' ' ******************** ' * BME280の初期設定 * ' ******************** ' Bme280init: I2cbuff(1) = &HF2 : I2cbuff(2) = &H05 '湿度のオーバー・サンプリング = ×16 I2cbuff(3) = &HF4 : I2cbuff(4) = &HB7 '温度のオーバー・サンプリング = ×16 , 圧力のオーバー・サンプリング = ×16 , 通常モード I2cbuff(5) = &HF5 : I2cbuff(6) = &H90 '通常モードの休止期間 = 500ms , IIRフィルター = ×16 I2csend Bme280_adr , I2cbuff(1) , 6 'I2Cバスで、6バイトのコマンドを送信する。 ' I2cbuff(1) = &H88 '補償の係数を読み出す。 I2creceive Bme280_adr , I2cbuff(1) , 1 , 26 'I2Cバスで、1バイトのコマンドを送信し、26バイトのデータを受信する。 ' Dig_t1 = Makeint(i2cbuff(1) , I2cbuff(2)) '温度の補償係数を変数にまとめる。 Dig_t2 = Makeint(i2cbuff(3) , I2cbuff(4)) Dig_t3 = Makeint(i2cbuff(5) , I2cbuff(6)) Dig_p1 = Makeint(i2cbuff(7) , I2cbuff(8)) '圧力の補償係数を変数にまとめる。 Dig_p2 = Makeint(i2cbuff(9) , I2cbuff(10)) Dig_p3 = Makeint(i2cbuff(11) , I2cbuff(12)) Dig_p4 = Makeint(i2cbuff(13) , I2cbuff(14)) Dig_p5 = Makeint(i2cbuff(15) , I2cbuff(16)) Dig_p6 = Makeint(i2cbuff(17) , I2cbuff(18)) Dig_p7 = Makeint(i2cbuff(19) , I2cbuff(20)) Dig_p8 = Makeint(i2cbuff(21) , I2cbuff(22)) Dig_p9 = Makeint(i2cbuff(23) , I2cbuff(24)) Dig_h1 = I2cbuff(26) '湿度の補償係数を変数にまとめる。 ' I2cbuff(1) = &HE1 I2creceive Bme280_adr , I2cbuff(1) , 1 , 7 'I2Cバスで、1バイトのコマンドを送信し、7バイトのデータを受信する。 ' Dig_h2 = Makeint(i2cbuff(1) , I2cbuff(2)) '湿度の補償係数を変数にまとめる。 Dig_h3 = I2cbuff(3) Dig_h4 = I2cbuff(4) : Shift Dig_h4 , Left , 4 Dig_h5 = I2cbuff(5) And &H0F : Dig_h4 = Dig_h4 + Dig_h5 Dig_h5 = I2cbuff(5) And &HF0 : Shift Dig_h5 , Right , 4 Dig_h6 = I2cbuff(6) : Shift Dig_h6 , Left , 4 : Dig_h5 = Dig_h5 + Dig_h6 Dig_h6 = I2cbuff(7) Return ' ' ********************************************** ' * BME280から測定データを読み出して補償を行う * ' ********************************************** ' Bme280read: I2cbuff(1) = &HF7 '測定したA/Dデータを読み出す。 I2creceive Bme280_adr , I2cbuff(1) , 1 , 8 'I2Cバスで、1バイトのコマンドを送信し、8バイトのデータを受信する。 ' Var4 = Makeint(i2cbuff(2) , I2cbuff(1)) '3バイトの圧力データを32ビットのDword変数に変換する。 Adc_p = Var4 : Shift Adc_p , Left , 4 Shift I2cbuff(3) , Right , 4 : Adc_p = Adc_p + I2cbuff(3) ' Var4 = Makeint(i2cbuff(5) , I2cbuff(4)) '3バイトの温度データを32ビットのDword変数に変換する。 Adc_t = Var4 : Shift Adc_t , Left , 4 Shift I2cbuff(6) , Right , 4 : Adc_t = Adc_t + I2cbuff(6) ' Var4 = Makeint(i2cbuff(8) , I2cbuff(7)) '2バイトの湿度データを32ビットのDword変数に変換する。 Adc_h = Var4 ' ' -------------------- ' * 温度の補償を行う * ' -------------------- ' ' var1 = ((((adc_T>>3) - ((BME280_S32_t)dig_T1<<1))) * ((BME280_S32_t)dig_T2)) >> 11; ' Shift Adc_t , Right , 3 : Var1 = Adc_t - Dig_t1 : Var1 = Var1 - Dig_t1 Var1 = Var1 * Dig_t2 : Shift Var1 , Right , 11 , Signed ' ' var2 = (((((adc_T>>4) - ((BME280_S32_t)dig_T1)) * ((adc_T>>4) - ((BME280_S32_t)dig_T1))) >> 12) * ((bme280_s32_t)dig_t3)) >> 14; ' Shift Adc_t , Right , 1 : Var2 = Adc_t - Dig_t1 Var2 = Var2 * Var2 : Shift Var2 , Right , 12 , Signed Var2 = Var2 * Dig_t3 : Shift Var2 , Right , 14 , Signed ' ' t_fine = var1 + var2; T = (t_fine * 5 + 128) >> 8; ' T_fine = Var1 + Var2 : Var2 = T_fine * 5 Var2 = Var2 + 128 : Shift Var2 , Right , 8 , Signed T = Var2 '[T] = 温度値。 [XXXX] -> [XX.XX]℃ ' ' -------------------- ' * 圧力の補償を行う * ' -------------------- ' ' var1 = (((BME280_S32_t)t_fine)>>1) - (BME280_S32_t)64000; ' Var1 = T_fine : Shift Var1 , Right , 1 , Signed Var1 = Var1 - 64000 ' ' var2 = (((var1>>2) * (var1>>2)) >> 11 ) * ((BME280_S32_t)dig_P6); ' Var2 = Var1 : Shift Var2 , Right , 2 , Signed Var2 = Var2 * Var2 : Shift Var2 , Right , 11 , Signed Var2 = Var2 * Dig_p6 ' ' var2 = var2 + ((var1*((BME280_S32_t)dig_P5))<<1); ' Var3 = Var1 * Dig_p5 : Shift Var3 , Left , 1 Var2 = Var2 + Var3 ' ' var2 = (var2>>2)+(((BME280_S32_t)dig_P4)<<16); ' Var3 = Dig_p4 : Shift Var3 , Left , 16 Shift Var2 , Right , 2 , Signed Var2 = Var2 + Var3 ' ' var1 = (((dig_P3 * (((var1>>2) * (var1>>2)) >> 13 )) >> 3) + ((((BME280_S32_t)dig_P2) * var1)>>1))>>18; ' Var3 = Dig_p2 * Var1 : Shift Var3 , Right , 1 , Signed Shift Var1 , Right , 2 , Signed Var1 = Var1 * Var1 : Shift Var1 , Right , 13 Var1 = Dig_p3 * Var1 : Shift Var1 , Right , 3 , Signed Var1 = Var1 + Var3 : Shift Var1 , Right , 18 , Signed ' ' var1 =((((32768+var1))*((BME280_S32_t)dig_P1))>>15); ' Var1 = 32768 + Var1 Var1 = Var1 * Dig_p1 : Shift Var1 , Right , 15 , Signed ' 'if (var1 == 0) ' If Var1 = 0 Then P = 0 'ゼロ除算による例外を避ける。 Else ' ' P = (((BME280_U32_t)(((BME280_S32_t)1048576)-adc_P) - (var2>>12))) * 3125; ' P = 1048576 - Adc_p : Shift Var2 , Right , 12 , Signed P = P - Var2 : P = P * 3125 ' ' if (P < 0x80000000) ' If P < &H80000000 Then ' ' P = (P << 1) / ((BME280_U32_t)var1); ' Shift P , Left , 1 : P = P / Var1 Else ' ' P = (P / (BME280_U32_t)var1) * 2; ' P = P / Var1 : P = P + P End If ' ' var1 = (((BME280_S32_t)dig_P9) * ((BME280_S32_t)(((p>>3) * (p>>3))>>13)))>>12; ' Var1 = P : Shift Var1 , Right , 3 Var1 = Var1 * Var1 : Shift Var1 , Right , 13 Var1 = Dig_p9 * Var1 : Shift Var1 , Right , 12 , Signed ' ' var2 = (((BME280_S32_t)(p>>2)) * ((BME280_S32_t)dig_P8))>>13; ' Var2 = P : Shift Var2 , Right , 2 Var2 = Var2 * Dig_p8 : Shift Var2 , Right , 13 , Signed ' ' P = (BME280_U32_t)((BME280_S32_t)P + ((var1 + var2 + dig_P7) >> 4)); ' Var1 = Var1 + Var2 : Var1 = Var1 + Dig_p7 Shift Var1 , Right , 4 , Signed P = P + Var1 '[P] = 気圧値。 [XXXXXX] -> [XXXX.XX]hPa End If ' ' -------------------- ' * 湿度の補償を行う * ' -------------------- ' ' v_x1_u32r = (t_fine - ((BME280_S32_t)76800)); ' Var1 = T_fine - 76800 ' ' v_x1_u32r = (((((adc_H << 14) - (((BME280_S32_t)dig_H4) << 20) - (((BME280_S32_t)dig_H5) * v_x1_u32r)) + ' ((BME280_S32_t)16384)) >> 15) * (((((((v_x1_u32r * ((BME280_S32_t)dig_H6)) >> 10) * (((v_x1_u32r * ' ((BME280_S32_t)dig_H3)) >> 11) + ((BME280_S32_t)32768))) >> 10) + ((BME280_S32_t)2097152)) * ' ((BME280_s32_t)dig_H2) + 8192) >> 14)); ' Var2 = Adc_h : Shift Var2 , Left , 14 Var3 = Dig_h4 : Shift Var3 , Left , 20 Var2 = Var2 - Var3 : Var3 = Dig_h5 * Var1 Var2 = Var2 - Var3 : Var2 = Var2 + 16384 Shift Var2 , Right , 15 , Signed Var3 = Var1 * Dig_h6 : Shift Var3 , Right , 10 , Signed T_fine = Var1 * Dig_h3 : Shift T_fine , Right , 11 , Signed T_fine = T_fine + 32768 : Var3 = Var3 * T_fine Shift Var3 , Right , 10 , Signed Var3 = Var3 + 2097152 Var3 = Var3 * Dig_h2 : Var3 = Var3 + 8192 Shift Var3 , Right , 14 , Signed Var1 = Var2 * Var3 ' ' v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((BME280_S32_t)dig_H1)) >> 4)); ' Var3 = Var1 : Shift Var3 , Right , 15 , Signed Var3 = Var3 * Var3 : Shift Var3 , Right , 7 , Signed Var3 = Var3 * Dig_h1 : Shift Var3 , Right , 4 , Signed Var1 = Var1 - Var3 ' ' v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r); ' If Var1 < 0 Then Var1 = 0 ' ' v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r); ' If Var1 > 419430400 Then Var1 = 419430400 ' ' return (BME280_U32_t)(v_x1_u32r>>12); ' Shift Var1 , Right , 12 , Signed Var1 = Var1 * 100 : Shift Var1 , Right , 10 , Signed '小数点以下第2位をまでを整数に桁上げして、1024で割る。 H = Var1 '[H] = 湿度値。 [XXXXX] -> [XXX.XX]% Return ' ' End