水温計ソ-スコード

水温計ソース

水温計外観

 //  文字列変換用バッファー
#define  STR_HENKAN_BUFF  50

//  I2Cライブラリ
#include  <Wire.h>

//時間処理用
//  DS3231タイムモジュール使用時  true  不使用時    false
#define  DS_3231  true
#define  DS_3231_ONDO  true
//*************************    DS_3231温度取得時
#include  <DS3231.h>
DS3231  clock;
RTCDateTime  tm;
#define  TMPTYOUSEI2  0  //  温度微調整
//*******************
//  時間設定時  true      通常使用は  false  に戻してコンパイルし直す
//  パソコンに同期できないときtrueのままだと
//  同期出来た時の以前の時間に初期化される
#define  TIMESETTEI  false
//***********************
#define  TIMETYOUSEI  0      //  時間微調整
//********************
//  SDカード設定
#include  <SD.h>
#include  <SPI.h>
#define  SD_SS  3    //  SD使用ソケット番号
//*************
File  myFile;
//filename
#define  FILENAME  "ondo"      //  保存ファイル名    ondo1.csv  の様になる
//***********************
#define  FILENAME_SUU  6    //filename  の長さ設定
#define  FILEMAX  131072    //1024*128  100Kバイト以下で保存
//********************
//ディスプレイ用
//LIQUIDCRYSTAL_I2C    使用時  true    LIQUIDCRYSTAL    使用時    false
#define  LIQUIDCRYSTALI2C  true
//****************************
//    ディスプレイ    アドレス・表示幅・桁
#define  LCD_ADDRESS  0x3f
#define  LCDSIZE_YOKO  16    //  16  or  20
#define  LCDSIZE_TATE    2        //  2  or  4
//*******************

#if  LIQUIDCRYSTALI2C==true    //  I2C  シリアルボード使用
    #include  <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C  lcd(LCD_ADDRESS,LCDSIZE_YOKO,LCDSIZE_TATE);

    #define  printIIC(args)  Wire.write(args)
    inline  size_t  LiquidCrystal_I2C::write(uint8_t  value)  {
        send(value,  Rs);
        return  1;
    }

#else    //  LiquidCrystal使用
    //  include  the  library  code:
    #include  <LiquidCrystal.h>
    //  initialize  the  library  with  the  numbers  of  the  interface  pins
    LiquidCrystal  lcd(8,  9,  4,  5,  6,  7);
    //***********************************

#endif

//温度・湿度用
#include  <OneWire.h>
#include  <DallasTemperature.h>
//温度モジュル接続ピン
//  Data  wire  is  plugged  into  port  2  on  the  Arduino
#define  ONE_WIRE_BUS  2
#define  ONDOKEI_SUU  1  //  DS18B20    温度計の数
//******************************
float  ondo1[ONDOKEI_SUU+1]={-126.90};  //温度記録用変数  DS18B20用
float  tmp_tyousei[ONDOKEI_SUU+1]={0,0};  //  温度微調整
//*********************************
//  DS18B20センサーモジュール  分解能セット
//0.5℃、0.25℃、0.125℃、0.0625℃に対応して、9、10、11、12ビットを選択す
#define  SENSER_BIT  12    //9~12  数字が大きいほど高精度  但し  時間がかかる
//********************
    DeviceAddress  ondokei1[ONDOKEI_SUU];    //  温度計アドレス    DS18B20用
//***************************************

//  Setup  a  oneWire  instance  to  communicate  with  any  OneWire  devices  (not  just  Maxim/Dallas  temperature  ICs)
OneWire  oneWire(ONE_WIRE_BUS);

//  Pass  our  oneWire  reference  to  Dallas  Temperature.  
DallasTemperature  sensors(&oneWire);

void  setup()  {

//        Serial.begin(115200);  //ディバッグ時    コメントアウトを外す
        while  (!Serial)  {
            ;  //  wait  for  serial  port  to  connect.  Needed  for  native  USB  port  only
        }
    
    clock.begin();

    //時間設定ONの時のみ    パソコンと同期    時間初期設定
    time_settei(TIMESETTEI);

      //LCD初期設定
    #if  LIQUIDCRYSTALI2C==true    //  I2C  シリアルボード使用
        lcd.init();
        lcd.backlight();
    #else    //  LiquidCrystal使用
        lcd.begin(LCDSIZE);
    #endif

    //  SDセットアップ
    sdsetup();

    //  DS18B20センサーモジュール温度計  アドレスセット
        int  i;
    for(i=0;i<ONDOKEI_SUU;++i){
        sensors.getAddress(ondokei1[i],i);
    }
        //  DS18B20センサーモジュール  分解能セット
        sensors.setResolution(SENSER_BIT);
}

