PICで温湿度、大気圧計

2016年9月26日

以前似たようなものを何度か作っていますが、いまいち中途半端だったので、作り直しました。

温湿度測定ICと、大気圧測定IC(気温もとれる)を買いました。秋月電子です。「AE-HDC1000」、「AE-LPS25H」。このICはI2Cですが、コマンド的には Raspbeyy Piでも使えると思います。SCL,SDAを繋ぎ変えるだけです。

温湿度計の温度と、大気圧計の温度で、常に1.5℃違います。多分温湿度計の方があっていると思います。大気圧計は基板の温度で上がっているのかもしれません。

USBまで付けていますが、気が向いたら使ってみようかと。現状では電源にしか使っていません。

クリスタルが付いていないので、FRCでUSBを使わないと動きません。

・表示上段が温湿度計の値。下段が大気圧計の値。

CIMG1131

 

799e0d19ae3c90083fa1d0d878f4a7cb

・いつものシリアル通信回路です。

bfd63dc16b777790cea869dc462f9116

 

 

今回はまじめにシリアル通信プログラムも作りました。計測器はキャラクタLCDをとってもいいし、見えない場所においても大丈夫になりました。

この液晶はこちら

CIMG1134

 

・今回は珍しくプログラムも載せてみます。何をしているのかが分かるだけですが。このままでは全く動きません。

コメントは適当なのですが、大体わかるでしょう。Raspberry Piでもこの手順でおkです。

・HDC1000

