04.picoで温湿度(SHT30) C言語


04.picoで温湿度(SHT30) C言語

前回使用したセンサーENV2には温湿度センサーICのSHT30も入ってるので今回はその測定プログラムです。配線は前回のままです。
途中からセンサーを手で握っているので値が上がっています。

SHT30の仕様

・I2C通信
・結露対策のためか、ヒーターのon/offが出来ます。

測定精度

2019/06 Ver6のデータシート(Ver3より精度が良くなっています)

相対湿度(±%RH)

・2.0typ(10~90% Ta=0~80℃)
・4.0typ(0~10,90~100% Ta=0~80℃)
・~4.0typ(0~10,90~100%で直線に変化 Ta=25℃)
・4.5max(10~90% Ta=25℃)
・~7.5max(0~10,90~100%で直線に変化 Ta=25℃)

温度(±℃)

・0.4max, 0.2typ(Ta=0~65℃)
・~1.0max,~0.6typ(Ta=-40~0,65~125℃で直線に変化)

ENV2回路図

センサーユニットENV2の回路図より、
https://docs.m5stack.com/en/unit/envII
・Vcc-SCLピン間、Vcc-SDAピン間にそれぞれ4.7kΩが入っていてプルアップしています。
・Vccから電圧レギュレータで3.3Vを作り、2つのICの電源電圧は3.3Vです。
・SHT30のアラート信号pinとリセット信号pinは、openで未使用です。
・I2CアドレスpinはGND接地で0x44固定です。(内部改造で0x45に変更可能)

データーシート

SHT30データシートVer6(英)
https://sensirion.com/media/documents/213E6A3B/61641DC3/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf

SHT30データーシートVer3(日)
https://電子うさぎ.com/wp-content/uploads/2018/11/Sensirion_Humidity_SHT3x_DIS_Datasheet_V3_J.pdf

SHTシリーズ品には、SHT30(湿度精度±2%typ) / SHT31(±2%) / SHT35(±1.5%)があります。

プログラム資料

pico + C言語 + i2cでwebにあった下記記事を参考にしました。
Raspberry Pi Picoでプログラミング10 i2c APIと気圧センサLPS25 (2021/4/13)
https://www.denshi.club/parts/2021/04/raspberry-pi-pico-10-i2c-lps25.html

機能

3.5-アラート信号 p9、3.6-リセット信号 p9、4.10-ヒーター p12 は使用しません。
* 上記数字は、日本語データシートより

モードは4.5-周期モード p10 を選択しました。
・繰返精度=高、1回/2秒の頻度での設定コマンドは "0x2032" の2byte p11
・読出しコマンドは、"0xE000" の2byte p11

コマンドフロー

p11 表10より送受コマンドとデータは、
1.書込み用としてI2Cアドレス1byte(0x44)の他に、測定設定コマンド2byte(0x2032)を送る。
2.呼出し用としてI2Cアドレス1byte(0x44)の他に、温度測定値MSB,LSB,チェックサム、湿度測定値MSB,LSB,チェックサムの計6byteを受取る。
* 1byte=8bit

換算式

測定データは、線形化、温度補償および電源電圧補償済の符号なし16bit整数(下式SRH,ST)で出力されますが、それを温湿度に換算する式 p13 は、
・相対湿度RH(%RH) = 100*SRH/(2^16-1)
 = 100*SRH/65535
 = SRH/655.36
・温度T(℃) = -45+175*ST/(2^16-1)
 = -45+175*ST/65535
 = ST*35/13107-45

プログラム

test.c


// SHT30で温湿度測定 i2c通信 C言語
// Picoでi2c 気圧センサLPS25から修正
//https://www.denshi.club/parts/2021/04/raspberry-pi-pico-10-i2c-lps25.html
#include <stdio.h>            // stdio_init_all使用
#include "hardware/i2c.h"     // I2C使用
#include "pico/binary_info.h" //
#include "pico/stdlib.h"      //
static int sht30_addr = 0x44; // I2Cアドレス 0x44 (改造で0x45)
#define I2C_PORT  i2c0        // i2c0 or i2c1
#define SDA_PIN 4             // SDA GP4(BMP280と同じ)
#define SCL_PIN 5             // SCL GP5

