Top Page 気象センサー&タイマーシールドの実装
自作工程のメモとして
27.Jun.2017
(更新:2018/09/06)


 前のページに 「Mighty CW Keyer のケースへの実装」を掲載しましたが、ケースの中身が大きく空洞になっており勿体ないので、ブレッドボードで実験していた気象センサー(AE-BME280)とタイマー(DS3231)を載せるシールドを作成しました。
CW-Keyerは、USBケーブルでパソコン(PC)に繋がっており、PCをONしている間は通電状態にあります。
私の場合は、交信を頻繁にするわけでも無く、日常的には温度・湿度・気圧・時刻を表示させておけば、購入したセンサー類を活用しながらブレッドボードを片付けることができることから作ってみました。
また、専用のPCBを作るほどでは有りませんが、最近FusionPCBへ発注する機会が多くなり、他のPCBと一緒に発注しました。




完成品1号機です。


Edit by bluegriffon2.3.1


1.回路

 特別な回路ではなく、ブレッドボード上で組んでいたままを写しただけになります。
3.3V側と5V側にはプルアップ抵抗の回路も書きましたが、各センサー・タイマーにはプルアップ抵抗が入っていると思いますので、配線は不要です。(あまりに勿体ないのでパターンを描いてみただけです)


■ 回路図


クリックして拡大版(PDF)になります。




2.シールドの実装

 CW Keyer のケースの中にそのまま取り付けるだけです。
ただし、気象センサーは密閉状態ではおかしいので、後面のパネルに3.5Φの穴を開けています。

■ シールドを実装した状態の後面


気象センサー(AE-BME280)は、ブレッドボード上でテストしていたものを直付けしています。
もし、このように実装するならL型のピンコネクタを後面から刺せば、後面パネルにギリギリの位置まで近づけられたかもしれません。


■ 後面パネルに開けた穴

  
試しに、失敗作の後面パネルに穴を開け、センサーの穴(塞いではいけない穴)が見えるようにしました。
ケース内の温度上昇が影響するか心配しましたが、温度等は後面パネルを外した状態と変わらなかったため良しとしました。


■ CW Keyer に気象センサーと時刻を表示させた状態


スピードのボリュームを左に回し切った時に、気象センサーと時刻を表示するようにしています。
右に少し回すと、k3ng CW Keyer に切り替わります。(キーヤーの画面も復活)



3.スケッチの工夫(k3ng CW Keyer と 気象センサー&タイマーの同居)

 k3ng CW Keyer は更新の頻度が比較的高く、直接書き込むことを最小限にしようとヘッダファイルの形式で挿入・貼付けをすることにしました。
同居させるスケッチを5つのファイル(jlb_Insert_top.h ・ jlb_Insert_setup.h ・ jlb_Insert_loop.h ・ jlb_Insert_loopend.h ・ jlb_paste_end.h)に分割して、k3ng keyer本体の空白行に挿入していきます。(5つのファイルは、 k3ng_keyer.ino ファイルと同じフォルダーに入れます。)
ただし、最後のファイルは、ヘッダファイル形式で挿入するとコンパイル時にエラー(記述が見つからない??)が出たため、貼り付けています。
また、当然ですがk3ng Keyer の内容と重複するところは、削除しています。

k3ng_keyer.ino ファイルの挿入位置等は、2018.08.04付での例です。
時計調整用のスケッチを追加・修正しました。(2018/09/07)

(1) jlb_Insert_top.h ファイルの挿入  

■ 挿入位置


■ jlb_Insert_top.h ファイルの内容
// k3ng_keyer.ino  ファイルの 1684 行に挿入 (Ver 2018/08/13)
// 1684  #include "jlb_Insert_top.h"
//
// 時間調整はM1 M2 ボタンを使う(プラス1秒=M1・マイナス1秒=M2)
// 注意:桁上がり桁下がりを考慮していないため、30秒前後の時に実行
// DS3231 を使用。ライブラリーは、DS1307
// k3ng CW Keyer と連携するときは、Keyerのloopエンドは、1538行目付近にある。
//

// #include <Wire.h>
// #include <TimeLib.h>
#include <DS1307RTC.h>

