Ⅲ. I2Cバスと複数センサー(ESP-WROOM-02)

 今回は定番になっている温度センサーや湿度センサーによる計測に取り組みます。ここでは温湿度と気圧の複合センサーを採用します。それに、もしや趣味の農作業に役立つかも知れないと、照度センサーもつないでみることにしました。
 少ないGPIOをフルに活用するためのI2C。センサーはI2C対応のものに限定して、すでに組み込み済みのRTCと同じラインに接続して計測します。

 ※スケッチのダウンロードは右側の[Download]ボタンをクリックしてください。    

1.計測ボードの所要機能

 前回RTCを設置した計測ボードに次の機能を持たせることにします。
  ①センサー増設への柔軟性
    各種センサーの増設に弾力的に対応できるハードウェア・ソフトウェア構造。
  ②測定データの管理機能
    複数センサーの測定結果をシンプルに管理できるデータ構造。
  ③測定結果の編集機能
    測定結果を簡潔に編集できる機能の装備。

2.使用する部品

(1)部品の規格・仕様
 今回のセンサーは以下のものを使用します。
 なお、BME280モジュールキットは秋月電子通商で購入しました。

 ・BME280使用 温湿度・気圧センサモジュールキット1個1,080円
 ・BH1750デジタル光量センサモジュール(手持ちのもの)1個200円
 ・配線材料少々
〔BME280の仕様〕
  ボッシュ社のBME280を搭載したセンサモジュールで、温度、湿度、気圧の3種を同時に測定できます。
  ・動作電圧: 1.71~3.6V
  ・温度: -40~+85℃ ±1℃
  ・湿度: 0~100% ±3%
  ・気圧: 300~1100hpa ±1hpa
  ・I2Cアドレス: 0x76, 0x77 5番ピン(SDO)で選択、GND接続で0x76
  ・基板サイズ: 10mm × 16mm
  ※I2CとSPIプロトコルに対応。I2C接続の場合は写真・左下のJ3にハンダを乗せてジャンパ接続します。
〔BH1750の仕様〕
  照度をアナログ電圧で出力するセンサ、ローム社のBH1750を搭載したセンサモジュールです。
  ・動作電圧: 3~5V
  ・照度: 0~65535lux ±1lux
  ・基板サイズ: 32.5mm × 15mm


(2)BME280の内部構造

 BME280は、下図のようなメモリー・レジスターで測定条件やキャリブレーション・データ、計測データなどを保持しています。大まかに整理すると次のとおりです。
  ・0x88~0xa1: キャリブレーション・データ
  ・0x0d: チップID
  ・0xe1~0xf0: キャリブレーション・データ
  ・0xf2: 湿度センサーの設定
  ・0xf4: 温度センサー・湿度センサーの設定、動作モードの設定
  ・0xf5: 測定間隔、フィルター等の設定
  ・0xf7~0xfe: 測定データ
 これに沿ってレジスターの内容を参照したり書き換えることでBME280を操作することができます。
  
 使用にあたっては、測定のタイミングやサンプリングなど初期条件の設定が必要になります。これらについては次の資料を参照してください。
    ・Bosch Sensoertec社の英文データシート(秋月電子のサイトから入手できます)
    ・SWITCH SCIENCE社 『BME280搭載 温湿度・気圧センサモジュールの使い方』
 SWITCH SCIENCE社ではサンプルスケッチをダウンロードすることができます。今回のBME280関係の計測処理には、このサンプルスケッチを利用しています。


(3)BH1750の内部構造

  BH1750はとてもシンプルで使いやすいセンサーです。次の図はローム社のマニュアルからの抜粋です。

 この例から、H-Resolution Mode(測定時間:120ms、分解能:1lx.)で計測する場合は、BH1750宛に測定モード指定として0x10を送信し、2バイトのデータを受信すればよいことがわかります。
 光量(照度)は、受信したHigh Byteを8ビット上位へシフトしてLow Byteと合成し、1.2で除算すれば求めることができまるわけです。

