ブレッドボード図
Arduinoのスケッチ
HDC1000_Thermometer.ino
/* * HDC100_Thermometer * * 2017.02.26 * * LCD5110_Basic Library: http://www.rinkydinkelectronics.com/library.php?id=44 * */ #include <Wire.h> #include <LCD5110_Basic.h> #include <avr/sleep.h> #include <avr/interrupt.h> #define HDC1000_ADDRESS 0x40 /* or 0b1000000 */ #define HDC1000_RDY_PIN A3 /* Data Ready Pin */ #define HDC1000_TEMPERATURE_POINTER 0x00 #define HDC1000_HUMIDITY_POINTER 0x01 #define HDC1000_CONFIGURATION_POINTER 0x02 #define HDC1000_SERIAL_ID1_POINTER 0xfb #define HDC1000_SERIAL_ID2_POINTER 0xfc #define HDC1000_SERIAL_ID3_POINTER 0xfd #define HDC1000_MANUFACTURER_ID_POINTER 0xfe #define HDC1000_CONFIGURE_MSB 0x10 /* Get both temperature and humidity */ #define HDC1000_CONFIGURE_LSB 0x00 /* 14 bit resolution */ #define WAKEUP_PIN 2 #define SLEEP_MODE_PIN 3 #define IO_PWR_PIN 7 #define MEASURE_INTERVAL (1000/2) #define WAKEUP_PERIOD 10 LCD5110 myGLCD(8,9,10,11,12); bool isSleepMode = true; int count; extern uint8_t SmallFont[]; extern uint8_t MediumNumbers[]; extern uint8_t BigNumbers[]; void setup() { // Sleep Mode pinMode(WAKEUP_PIN, INPUT_PULLUP); pinMode(SLEEP_MODE_PIN, INPUT_PULLUP); // I/O Power pinMode(IO_PWR_PIN, OUTPUT); digitalWrite(IO_PWR_PIN, HIGH); // LCD myGLCD.InitLCD(); // HDC1000 Wire.begin(); Wire.setClock(400000); pinMode(HDC1000_RDY_PIN, INPUT); delay(15); /* Wait for 15ms */ configure(); Serial.begin(9600); Serial.print("Manufacturer ID = 0x"); Serial.println(getManufacturerId(), HEX); Serial.println(); } float calcDiscomfort(float temperature, float humidity) { return 0.81 * temperature + 0.01 * humidity * (0.99 * temperature - 14.3) + 46.3; } void loop() { float temperature, humidity, discomfort; getTemperatureAndHumidity(&temperature, &humidity); discomfort = calcDiscomfort(temperature, humidity); Serial.print("Temperature = "); Serial.print(temperature); Serial.print(" degree, Humidity = "); Serial.print(humidity); Serial.print("%, Discomfort = "); Serial.println(discomfort); //myGLCD.clrScr(); myGLCD.setFont(BigNumbers); myGLCD.printNumF(temperature, 1, RIGHT, 0); myGLCD.setFont(MediumNumbers); myGLCD.printNumF(humidity, 1, LEFT, 32); myGLCD.printNumF(discomfort, 0, RIGHT, 32); myGLCD.setFont(SmallFont); if (isSleepMode) { myGLCD.print("SLP", LEFT, 0); } else { myGLCD.print("CON", LEFT, 0); } delay(MEASURE_INTERVAL); // Check Sleep Mode isSleepMode = digitalRead(SLEEP_MODE_PIN); // Sleep if (isSleepMode) { count++; if (count >= WAKEUP_PERIOD) { Serial.println("Sleep mode start!!"); count = 0; sleepAndWakeup(WAKEUP_PIN); } } } //----------------------------------------------------------------------------------------------- // Sleep Mode //----------------------------------------------------------------------------------------------- void wakeup() { Serial.println("Wakeup!!"); } int sleepAndWakeup(int interruptNo) { Serial.println("sleepAndWake Process start!!"); if (digitalRead(WAKEUP_PIN) == LOW) { Serial.println("WAKEUP_PIN Low Level"); } else { Serial.println("WAKEUP_PIN High Level"); } Serial.println("sleep enable"); delay(100); // Sleep myGLCD.enableSleep(); digitalWrite(IO_PWR_PIN, LOW); attachInterrupt(digitalPinToInterrupt(interruptNo), wakeup, FALLING); noInterrupts(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); interrupts(); sleep_cpu(); // Wakeup sleep_disable(); detachInterrupt(digitalPinToInterrupt(interruptNo)); digitalWrite(IO_PWR_PIN, HIGH); myGLCD.disableSleep(); return 0; } //----------------------------------------------------------------------------------------------- // HDC1000 //----------------------------------------------------------------------------------------------- void configure() { Wire.beginTransmission(HDC1000_ADDRESS); Wire.write(HDC1000_CONFIGURATION_POINTER); Wire.write(HDC1000_CONFIGURE_MSB); Wire.write(HDC1000_CONFIGURE_LSB); Wire.endTransmission(); } int getManufacturerId() { int manufacturerId; Wire.beginTransmission(HDC1000_ADDRESS); Wire.write(HDC1000_MANUFACTURER_ID_POINTER); Wire.endTransmission(); Wire.requestFrom(HDC1000_ADDRESS, 2); while (Wire.available() < 2) { ; } manufacturerId = Wire.read() << 8; manufacturerId |= Wire.read(); return manufacturerId; } void getTemperatureAndHumidity(float *temperature, float *humidity) { unsigned int tData, hData; Wire.beginTransmission(HDC1000_ADDRESS); Wire.write(HDC1000_TEMPERATURE_POINTER); Wire.endTransmission(); while (digitalRead(HDC1000_RDY_PIN) == HIGH) { ; } Wire.requestFrom(HDC1000_ADDRESS, 4); while (Wire.available() < 4) { ; } tData = Wire.read() << 8; tData |= Wire.read(); hData = Wire.read() << 8; hData |= Wire.read(); *temperature = tData / 65536.0 * 165.0 - 40.0; *humidity = hData / 65536.0 * 100.0; }
ATMega328P単体で内蔵RC8MHzで動作はできた。1MHzでも動作はするが、LCDの表示が遅い。
電池駆動しようと思うので電源に電流計(テスタ)をつないで消費電流を測定してみた。
内蔵RC8MHz駆動
動作中: 8.4mA
スリープ中: 1.6mA
内蔵RC1MHz駆動
動作中: 6.2mA
スリープ中: 1.5mA
ATMega328PのDATASHEETを見ると、スリープ時はもっと少なくても良さそうな気がする。予想よりかなり多い。スリープ中にHDC1000とLCDにまわしている電源ラインを抜いてもほとんど変わらない。
スイッチをプルアップしている抵抗には通常時は電流が流れないと思うし、I2Cのプルアップもオープンドレインなので無信号時にはほとんど流れないと思う。もうちょっとAVRのDATASHEETをちゃんと読まないとダメかな~?
ボタン電池ではもちろん、700mAh程度ある単4を2本直列にして3V駆動させても、700mAh / 1.6mA ≒ 438hで18日程度しか持たなさそうだ。
めんどくさそうなので当分保留(^q^;
Github:
https://github.com/ryood/HDC1000_Thermometer
0 件のコメント:
コメントを投稿