[Arduinoのすすめ][ArduinoConf][ArduinoMonitor][iArduino]

温湿度・気圧計を作ってみる(LPS331AP + SHT11 + I2C LCD)

気圧センサLPS331APと 温湿度センサSHT11I2C液晶を組み合わせて、液晶表示の温湿度・気圧計を作ってみます。 電源は気圧センサに合わせて3.3[V]にし、3.3[V]動作のArduinoを使います。

回路図

気圧センサと液晶がI2C接続なのでピンを共有します。バスにつけるプルアップ抵抗も共通になります。Arduinoは必ず3.3[V]動作のものを使います。回路図はストロベリーリナックスのモジュールに合わせています。他社のものを使う場合は読み替えてください。

スケッチ

スケッチは235行ありますが、 のスケッチをほぼ組み合わせただけになっているのが分かると思います。 「ストロベリー・リナックス/秋月電子の低電圧I2C液晶を使う」のライブラリが必要です。
// include the library code:
#include <I2CLiquidCrystal.h>
#include <Wire.h>

// --------------------- LPS331AP -------------------------
const byte LPS331AP_ADDR = B1011100;  // SA0 = GND
//const byte LPS331AP_ADDR = B1011101;// SA0 = VDD_IO

const byte LPS331AP_WHOAMI = 0x0f;
const byte LPS331AP_CTRL1 = 0x20;
const byte LPS331AP_CTRL2 = 0x21;
const byte LPS331AP_CTRL3 = 0x22;
const byte LPS331AP_P_LL = 0x28;
const byte LPS331AP_P_L  = 0x29;
const byte LPS331AP_P_H  = 0x2A;
const byte LPS331AP_T_L  = 0x2B;
const byte LPS331AP_T_H  = 0x2C;

// --------------------- SHT1X -------------------------
const int SHT_SCK = 2;
const int SHT_DAT = 3;

const byte SHT_MeasureTemperature  = B00011;
const byte SHT_MeasureHumidity     = B00101;
const byte SHT_ReadStatusRegistor  = B00111;
const byte SHT_WriteStatusRegistor = B00110;
const byte SHT_SoftReset           = B11110;

struct SHT_result {
  unsigned short res;
  byte crc;
  byte err;
};

inline void SHT_clk()
{
  digitalWrite(SHT_SCK, HIGH);
  digitalWrite(SHT_SCK, LOW);
}


// ----------------------- I2CLCD ----------------------------
// initialize the library
// uncomment next line if you are using a LCD from Straberry Linux
I2CLiquidCrystal lcd(40, false);
                  //  |    +--- set true if the power suply is 5V, false if it is 3.3V
                  //  +-------- contrast (0-63)
// uncomment next line if you are using a LCD from Akizuki denshi
// I2CLiquidCrystal lcd;

// ---------------------- setup function --------------------
void setup() {
  digitalWrite(SHT_SCK, LOW);
  digitalWrite(SHT_DAT, HIGH); // pull-up  
  pinMode(SHT_SCK, OUTPUT);
  pinMode(SHT_DAT, INPUT);

  Serial.begin(9600);
  while (!Serial) {}

  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  LPS331AP_write(LPS331AP_CTRL1, B10010000);
                             //   |||||||+ SPI Mode selection
                             //   ||||||+- DELTA_EN
                             //   |||||+-- BDU: block data update
                             //   ||||+--- DIFF_EN: interrupt circuit enable
                             //   |+++---- ODR2, ODR1, ODR0 (1Hz)
                             //   +------- PD: 0: power down, 1: active
}