/*  未使用
static void read_registers(uint8_t reg, uint8_t *buf, uint16_t len) {
  i2c_write_blocking(I2C_PORT, sht30_addr, ®, 1, true); 
  i2c_read_blocking(I2C_PORT, sht30_addr, buf, len, false);
}*/
static void write_register(uint8_t reg, uint8_t data) {  // 2byte送信
  uint8_t buf[2]; // 2byte
  buf[0] = reg;   // 下位8bit
  buf[1] = data;  // 上位8bit
  int A = i2c_write_blocking(I2C_PORT, sht30_addr, buf, 2, true); //2バイト書込む
  //printf("%dbyte書込みました。\n",A);
}
int main() {
  uint8_t buf3[3];                         // 3byte受信データ定義
  uint8_t buf6[6];                         // 6byte受信データ定義
  int32_t tmp, hum;                        // 温度と湿度変数定義
  stdio_init_all();                        // 標準stdioを初期化
  sleep_ms(3000);                          // 3秒待つ
  printf("\ni2c%d",i2c_hw_index(I2C_PORT));// I2C_PORT表示
  printf(", SDA = GP%d, SCL = GP%d\n",SDA_PIN,SCL_PIN);//SDA SCLのGP表示
  int f = i2c_init(I2C_PORT, 100 * 1000);//I2C初期化(port,ボーレート(Hz))
  printf("ボーレート = %.1fkHz\n",(float)(f/1000));  // f(Hz)表示
  gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);//GPIO機能選択(GPIO番号,GPIO関数)
  gpio_set_function(SCL_PIN, GPIO_FUNC_I2C);// SCLピンも同様
  gpio_pull_up(SDA_PIN); //プルアップ 未送信時Hにするため 回路に入っているので不要かも
  gpio_pull_up(SCL_PIN);           // SCLピンも同様
  write_register(0xF3, 0x2D);      // 状態読込みコマンド(0xF320) p13 上の関数
  i2c_read_blocking(I2C_PORT, sht30_addr, buf3, 3, false); // 3byte読取る
  int A = buf3[0] << 8 | buf3[1];  // 整数化 buf3[2]はチェックサム
  printf("状態レジスタ = %d (初期値32784)\n",A);  // 表示
  write_register(0x20, 0x32);      // 測定モード設定コマンド p11 上の関数
  // 繰返精度高(低-高) 連続頻度0.5回/秒(0.5-10)で0x2032
  while (1) {                      // 永久ループ
    write_register(0xE0, 0x00);    // データ読出しコマンド(0xF000) 
    i2c_read_blocking(I2C_PORT, sht30_addr, buf6, 6, false);// 6byte読取る
    tmp = buf6[0] << 8 | buf6[1];  // 2byte整数化 buf6[2]はチェックサム
    hum = buf6[3] << 8 | buf6[4];  // 2byte整数化 buf6[5]はチェックサム
    printf("%.1f℃", (float)(tmp * 35.0 / 13107.0 - 45.0));  // 温度表示 式p13
    printf(" %.0f%%\n",(float)(hum / 655.36));                 // 湿度表示 式p13
    //printf("  0:%3d/%3d/%3d/%3d/%3d/%3d:5\n",buf6[0],buf6[1],buf6[2],buf6[3],buf6[4],buf6[5]); //各buf表示
    sleep_ms(5000);                                          // 5秒待つ
  }
  return 0;
}

CMakeLists.txt


cmake_minimum_required(VERSION 3.12)
include(pico_sdk_import.cmake)
project(project1 C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
#----------
add_executable(test test.c)
#----------
target_link_libraries(test pico_stdlib hardware_i2c)
pico_enable_stdio_usb(test 1)
pico_enable_stdio_uart(test 0)
pico_add_extra_outputs(test)