激安マイコン基板で温度・湿度センサーの値を読み取ってみた

ストロベリーリナックスで購入できるMSP430 LaunchPadと中国製らしい温度・湿度センサーDHT22を使ってみた。


DHT22からセンサーの値を読み取るには1本の信号だけを使って行う。この1本線のプロトコルは、モールス信号みたいに信号のHigh期間の長さで0/1を表現するので、カウンタで長さを数えてやればいい。

開発環境のデバッガを走らせてみると、確かにデータを受信できている。(MSP430のスピードが遅いためか、for文で回すとうまく受信できなかったのでベタ書きするようにした)

一度に受信するデータは5バイトで、上から順に

  1. 湿度のHigh Byte
  2. 湿度のLow Byte
  3. 温度のHigh Byte
  4. 温度のLow Byte
  5. CheckSum(1〜4を足した値)

となっている。

ちなみに、このときの湿度と温度は、

  • 湿度=0x01CE=462=46.2%
  • 温度=0x00DE=222=22.2℃

というそれっぽい値だった。
もちろんCheckSumもOK。

//******************************************************************************
//  MSP430x2xx Demo - Software Toggle P1.0
//
//  Description; Toggle P1.0 by xor'ing P1.0 inside of a software loop.
//  ACLK = n/a, MCLK = SMCLK = default DCO
//
//                MSP430x2xx
//             -----------------
//         /|\|              XIN|-
//          | |                 |
//          --|RST          XOUT|-
//            |                 |
//            |             P1.0|-->LED
//
//  A. Dannenberg
//  Texas Instruments, Inc
//  January 2006
//  Built with IAR Embedded Workbench Version: 3.40A
//******************************************************************************

#include "msp430.h"

int main(void)
{
  volatile unsigned char data[5];
  volatile unsigned char sum;
  volatile unsigned int i;
  char cnt0, cnt1;
  
  WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer
  P1DIR = 0x01;                        // Set P1.0 to output direction
                                        // 0: input, 1: output
  P1OUT = 0x00;
  
  for (;;)
  {
    // output start signal to P1.4
    P1DIR |= 0x10;
    
    // delay
    i = 1000;
    do { i--; } while (i != 0);
    
    P1DIR &= ~0x10;
    
    while ((P1IN & 0x10) != 0); // wait DHT response
    while ((P1IN & 0x10) == 0); // response
    while ((P1IN & 0x10) != 0); // sense
    
#define RECV(d)                                    \
        cnt0 = 0;                                  \
        do { cnt0++; } while ((P1IN & 0x10) == 0); \
        cnt1 = 0;                                  \
        do { cnt1++; } while ((P1IN & 0x10) != 0); \
        data[d] = data[d] << 1;                    \
        if (cnt0 < cnt1) {                         \
          data[d] += 1;                            \
        }

    // 1st byte
    RECV(0);
    RECV(0);
    RECV(0);
    RECV(0);
    RECV(0);
    RECV(0);
    RECV(0);
    RECV(0);
    
    // 2nd byte
    RECV(1);
    RECV(1);
    RECV(1);
    RECV(1);
    RECV(1);
    RECV(1);
    RECV(1);
    RECV(1);
    
    // 3rd byte
    RECV(2);
    RECV(2);
    RECV(2);
    RECV(2);
    RECV(2);
    RECV(2);
    RECV(2);
    RECV(2);
    
    // 4th byte
    RECV(3);
    RECV(3);
    RECV(3);
    RECV(3);
    RECV(3);
    RECV(3);
    RECV(3);
    RECV(3);
    
    // 5th byte
    RECV(4);
    RECV(4);
    RECV(4);
    RECV(4);
    RECV(4);
    RECV(4);
    RECV(4);
    RECV(4);
    
    // checksum
    sum = 0;
    sum += data[0];
    sum += data[1];
    sum += data[2];
    sum += data[3];
    
    // compare
    if (sum == data[4])
      P1OUT |=  0x01; // OK
    else
      P1OUT &= ~0x00; // NG
  }
}