怀揣少年梦 发表于 2021-7-26 20:51

【ESP32-C3-DevKitM-1】ESP32-C3读取SHT3X温湿度传感器的温湿度值

<p style="text-align:justify">&nbsp;</p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">本次使用</font><font face="Calibri">SHT3X</font><font face="宋体">温湿度传感器获取当前环境的温湿度。</font><font face="Calibri">SHT3X</font><font face="宋体">温湿度传感器,它具备校准、线性、温度补偿、快速测量、快速启动的特点,并且精度比较高,温度精度在&plusmn;</font><font face="Calibri">0.3</font><font face="宋体">℃,湿度精度在&plusmn;</font><font face="Calibri">2%RH</font><font face="宋体">;供电范围为</font><font face="Calibri">2.4V-5.5v</font><font face="宋体">,故使用</font><font face="Calibri">ESP32</font><font face="宋体">的</font><font face="Calibri">3.3V</font><font face="宋体">引脚进行供电;接口是使用</font><font face="Calibri">I2C</font><font face="宋体">,速度可达</font><font face="Calibri">1MHz</font><font face="宋体">,有两个可选地址。它的引脚电路图和实物图如下所示。</font></span></span></span></span></p>

<p class="imagemiddle" style="text-align: center;"></p>

<p class="imagemiddle" style="text-align: center;"></p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p class="imagemiddle" style="text-align: center;"></p>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">使用的引脚</font><font face="Calibri">:</font></span></span></span></span></p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">PIN18 &nbsp;SDA </font></span></span></span></span></p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">PIN19 &nbsp;SCL</font></span></span></span></span></p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">VIN &nbsp;&nbsp;&nbsp;3.3V</font></span></span></span></span></p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">AD &nbsp;&nbsp;&nbsp;GND</font></span></span></span></span></p>

<p style="text-indent:21.0000pt; text-align:justify">&nbsp;</p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">程序编写:</font></span></span></span></span></p>

<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">1</font><font face="宋体">、配置</font><font face="Calibri">I2C</font><font face="宋体">接口参数,主机模式、</font><font face="Calibri">IO</font><font face="宋体">口、通信速度等</font></span></span></span></span></p>

<p class="imagemiddle" style="text-align: center;"></p>

<pre>
<code>/**
* @brief i2c master initialization
*/
esp_err_t i2c_master_init(void)
{
    int i2c_master_port = IIC_CTRL_NUM;
    i2c_config_t conf;
    conf.mode = I2C_MODE_MASTER;//主机模式
    conf.sda_io_num = SDA_PIN_NUM;//使用IO作为SDA引脚
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;//上拉使能
    conf.scl_io_num = SCL_PIN_NUM;//使用IO作为SCL引脚
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;//上拉使能
    conf.master.clk_speed = 100000;   /* 标准模式(100 kbit/s) */
    i2c_param_config(i2c_master_port, &amp;conf);
    return i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0);
}</code></pre>

<p style="text-indent:21.0000pt; text-align:justify">&nbsp;</p>

<ol start="2">
        <li style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">编写发命令函数</font></span></span></span></span></li>
</ol>

<p class="imagemiddle" style="text-align: center;"></p>

<pre>
<code>/* 描述:向SHT30发送一条16bit指令
* 参数cmd:SHT30指令(在SHT30_MODE中枚举定义)
* 返回值:成功返回ESP_OK                     */
esp_err_t SHT3x_Send_Cmd(sht3x_cmd_t sht3x_cmd)
{
    uint8_t cmd_buffer;
    //发送16位的命令头
    //先将低8位右移8位
    cmd_buffer = sht3x_cmd &gt;&gt; 8;
    cmd_buffer = sht3x_cmd;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();//创建连接
    i2c_master_start(cmd);//传输开始
    i2c_master_write_byte(cmd, SHT3X_DeviceAddr | WRITE_BIT, ACK_CHECK_EN);//写命令
    i2c_master_write_byte(cmd, cmd_buffer, ACK_CHECK_EN);//发送低字节
    i2c_master_write_byte(cmd, cmd_buffer, ACK_CHECK_EN);//发送高字节
    i2c_master_stop(cmd);//停止传输
    esp_err_t ret = i2c_master_cmd_begin(IIC_CTRL_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);//删除连接
       
        return ret;
}</code></pre>