void  loop()  {

    //ディスプレイ表示
    //日付・時間
    time_dsp_hyouji();
    //温度
    ondo_syutoku();
    //  データの保存
    data_hozon();
}

//  ディスプレイへの日・時の表示
void  time_dsp_hyouji(){
    //時間の取得
    tm  =  clock.getDateTime();
    int  yoko=1;
    int  haba=9;
    String  hyouji1;
      //    日時の表示開始
    if(LCDSIZE_YOKO  >=  20  ||  ONDOKEI_SUU<=1){
            hyouji(0,  0,1,  "x27");
            hyouji1  =  String(tm.year  -  2000)  +  "/";
        }else{
            hyouji1  =  "";
            haba=5;
            yoko=0;  
      }
    hyouji1  +=  String(tm.month)  +  "/"  +  String(tm.day);
    string_hyouji(yoko,  0,  haba,  hyouji1);
    if  (tm.hour  <  10)  {
        hyouji(0,  1,  1,  "  ");
        ketahyouji(1,  1,  1,  tm.hour);
    }  else  {
        ketahyouji(0,1,  2,  tm.hour);
    }
    hyouji(2,  1,  1,  ":");
    ketahyouji(3,  1,  2,  tm.minute);
    if(LCDSIZE_YOKO  >=  20  ||  ONDOKEI_SUU<=1){
        hyouji(5,  1,  1,  ":");
        ketahyouji(6,  1,  2,  tm.second);
    }
}

//  温度取得    →    表示
void  ondo_syutoku(){  
    int  ondohyouji_suu  =  ONDOKEI_SUU;  //温度表示の総数    DS_3231を含む
      
    //  DS3231内蔵温度計
    clock.forceConversion();
    if(DS_3231_ONDO){
        ondo1[0]  =clock.readTemperature()  +  TMPTYOUSEI2  ;  //  call  sensors.requestTemperatures()  to  issue  a  global  temperature
                                                                      //温度微調整
        tmp_tyousei[0]  =  TMPTYOUSEI2  ;
        ondohyouji_suu  +=1;
    }
    //  DS18B20センサーモジュール温度計  
    //  call  sensors.requestTemperatures()  to  issue  a  global  temperature  
    //  request  to  all  devices  on  the  bus  
    sensors.requestTemperatures();  //  Send  the  command  to  get  temperatures
        int  i;
    for(i=0;i<ondohyouji_suu;++i){
        if(DS_3231_ONDO){
            ondo1[i+1]  =sensors.getTempCByIndex(i)  +  tmp_tyousei[i+1]  ;  //  call  sensors.requestTemperatures()  to  issue  a  global  temperature
                                                                //温度微調整
        }else{
            ondo1[i]  =sensors.getTempCByIndex(i)  +  tmp_tyousei[i]  ;  //  call  sensors.requestTemperatures()  to  issue  a  global  temperature
                                                                //温度微調整
        }
    }
    ondo_dsp_hyouji(ondohyouji_suu);
}