// ---------------------- loop function --------------------
void loop() {
  // -------------- SHT11 ------------------
  struct SHT_result ret;
  float h, t1;
  
  ret = SHT_read(SHT_MeasureHumidity);
  h = -4.0 + 0.0405*ret.res -2.8*0.000001*ret.res*ret.res;

  ret = SHT_read(SHT_MeasureTemperature);
  t1 = -40.00 + 0.01*ret.res;

// ------------- LPS331AP -----------------
  long P;
  short T;
  float p, t2;

  P = LPS331AP_read(LPS331AP_P_H);
  P = (P << 8) | LPS331AP_read(LPS331AP_P_L);
  p = P = (P << 8) | LPS331AP_read(LPS331AP_P_LL);
  p = p/4096.0;

  T = LPS331AP_read(LPS331AP_T_H);
  t2 = T = (T << 8) | LPS331AP_read(LPS331AP_T_L);
  t2 = 42.5 + t2/480.0;

// Output to serial  
  Serial.print(h);
  Serial.print(" % ");
  Serial.print(t1);
  Serial.print(" C ");

  Serial.print(p);  // pressure in [mbar]/[hPa]
  Serial.print(" hPa ");
  Serial.print(t2);  // temprerature in [`C]
  Serial.println(" C");

// Print to LCD
  lcd.setCursor(0, 0);
  lcd.print(h);
  lcd.print("% ");
  lcd.print(t1);
  lcd.print("C");

  lcd.setCursor(0, 1);
  lcd.print(p);
  lcd.print("hPa ");
  lcd.print(t2);
  lcd.print("C");
  
  delay(5000);
}

// --------------------- LPS331AP -------------------------
void LPS331AP_write(byte reg, byte val)
{
  Wire.beginTransmission(LPS331AP_ADDR);
  Wire.write(reg);
  Wire.write(val);
  Wire.endTransmission();  
}

byte LPS331AP_read(byte reg)
{
  byte ret = 0;
  // request the registor
  Wire.beginTransmission(LPS331AP_ADDR);
  Wire.write(reg);
  Wire.endTransmission();  

  // read
  Wire.requestFrom((unsigned int)LPS331AP_ADDR, 1);
  
  while (Wire.available()) {
    ret = Wire.read();
  }
  
  return ret;
}

// --------------------- SHT1X ----------------------------
struct SHT_result SHT_read(byte cmd)
{
  struct SHT_result ret;
  
  ret.err = 0;
  digitalWrite(SHT_DAT, HIGH);
  pinMode(SHT_DAT, OUTPUT);

  // send START
  digitalWrite(SHT_SCK, HIGH);
  digitalWrite(SHT_DAT, LOW);
  digitalWrite(SHT_SCK, LOW);
  digitalWrite(SHT_SCK, HIGH);
  digitalWrite(SHT_DAT, HIGH);
  digitalWrite(SHT_SCK, LOW);
 
  // send address = 000
  digitalWrite(SHT_DAT, LOW);
  SHT_clk();
  SHT_clk();
  SHT_clk();

  for (int i=0; i<5; i++) {
    if ((cmd & B10000) != 0)
      digitalWrite(SHT_DAT, HIGH);
    else
      digitalWrite(SHT_DAT, LOW);
    SHT_clk();
    cmd <<= 1;
  }
  pinMode(SHT_DAT, INPUT);
  digitalWrite(SHT_DAT, HIGH);
  // wait for ACK
  unsigned long cur = millis();
  while (digitalRead(SHT_DAT) == HIGH) {
    if ((millis()-cur)>1000) {
      ret.err = 1;
      return ret;
    }
  }
  // send clk
  SHT_clk();
  
  // wait for data to come
  cur = millis();
  while (digitalRead(SHT_DAT) == HIGH) {
      if ((millis()-cur)>1000) {
      ret.err = 1;
      return ret;
    }
  }

  ret.res = 0;
  for (int j=0; j<2; j++) {
    for (int i=0; i<8; i++) {
      ret.res <<= 1;
      if (digitalRead(SHT_DAT) == HIGH)
        ret.res |= 1;
      SHT_clk();
    }
    // Send ACK
    pinMode(SHT_DAT, OUTPUT);
    digitalWrite(SHT_DAT, LOW);
    SHT_clk();
    pinMode(SHT_DAT, INPUT);
    digitalWrite(SHT_DAT, HIGH);
  }

  ret.crc = 0;
  for (int i=0; i<8; i++) {
    ret.crc <<= 1;
    if (digitalRead(SHT_DAT) == HIGH)
      ret.crc |= 1;
    SHT_clk();
  }
  // Skip ACK
  SHT_clk();
  
  // CRC をチェックした方がいい
  
  return ret;
}

ダウンロード

上記のスケッチです


Arduinoのすすめ
Copyright (c) 2013, Noriaki Mitsunaga