<p align="justify" style="text-align:justify">&nbsp;</p>

<ol start="3">
        <li align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-justify:inter-ideograph"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">编写读数据函数。</font></span></span></span></span></span></li>
</ol>

<p class="imagemiddle" style="text-align: center;"></p>

<pre>
<code>/* 描述:从SHT3x读取数据
* 参数data_len:读取多少个字节数据
* 参数data_arr:读取的数据存放在一个数组里
* 返回值:读取成功返回ESP_OK
*/
esp_err_t SHT3x_Recv_Data(size_t data_len, uint8_t* data_arr)
{
        i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, SHT3X_DeviceAddr | READ_BIT, ACK_CHECK_EN);
    if (data_len &gt; 1) {
      i2c_master_read(cmd, data_arr, data_len - 1, ACK_VAL);
    }
    i2c_master_read_byte(cmd, data_arr + data_len - 1, NACK_VAL);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(IIC_CTRL_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);

        return ret;
}</code></pre>

<ol start="4">
        <li align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-justify:inter-ideograph"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">编写</font><font face="Calibri">SHT3X</font><font face="宋体">初始化函数。</font></span></span></span></span></span></li>
</ol>

<pre>
<code>/* 描述:SHT3x初始化函数,并将其设置为周期测量模式
* 参数:无
* 返回值:初始化成功返回ESP_OK */
esp_err_t sht3x_mode_init(void)
{
    /* 初始化IIC控制器 */
    ESP_ERROR_CHECK(i2c_master_init());
    /* 设置为周期测量模式 */
    esp_err_t ret = SHT3x_Send_Cmd(MEDIUM_2_CMD);
        return ret;
}</code></pre>

<p align="justify" style="margin-left:28px; text-align:justify">&nbsp;</p>

<ol start="5">
        <li align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-justify:inter-ideograph"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">CRC</font><font face="宋体">校验函数</font></span></span></span></span></span></li>
</ol>

<pre>
<code>/* 描述:数据CRC校验
* 参数message:需要校验的数据
* 参数initial_value:crc初始值
* 返回值:计算得到的CRC码 */
#define CRC8_POLYNOMIAL 0x131
uint8_t CheckCrc8(uint8_t* const message, uint8_t initial_value)
{
    uint8_tremainder;          //余数
    uint8_ti = 0, j = 0;//循环变量

    /* 初始化 */
    remainder = initial_value;
    for(j = 0; j &lt; 2;j++)
    {
      remainder ^= message;
      /* 从最高位开始依次计算*/
      for (i = 0; i &lt; 8; i++)
      {
            if (remainder &amp; 0x80)
                remainder = (remainder &lt;&lt; 1)^CRC8_POLYNOMIAL;
            else
                remainder = (remainder &lt;&lt; 1);
      }
    }
    /* 返回计算的CRC码 */
    return remainder;
}</code></pre>

<ol start="6">
        <li align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-justify:inter-ideograph"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">读取温湿度值函数</font></span></span></span></span></span></li>
</ol>

<p class="imagemiddle" style="text-align: center;"></p>

<p class="imagemiddle">&nbsp; &nbsp; &nbsp; &nbsp; 根据这个图,编写温湿度程序。</p>