3.組み立てと配線

(1)計測ボードの配線

 BME280とBH1750モジュールの端子と接続先は図のとおりです。

 計測ボードの空きスペースに2つのセンサーを追加します。上図の接続先に従って写真のように配線します。ここで注意しなければならないのは、BH1750はRTCと同じ5V電源を使用しますが、BME280は3.3Vを使用する点です。写真のブレッドボードでは、上側の赤線を5V、下側の赤線を3.3Vラインとして組み付けています。電源のマイナスラインは共通なので、ボード上の右端で緑のジャンプワイヤーで直結しています。各センサーのSCLとSDAは、それぞれオレンジと黄色のジャンパーコードで並列に結ぶだけです。


(2)ボード間の配線

 MCUボードから計測ボードへの接続はI2Cの2本の線だけです。計測ボードの電源は、専用電源から5Vが赤色ジャンパーコードで上のプラスライン(赤色)へ、その下のマイナスライン(青色)には緑色でGNDが接続されています。3.3Vはオレンジのコードで下のプラスライン(赤色)へつながれています。


 〔回路図〕

4.ソフト開発のポイント

 先にも述べたように、BME280の計測関係のコードはSWITCH SCIENCE社のサンプルスケッチを利用しています。コードの細かい部分については、前掲のSWITCH SCIENCE社のページを参照してください。またBosch Sensoertec社のデータシートは英文ですが、きわめて詳細な説明があるので一読をお勧めします。
(1)計測用データ領域と計測結果を収納するデータ型

 1行目: BME280用のグローバル変数は次の2行です。unsigned long型のhum_raw, temp_raw, pres_rawは
     気圧、温度、湿度レジスターから取り込んだ計測値が格納されます。t_fineは計測値の較正処理で使用
     する共用フィールドです。
 5行目: BME280の初期化時に、計測値の較正処理に使用する値をレジスターから取得して格納します。
 26行目: 較正処理された計測結果と計測日時を収納するための構造体MeasuredResultを定義します。
 33行目: MeasuredResult型のデータ領域rstMeasuredを割り付けます。
//BME280 Global variables
unsigned long int hum_raw, temp_raw, pres_raw;
signed long int t_fine;

//BME280 Calibration variables
uint16_t dig_T1;
 int16_t dig_T2;
 int16_t dig_T3;
uint16_t dig_P1;
 int16_t dig_P2;
 int16_t dig_P3;
 int16_t dig_P4;
 int16_t dig_P5;
 int16_t dig_P6;
 int16_t dig_P7;
 int16_t dig_P8;
 int16_t dig_P9;
 int8_t  dig_H1;
 int16_t dig_H2;
 int8_t  dig_H3;
 int16_t dig_H4;
 int16_t dig_H5;
 int8_t  dig_H6;
 
//Measured result
struct MeasuredResult {
    double  temperature;
    double  pressure;
    double  humidity;
    int     illuminance;
    String  datetime;
};
MeasuredResult rstMeasured;


(2)BME280サンプルスケッチ内の計測メソッド

 SWITCH SCIENCE社サンプルスケッチのうち、初期化処理setupに記述されている計測条件の設定部分は、prepareBME280というメソッド名で独立させました。これを含め、サンプルスケッチ内のメソッドを簡単に整理しておきます。
  ・void prepareBME280()
    温度、湿度、気圧それぞれの測定条件を設定して、readTrimメソッドを実行します。
  ・void readTrim()
    BME280のI2Cスレーブアドレスで通信を開始し、レジスターに記録されているキャリブレーション
    (較正)用のデータをグローバル変数に格納します。
  ・void writeReg(uint8_t reg_address, uint8_t data)
    reg_addressで指定されたレジスターに1バイトのdataを書き込みます。
  ・void readData()
    計測値が記録されているレジスターから、グローバル変数に気圧、温度、湿度の計測値を格納します。
  ・signed long int calibration_T(signed long int adc_T)
    adc_Tで与えられた計測値とグローバル変数の較正値を使って温度の較正結果を通知します。
  ・unsigned long int calibration_P(signed long int adc_P)
    adc_Pで与えられた計測値とグローバル変数の較正値を使って気圧の較正結果を通知します。
  ・unsigned long int calibration_H(signed long int adc_H)
    adc_Hで与えられた計測値とグローバル変数の較正値を使って湿度の較正結果を通知します。
 各メソッドともかなり複雑になっていますが、先のBME280の内部構造のレジスター図を見ながら、データのビットシフトと合成・分割を意識して眺めると納得、ガッテンでしょう!


