micro:bit / mbed / 温湿度センサーAM2302 (DHT22) / 1回だけ測定する

f:id:ti-nspire:20181115031031p:plain
f:id:ti-nspire:20181114082116p:plain

#include "MicroBit.h"
MicroBit uBit;

//MicroBitPin P0 = uBit.io.pin[0];
MicroBitPin P0 = uBit.io.P0; // P0端子に信号ラインを接続する。

// 40要素の配列からバイトデータとして抜き出すための函数。
uint8_t getByte(uint8_t buf[], uint8_t pos){ // (どの配列の、何バイト目)を抜き出す。
    uint8_t Pos = (8*pos)-7;
    uint8_t sute = 0;
    for(int i=Pos ; i<(Pos+8); i++){
        sute |= buf[i] << (Pos+7-i);
    }
    return sute;
}

int main(void){
    uBit.init();
    
    // スタートシーケンスを開始する。 
    P0.setDigitalValue(1);// P0を一旦Hにしてから、
    P0.setDigitalValue(0);// P0をLにして、
    uBit.sleep(1);        // Lの状態を0.8~20ミリ秒間保ってから、
    P0.getDigitalValue(); // P0のIOをINに(Hi-Zに)切り替えて(バスはプルアップされているのでこのときHになる)、
    while(P0.getDigitalValue() == 1){;} // センサー側がバスをLにするのを待つ。
    
    // スタートビットも含めて全部で41ビットの1/0をパルス幅(ループ回数)から判定する。
    uint8_t buf[41];
    uint8_t threshold;
    for(int j=0; j<41; j++){
        while(P0.getDigitalValue()==0){;} // バスがHになるのを待って、Hになったら、
        
        int counter;
        for(counter=1; counter<50; counter++){  // カウントを始めて、
            if(P0.getDigitalValue()==0){break;} // Lになったらカウントをやめて、
        }
        if(j==0){threshold=counter/2;}          // スタートビットのパルス幅の半分の長さを1/0判定の閾値として、
        buf[j] = (counter > threshold) ? 1 : 0; // ループ回数から1か0かを判定する。
    }

    // スタートビットを除く40要素の値を5つのバイトデータに変換する。
    /*
    uint8_t humidHigh = buf[1] <<7|buf[2] <<6|buf[3] <<5|buf[4] <<4|buf[5] <<3|buf[6] <<2|buf[7] <<1|buf[8];
    uint8_t humidLow  = buf[9] <<7|buf[10]<<6|buf[11]<<5|buf[12]<<4|buf[13]<<3|buf[14]<<2|buf[15]<<1|buf[16];
    uint8_t tempHigh  = buf[17]<<7|buf[18]<<6|buf[19]<<5|buf[20]<<4|buf[21]<<3|buf[22]<<2|buf[23]<<1|buf[24];
    uint8_t tempLow   = buf[25]<<7|buf[26]<<6|buf[27]<<5|buf[28]<<4|buf[29]<<3|buf[30]<<2|buf[31]<<1|buf[32];
    uint8_t parity    = buf[33]<<7|buf[34]<<6|buf[35]<<5|buf[36]<<4|buf[37]<<3|buf[38]<<2|buf[39]<<1|buf[40];
    */
    uint8_t bytes[5];
    for(int i=0; i<5; i++){
        bytes[i] = getByte(buf, i+1);
    }
    uint8_t humidHigh = bytes[0];
    uint8_t humidLow  = bytes[1];
    uint8_t tempHigh  = bytes[2];
    uint8_t tempLow   = bytes[3];
    uint8_t parity    = bytes[4];
    
    // 湿度を計算する。2つの8ビットデータを16ビットに並べ替えて10で割る。
    float humid = (float)((humidHigh<<8) | humidLow) / 10.0f;
        
    // 温度を計算する。湿度と同じく2つの8ビットデータを16ビットに並べ替えて10で割ればよいが、
    uint16_t tempTemp = (tempHigh<<8) | tempLow;
    if(tempHigh & 0x80){                 // 最上位ビットに1が立っていたら氷点下なので、
        tempTemp = -(tempTemp & 0x7fff); // 符号ビットを消してから符号を反転して、
    }
    float temp = (float)tempTemp / 10.0f; // 10で割る。
        
    // パリティバイトと比較するための値を計算しておく。
    uint8_t paritySum = (humidHigh + humidLow + tempHigh + tempLow) & 0xff;
    
    printf("相対湿度: %0.1f%%\n", humid);
    printf("温度: %0.1f\n", temp);
    printf("パリティバイト: %d, データ4バイトの和: %d\n", parity, paritySum);
    
    release_fiber();
    return 0;
}