<pre>
<code>/* 描述:温湿度数据获取函数,周期读取,注意,需要提前设置周期模式   
* 参数Tem_val:存储温度数据的指针, 温度单位为°C
* 参数Hum_val:存储湿度数据的指针, 温度单位为%
* 返回值:0-读取成功,1-读取失败 **********************************/
uint8_t sht3x_get_humiture_periodic(double *Tem_val,double *Hum_val)
{
        uint8_t ret=0;
        uint8_t buff;
        uint16_t tem,hum;
        double Temperature=0;
        double Humidity=0;

        ret = SHT3x_Send_Cmd(READOUT_FOR_PERIODIC_MODE);       
        ret = SHT3x_Recv_Data(6,buff);
       
        /* 校验温度数据和湿度数据是否接收正确 */
        if(CheckCrc8(buff, 0xFF) != buff || CheckCrc8(&amp;buff, 0xFF) != buff)
        {       
                printf("CRC_ERROR,ret = 0x%x\r\n",ret);
                return 1;
        }
               
        /* 转换温度数据 */
        tem = (((uint16_t)buff&lt;&lt;8) | buff);//温度数据拼接
        Temperature= (175.0*(double)tem/65535.0-45.0) ;        // T = -45 + 175 * tem / (2^16-1)
       
        /* 转换湿度数据 */
        hum = (((uint16_t)buff&lt;&lt;8) | buff);//湿度数据拼接
        Humidity= (100.0*(double)hum/65535.0);                        // RH = hum*100 / (2^16-1)
       
        /* 过滤错误数据 */
        if((Temperature&gt;=-20)&amp;&amp;(Temperature&lt;=125)&amp;&amp;(Humidity&gt;=0)&amp;&amp;(Humidity&lt;=100))
        {
                *Tem_val = Temperature;
                *Hum_val = Humidity;
                return 0;
        }
        else
                return 1;
}</code></pre>

<p class="imagemiddle" style="text-align: center;">&nbsp;</p>

<p align="justify" style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="text-justify:inter-ideograph"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">7</font><font face="宋体">、主函数</font></span></span></span></span></span></p>

<pre>
<code>void app_main(void)
{
    vTaskDelay(200);
   double Tem_val,Hum_val;
    ESP_ERROR_CHECK(sht3x_mode_init());
   
    while(1)
    {

      /* 采集温湿度数据 */
      if(sht3x_get_humiture_periodic(&amp;Tem_val,&amp;Hum_val) == 0)
      {
          printf("temperature:%6.2lf °C, humidity:%6.2lf %% \n",Tem_val,Hum_val);
          printf("\r\n************************************************************\r\n");

      }
      else
          printf("Get_Humiture ERR\r\n");

       vTaskDelay(200);

    }
}</code></pre>

<p>&nbsp; &nbsp; &nbsp; &nbsp; 8、头文件</p>

<pre>
<code>#ifndef _SHT3x_H
#define _SHT3x_H

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;sys/param.h&gt;
#include "driver/i2c.h"


#define WRITE_BIT 0x00                      /*!&lt; I2C master write */
#define READ_BIT 0x01                     /*!&lt; I2C master read*/

#define ACK_CHECK_EN 0x1                  /*!&lt; I2C master will check ack from slave   */
#define ACK_CHECK_DIS 0x0                   /*!&lt; I2C master will not check ack from slave */
#define ACK_VAL 0x0                         /*!&lt; I2C ack value*/
#define NACK_VAL 0x1                        /*!&lt; I2C nack value */


#define IIC_CTRL_NUM I2C_NUM_0             /*!&lt; I2C port number */
#define SDA_PIN_NUM 18                      /*!&lt; gpio number for I2C data*/
#define SCL_PIN_NUM 19                      /*!&lt; gpio number for I2C clock */


#define SHT3X_DeviceAddr (0x44&lt;&lt;1)          /* SHT3X的器件地址 */



