2016年5月3日火曜日

HDC1000と7Seg LEDを使って温度湿度を測定

小ネタ実験です。実用性はほとんどなさそうですがArduinoで実験してみました。

回路図(7Seg LED)

aitendoの福袋に入っていた7Segx4のLEDを使ってみた。カソード・コモンでアノード側はABCDEFGの7セグメント+ドット(P)の8本。カソードは4桁分の4本。

アノード側に電流制限抵抗(R1~R8)を入れた。抵抗値は220Ω。カソードは直接Arduinoのピンにつないでsinkさせると電流が大きすぎるのでQ1~Q4のNch MOSFET(手持ちの2N7000)でスイッチングさせた。

NPNトランジスタでもスイッチングできるが、ベース電流を制限する抵抗が必要になる。

7Segx4のLEDのピン配列

なんとも複雑なピン配置。

ブレッドボード図

上側のブレッドボードが7Seg LEDで下側のブレッドボードがHDC1000。


7Segの方はたった4桁の数値を表示させるだけなのにそこそこ複雑な配線になった。

HDC1000の方はI2C接続でプルアップ抵抗も基板上に載っているのでシンプルだ。SCL、SDAはArduinoのハードウェアI2C用のA0、A1 A4、A5ピン、RDYもA2 A3に接続。

Arduinoのスケッチ


7Segの表示にはSevSegライブラリを使用。デフォルトで4桁の7 Seg LEDに対応していてほとんどそのまま使えた。

コモン・カソードのLEDでカソードをNch MOSFETでスイッチングしているので、
void begin(byte hardwareConfig, byte numDigitsIn, byte digitPinsIn[], byte segmentPinsIn[]);
のhardwareConfigパラメーターに「NP_COMMMON_CATHODE」を指定した。

HDC1000の制御はgarretlabさんのスケッチを使わせていただいた。

動作としては温度と湿度を交互に表示するようにした。

/*
  HDC1000で温度/湿度を読み取り7Seg4桁のLEDに表示
  
  2016.05.03
*/
#include <Wire.h>  
#include "SevSeg.h"

// HDC1000
#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 */

// SevSeg
SevSeg sevseg; //Instantiate a seven segment controller object

#define DISPLAY_TEMPERATURE  0
#define DISPLAY_HUMIDITY    1
int displayMode;

void setup() {
  byte numDigits = 4;   
  byte digitPins[] = {2, 3, 4, 5};
  byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};

  sevseg.begin(N_TRANSISTORS, numDigits, digitPins, segmentPins);
  sevseg.setBrightness(90);
  
  Wire.begin();
  pinMode(HDC1000_RDY_PIN, INPUT);
 
  delay(15); /* Wait for 15ms */
  configure();
}

void loop() {
  static int cnt = 100;
  float temperature, humidity;

  cnt++;
  if (cnt > 100) {
    cnt = 0;
    getTemperatureAndHumidity(&temperature, &humidity);
    if (displayMode == DISPLAY_TEMPERATURE) {
      sevseg.setNumber(temperature, 2);
      displayMode = DISPLAY_HUMIDITY;
    } else {
      sevseg.setNumber(humidity, 2);
      displayMode = DISPLAY_TEMPERATURE;
    }
  }
    
  sevseg.refreshDisplay(); // Must run repeatedly
}

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;
}
/// END ///

メモ:

ダイナミック表示という、各桁を順番に表示させて残像で全桁が表示されているように見せかける方法で表示している。数値を変更して書き換える頻度が高いとかなりちらつく。(0.1ms程度)

LEDの表示だけでArduinoのD2~D13とデジタルピンをほとんど使ってしまう。

配線めんどくさくてLEDは消費電流も大きいので使いどころがあるかどうか。