#include #include #include #include #include File myFile; LiquidCrystal lcd(9, 8, 5, 4, 3, 2); // デフォルトから変更 12 ->9 11->8 // RTC関係の変数 char dtString[20]="yyyy/mm/dd hh:mm:ss"; // テンプレート用文字列で初期化 byte RtcADR = 0xA2 >> 1; // RTCのアドレス // 気圧計関係の変数 const int addresPsensor = 0x60; // 気圧計のI2Cアドレス float a0, b1, b2, c12, c11, c22; float Pha, Temp; int tempOffset, pressOffset; unsigned int Padc; unsigned int Tadc; char fileName[11] = "yymmdd.csv"; // ファイル名 void setup() { unsigned int x; pinMode(6, INPUT); // RTCの /INT信号を接続 digitalWrite(6, HIGH); // オープンドレインなのでプルアップ pinMode(13, OUTPUT); // 動作表示LED Serial.begin(9600); lcd.begin(16, 2); // RTCの初期設定 Rtc.begin(); // AdjustRtcTime(); // 時刻合わせが必要な場合に使う SetRtcTimer(); // 定周期タイマーの設定 // SDカードの初期化 if (!SD.begin(10)) { Serial.println("SD initialization failed!"); lcd.print("SD failed. Halt!"); for(;;); // ここでHalt } Serial.println("SD initialization done."); lcd.print("SD ok!"); // 気圧計の初期設定 // EEPROM.write(1, 27); // 温度補正値書き込み // EEPROM.write(3, 75); // 気圧補正値 x = EEPROM.read(0); // EEROMから温度の補正値読み出し unit=0.1℃ x = x << 8; tempOffset = x; //上位8ビット x = EEPROM.read(1); tempOffset = tempOffset | x; // 下位8ビット x = EEPROM.read(2); // 気圧の補正値 x = x << 8; pressOffset = x; // 上位 x = EEPROM.read(3); pressOffset = pressOffset | x; // 下位 Serial.print(tempOffset); Serial.print(", "); Serial.println(pressOffset); byte doC[8] = { // 外字で℃を作る B00011, B00011, B01100, B10010, B10000, B10010, B01100, }; lcd.createChar(0, doC); delay(1000); // 気圧計が立ち上がるまで待つ Wire.beginTransmission(addresPsensor); Wire.write(0x04); // Read coefficient data Wire.endTransmission(); Wire.requestFrom(addresPsensor, 12); // Request 12 bytes if (Wire.available()) { a0 = read_coefficients(16, 3, 0); b1 = read_coefficients(16, 13, 0); b2 = read_coefficients(16, 14, 0); c12 = read_coefficients(14, 13, 9); c11 = read_coefficients(11, 10, 11); c22 = read_coefficients(11, 10, 15); } Serial.println("1000 * coefficient a0, b1, b2, c12, c11, c22 "); Serial.print(a0*1000); Serial.print(", "); Serial.print(b1*1000); Serial.print(", "); Serial.print(b2*1000); Serial.print(", "); Serial.print(c12*1000); Serial.print(", "); Serial.print(c11*1000); Serial.print(", "); Serial.println(c22*1000); Rtc.available(); // 時刻を取得 convString(); // RTCの時刻(BCD)を文字列に変換してdtStringに格納 fileName[0] = dtString[2]; // y ファイル名の決定 fileName[1] = dtString[3]; // y fileName[2] = dtString[5]; // m fileName[3] = dtString[6]; // m fileName[4] = dtString[8]; // d fileName[5] = dtString[9]; // d Serial.print("File Name = "); Serial.println(fileName); myFile = SD.open(fileName, FILE_WRITE); // setupで取得したファイル名を使用 myFile.println(); // 改行 myFile.print("Record Start. tempOffset="); myFile.print(tempOffset); myFile.print(" pressOffset="); myFile.println(pressOffset); myFile.close(); } void loop() { float sumP, sumT; long outP, outT; // 表示用データ int n; sumP = 0; sumT = 0; waitTimer(); // RTCの /INT信号を待つ for( n=0; n < 10; n++){ // 安定待ちのため10回ダミーリード sensData(); } for(n=0; n<100; n++){ // バラツキが大きいので100回アベレージング sensData(); sumP = sumP + Pha; sumT = sumT + Temp; } outT = int(sumT /10 + 0.5) + tempOffset; // 小数点以下1桁の値に丸める outP = int(sumP /10 + 0.5) + pressOffset; Rtc.available(); // 時刻を取得 convString(); // RTCの時刻(BCD)を文字列に変換してdtStringに格納 Serial.print(dtString); // シリアルに書き出し Serial.print(", "); Serial.print(outT); Serial.print(", "); Serial.println(outP); //  SDカードに書き込み // if(dtString[18] == '0' ) { // 10秒毎に記録 if( ( (dtString[15] == '0') | (dtString[15] =='5') ) & (dtString[17] == '0') & (dtString[18] == '0') ) { // 5分00秒か0分00秒に記録 myFile = SD.open(fileName, FILE_WRITE); // setupで取得したファイル名を使用 myFile.print(dtString); myFile.print(", "); myFile.print(outT / 10); // 小数点以上の値 myFile.print("."); myFile.print(outT % 10); // 10で割った余り myFile.print(", "); myFile.print(outP/10); // 小数点以上の値 myFile.print("."); myFile.print(outP % 10); // 10で割った余り myFile.print(", "); myFile.print(Tadc); // 補正前の温度センサの値 myFile.print(", "); myFile.println(Padc); // 補正前の圧力センサの値 myFile.close(); } lcd.setCursor(0, 0); // 液晶に書き出し 先頭に1文字ブランク lcd.print(" "); for( n=5; n <= 18; n++){ // 入りきらないので年は省略 lcd.print(dtString[n]); } lcd.setCursor(0 , 1); if(outT < 0){ lcd.print("-"); } else { lcd.print(" "); } if(abs(outT)<100){ lcd.print(" "); } lcd.print(outT/10); lcd.print("."); lcd.print(outT % 10); lcd.write(8); // 本当は0を指定すべき(後日修正要す) // lcd.print("C"); lcd.setCursor(7, 1); if(outP < 10000) { lcd.print(" "); } lcd.print(outP/10); lcd.print("."); lcd.print(outP % 10); lcd.print("hPa"); } // Loopの末尾 void convString(){ // RTCの2バイトのBCDを文字に変換し時刻の文字列を作る byte x; dtString[0]='2'; dtString[1]='0'; x = Rtc.years(); dtString[2] = upper2chr(x); dtString[3] = lower2chr(x); x = Rtc.months(); dtString[5] = upper2chr(x); dtString[6] = lower2chr(x); x = Rtc.days(); dtString[8] = upper2chr(x); dtString[9] = lower2chr(x); x = Rtc.hours(); dtString[11] = upper2chr(x); dtString[12] = lower2chr(x); x = Rtc.minutes(); dtString[14] = upper2chr(x); dtString[15] = lower2chr(x); x = Rtc.seconds(); dtString[17] = upper2chr(x); dtString[18] = lower2chr(x); } char upper2chr(byte x){ // 上位をAsciiコードに変換 return (x >> 4) + 0x30; } char lower2chr(byte x){ // 下位をAsciiコードに変換 return (x & 0x0f) + 0x30; } void waitTimer(){ // RTCの /INT信号を待つ while(digitalRead(6) == HIGH){ // HIGHなのでLOWになるまで待つ } while(digitalRead(6) == LOW){ // 再びHIGHになるまで待つ digitalWrite(13, HIGH); // LED ON } digitalWrite(13, LOW); // LED OFF } void AdjustRtcTime(){ // 時計の時刻合わせに使用。数値は修正要 byte date_and_time[7]; date_and_time[0] = 0x00; // 0秒 date_and_time[1] = 0x55; // 5分 date_and_time[2] = 0x15; // 20時 date_and_time[3] = 0x19; // 2日 date_and_time[4] = 0x00; // X曜日 日曜日 = 0 〜 土曜日 = 6 date_and_time[5] = 0x08; // 8月 date_and_time[6] = 0x12; // 12年 Rtc.sync(date_and_time); } void SetRtcTimer(){ // 定周期タイマー割り込みの設定 Wire.beginTransmission(RtcADR); Wire.write(0x0e); // タイマー停止 Wire.write(0x00); Wire.endTransmission(); Wire.beginTransmission(RtcADR); Wire.write(0x01); // コントロールレジスタ-2の設定 Wire.write(0x11); // TI/TP=on, TIE=on Wire.endTransmission(); Wire.beginTransmission(RtcADR); Wire.write(0x0f); // タイマー設定値 Wire.write(0x01); // 1回毎 Wire.endTransmission(); Wire.beginTransmission(RtcADR); Wire.write(0x0e); // タイマースタート Wire.write(0x82); // TEビットon, カウンタソースクロックは1秒を設定 Wire.endTransmission(); } void sensData () { Wire.beginTransmission(addresPsensor); Wire.write(0x12); // Start both conversions(Pressure and Temperature) Wire.write(0x01); Wire.endTransmission(); delay(5); Wire.beginTransmission(addresPsensor); Wire.write((uint8_t)0x00); // Read pressure and temperature Wire.endTransmission(); Wire.requestFrom(addresPsensor, 4); // Request 4 bytes if(Wire.available()) { Padc = read_adc(); Tadc = read_adc(); int signedTadc = Tadc; // float Pcomp = a0 + (b1 + c11 * Padc + c12 * Tadc) * Padc + (b2 + c22 * Tadc) * Tadc; // 22976 float Pcomp = a0 + (b1 + c12 * Tadc) * Padc + (b2 * Tadc); // c11 とc22はゼロなので計算省略(84バイト節約) Pha = Pcomp * 650 / 1023 + 500; Temp = 25 - (signedTadc - 472) / 5.35; } delay(1); } float read_coefficients(int total_bits, int fractional_bits, int zero_pad) { unsigned char msb, lsb; // unsigned int msb,lsb; msb = Wire.read(); lsb = Wire.read(); Serial.print("mbs = "); Serial.print(msb); Serial.print(", lsb = "); Serial.println(lsb); return ((float) ((msb << 8) + lsb) / ((long)1 << (16 - total_bits + fractional_bits + zero_pad))); } unsigned int read_adc() { unsigned char msb, lsb; msb = Wire.read(); lsb = Wire.read(); return (((unsigned int)msb << 8) + lsb) >> 6; }