(3)BH1750のメソッド

 2つのメソッドで構成されています。
  ・void prepareBH1750(int i2cAddress)
    与えられたI2CアドレスのBH1750を初期化して、H-Resolution Mode(測定時間:120ms、分解能:1lx.)
    で計測するよう指示します。
    ここでは標準的な計測モードに固定していますが、さらに分解能の精粗を指定することもできます。
  ・int measureIlluminance(int i2cAddress)
    後続のint measureIlluminance(int i2cAddress, byte *buff)を使って、レジスターから2バイトの
    計測結果を取り出し、1.2で除算して得られた照度を通知します。


(4)その他のメソッド

 主処理の反復処理部は、次の2つのメソッドを利用するだけで計測と結果編集が完了します。
  ・void doMeasurement()
    計測結果の取得、較正処理、日時情報の取得など一連の処理を行って、MeasuredResult型の
    rstMeasuredに結果を格納します。
  ・String editMeasuredResult(MeasuredResult data)
    MeasuredResult型の結果情報をカンマ区切りのテキスト文字列に編集して通知します。
 なお編集処理では、次の2つのメソッドを使用しています。
  ・char *printNum(char *buf, double field, int len, int decimal)
    実数型の編集。
  ・char *printNum(char *buf, int field, int len)
    整数型の編集。

5.スケッチの実行

(1)実行結果と評価

 シリアルモニターを表示させた状態でスケッチを実行すると、項目見出しに続いて1秒ごとに測定結果が表示されます。照度Illum(lx)の左に空白が多いのは、センサーにLEDライトなどを当てると2桁大きい値を表示するためです。
 スケッチの計測関連のメソッドはかなり複雑ですが、主処理はシンプルな記述で計測と結果編集を行うことができます。また今後のI2Cセンサーの増設に対しても、個別の計測・較正ロジックさえ追加すれば、MeasuredResult型へのフィールド追加と、doMeasurmentとeditMeasuredResultへの軽微な追加で対応することが可能になりました。



(2)スケッチ全景

 主処理の部分だけを簡単に見ておきましょう。
 初期化処理setupでは、シリアルモニターとI2Cインターフェイスの初期化を行い、BME280とBH1750を初期化しています。続いて計測メソッドdoMeasurementを実行。これは起動直後の計測で、不安定な計測値の取得を回避するためのダミー処理です。
 反復処理loopでは、計測を実行するためにdoMeasurementメソッドを呼び、editMeasuredResultで編集結果をシリアルモニターに表示するだけです。
/*
 * File:      espI2C.ino
 * Function:  Measure temperature, humidity, atmospheric pressure and illuminance.
 * Date:      2017/01/18
 * Author:    Marchan
 * 
 * Hardware   MCU:  ESP-WROOM-02(ESP8266)
 *            RTC:  DS1307 I2C Real time clock module.
 *          + Combined humidity and pressure sensor: BME280
 *          + Digital illuminance sensor: BH1750
 *
 * Remarks:   Code for measurement and calibration of 'BME 280' uses
 *                        SWITCH SCIENCE sample sketch(BME280_I2C.zip).
 *                        https://www.switch-science.com//catalog/2236/
 */
#include <Wire.h>

// I2C Address
#define DS1307_ADDRESS 0x68   // Realtime clock
#define BME280_ADDRESS 0x76   // Humidity, Pressure and Temperature sensor
#define BH1750_ADDRESS 0x23   // Illuminance sensor