/* 枚举SHT3x命令列表 */
typedef enum
{
    /* 软件复位命令 */
    SOFT_RESET_CMD = 0x30A2,       
    /* 单次测量模式
    命名格式:Repeatability_CS_CMD
    CS: Clock stretching */
    HIGH_ENABLED_CMD    = 0x2C06,
    MEDIUM_ENABLED_CMD= 0x2C0D,
    LOW_ENABLED_CMD   = 0x2C10,
    HIGH_DISABLED_CMD   = 0x2400,
    MEDIUM_DISABLED_CMD = 0x240B,
    LOW_DISABLED_CMD    = 0x2416,

    /* 周期测量模式
    命名格式:Repeatability_MPS_CMD
    MPS:measurement per second */
    HIGH_0_5_CMD   = 0x2032,
    MEDIUM_0_5_CMD = 0x2024,
    LOW_0_5_CMD    = 0x202F,
    HIGH_1_CMD   = 0x2130,
    MEDIUM_1_CMD   = 0x2126,
    LOW_1_CMD      = 0x212D,
    HIGH_2_CMD   = 0x2236,
    MEDIUM_2_CMD   = 0x2220,
    LOW_2_CMD      = 0x222B,
    HIGH_4_CMD   = 0x2334,
    MEDIUM_4_CMD   = 0x2322,
    LOW_4_CMD      = 0x2329,
    HIGH_10_CMD    = 0x2737,
    MEDIUM_10_CMD= 0x2721,
    LOW_10_CMD   = 0x272A,
        /* 周期测量模式读取数据命令 */
        READOUT_FOR_PERIODIC_MODE = 0xE000,
        /* 读取传感器编号命令 */
        READ_SERIAL_NUMBER = 0x3780,
} sht3x_cmd_t;


esp_err_t SHT3x_Send_Cmd(sht3x_cmd_t sht3x_cmd);
esp_err_t SHT3x_Recv_Data(size_t data_len, uint8_t* data_arr);
esp_err_t sht3x_mode_init(void);
uint8_t CheckCrc8(uint8_t* const message, uint8_t initial_value);
uint8_t sht3x_get_humiture_periodic(double *Tem_val,double *Hum_val);

#endif

</code></pre>

<p>&nbsp; &nbsp; &nbsp; &nbsp; 9、效果图</p>

<p>&nbsp;</p>

<p class="imagemiddle" style="text-align: center;"></p>

<p>当前手机显示温度,可见温度挺准的</p>

<p>&nbsp;</p>

<p class="imagemiddle" style="text-align: center;"></p>

<p>&nbsp;</p>

Jacktang 发表于 2021-7-26 21:58

<p>ESP32-C3和SHT3X配合的挺好</p>

<p>湿度的准确度应该也可以</p>

怀揣少年梦 发表于 2021-7-27 08:13

Jacktang 发表于 2021-7-26 21:58
ESP32-C3和SHT3X配合的挺好

湿度的准确度应该也可以

<p>第一次玩温湿度传感器,多谢指点</p>

linux_cc 发表于 2021-7-28 22:52

<p>你好,楼主,你开发ESP32是用什么开发环境,上手难度大吗。</p>

怀揣少年梦 发表于 2021-7-29 11:31

linux_cc 发表于 2021-7-28 22:52
你好,楼主,你开发ESP32是用什么开发环境,上手难度大吗。

<p>用的VS CODE,上手难度不大</p>

linux_cc 发表于 2021-8-23 22:32

怀揣少年梦 发表于 2021-7-29 11:31
用的VS CODE,上手难度不大

<p>你好,我在学习使用ESP32和ESP8266。上回请教过用VS CODE开发EPS32或ESP8266,但是网上搜索怎么搭建VSCODE开发环境还没弄清楚,能否请教下,我装了VSCODE ,还需要装其他内容吗。</p>

怀揣少年梦 发表于 2021-8-24 10:52

linux_cc 发表于 2021-8-23 22:32
你好,我在学习使用ESP32和ESP8266。上回请教过用VS CODE开发EPS32或ESP8266,但是网上搜索怎么搭建VSCOD ...

<p><a href="https://bbs.eeworld.com.cn/thread-1170507-1-1.html">【ESP32-C3-DevKitM-1】ESP32-C3开发环境搭建 - 国产芯片交流 - 电子工程世界-论坛 (eeworld.com.cn)</a></p>

<p>可以参考我这个开发环境搭建。</p>
页: [1]
查看完整版本: 【ESP32-C3-DevKitM-1】ESP32-C3读取SHT3X温湿度传感器的温湿度值