' ' ********************************************** ' * * ' * AVR & BASCOM-AVR トレーニング・ボード * ' * 初期設定 Ver.1.01 * ' * * ' * AVR is using ATmega88P * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2010.10.29 * ' ********************************************** ' $regfile = "m88pdef.dat" '使用するAVRを設定。 $crystal = 16000000 'AVRクロックを設定。 ' $hwstack = 64 'ハードウェア・スタックの容量を設定。 $swstack = 10 'ソフトウェア・スタックの容量を設定。 $framesize = 24 'フレーム領域の容量を設定。 ' ' * ポート名の定義 * ' Sw_1 Alias Pind.0 'スイッチ[1]の接続ポート。 Sw_2 Alias Pind.1 'スイッチ[2]の接続ポート。 Sw_3 Alias Pind.2 'スイッチ[3]の接続ポート。 Sw_4 Alias Pind.3 'スイッチ[4]の接続ポート。 ' Led_1r Alias Portd.4 'LED1[赤]の接続ポート。 Led_2g Alias Portd.5 'LED2[緑]の接続ポート。 Led_3y Alias Portd.6 'LED3[黄]の接続ポート。 Led_4b Alias Portd.7 'LED4[青]の接続ポート。 Sp_out Alias Portc.5 'スピーカーの接続ポート。 ' Ad_photo Alias 0 '光センサーのA/Dコンバータ・チャネル番号。 Ad_thermo Alias 1 '温度センサーのA/Dコンバータ・チャネル番号。 Ad_ain1 Alias 2 '測定入力[1]のA/Dコンバータ・チャネル番号。 Ad_ain2 Alias 3 '測定入力[2]のA/Dコンバータ・チャネル番号。 Ad_ain3 Alias 4 '測定入力[3]のA/Dコンバータ・チャネル番号。 Ad_spin Alias 5 'スピーカー入力のA/Dコンバータ・チャネル番号。 ' ' * ポートの初期設定 * ' Config Led_1r = Output 'LED1の接続ポートを出力に設定する。 ' Config Led_2g = Output 'LED2の接続ポートを出力に設定する。 Config Led_3y = Output 'LED3の接続ポートを出力に設定する。 ' Config Led_4b = Output 'LED4の接続ポートを出力に設定する。 Config Sp_out = Output 'スピーカーの接続ポートを出力に設定する。 ' Set Portd.0 'スイッチ[1]の接続ポートをプルアップする。 Set Portd.1 'スイッチ[2]の接続ポートをプルアップする。 ' Set Portd.2 'スイッチ[3]の接続ポートをプルアップする。 ' Set Portd.3 'スイッチ[4]の接続ポートをプルアップする。 Didr0 = &B00111111 'デジタル入力禁止レジスタの設定。 ' ' * LCDの初期設定 * ' Config Lcdmode = Port 'LCDを4ビットのポートモードに設定。 Config Lcdbus = 4 'LCDデータバスを4bitに設定。 Config Lcdpin = Pin , Db4 = Portb.3 , Db5 = Portb.2 'LCDのポート割り当て。 Config Lcdpin = Pin , Db6 = Portb.1 , Db7 = Portb.0 Config Lcdpin = Pin , E = Portb.4 , Rs = Portb.5 Config Lcd = 16 * 2 'LCD表示を16文字2行に設定。 Cls 'LCD表示をすべて消去。 ' ' * A/Dコンバータの初期設定 * ' Config Adc = Single , Prescaler = Auto , Reference = Avcc 'A/Dコンバータの設定。 Start Adc 'A/Dコンバータに電源を供給。 ' ' ↓********************************************↓ ' ↓ これ以降に各自のプログラムを作成して下さい ↓ ' ↓********************************************↓ ' '-------------------------------------------------------------------------------------------------- ' ' ****************************************** ' * CCS811 CO2 , VOC センサー (+ BME280) * ' * テスト・プログラム * ' * Copyright O-Family 2017.10.25 * ' ****************************************** ' ' Ver. 0.01 新規作成バージョン。 2017.10.25 ' Ver. 0.02 [nINT]の接続ポートをPD5に変更。 2017.10.28 ' ' ' * ポート名の定義 * ' Ccs811_nwake Alias Portd.7 'CCS811の[nWAKE]ピン接続ポート。 Ccs811_nint Alias Pind.5 'CCS811の[nINT]ピン接続ポート。 ' Const Ccs811_adr = &HB4 'CCS811のI2Cアドレス。 Const Bme280_adr = &HEC 'BME280のI2Cアドレス。 ' ' * 変数の宣言 * ' Dim Eco2 As Word 'eCO2(等価CO2)値 ppm。 Dim Tvoc As Word 'TVOC(総VOC)値 ppb。 Dim I2cbuff(30) As Byte 'I2C送受信バッファー。 Dim I2clength As Byte 'I2C受信データのバイト数。 Dim Ccs811status As Byte 'CCS811のステータス。 Dim Ccs811mode As Byte 'CCS811の測定モード(サンプリング間隔)。 (0:1秒, 1:10秒, 2:60秒) Dim Dispmode As Byte 'LCDの表示モード。(0:VOC値表示, 1:気圧値表示, 2:CCS811のサンプリング間隔表示) Dim Bme280status As Byte 'BME280のステータス。(0:接続なし, 1:接続あり) ' Dim T As Integer , H As Integer , P As Dword '温度値,湿度値,気圧値の変数。 Dim Tempstr As String * 20 '汎用テンポラリ変数 String型 Dim Tempi1 As Integer '汎用テンポラリ変数 Integer型 No.1 ' Dim Dummy As Eram Long 'EEPROM 4バイトのダミーエリア。 Dim Eepccs811mode As Eram Byte 'EEPROM CCS811の測定モード(サンプリング間隔)。 (0:1秒, 1:10秒, 2:60秒) Dim Eepdispmode As Eram Byte 'EEPROM LCDの表示モード。(0:VOC値表示, 1:気圧値表示, 2:CCS811のサンプリング間隔表示) ' ' * ポートの初期設定 * ' Config Ccs811_nwake = Output 'CCS811の[nWAKE]ピン接続ポートを出力に設定する。 Set Ccs811_nwake 'CCS811の[nWAKE]ピンを[H]にする。 ' ' * I2Cの初期設定 * ' $lib "i2cV2.LBX" '修正版のI2Cライブラリを組み込む。 Config Scl = Portd.2 'I2CバスのSCLラインを接続するポートピンを設定。 Config Sda = Portd.3 'I2CバスのSDAラインを接続するポートピンを設定。 I2cinit 'I2CバスのSCL,SDAラインを初期化する。 ' ' * カスタム文字をLCDに設定する * ' Deflcdchar 0 , &H06 , &H05 , &H06 , &H04 , &H00 , &H00 , &H00 , &H00 'カスタム文字[p]をLCDへ書き込む。 Deflcdchar 1 , &H18 , &H14 , &H18 , &H10 , &H00 , &H1A , &H15 , &H15 'カスタム文字[pm]をLCDへ書き込む。 Deflcdchar 2 , &H18 , &H14 , &H18 , &H10 , &H04 , &H06 , &H05 , &H06 'カスタム文字[pb]をLCDへ書き込む。 Deflcdchar 3 , &H00 , &H00 , &H0C , &H12 , &H04 , &H08 , &H1E , &H00 'カスタム文字[下付2]をLCDへ書き込む。 Deflcdchar 4 , &H08 , &H14 , &H08 , &H06 , &H09 , &H08 , &H09 , &H06 'カスタム文字[℃]をLCDへ書き込む。 Deflcdchar 5 , &H10 , &H18 , &H14 , &H14 , &H02 , &H05 , &H06 , &H04 'カスタム文字[hp]をLCDへ書き込む。 Cursor Off 'LCDのカーソルをオフにする。 ' ' * EEPROMのデータを確認する * ' If Eepccs811mode > 2 Then 'If EEPROMが初期値か? Then Eepccs811mode = 0 'EEPROM CCS811の測定モード(サンプリング間隔)。 (0:1秒, 1:10秒, 2:60秒) Eepdispmode = 0 'EEPROM LCDの表示モード。(0:VOC値表示, 1:気圧値表示, 2:CCS811のサンプリング間隔表示) End If Ccs811mode = Eepccs811mode Dispmode = Eepdispmode ' ' * Timerの設定 * ' Config Timer1 = Timer , Prescale = 1024 , Clear Timer = 1 'Timer1の設定。16,000,000Hz / 1024 = 15,625Hz Compare1a = 15625 - 1 '15,625Hz / 1Hz(1秒) = 15625カウント ' ' * CCS811の接続を確認する * ' Waitms 30 'CCS811の起動時間(tSTART)を待つ。 Reset Ccs811_nwake 'CCS811の[nWAKE]ピンを[L]にする。 Waitus 60 'CCS811の[nWAKE]=[L]からの起動時間(tAWAKE)を待つ。 ' I2cbuff(1) = &H20 '[HW_ID]レジスター。 I2clength = 1 'I2Cの受信バイト数。 Gosub Ccs811read 'CCS811からI2Cでデータを読み出す If I2cbuff(1) <> &H81 Then 'If CCS811のチップ識別番号が返ってこないか? Then Tempstr = " Not found!" Else '[HW_ID]が正常(81h)の場合。 I2cbuff(1) = &H00 '[STATUS]レジスター。 I2clength = 1 'I2Cの受信バイト数。 Gosub Ccs811read 'CCS811からI2Cでデータを読み出す If I2cbuff(1).4 = 0 Then 'If CCS811に有効なアプリケーションがロードされていないか? Then Tempstr = " Appli invalid!" Else '有効なアプリケーションがロードされている場合。 I2cbuff(1) = &HF4 '[APP_START]レジスター。 I2csend Ccs811_adr , I2cbuff(1) , 1 'I2Cバスで、1バイトのアドレスを送信する。 ' I2cbuff(1) = &H00 '[STATUS]レジスター。 I2clength = 1 'I2Cの受信バイト数。 Gosub Ccs811read 'CCS811からI2Cでデータを読み出す If I2cbuff(1).7 = 0 Then 'If CCS811がアプリケーション・モードになっていないか? Then Tempstr = " Not appli mode!" Else 'CCS811がアプリケーション・モードになっている場合。 If I2cbuff(1).0 = 1 Then 'If CCS811のエラーがあるか? Then I2cbuff(1) = &HE0 '[ERROR_ID]レジスター。 I2clength = 1 'I2Cの受信バイト数。 Gosub Ccs811read 'CCS811からI2Cでデータを読み出す Tempstr = " Error! " + Bin(i2cbuff(1)) 'エラーのビットを表示する。 Else 'エラーがない場合。 Tempstr = "" End If End If End If End If ' If Tempstr <> "" Then 'If CCS811の起動にエラーがあるか? Then Locate 1 , 1 Lcd "# CCS811" Locate 2 , 1 Lcd Tempstr Sound Sp_out , 100 , 6666 '200Hzの音を500mS鳴らす。 Stop End If ' Gosub Ccs811init 'CCS811の初期設定。 Set Ccs811_nwake 'CCS811の[nWAKE]ピンを[H]にする。 ' ' * BME280の接続を確認する * ' Waitms 30 'CCS811のI2C通信の内部処理時間を待つ。 I2cbuff(1) = &HD0 '[ID]レジスター。 I2creceive Bme280_adr , I2cbuff(1) , 1 , 1 'I2Cバスで、1バイトのコマンドを送信し1バイトのデータを受信する。 If I2cbuff(1) = &H60 Then 'If BME280のチップ識別番号が返ってきたか? Then Gosub Bme280init 'BME280の初期設定。 Bme280status = 1 Else 'BME280が確認できない場合。 Locate 1 , 1 Lcd "# BME280" Locate 2 , 1 Lcd " Not found!" Sound Sp_out , 100 , 6666 '200Hzの音を500mS鳴らす。 Wait 3 Bme280status = 0 Cls End If ' ' * 初期画面の表示 * ' Gosub Line2disp 'LCDの下段右側を表示する。 Gosub Pbdisp '気圧値をLCDに表示する。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: ' ' * 1秒間隔の処理 * ' If Tifr1.ocf1a = 1 Then 'If 1秒経過したか? Then Set Tifr1.ocf1a 'Timer1の比較A一致フラグをリセット。 ' ' * BME280から温度・湿度・気圧値を読み出す * ' If Bme280status <> 0 Then 'If BME280が接続されているか? Then Gosub Bme280read 'BME280から測定データを読み出して補償を行う。 T = T / 10 '温度値の小数点以下を1桁にする。 H = H / 10 '湿度値の小数点以下を1桁にする。 ' ' * 温度と湿度をLCDに表示する * ' Tempstr = Str(t) '温度値を表示する。 Locate 1 , 1 If T < 0 Then 'If マイナスの値か? Then Lcd Format(tempstr , " 0.0") Else 'プラス値の場合。 Lcd Format(tempstr , " 0.0") End If Locate 1 , 6 Lcd Chr(4) '温度の単位[℃] ' Tempstr = Str(h) '湿度値を表示する。 Locate 2 , 1 Lcd Format(tempstr , " 0.0") ; "%" ' ' * 気圧値をLCDに表示する * ' Gosub Pbdisp '気圧値をLCDに表示する。 End If End If ' ' * CCS811からの測定完了[nINT]信号の処理 * ' If Ccs811_nint = 0 Then 'If CCS811の[nINT] = [L] 測定完了か? Then ' ' * CCS811からCO2とVOCを読み出す * ' Reset Ccs811_nwake 'CCS811の[nWAKE]ピンを[L]にする。 Waitus 60 'CCS811の[nWAKE]=[L]からの起動時間(tAWAKE)を待つ。 ' I2cbuff(1) = &H02 '[ALG_RESULT_DATA]レジスター。 I2clength = 5 'I2Cの受信バイト数。 Gosub Ccs811read 'CCS811からI2Cでデータを読み出す ' Eco2 = Makeint(i2cbuff(2) , I2cbuff(1)) '2バイトのECO2データをワード変数に変換する。 Tvoc = Makeint(i2cbuff(4) , I2cbuff(3)) '2バイトのTVOCデータをワード変数に変換する。 Ccs811status = I2cbuff(5) 'CCS811のステータスを一時保管する。 ' ' * CCS811に温度と湿度の環境パラメータを書き込む * ' If Bme280status <> 0 Then 'If BME280が接続されているか? Then Tempi1 = H / 5 '[湿度 x 512]の上位バイトのみ使用。(48.5% x 512 = 24832 = 6100h -> 485 / 5 = 97 = 61h) I2cbuff(2) = Low(tempi1) 'インテジャー型変数の下位バイトを取り出す。 I2cbuff(3) = &H00 ' Tempi1 = T + 250 '温度値に25℃のオフセットを加算する。 If Tempi1 < 0 Then 'If 温度+25℃のオフセットがマイナスか? Then Tempi1 = 0 End If Tempi1 = Tempi1 / 5 '[温度+25℃ x 512]の上位バイトのみ使用。(23.5℃ + 25℃[ofs] x 512 = 24832 = 6100h -> (23.5 + 25) / 5 = 97 = 61h) I2cbuff(4) = Low(tempi1) 'インテジャー型変数の下位バイトを取り出す。 I2cbuff(5) = &H00 ' I2cbuff(1) = &H05 '[ENV_DATA]レジスター。 I2csend Ccs811_adr , I2cbuff(1) , 5 'I2Cバスで、1バイトのアドレスと4バイトのデータを送信する。 End If ' Set Ccs811_nwake 'CCS811の[nWAKE]ピンを[H]にする。 ' ' * CO2とVOCをLCDに表示する * ' If Ccs811status.0 = 0 Then 'If [ERROR](STATUSのbit0)は無いか? Then Locate 1 , 8 'CO2の値をLCDに表示する。 Tempstr = Str(eco2) '数値変数を文字変数に変換する。 Lcd "CO{003}" ; Format(tempstr , " 0") ; Chr(0) ; Chr(1) ' Gosub Line2disp 'LCDの下段右側を表示する。 ' Else 'エラーが発生している場合。 Locate 1 , 8 Lcd "# Error! " Reset Ccs811_nwake 'CCS811の[nWAKE]ピンを[L]にする。 Waitus 60 'CCS811の[nWAKE]=[L]からの起動時間(tAWAKE)を待つ。 I2cbuff(1) = &HE0 '[ERROR_ID]レジスター。 I2clength = 1 'I2Cの受信バイト数。 Gosub Ccs811read 'CCS811からI2Cでデータを読み出す Set Ccs811_nwake 'CCS811の[nWAKE]ピンを[H]にする。 Locate 2 , 8 Lcd " " ; Bin(i2cbuff(1)) 'エラーのビットを表示する。 Sound Sp_out , 100 , 6666 '200Hzの音を500mS鳴らす。 End If End If ' ' * スイッチの入力処理 * ' Debounce Sw_1 , 0 , Sw1on '[SW1]が押されたか? Debounce Sw_2 , 0 , Sw2on '[SW2]が押されたか? ' Goto Main '-------------------------------------------------------------------------------------------------- ' ' * スイッチ[1]が押された場合 * ' Sw1on: If Ccs811status.0 = 0 Then 'If CCS811のエラーは無いか? Then Dispmode = Dispmode + 1 If Dispmode > 2 Then 'If 表示モードの上限か? Then Dispmode = 0 End If Eepdispmode = Dispmode 'EEPROMに保管する。 Gosub Line2disp 'LCDの下段右側を表示する。 Gosub Pbdisp '気圧値をLCDに表示する。 Sound Sp_out , 200 , 333 '4000Hzの音を50mS鳴らす。 End If Goto Main ' ' * スイッチ[2]が押された場合 * ' Sw2on: If Ccs811status.0 = 0 Then 'If CCS811のエラーは無いか? Then If Dispmode = 2 Then 'If 表示モードがサンプリング間隔表示か? Then Ccs811mode = Ccs811mode + 1 If Ccs811mode > 2 Then 'If サンプリング間隔の上限か? Then Ccs811mode = 0 End If Eepccs811mode = Ccs811mode 'EEPROMに保管する。 ' Reset Ccs811_nwake 'CCS811の[nWAKE]ピンを[L]にする。 Waitus 60 'CCS811の[nWAKE]=[L]からの起動時間(tAWAKE)を待つ。 Gosub Ccs811init 'CCS811の初期設定。 Set Ccs811_nwake 'CCS811の[nWAKE]ピンを[H]にする。 ' Gosub Line2disp 'LCDの下段右側を表示する。 Gosub Pbdisp '気圧値をLCDに表示する。 Sound Sp_out , 200 , 333 '4000Hzの音を50mS鳴らす。 End If End If Goto Main ' ' --------------------------------------- ' * LCDの下段右側を表示するサブルーチン * ' --------------------------------------- ' Line2disp: Locate 2 , 8 'LCDの下段右側の表示を選択する。 Select Case Dispmode Case 0 : 'VOC値の表示モードの場合。 Tempstr = Str(tvoc) '数値変数を文字変数に変換する。 Lcd "Voc" ; Format(tempstr , " 0") ; Chr(0) ; Chr(2) ' Case 2 : 'CCS811のサンプリング間隔表示の場合。 Lcd "Smp: sec" Locate 2 , 12 Select Case Ccs811mode Case 0 : Lcd " 1" Case 1 : Lcd "10" Case 2 : Lcd "60" End Select End Select Return ' ' ------------------------------------- ' * 気圧値をLCDに表示するサブルーチン * ' ------------------------------------- ' Pbdisp: If Ccs811status.0 = 0 Then 'If CCS811のエラーは無いか? Then If Dispmode = 1 Then '表示モードが気圧値か? Then Locate 2 , 8 If Bme280status <> 0 Then 'If BME280が接続されているか? Then P = P / 10 '気圧値の小数点以下を1桁にする。 Tempstr = Str(p) '気圧値を表示する。 Lcd "P " ; Format(tempstr , " 0.0") ; Chr(5) Else Lcd "---------" End If End If End If Return '################################################################################################## ' ' * CCS811用の変数を宣言 * ' Dim Ccs811temp1 As Byte ' ' *********************************** ' * CCS811からI2Cでデータを読み出す * (I2cbuff(1) = CCS811のレジスターアドレス。 , I2clength = 読み出すデータのバイト数) ' *********************************** (I2cbuff(1)〜 読み出したレジスターのデータ) ' Ccs811read: I2csend Ccs811_adr , I2cbuff(1) , 1 'I2Cバスで、1バイトのアドレスを送信する。 ' ! rcall _release_scl 'CCS811のクロック・ストレッチ(内部処理の待ち時間)が終わるのを待つ。 ### BASCOMのバグにより ### ' I2cstart 'I2Cバスを、[スタート・コンディション]にする。 I2cwbyte Ccs811_adr + &H01 'スレーブ・アドレス + 読み出しを送信。 Ccs811temp1 = 1 While I2clength <> 1 'If 受信データのバイト数が1以上か? Then I2crbyte I2cbuff(ccs811temp1) , Ack Ccs811temp1 = Ccs811temp1 + 1 I2clength = I2clength - 1 Wend I2crbyte I2cbuff(ccs811temp1) , Nack I2cstop '[ストップ・コンディション]の状態にする。 Return ' ' ******************** ' * CCS811の初期設定 * ' ******************** ' Ccs811init: I2cbuff(1) = &H01 '[MEAS_MODE]レジスター。 Select Case Ccs811mode 'CCS811の測定モード(サンプリング間隔)。 (0:1秒, 1:10秒, 2:60秒) Case 0 : I2cbuff(2) = &B0001_1000 '001:モード1 毎秒測定。 測定完了で[nINT]へ割り込みを発生。 Case 1 : I2cbuff(2) = &B0010_1000 '010:モード2 10秒毎に測定。 測定完了で[nINT]へ割り込みを発生。 Case 2 : I2cbuff(2) = &B0011_1000 '011:モード3 60秒毎に測定。 測定完了で[nINT]へ割り込みを発生。 End Select I2csend Ccs811_adr , I2cbuff(1) , 2 'I2Cバスで、1バイトのアドレスと1バイトのデータを送信する。 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) = &HB0 '通常モードの休止期間 = 1s , 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