//  ディスプレイへの温度表示
void  ondo_dsp_hyouji(int  ondohyouji_suu){
      int  yoko=10;
    if(LCDSIZE_YOKO  <  20  &&  ondohyouji_suu>LCDSIZE_TATE){
        yoko=6;
    }
      int  i;
      char  *no;
      int  len;
      int  tate;
    for(i=LCDSIZE_TATE;i<ondohyouji_suu;++i){  //  2ページ目以降から表示
        no=str_to_char(String(i+1)+String(":"));
        len=strlen(no);
        tate=  i  %  LCDSIZE_TATE;
        hyouji(yoko,tate  ,len,no);
        if(  ondo1[i]>-125+  tmp_tyousei[i]){
                ondo1[i]=ondo_hyouji(yoko+len,  tate  ,  ondo1[i]);
        }else{
                hyouji(yoko+len,tate  ,LCDSIZE_YOKO-yoko-len,"");
        }
        if(  tate==LCDSIZE_TATE-1){
            delay(2500);
        }
    }
    if(  tate!=LCDSIZE_TATE-1  &&  LCDSIZE_TATE  <  ondohyouji_suu){    //  ページ余白の消去
        for(tate=tate+1;tate<LCDSIZE_TATE;++tate){
            hyouji(yoko,tate  ,LCDSIZE_YOKO-yoko,"");          
        }
        delay(2500);
    }
        
    for(i=0;i<LCDSIZE_TATE  &&  i<  ondohyouji_suu  ;++i){    //    1ページ目
        if(LCDSIZE_YOKO  <  20  &&  ondohyouji_suu<=2){
            len=0;
        }else{
            no=str_to_char(String(i+1)+String(":"));
            len=strlen(no);
            hyouji(yoko,i  ,len,no);
        }
        if(  ondo1[i]>-125+  tmp_tyousei[i]){
                ondo1[i]=ondo_hyouji(yoko+len,  i  ,  ondo1[i]);
          }else{
                hyouji(yoko+len,i  ,LCDSIZE_YOKO-yoko-len,"");
          }
    }
    if(  i<LCDSIZE_TATE){        //  ページ余白の消去
        for(i;i<LCDSIZE_TATE;++i){
            hyouji(yoko,i  ,LCDSIZE_YOKO-yoko,"");          
        }
    }
    if(  LCDSIZE_TATE<ondohyouji_suu){        
        delay(2500);
    }
}

//  データの保存
void  data_hozon(){
    static  int  h;

    char  *file_tmp;
    char  file[FILENAME_SUU+5];

    if  (h  !=  tm.hour){
        h  =  tm.hour;

        file_tmp=filename();
        strcpy(file,file_tmp);
        bool  ari=isfile(file);

        //  open  a  file
        myFile  =  SD.open(file,  FILE_WRITE);
        if(myFile){
            int  kaisuu=ONDOKEI_SUU;
            if(DS_3231  ){
                kaisuu  +=  1;
            }
  
              if(ari==0){
                myFile.print(""ネン","ツキ","ヒ","ジ","フン","ビョウ"");
                  int  i=0;
                  String  str_s;
                  char  *str_henkan;
                for(i=0;i<kaisuu;++i){
                      str_s=String(","オンド")+String(i+1)+String(""");
                      str_henkan=str_to_char(str_s);                                    
                      myFile.print(str_henkan);          
                }
                myFile.println("");
            }
            myFile.print(tm.year);
            myFile.print(",");
            myFile.print(tm.month);
            myFile.print(",");
            myFile.print(tm.day);
            myFile.print(",");
            myFile.print(tm.hour);
            myFile.print(",");
            myFile.print(tm.minute);
            myFile.print(",");
            myFile.print(tm.second);                

              int  i=0;
            for(i=0;i<kaisuu;++i){
                myFile.print(",");
                if(ondo1[i]>-125+  tmp_tyousei[i]){
                    myFile.print(ondo1[i]);
                }
            }
            myFile.println("");
            hyouji(0,  1  ,  16,"カキコミシュウリョウ");  
        }else{
            hyouji(0,  1  ,  16,"ファイルオープンエラー");
        }
        myFile.close();
        delay(1000);
        hyouji(0,  1,  16,  "@  ");
    }
}

//液晶表示用関数  char
void  hyouji(int  yoko,  int  tate,  int  haba,  char  *text)  {
    utf_del_uni(text);
  
    //文字化け防止のため1字ずつ表示
    int  i  =  0;
    int  j  =  0;
    while  (text[i]  !=  ”  &&  i<haba  )  {
        lcd.setCursor(yoko  +  i,  tate);
        lcd.print(text[i]);
        i++;
    }
    while  (i  <  haba)  {
        lcd.setCursor(yoko  +  i,  tate);
        lcd.print(‘  ’);
        i++;
    }
}

//  UTF-8  to  ASCIIコード変換
void  utf_del_uni(char  *s)  {
    byte  i  =  0;
    byte  j  =  0;
    while  (s[i]  !=  ”)  {
        if  ((byte)s[i]  ==  0xEF)  {
            if  ((byte)s[i  +  1]  ==  0xBE)  s[i  +  2]  +=  0x40;
            i  +=  2;
        }
        s[j]  =  s[i];
        i++;
        j++;
    }    
    s[j]  =  ”;
}

//stringの表示
char  *string_hyouji(int  yoko,  int  tate,  int  haba,  String  hyouji1)  {
    //最後に文字を入れておかないと数字の最後が表示されない
    hyouji1  =  hyouji1  +  ’  ’;
    int  len  =  hyouji1.length()-1;  //  文字列長さ
    hyouji1[len]=”;
    char  *str_henkan;
    str_henkan=str_to_char(hyouji1);
    hyouji(yoko,  tate,  haba,str_henkan);
    //短いときに旧表示を消去
    return(str_henkan);
}