const String strTitle = "Temp(C), Press(hPa), Hum(%), Illum(lx), Date Time";

// DS1307 Clock data
struct ClockData {
    byte year;
    byte month;
    byte day;
    byte week;
    byte hour;
    byte minute;
    byte sec;
    byte ctrl;
};
ClockData dtClock;

//BME280 Global variables
unsigned long int hum_raw, temp_raw, pres_raw;
signed long int t_fine;

//BME280 Calibration variables
uint16_t dig_T1;
 int16_t dig_T2;
 int16_t dig_T3;
uint16_t dig_P1;
 int16_t dig_P2;
 int16_t dig_P3;
 int16_t dig_P4;
 int16_t dig_P5;
 int16_t dig_P6;
 int16_t dig_P7;
 int16_t dig_P8;
 int16_t dig_P9;
 int8_t  dig_H1;
 int16_t dig_H2;
 int8_t  dig_H3;
 int16_t dig_H4;
 int16_t dig_H5;
 int8_t  dig_H6;
 
//Measured result
struct MeasuredResult {
    double  temperature;
    double  pressure;
    double  humidity;
    int     illuminance;
    String  datetime;
};
MeasuredResult rstMeasured;

/*****************************************************************************
 *                          Predetermined Sequence                           *
 *****************************************************************************/
void setup() {
    Serial.begin(115200);

    // Prepare I2C protocol.
    Wire.begin();
    
    // Prepare measurment
    prepareBME280();      // Humidity, Pressure and Temperature sensor
    delay(500);
    prepareBH1750(BH1750_ADDRESS);  // Illuminance sensor

    // Dummy measurement
    doMeasurement();
    delay(100);
    Serial.println("");
    Serial.println(strTitle);
}

void loop() {
    // Measurment
    doMeasurement();

    // Display measured result.
    Serial.println(editMeasuredResult(rstMeasured));
    delay(1000);
}
/*****************************************************************************/

/*
 * Measure and  calibrate BME280, also illuminance
 *    Result stored into rstMeasured structure.
 */
void doMeasurement()
{
    // Read BME280 measured result
    readData();
    // Calibration
    long temp_cal = calibration_T(temp_raw);
    long press_cal = calibration_P(pres_raw);
    long hum_cal = calibration_H(hum_raw);

    // Measurement illuminance
    int val = measureIlluminance(BH1750_ADDRESS);
    
    // Get date and time data from DS1307
    getDateTime(&dtClock);
    
    //Store into measured resut structure
    rstMeasured.temperature = (double)temp_cal / 100.0;
    rstMeasured.pressure = (double)press_cal / 100.0;
    rstMeasured.humidity = (double)hum_cal / 1024.0;
    rstMeasured.illuminance = (int)val;    
    rstMeasured.datetime = editDateTime(dtClock);
}

/*
 * Edit measured result data.
 *    Argument: (struct)Measured result.
 *    Return:   Edited result.
 */
String editMeasuredResult(MeasuredResult data)
{
    char wbuf[20];
    String strWork = "";
    printNum(wbuf, data.temperature, 4, 1);
    strWork.concat(wbuf);
    strWork.concat(",");
    printNum(wbuf, data.pressure, 7, 1);
    strWork.concat(wbuf);
    strWork.concat(",");
    printNum(wbuf, data.humidity, 5, 1);
    strWork.concat(wbuf);
    strWork.concat(",");
    printNum(wbuf, data.illuminance, 6);
    strWork.concat(wbuf);
    strWork.concat(", ");
    strWork.concat(data.datetime);
    return strWork;
}

/*
 * Print numeric (double, float)
 *    Argument: char* buffer, double data, int edit-length, int decimal.
 */
char *printNum(char *buf, double field, int len, int decimal)
{
    *buf ='\0';
    char bufw[40];
    dtostrf(field, len, decimal, bufw);
    strcpy(buf, bufw);
    return buf;
}