四捨五入間違えてね?(プログラムを書き換えて書き込んで確認するのが面倒なので、メモとしてわざわざ残します。

#include "HardwareProfile.h"
#include "GenericTypeDefs.h"
#include "register.h"
#include "I2C.h"
#include "HDC1000.h"
#include "lib.h"

// ----------------------------------------------------------------------------
//
//
bool InitializeHDC1000(int Module)
{
    // Configuration
//    I2C_WriteData(Module, I2C_ADDRESS_HDC1000, 2, 0x00, 0x90);
    int16_t dummy = 0;
    
    WriteRegister(REGISTER_TEMP1, &dummy, 1);
    WriteRegister(REGISTER_HUM,   &dummy, 1);
    
    I2C_Start(Module);
    
    // config
    if(!I2C_Write(Module, (I2C_ADDRESS_HDC1000 << 1) | I2C_WRITE)) {
        I2C_BussReset(Module);
        return FALSE;
    }    
    
    if(!I2C_Write(Module, 0x02)) {
        I2C_BussReset(Module);
        return FALSE;
    }    
    
    // reset, mode 1
//    if(!I2C_Write(Module, 0x90)) {
    // mode 1
    if(!I2C_Write(Module, 0x10)) {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    I2C_Stop(Module);
    
    // サンプリング 開始
    I2C_Start(Module);
    
    if(!I2C_Write(Module, (I2C_ADDRESS_HDC1000 << 1) | I2C_WRITE)) {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    if(!I2C_Write(Module, 0x00)) {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    I2C_Stop(Module);
    
//    delayCT1m(20);          // 14m以上
}

// ----------------------------------------------------------------------------
//
//
BOOL HDC1000_SetRegisterHumidityTemp(int Module)
{
    unsigned char data;
    unsigned short temp, humidity;
    float a, b;

    // 測定データ読み出し。変換開始から14msec以上
    I2C_Start(Module);
    
    if(!I2C_Write(Module, (I2C_ADDRESS_HDC1000 << 1) | I2C_READ)) {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    if(I2C_Read(Module, &data)) {
        I2C_SendACK(Module);
        temp = (unsigned short)data << 8;
    }
    else {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    if(I2C_Read(Module, &data)) {
        I2C_SendACK(Module);
        temp |= data;
    }
    else {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    if(I2C_Read(Module, &data)) {
        I2C_SendACK(Module);
        humidity = (unsigned short)data << 8;
    }
    else {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    if(I2C_Read(Module, &data)) {
        I2C_SendNACK(Module);
        humidity |= data;
    }
    else {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    I2C_Stop(Module);
    
    a = ((float)temp / 0x10000) * 165.0 - 40.0;
    b = ((float)humidity / 0x10000) * 100.0;
    
    temp = (short)(a * 10.0 + 0.05);
    humidity = (short)(b * 10.0 + 0.05);
    
    WriteRegister(REGISTER_TEMP1, &temp,     1);
    WriteRegister(REGISTER_HUM  , &humidity, 1);
    
    // サンプリング 開始
    I2C_Start(Module);
    
    if(!I2C_Write(Module, (I2C_ADDRESS_HDC1000 << 1) | I2C_WRITE)) {
        I2C_BussReset(Module);
        return FALSE;
    }
            
    if(!I2C_Write(Module, 0x00)) {
        I2C_BussReset(Module);
        return FALSE;
    }
            
    I2C_Stop(Module);
    
    return TRUE;
}

変換時間14msecですが、そんなに高速でとっても意味はないので、測定値を読み取ったらOne shotで変換開始しておきます。1秒に1回読み取っているので、waitも必要なくこれがいいかと。

 

・LPS25H

Repeat startを使っています。

long pressure; shortじゃね?リトルエンディアンだからたまたま動いてる?

#include <xc.h>
#include "HardwareProfile.h"
#include <GenericTypeDefs.h>
#include "lib.h"
#include "register.h"
#include "I2C.h"
#include "LPS25H.h"

// ----------------------------------------------------------------------------
//
//
bool InitializeLPS25H(int Module)
{
    int16_t dummy = 0;
    
    I2C_Start(Module);
    
    if(!I2C_Write(Module, (I2C_LPS25H_ADDRESS_SDO_GND << 1) | I2C_WRITE)) {
        I2C_BussReset(Module);
        return FALSE;
    }    
    
    if(!I2C_Write(Module, LPS25H_REGISTER_CTRL_REG1)) {
        I2C_BussReset(Module);
        return FALSE;
    }    
    

//    if(!I2C_Write(Module, 0x90)) {    // Power on, 1Hz
    if(!I2C_Write(Module, 0x80)) {    // Power on, One shot
        I2C_BussReset(Module);
        return FALSE;
    }    
    
    I2C_Stop(Module);
    
    I2C_Start(Module);
    
    // Oen shot
    if(!I2C_Write(Module, (I2C_LPS25H_ADDRESS_SDO_GND << 1) | I2C_WRITE)) {
        I2C_BussReset(Module);
        return FALSE;
    }    
    
    if(!I2C_Write(Module, LPS25H_REGISTER_CTRL_REG2)) {
        I2C_BussReset(Module);
        return FALSE;
    }    

    if(!I2C_Write(Module, 0x01)) {
        I2C_BussReset(Module);
        return FALSE;
    }    
    
    I2C_Stop(Module);
    
    WriteRegister(REGISTER_TEMP2,    &dummy, 1);
    WriteRegister(REGISTER_PRESSURE, &dummy, 1);
}


// ----------------------------------------------------------------------------
//
//
BOOL LPS25H_SetRegisterPressureTemp(int Module)
{
    unsigned char data;
    unsigned char status;
    short temp;
    long pressure;
    float a, b;
    
    // 変換データサンプリング 
    I2C_Start(Module);
    
    // データ連続読み出し
    if(!I2C_Write(Module, (I2C_LPS25H_ADDRESS_SDO_GND << 1) | I2C_WRITE)) {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    // 連続は 0x80 を付ける
    if(!I2C_Write(Module, LPS25H_REGISTER_READ_TOP | 0x80)) {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    // Repeat start
    if(!I2C_RepeatStart(Module)) {
        I2C_BussReset(Module);
        return FALSE;
    }
//    I2C_Start(Module);
    
    if(!I2C_Write(Module, (I2C_LPS25H_ADDRESS_SDO_GND << 1) | I2C_READ)) {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    if(I2C_Read(Module, &data)) {
        I2C_SendACK(Module);
        status = data;
    }
    else {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    // 圧力読み出し
    if(I2C_Read(Module, &data)) {
        I2C_SendACK(Module);
        pressure = data;
    }
    else {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    if(I2C_Read(Module, &data)) {
        I2C_SendACK(Module);
        pressure |= (long)data << 8;
    }
    else {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    if(I2C_Read(Module, &data)) {
        I2C_SendACK(Module);
        pressure |= (long)data << 16;
    }
    else {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    // 温度読み出し
    if(I2C_Read(Module, &data)) {
        I2C_SendACK(Module);
        temp = data;
    }
    else {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    if(I2C_Read(Module, &data)) {
        I2C_SendNACK(Module);
        temp |= (short)data << 8;
    }
    else {
        I2C_BussReset(Module);
        return FALSE;
    }
    
    I2C_Stop(Module);
    
    a = pressure / 4096.0;
    b = 42.5 + (temp / 480.0);
//    b = 42.5 + (0 / 480.0);
    
    pressure = (short)(a * 10.0 + 0.05);
    temp = (short)(b * 10.0 + 0.05);
    
    WriteRegister(REGISTER_TEMP2,    &temp,     1);
    WriteRegister(REGISTER_PRESSURE, &pressure, 1);
    
    // 次の読み込み用にA/Dしておく
//    delayCT1m(1);
    
    I2C_Start(Module);
    
    // Oen shot
    if(!I2C_Write(Module, (I2C_LPS25H_ADDRESS_SDO_GND << 1) | I2C_WRITE)) {
        I2C_BussReset(Module);
        return FALSE;
    }    
    
    if(!I2C_Write(Module, LPS25H_REGISTER_CTRL_REG2)) {
        I2C_BussReset(Module);
        return FALSE;
    }    
    
    if(!I2C_Write(Module, 0x01)) {
        I2C_BussReset(Module);
        return FALSE;
    }    
    
    I2C_Stop(Module);

    return TRUE;
}

連続読み出しにはレジスタアドレスに | 0x80を付けます。