//string  to  char[]変換
char  *str_to_char(String  text1){
    static  char  str_henkan[STR_HENKAN_BUFF];
    int  len  =  text1.length();  //  文字列長さ
    text1.toCharArray(str_henkan,  len  +  1);  
    return  str_henkan;
}

//  数字桁合わせ表示        01  など
char  *  ketahyouji(int  yoko,  int  tate,  int  haba,  int  suu)  {
    String  hyouji1  =  String(suu);
    int  len  =  hyouji1.length();  //  文字列長さ
    int  i  =  0;
    while  (i  +  len  <  haba)  {
        hyouji1  =  "0"  +  hyouji1;
        ++i;
    }
    char  *str_henkan;
    str_henkan=str_to_char(hyouji1);
    hyouji(yoko,  tate,  haba,  str_henkan);
    return(str_henkan);
}

//温度  0.1℃表示
float  ondo_hyouji(int  yoko,  int  tate,  float    t)  {    
  //  小数第1位までで四捨五入する
    t  =  round1(t,-1);
    String  hyouji1  =  String(t);
    char  *str_henkan;
    str_henkan=str_to_char(hyouji1);
    int  len  =  hyouji1.length();  //  文字列長さ
    *(str_henkan+len-1)=’xDF’;
    *(str_henkan+len)=’C’;
    *(str_henkan+len+1)=”;
    hyouji(yoko,  tate,LCDSIZE_YOKO-yoko,  str_henkan);
    return(t);
}

/*四捨五入(10のn乗の位を処理)*/
float  round1(float  d,  int  n){
        double  dst;
        d  =  d  *  pow(10,  -n  );            /*処理を行う桁を10-1  の位にする*/
        if(d>=0){
            dst  =  (double)(int)(d    +  0.5);
        }else{              //  マイナスの時は絶対値にマイナスを付ける
                        dst  =  (double)(int)(d    -  0.5);
        }
        return        dst  *  pow(10,  n  );          /*処理を行った桁を元に戻す*/
}

//時間取得関数

//時間設定ONの時のみ    パソコンと同期    時間初期設定

//  get  the  date  and  time  the  compiler  was  run
void  time_settei(bool  settei1){
    //時計初期設定
          static  bool  timefirst=true;  //初回呼び出し時のみ実行
    if  (settei1  &&  timefirst)  {
          clock.setDateTime(__DATE__,  __TIME__);  
          tm  =  clock.getDateTime();
                //時計時間微調整
          if  (tm.second  +  TIMETYOUSEI  >=  60)  {
              tm.second  =  tm.second  +  TIMETYOUSEI  -  60;
              tm.minute  +=  1;
          }  else  {
              tm.second  =  tm.second  +  TIMETYOUSEI;
          }
          //  and  configure  the  RTC  with  this  info
          clock.setDateTime(tm.year,tm.month,  tm.day,tm.hour,tm.minute,  tm.second);
      }
      timefirst=false;
      return;
}

    

//  ファイル関係関数

//  SDセットアップ
void  sdsetup(){
    if  (!SD.begin(SD_SS))  {
            hyouji(0,  0,  16,  "SDinitialization");
            hyouji(0,  1,  16,  "  failed!");
            delay(5000);
        return;
    }
}

//  file有り無し
bool  isfile(char  *text){
    if  (SD.exists(text))  {
        return  1;
    }  else  {
        return  0;
    }
}

//保存filename決定
char  *filename(){
      String  filename_s;
      static  char  filename1[FILENAME_SUU+4]="";
      static  int  i=1;
      uint32_t  filesize=FILEMAX;  //  FILEMAXバイト以下で保存
      int  isfile=0;
      char  *filename_c;
      while(isfile==0  &&  filesize>=FILEMAX){  //  FILEMAXバイト以下で保存
              filename_s=String(FILENAME)+String(i)+String(".csv");
              filename_c=str_to_char(filename_s);
              strcpy(filename1,filename_c);
              myFile=SD.open(filename1,FILE_READ);  
              if(myFile){
                    filesize=myFile.size();
                    isfile=0;
              }else{
                    isfile=1;
              }
              myFile.close();
              ++i;
        }
        –i;
        return  filename1;
}

        
タイトルとURLをコピーしました