/*
 * Print numeric (int, long)
 *    Argument: char* buffer, int data, int edit-length.
 */
char *printNum(char *buf, int field, int len)
{
    *buf = '\0';
    char bufw[40];
    sprintf(bufw, "%d", field);
    int lenw = strlen(bufw);
    int i;
    for (i = 0; i < len - lenw; i++) {
        *(buf + i) = ' ';
    }
    *(buf + i) = '\0';
    strcat(buf, bufw);
    return buf;
}

/* ======================== DS1307 Clock Control ============================*/

/*
 * Read data from DS1307 Register 
 */
void getDateTime(ClockData *dt)
{
    int iValue = 0;
  
    Wire.beginTransmission(DS1307_ADDRESS);
    Wire.write(iValue);
    Wire.endTransmission();
    Wire.requestFrom(DS1307_ADDRESS, 7);
    dt->sec = Wire.read();
    dt->minute = Wire.read();
    dt->hour = Wire.read();
    dt->week = Wire.read();
    dt->day = Wire.read();
    dt->month = Wire.read();
    dt->year = Wire.read();
}

/*
 * Tell day of week from code.
 */
String tellDayOfWeek(byte num)
{
    static String week[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  
    if (num >= 1 && num <= 7)
      return week[num-1];
    else
      return "";
}

/*
 * Set DS1307 time register.
 *    Argument: (String)Time string 'hh:mm:ss'.
 */
void setTime(String sTime)
{
    byte bValue = 0x00;   //Top Address
    String buf = sTime;
    buf.replace(":", "");  buf.trim();
    if (buf.length() == 6) {
        byte hour = (buf.charAt(0) << 4) + (buf.charAt(1) & 0x0f);
        byte minute = (buf.charAt(2) << 4) + (buf.charAt(3) & 0x0f);
        byte sec = (buf.charAt(4) << 4) + (buf.charAt(5) & 0x0f);
        Wire.beginTransmission(DS1307_ADDRESS);
        Wire.write(bValue);
        Wire.write(sec);
        Wire.write(minute);
        Wire.write(hour);
        Wire.endTransmission();
    }
}

/*
 * Set DS1307 date register.
 *    Argument: (String)Time string 'yy/mm/dd/w'.
 */
void setDate(String sDate)
{
    byte bValue = 0x03;   //Top Address
    String buf = sDate;
    buf.replace("/", "");  buf.trim();
    if (buf.length() >= 6) {
        byte year = (buf.charAt(0) << 4) + (buf.charAt(1) & 0x0f);
        byte month = (buf.charAt(2) << 4) + (buf.charAt(3) & 0x0f);
        byte day = (buf.charAt(4) << 4) + (buf.charAt(5) & 0x0f);
        byte week;
        if (buf.length() == 7) {
            week = (buf.charAt(6) & 0x07);
          if (week < 0x01 || week > 0x07)
            week = 0x01;
        }
        Wire.beginTransmission(DS1307_ADDRESS);
        Wire.write(bValue);
        Wire.write(week);
        Wire.write(day);
        Wire.write(month);
        Wire.write(year);
        Wire.endTransmission();
    }
}

/*
 * Edit DS1307 date and time.
 */
String editDateTime(ClockData dt)
{
    return editDate(dt) + " " + editTime(dt);
}

/*
 * Edit time register.
 */
String editTime(ClockData dt)
{
    String buf = "";
    char wbuf[12];
    sprintf(wbuf, "%02x:%02x:%02x", (int)dt.hour, (int)dt.minute, (int)dt.sec);
    buf.concat(wbuf);
    return buf;
}

/*
 * Edit date register.
 */
String editDate(ClockData dt)
{
    String buf = "20";
    char wbuf[12];
    sprintf(wbuf, "%02x/%02x/%02x", (int)dt.year, (int)dt.month, (int)dt.day);
    buf.concat(wbuf);
    return buf;
}

/* ====================== BME280 T-P-H Measurement ==========================*/

/*
 * Initiate BME280 and get calibration variables.
 */
void prepareBME280()
{
    uint8_t osrs_t = 1;             //Temperature oversampling x 1
    uint8_t osrs_p = 1;             //Pressure oversampling x 1
    uint8_t osrs_h = 1;             //Humidity oversampling x 1
    uint8_t mode = 3;               //Normal mode
    uint8_t t_sb = 5;               //Tstandby 1000ms
    uint8_t filter = 0;             //Filter off 
    uint8_t spi3w_en = 0;           //3-wire SPI Disable
    
    uint8_t ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode;
    uint8_t config_reg    = (t_sb << 5) | (filter << 2) | spi3w_en;
    uint8_t ctrl_hum_reg  = osrs_h;

    writeReg(0xF2,ctrl_hum_reg);
    writeReg(0xF4,ctrl_meas_reg);
    writeReg(0xF5,config_reg);
    readTrim();
}

/*
 * Read calibration variables into structure.
 */
void readTrim()
{
    uint8_t data[32],i=0;
    Wire.beginTransmission(BME280_ADDRESS);
    Wire.write(0x88);
    Wire.endTransmission();
    Wire.requestFrom(BME280_ADDRESS,24);
    while(Wire.available()){
        data[i] = Wire.read();
        i++;
    }
    
    Wire.beginTransmission(BME280_ADDRESS);
    Wire.write(0xA1);
    Wire.endTransmission();
    Wire.requestFrom(BME280_ADDRESS,1);
    data[i] = Wire.read();
    i++;
    
    Wire.beginTransmission(BME280_ADDRESS);
    Wire.write(0xE1);
    Wire.endTransmission();
    Wire.requestFrom(BME280_ADDRESS,7);
    while(Wire.available()){
        data[i] = Wire.read();
        i++;    
    }
    dig_T1 = (data[1] << 8) | data[0];
    dig_T2 = (data[3] << 8) | data[2];
    dig_T3 = (data[5] << 8) | data[4];
    dig_P1 = (data[7] << 8) | data[6];
    dig_P2 = (data[9] << 8) | data[8];
    dig_P3 = (data[11]<< 8) | data[10];
    dig_P4 = (data[13]<< 8) | data[12];
    dig_P5 = (data[15]<< 8) | data[14];
    dig_P6 = (data[17]<< 8) | data[16];
    dig_P7 = (data[19]<< 8) | data[18];
    dig_P8 = (data[21]<< 8) | data[20];
    dig_P9 = (data[23]<< 8) | data[22];
    dig_H1 = data[24];
    dig_H2 = (data[26]<< 8) | data[25];
    dig_H3 = data[27];
    dig_H4 = (data[28]<< 4) | (0x0F & data[29]);
    dig_H5 = (data[30] << 4) | ((data[29] >> 4) & 0x0F);
    dig_H6 = data[31];   
}

/*
 * Write data into BME280 register.
 *    Argument: (uint8_t)Register address, (uint8_t)data.
 */
void writeReg(uint8_t reg_address, uint8_t data)
{
    Wire.beginTransmission(BME280_ADDRESS);
    Wire.write(reg_address);
    Wire.write(data);
    Wire.endTransmission();    
}

/*
 * Read data from BME280 register.
 */
void readData()
{
    int i = 0;
    uint32_t data[8];
    Wire.beginTransmission(BME280_ADDRESS);
    Wire.write(0xF7);
    Wire.endTransmission();
    Wire.requestFrom(BME280_ADDRESS,8);
    while(Wire.available()){
        data[i] = Wire.read();
        i++;
    }
    pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
    temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
    hum_raw  = (data[6] << 8) | data[7];
}

/*
 * Calibration [Temperature]
 */
signed long int calibration_T(signed long int adc_T)
{
    signed long int var1, var2, T;
    var1 = ((((adc_T >> 3) - ((signed long int)dig_T1<<1))) * ((signed long int)dig_T2)) >> 11;
    var2 = (((((adc_T >> 4) - ((signed long int)dig_T1)) * ((adc_T>>4) - ((signed long int)dig_T1))) >> 12) * ((signed long int)dig_T3)) >> 14;
    
    t_fine = var1 + var2;
    T = (t_fine * 5 + 128) >> 8;
    return T; 
}

/*
 * Calibration [Pressure]
 */
unsigned long int calibration_P(signed long int adc_P)
{
    signed long int var1, var2;
    unsigned long int P;
    var1 = (((signed long int)t_fine)>>1) - (signed long int)64000;
    var2 = (((var1>>2) * (var1>>2)) >> 11) * ((signed long int)dig_P6);
    var2 = var2 + ((var1*((signed long int)dig_P5))<<1);
    var2 = (var2>>2)+(((signed long int)dig_P4)<<16);
    var1 = (((dig_P3 * (((var1>>2)*(var1>>2)) >> 13)) >>3) + ((((signed long int)dig_P2) * var1)>>1))>>18;
    var1 = ((((32768+var1))*((signed long int)dig_P1))>>15);
    if (var1 == 0)
    {
        return 0;
    }    
    P = (((unsigned long int)(((signed long int)1048576)-adc_P)-(var2>>12)))*3125;
    if(P<0x80000000)
    {
       P = (P << 1) / ((unsigned long int) var1);   
    }
    else
    {
        P = (P / (unsigned long int)var1) * 2;    
    }
    var1 = (((signed long int)dig_P9) * ((signed long int)(((P>>3) * (P>>3))>>13)))>>12;
    var2 = (((signed long int)(P>>2)) * ((signed long int)dig_P8))>>13;
    P = (unsigned long int)((signed long int)P + ((var1 + var2 + dig_P7) >> 4));
    return P;
}

/*
 * Calibration [Humidity]
 */
unsigned long int calibration_H(signed long int adc_H)
{
    signed long int v_x1;
    
    v_x1 = (t_fine - ((signed long int)76800));
    v_x1 = (((((adc_H << 14) -(((signed long int)dig_H4) << 20) - (((signed long int)dig_H5) * v_x1)) + 
              ((signed long int)16384)) >> 15) * (((((((v_x1 * ((signed long int)dig_H6)) >> 10) * 
              (((v_x1 * ((signed long int)dig_H3)) >> 11) + ((signed long int) 32768))) >> 10) + (( signed long int)2097152)) * 
              ((signed long int) dig_H2) + 8192) >> 14));
   v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * ((signed long int)dig_H1)) >> 4));
   v_x1 = (v_x1 < 0 ? 0 : v_x1);
   v_x1 = (v_x1 > 419430400 ? 419430400 : v_x1);
   return (unsigned long int)(v_x1 >> 12);   
}

/* ========================= BH1750 Illuminance =============================*/

/*
 * Initiate BH1750
 */
void prepareBH1750(int i2cAddress)
{
    Wire.beginTransmission(i2cAddress);  
    Wire.write(0x10); 
    Wire.endTransmission();
    delay(180);
}

/*
 * Measure illuminance
 */
int measureIlluminance(int i2cAddress)
{
    uint16_t val = 0;
    byte buf[2]; 
    if (measureIlluminance(i2cAddress, buf) == 2){
        val = ((buf[0] << 8) | buf[1]) / 1.2;   // Calculate
        return (int)val;
    }
    return 0;
}  
int measureIlluminance(int i2cAddress, byte *buff)
{
    int i = 0;
    *buff = 0x00;
    Wire.beginTransmission(i2cAddress); 
    Wire.requestFrom(i2cAddress, 2);  
    while (Wire.available())  
    { 
        *(buff + i) = Wire.read();
        i++;
    }
    Wire.endTransmission();  
    return i; 
}
 次回は、SDカードを増設してデータの記録を可能にします。合わせてアナログ入力センサーも増設、お楽しみに!

 
Copyright (C) 2011-2024 Marchan, All rights reserved.