const char *monthName[12] = {
  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
// スイッチサイエンス社のBME280サンプスケッチ
#define BME280_ADDRESS 0x76
unsigned long int hum_raw, temp_raw, pres_raw;
signed long int t_fine;

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;

tmElements_t tm;

#define SerialOutFlag false  // シリアル出力する場合は true 、出力しない false
int b4sec;    // 前回表示した秒値を格納。
int valarm = 0;  // アラームセットに使用
int valdatetime = 0; // 時刻セットに使用
int cal_Minute;  // アラームセットに使用
int w_sw, SSt, MM, UU;  // 時刻セットに使用
int ST;                 // 時刻セットに使用
int MaxVal, MinVal;     // 時刻セットに使用

// -------------------------------------------




(2) jlb_Insert_setup.h ファイルの挿入

■ 挿入位置


■ jlb_Insert_setup.h ファイルの内容
// k3ng_keyer.ino  ファイルの 1717 行に挿入 (Ver 2018/08/13)
// 1717  #include "jlb_Insert_setup.h"

// -------------------------------------------

pinMode(6, INPUT_PULLUP);
pinMode(7, OUTPUT);
pinMode(15, OUTPUT);

//BME280初期設定
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;

// I2CのSETUP
Wire.begin();

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

readTrim();

// -------------------------------------------




(3) jlb_Insert_loop.h ファイルの挿入

■ 挿入位置


■ jlb_Insert_loop.h ファイルの内容
// k3ng_keyer.ino  ファイルの 1724 行に挿入 (Ver 2018/08/13)
// 1724  #include "jlb_Insert_loop.h"
// -------------------------------------------
digitalWrite(15, digitalRead(6));
if (analogRead(0) < 5 )  // ■■スピードボリュームが最小ならタイマー温度表示の処理
{

  if (RTC.read(tm)) {    // RTCから時間が読み出せれば◆
    // COMボタンが2秒以上押されたら時刻調整に入る。 (2018/09/06)
    // 2月のうるう年も考慮済。
    //
    // 通常状態で時間調整 プラス・マイナス1秒を M1+ M2- ボタンで調節する。
    // アナログ入力の実測値:COM=0 ,M1=89 ,M2=166 ,M3=231 ( 0 --- 1023 )
    // 注意:秒が30秒前後の時に実行すること
    // (簡易設定のため、桁上がり桁下がりを考慮せず)
    //
    // M3ボタンをアラームに使う (2017/10/31)
    // LCD 0行、10桁目に'"'文字を表示するとアラームのセットが有り

    SSt = analogRead(1);
    if (SSt < 50 ) { //  COMボタン押された
      ST = 0;
      while (SSt < 50) { // COMボタンを放すまで待つ
        delay(100);
        ST++;
        SSt = analogRead(1);
      }
      if (ST > 20) { // 100mS X 20 = 2秒以上なら
        beep();
        delay(50);
        // COMボタンなら 時間設定 (2018/09/06)
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("M1:+ M2:- M3:Set");
        lcd.setCursor(0, 1);
        lcd.print("Set YYYY        "); // ----■■年の設定■■-------
        valdatetime = tm.Year + 1970;
        MaxVal = 2040;
        MinVal = 2018;
        YMDHMSset(); // ボタン操作による加減算処理へ
        tm.Year = CalendarYrToTm(valdatetime);
        RTC.write(tm);    // 時間をDS3231 へセットする
        beep();
        // うるう年を判定
        if (((tm.Year + 2 ) % 4) == 0) {
          UU = 1; // うるう年
        } else {
          UU = 0; // 通常年
        }

        // --------------------------------------■■月の設定■■-------
        lcd.setCursor(0, 1);
        lcd.print("Set MM          ");
        valdatetime = tm.Month;
        MaxVal = 12;
        MinVal = 1;
        YMDHMSset(); // ボタン操作による加減算処理へ
        tm.Month = valdatetime;
        RTC.write(tm);    // 時間をDS3231 へセットする
        MM = valdatetime; // セットした月を記憶
        beep();
        // 大小の月を判定
        switch (MM) {
          case 1:
          case 3:
          case 5:
          case 7:
          case 8:
          case 10:
          case 12:
            MaxVal = 31;
            break;
          case 2:
            if (UU == 0) {
              MaxVal = 28;
            } else {
              MaxVal = 29; // うるう年
            }
            break;
          case 4:
          case 6:
          case 9:
          case 11:
            MaxVal = 30;
            break;
        }

        // ---------------------------------------■■日の設定■■-------
        lcd.setCursor(0, 1);
        lcd.print("Set DD          ");
        valdatetime = tm.Day;
        // MaxVal は月の設定部分で決定済み
        MinVal = 1;
        YMDHMSset(); // ボタン操作による加減算処理へ
        tm.Day = valdatetime;
        RTC.write(tm);    // 時間をDS3231 へセットする
        beep();

        // ---------------------------------------■■時の設定■■-------
        lcd.setCursor(0, 1);
        lcd.print("Set Hour        ");
        valdatetime = tm.Hour;
        MaxVal = 23;
        MinVal = 0;
        YMDHMSset(); // ボタン操作による加減算処理へ
        tm.Hour = valdatetime;
        RTC.write(tm);    // 時間をDS3231 へセットする
        beep();

        // --------------------------------------■■分の設定■■-------
        lcd.setCursor(0, 1);
        lcd.print("Set Min.        ");
        valdatetime = tm.Minute;
        MaxVal = 59;
        MinVal = 0;
        YMDHMSset(); // ボタン操作による加減算処理へ
        tm.Minute = valdatetime;
        RTC.write(tm);    // 時間をDS3231 へセットする
        beep();

        // ----------------------------------------■■秒の設定■■-------
        lcd.setCursor(0, 1);
        lcd.print("Set Sec.        ");
        valdatetime = tm.Second;
        MaxVal = 59;
        MinVal = 0;
        YMDHMSset(); // ボタン操作による加減算処理へ
        tm.Second = valdatetime;
        RTC.write(tm);    // 時間をDS3231 へセットする

        // ----------------------------------------■■設定終わり■■-------

        beep();
        delay(300);
        beep();
        lcd.clear();
      }
    }

    if ((SSt > 70) && (SSt < 120)) { // M1ボタンなら +1秒
      if (tm.Second > 57) {  // 57秒より上なら3秒待ち(2018/09/26)
        beep();
        delay(3000);
        beep();
      } else {
        tm.Second++;
        // and configure the RTC with this info
        RTC.write(tm);    // 時間をDS3231 へセットする
        beep();
      }
      delay(200);
    }
    if ((SSt > 150) && (SSt < 180)) { // M2ボタンなら -1秒
      if (tm.Second < 3) {  // 3秒より下なら3秒待ち(2018/09/26)
        beep();
        delay(3000);
        beep();
      } else {
        tm.Second--;
        // and configure the RTC with this info
        RTC.write(tm);    // 時間をDS3231 へセットする
        beep();
      }
      delay(200);
    }

    if ((SSt > 200) && (SSt < 250)) { // M3ボタンなら アラーム選択 (2017/10/31)
      ST = 0;
      while ((SSt > 200) && (SSt < 250)) { // M3ボタンを放すまで待つ
        delay(100);
        ST++;
        SSt = analogRead(1);
      }
      if (ST > 20) { // 100mS X 20 = 2秒以上なら
        beep();
        delay(50);

        lcd.clear();
        lcd.setCursor(0, 1);
        lcd.print("Next=M1,Exit=M2 ");
        int w_sw = 1;
        while (w_sw) {
          SSt = analogRead(1);
          if ((SSt > 70) && (SSt < 120)) { // M1ボタンなら
            while ((SSt > 70) && (SSt < 120)) { // M1ボタンを放すまで待つ
              delay(50);
              SSt = analogRead(1);
            }
            valarm++;
            if (valarm == 4) valarm = 0;
          }
          switch (valarm) {
            case 0:
              lcd.setCursor(0, 0);
              lcd.print("NON ALARM       ");
              break;
            case 1:
              lcd.setCursor(0, 0);
              lcd.print("ALARM 1 Minute  ");
              break;
            case 2:
              lcd.setCursor(0, 0);
              lcd.print("ALARM 10 Minute ");
              break;
            case 3:
              lcd.setCursor(0, 0);
              lcd.print("ALARM 15 Minute ");
              break;
            default:
              break;
          } // switch (valarm) end
          //delay(50);
          if ((SSt > 150) && (SSt < 180)) { // M2ボタンなら Exit
            while ((SSt > 150) && (SSt < 180)) { // M2ボタンを放すまで待つ
              delay(50);
              SSt = analogRead(1);
            }
            w_sw = 0;
          }
        } // while (w_sw)
        lcd.clear();
      }
    }


    // アラーム処理 1分・10分・15分 毎にアラーム
    if (tm.Second == 0) {
      switch (valarm) {
        case 1:
          beep();
          delay(300);
          break;
        case 2:
          cal_Minute = (tm.Minute + 1) % 10;
          if (cal_Minute == 1) {
            beep();
            delay(300);
          }
          break;
        case 3:
          cal_Minute = (tm.Minute + 1) % 15;
          if (cal_Minute == 1) {
            beep();
            delay(300);
          }
          break;
        default:
          break;
      } // switch
    }

  } else {    // RTCから時間が読み出せ無ければ◆
    if (RTC.chipPresent()) {
      lcd.setCursor(0, 0);
      lcd.print("run the SetTime");
    } else {
      lcd.setCursor(0, 0);
      lcd.print("DS1307 read error!");
    }
    delay(9000);
  }
  if (b4sec != tm.Second ) { // 取得した秒値が違えば、表示する
    b4sec = tm.Second;
    TempClockDisp();
  }
  // delay(1000);

} else {
  // -------------------------------------------

まず、先頭行にある if (analogRead(0) < 5 ) でスピードのVRを読み出しています。
もし、左に回し切っている状態なら、気象・時刻の処理をするよう判断します。       
また、時間(秒単位)を調節できるよう、M1・M2ボタンを使っています。
M1・M2ボタンでの操作時に、 beep(); を入れてみました。
ボタン処理後のdelayを500==>200に変更(2017/10/18)
アラーム設定と次のタイマーの日時(時刻)を追加しています。

■ タイマー日時設定のイメージ



(4) jlb_Insert_loopend.h ファイルの挿入

■ 挿入位置



■ jlb_Insert_loopend.h ファイルの内容
// k3ng_keyer.ino  ファイルの 1867 行に挿入 (Ver 2018/08/13)
// 1867   #include "jlb_Insert_loopend.h"
 }    // loop end




ここは、ループの終了位置 "}" を挿入するだけです。


(5) jlb_paste_end.h ファイルの貼付

■ 貼付け位置



■ jlb_paste_end.h ファイルの内容
// k3ng_keyer.ino  ファイルの 20806 行(最下行の下)にこのファイル全体を貼り付ける。 (Ver 2018/08/13)
// 編集は jlb_paste_end.h ファイルにて行い、その都度貼り付けること。
void TempClockDisp() {    // 温度・湿度・気圧・時間を表示

  // アラームマークを表示する(2017/10/31)
  lcd.setCursor(10, 0);
  if (valarm > 0) lcd.write('"'); else lcd.write(' ');

  // LCD へ出力する。
  // 時分秒
  lcd.setCursor(11, 0);
  if (tm.Month < 10 )   lcd.write(' ');
  lcd.print(tm.Month);
  lcd.write('/');
  lcd2digits(tm.Day);

  lcd.setCursor(8, 1);
  lcd2digits(tm.Hour);
  lcd.print(":");
  lcd2digits(tm.Minute);
  lcd.print(":");
  lcd2digits(tm.Second);

  /*
      // 年月日 表示エリヤの関係で使わない
      lcd.setCursor(0, 1);
      lcd.print(tmYearToCalendar(tm.Year));
      lcd.print("/");
      lcd2digits(tm.Month);
      lcd.print("/");
      lcd2digits(tm.Day);
      lcd.print(" ");
  */

  // 温度・湿度・気圧を表示
  double temp_act = 0.0, press_act = 0.0, hum_act = 0.0;
  signed long int temp_cal;
  unsigned long int press_cal, hum_cal;
  int aa;

  readData();

  temp_cal = calibration_T(temp_raw);
  press_cal = calibration_P(pres_raw);
  hum_cal = calibration_H(hum_raw);
  temp_act = (double)temp_cal / 100.0;
  press_act = (double)press_cal / 100.0;
  hum_act = (double)hum_cal / 1024.0;
  //初期値が小数点以下2桁のため Serial.print(XXXXX,1); ,1 で
  //小数点以下2桁目を四捨五入し、小数点以下1桁出力とする。

  switch (tm.Second) {  // ■■■ 10秒毎に表示
    case 0:
    case 10:
    case 20:
    case 30:
    case 40:
    case 50:
      // I2C LCD に表示する
      //初期値が小数点以下2桁のため lcd.print(XXXXX,1); ,1 で
      //小数点以下2桁目を四捨五入し、小数点以下1桁出力とする。
      lcd.setCursor(0, 0);
      temp_act = temp_act - 2.4;    // ■温度センサーの出力が高すぎるため -2.4度引く。
      lcd.print(temp_act, 1);
      lcd.print("c  ");
      lcd.setCursor(0, 1);
      if (press_act < 999.95) lcd.print(" ");
      lcd.print(press_act, 1);
      lcd.print("h ");
      lcd.setCursor(7, 0);
      lcd.print(hum_act, 0);
      lcd.print("%");
  }
}

// ■◆■■これ以降、タイマーDS3231関係の記述

// LCDへの出力を2桁にする print2digits を参照して追加。
void lcd2digits(int number) {
  if (number >= 0 && number < 10) {
    lcd.print('0');
  }
  lcd.print(number);
}

void YMDHMSset()  // 時間調整用のM1,M2,M3ボタン操作部分(2018/09/07)
{
  while (1) {
    SSt = analogRead(1);
    if ((SSt > 70) && (SSt < 120)) { // M1ボタンなら
      while ((SSt > 70) && (SSt < 120)) { // M1ボタンを放すまで待つ
        delay(50);
        SSt = analogRead(1);
      }
      valdatetime++;
      if (valdatetime > MaxVal) valdatetime = MinVal;
    }
    SSt = analogRead(1);
    if ((SSt > 150) && (SSt < 180)) { // M2ボタンなら
      while ((SSt > 150) && (SSt < 180)) { // M2ボタンを放すまで待つ
        delay(50);
        SSt = analogRead(1);
      }
      valdatetime--;
      if (valdatetime < MinVal) valdatetime = MaxVal;
    }
    lcd.setCursor(10, 1);
    if (valdatetime < 10) {
      lcd.write('0');
      lcd.print(valdatetime);
    }
    //delay(50);
    if ((SSt > 200) && (SSt < 250)) { // M3ボタンなら Exit
      while ((SSt > 200) && (SSt < 250)) { // M3ボタンを放すまで待つ
        delay(50);
        SSt = analogRead(1);
      }
      return;
    }
  } // while END
}

// ■◆■■ここまで、タイマーDS3231関係の記述

////////////////////////////////////////////////////////////////
// ■■■これ以降、BME280 温度・湿度・気圧関係の記述
void readTrim()   // BME280の処理
{
  uint8_t data[32], i = 0;                   // Fix 2014/04/06
  Wire.beginTransmission(BME280_ADDRESS);
  Wire.write(0x88);
  Wire.endTransmission();
  Wire.requestFrom(BME280_ADDRESS, 24);      // Fix 2014/04/06
  while (Wire.available()) {
    data[i] = Wire.read();
    i++;
  }

  Wire.beginTransmission(BME280_ADDRESS);    // Add 2014/04/06
  Wire.write(0xA1);                          // Add 2014/04/06
  Wire.endTransmission();                    // Add 2014/04/06
  Wire.requestFrom(BME280_ADDRESS, 1);       // Add 2014/04/06
  data[i] = Wire.read();                     // Add 2014/04/06
  i++;                                       // Add 2014/04/06

  Wire.beginTransmission(BME280_ADDRESS);
  Wire.write(0xE1);
  Wire.endTransmission();
  Wire.requestFrom(BME280_ADDRESS, 7);       // Fix 2014/04/06
  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); // Fix 2014/04/06
  dig_H6 = data[31];                                   // Fix 2014/04/06
}
void writeReg(uint8_t reg_address, uint8_t data)
{
  Wire.beginTransmission(BME280_ADDRESS);
  Wire.write(reg_address);
  Wire.write(data);
  Wire.endTransmission();
}
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];
}

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;
}

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;
}

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);
  // ■■■ここまで、温度・湿度・気圧関係の記述
  /////////////////////////////////////////////////////////////////
}

