/* LPS331APを使った気圧/高度計 ラジオペンチ 2014/2/11 http://radiopench.blog96.fc2.com/ */ #include #include LiquidCrystal lcd(12,11,5,4,3,2); // 標準のピンアサイン(液晶シールド用) float hPa, temp, alt; float hPaData[10]; // 移動平均計算用配列 float tempData[10]; // int lps331_I2C_adr = 0x5d; // SDO=HIGH:0x5D intにしないとなぜかエラーになる int avCount=0; // 移動平均のデータ数カウンタ void setup(){ pinMode(13, OUTPUT); Wire.begin(); Serial.begin(9600); lcd.begin(16,2); defGaiji(); // 液晶の外字を定義 if(LPS331read(0x0F) != 0xBB){ // 気圧センサーとの通信を確認 lcd.print("LPS331 not found"); for(;;){ } } LPS331setup(); // 気圧センサーの初期設定 Serial.println("Press(hPa), Temp(degC), Alutitude(m)"); // ログデータの列名 delay(100); } void loop(){ hPa = 0.0; temp = 0.0; for(int i=1; i <= 10; i++){ // 10回 LPS331exec(); // 測定開始処理 hPa = hPa + LPS331press(); // 気圧読み取り、累積 temp = temp + LPS331temp(); // 気温読み取り、累積 } hPa = hPa / 10.0; // 平均を求める temp = temp / 10.0; // 移動平均処理 for(int i=9; i >= 1; i--){ // 移動平均計算用にデータを配列に記録 hPaData[i] = hPaData[i-1]; // 配列の値を後ろにずらす tempData[i] = tempData[i-1]; } hPaData[0]=hPa; // 配列の先頭に最新値を入力 tempData[0]=temp; avCount++; if(avCount >= 10){ // 開始時の値の乱れ防止 avCount =10; } hPa=0.0; temp=0.0; for(int i=0; i <= 9; i++){ // 配列の合計を求める(floatなので全部再計算) hPa= hPa + hPaData[i]; temp = temp + tempData[i]; } hPa = (float) hPa/avCount; // 移動平均値を求める temp =(float) temp/avCount; // 標高計算 alt = 153.8 * (temp + 273.2) * (1.0 - pow(hPa / 1013.25, 0.1902)); digitalWrite(13, HIGH); // 動作表示用にLED ON disp(); // 各種表示 digitalWrite(13, LOW); // LED OFF delay(10); } // loop void disp(){ // 表示 Serial.print(hPa,3); // シリアルへ測定結果を流す Serial.print(", "); Serial.print(temp,3); Serial.print(", "); Serial.println(alt,3); lcd.setCursor(0,0); // 液晶へ表示 lcd.print(temp,1); lcd.write(0x02); // 外字で℃表示 lcd.print(" "); lcd.print(alt,2); lcd.print("m "); lcd.setCursor(0,1); if(hPa < 1000.0){ lcd.print(" "); } lcd.print(hPa,2); lcd.write(0x01); // 外字でhPa表示 lcd.print(" "); // ゴミ消し } void LPS331setup(){ // センサーの初期設定 byte x; x = LPS331read(0x20); x = x & 0x7F; // PDビットクリア LPS331write(0x20, x); LPS331write(0x10, 0x7A); // アベレージング回数設定:気圧512回、温度128回 // LPS331write(0x10, 0x00); // アベレージング回数設定:気圧1回、温度1回 LPS331write(0x20, 0x04); // ワンショット、BDU有効、 LPS331write(0x20, 0x84); // PDビットON(パワーON) delay(2); // 動作開始まで待つ } void LPS331exec(){ // 気圧測定を開始しデータが確定するまで待つ byte x; x = LPS331read(0x21); // 制御レジスタの x = x | 0x01; // ONE_SHOTビットONにして LPS331write(0x21, x); // 変換スタート while((LPS331read(0x27) & 0x03) != 0x03){ // 測定完了まで待つ } } float LPS331press(){ // 気圧データーを読んでhPaを返す long x; // データーは24ビット x = LPS331read(0x2A); // MSB x = LPS331read(0x29) | (x << 8); x = LPS331read(0x28) | (x << 8); // LSB return (float) x / 4096.0; } float LPS331temp(){ // 温度データーを呼んで℃の値を返す int x; // データーは符号付16ビット x = LPS331read(0x2C); // MSB x = LPS331read(0x2B) | (x << 8); // LSB return (float)(x / 480.0) + 42.5; } void LPS331write(byte adr, byte data){ // LPS331の指定アドレスに書き込み Wire.beginTransmission(lps331_I2C_adr); Wire.write(adr); Wire.write(data); Wire.endTransmission(); } byte LPS331read(byte adr){ // LPS331の指定アドレスを読み出し Wire.beginTransmission(lps331_I2C_adr); Wire.write(adr); Wire.endTransmission(); Wire.requestFrom(lps331_I2C_adr, 1); // 1バイトだけ読む return Wire.read(); } // 液晶の外字設定 void defGaiji(){ byte hPascal[8] = { // hPa B10000, B10000, B11100, B10111, B10101, B00111, B00100, }; lcd.createChar(1, hPascal); byte degC[8] = { // ℃ B11000, B11000, B00110, B01001, B01000, B01001, B00110, }; lcd.createChar(2, degC); }