このファイルだけは、ヘッダファイルとして挿入できず、その内容を貼り付けることにしています。







9.その他気づいたこと

(1) 電池の消耗
一日中電源を入れない機会があり、その時に時間がくるっていることに気が付きました。
充電タイプのLIR2032 3.6V リチウムイオン充電式ボタン電池を見てみると、約2V程度しかありません。
新品を購入して電圧を見ると、4Vもあり早速交換しました。(2017/10/18)

(2) 再び電池の消耗
前回の交換から約10か月で再び時計がくるっていることに気づきました。
今回も充電タイプのLIR2032が消耗していました。
そこで、予備に購入していたタイマーモジュールと交換して、取り外しやすいようにソケット処理と、非充電式ボタン電池(CR2032)に変更しました。(2018/09/06)


99.タイマーモジュールのソケット処理と非充電対応(2018/09/06)

上記の「9. その他気づいたこと」に有りますように充電池が消耗するのが早いようなので、タイマーモジュールを交換して、取り外しやすいようにソケット処理と、ボタン電池(CR2032)用に回路変更を加えました。

■ L形ピンソケットの取付




■ タイマーモジュールの非充電対応化


非充電のボタン電池を使うため200オームの抵抗を外しています。
格安品で入手したものですが、初めから充電回路が生きたままCR2032が付いていました。


■ 実装状態


少しベース基板からはみ出しますが支障が無いのでこの形で使う予定です。
組付け時の電池電圧は3.3Vでした。