fxyc87 发表于 2021-2-7 16:40

【树莓派Pico测评】-制作红外体温计( I2C接口测试+MLX90614)

<div class='showpostmsg'> 本帖最后由 fxyc87 于 2021-2-7 16:46 编辑

<p>我上个贴子发布了如何利用USB进行串口通信,</p>

<p><a href="https://bbs.eeworld.com.cn/thread-1156658-1-1.html" target="_blank" title="【树莓派Pico测评】- USB CDC串口通信(BSP编译,非MicroPython)">【树莓派Pico测评】- USB CDC串口通信(BSP编译,非MicroPython)</a></p>

<p>这次发布一个I2C的例子,刚好我手头上有MLX90614,市场上的手持红外测温的清一色的都是用的它</p>

<p>这个芯片我买了大概5-6年了,一直吃灰,刚好最近玩PICO时又从宝箱里翻出了它,刚好在这个疫情后时代用得上</p>

<p>程序基于我上次的程序进行修改,这里我只发出主程序</p>

<pre>
<code class="language-cpp">#include &lt;stdio.h&gt;
#include "pico/stdlib.h"
#include "pico/stdio_usb.h"
#include "hardware/i2c.h"

// I2C 声明
#define I2C_PORT i2c0
#define I2C_SDA 0
#define I2C_SCL 1
//MLX90614 声明
#define MLX90614_ADDR 0x5a      //地址

#define CMD_RAM(n)(0|n)
#define CMD_EEPROM(n) (32|n)               //001x xxxx* EEPROM Access
#define CMD_FLAG(n) (0xf0)            //1111_0000** Read Flags
#define CMD_SLEEP(n) (0xff)                      //1111_1111 Enter SLEEP mode


//led 声明
#define LED 25
//usb 声明

//函数申明
int ReadData(uint8_t reg_addr);       //
//变量申明
uint16_t MLX90614_value;            //读取的16位原始结果

int main()
{
    //USB初始化
    stdio_usb_init();
    //LED初始化
    gpio_init(LED);
    gpio_set_dir(LED,GPIO_OUT);
    gpio_put(LED,1);
    //LED闪烁提示
    sleep_ms(5000);
    for(int i=0;i&lt;10;i++){
      sleep_ms(100);
      gpio_put(LED,0);
      sleep_ms(100);
      gpio_put(LED,1);
    }

    //MLX90614切换到I2C模式,SCL至少低电平 1.44ms
    gpio_set_function(I2C_SCL, GPIO_FUNC_SIO);
    gpio_set_dir(I2C_SCL, GPIO_OUT);
    gpio_put(I2C_SCL, 0);
    sleep_ms(5);
    gpio_put(I2C_SCL, 1);
    sleep_ms(30);

    // I2C 50Khz.
    i2c_init(I2C_PORT, 50*1000);
   
    gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
    gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
    gpio_pull_up(I2C_SDA);
    gpio_pull_up(I2C_SCL);

    /*MLX90614 RAM地址
ta本体温度,      6
温度1            7
温度2            8
    */

    /*MLX90614 EEPROM地址
Tomax         0x00 Yes
Tomin         0x01 Yes
PWMCTRL   0x02 Yes
Ta range      0x03 Yes
Emissivity      0x04 Yes
Config Register1 0x05 Yes
SMBus address (LSByte only) 0x0E Yes
    */
    //读取EEPROM配置数据
    float max, min;

    int r= ReadData(CMD_EEPROM(0));
    if (r &lt; 3) {
      printf("读取配置失败\n");
      while (1);
    }
    printf("dat:%d\n", MLX90614_value);
    max = MLX90614_value / 100.0f - 273.15f;
    printf("Tomax:%f\n", max);
    r = ReadData(CMD_EEPROM(1));
    if (r &lt; 3) {
      printf("读取RAM失败\n");
      while (1);
    }
    printf("dat:%d\n", MLX90614_value);
    min = MLX90614_value / 100.0f - 273.15f;
    printf("Tomax:%f\n", min);

    while(1){
      //本体温度
      float temp1,temp2;
      int r;

      r = ReadData(CMD_RAM(6));
      if (r &lt; 3) {
            printf("读取温度6失败\n");
            while (1);
      }
      temp1 = MLX90614_value * 0.02f-273.15;

      r = ReadData(CMD_RAM(7));
      if (r &lt; 3) {
            printf("读取温度7失败\n");
            while (1);
      }
      temp2 = MLX90614_value * 0.02f - 273.15;
      printf("temp:%3.2f,%3.2f\t@eeworld.fxyc87\n", temp1,temp2);

       //打印出读的数据
      
      gpio_put(LED, 1);
      sleep_ms(500);
      gpio_put(LED, 0);
      sleep_ms(500);
    }

    return 0;
}
/*
读取MLX90614寄存器数据   
reg_addr 地址有 CMD_RAM(a),CMD_EEPROM(a),CMD_FLAG(a),CMD_SLEEP(a)
读取成功,返回数据长度
失败:-1
*/
int ReadData(uint8_t reg_addr) {       //
    uint8_t bf;
    int r = 0;
      //先写站号及命令码 nostop=false 写入后不发送i2c停止指令
      //PICO_ERROR_TIMEOUT
    r = i2c_write_timeout_us(I2C_PORT, MLX90614_ADDR, &amp;reg_addr, 1, true, 2000);    //超时2ms
    if (r &lt; 1) {
      return -1;
    }
    //再读数据      lsb,msb,pec
    r = i2c_read_timeout_us(I2C_PORT, MLX90614_ADDR, &amp;bf, 3, false, 2000);
    if (r &lt; 1) {
      return -1;
    }
    MLX90614_value = bf + (bf &lt;&lt; 8);
    return r;
}</code></pre>

<p>以主是主程序,程序比较简单,输出当前温度及芯片本体温度,参数及地址参照MLX90614手册进行就好了</p>

<p></p>

<p>&nbsp;</p>

<p>编译主程序,并且复制程序</p>

<p></p>

<p>硬件链接图:</p>

<p></p>

<p>运行效果展示</p>

<p></p>

<p>从上图中可以看出,室温/芯片温度约16度左右,基本正常,手摸一下温度会慢慢升高</p>

<p>目标物体温度,无物体时约15.61度,差不多室温,手腕放主去,2秒后升到33度左右,</p>

<p>和公司的每天早上量体温的机器基本一致,至于为什么不是36,37度我也不知道,应该是出厂就校准过的啊,不应该差这么多吧?可能是一些参数还需要配置,比如测量温度上下限等,有空了再试试。</p>

<p>等节后了加工一个PCB,再找个漂亮的盒子,再搞个小屏,这样就是一个成品模块了。</p>

<p>这芯片买的时候180,现在估计卖300也能卖出去,哈,增值啊。</p>

<p>不该2019年底的时候把&nbsp;MLX90640,如果这个没卖玩起来更爽。32*24像素的红外相机啊!</p>

<p>&nbsp;</p>

<p>再列个网址&nbsp;https://raspberrypi.github.io/pico-sdk-doxygen/group__hardware__i2c.html</p>

<p>这个网址是关于I2C的SDK API说明,当然其它API这里也有看到介绍</p>

<p>https://raspberrypi.github.io/pico-sdk-doxygen/group__hardware.html</p>

<p>&nbsp;</p>

<p>**** Hidden Message *****</p>
</div><script>                                var loginstr = '<div class="locked">查看精华帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                               
                                if(parseInt(discuz_uid)==0){
                                                                                        (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                }
</script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

fxyc87 发表于 2021-2-7 17:22

<p></p>

<p>硬件链接</p>

<p>SDA接P00,</p>

<p>SCL接P01</p>

annysky2012 发表于 2021-2-8 09:30

赞赞赞赞,期待成品。这个灵敏度怎么样

fxyc87 发表于 2021-2-8 09:44

annysky2012 发表于 2021-2-8 09:30
赞赞赞赞,期待成品。这个灵敏度怎么样

<p>MLX90614有好几个子系列,</p>

<p>5V的,3V的,还有角度</p>

<p>有90度视野的,有30度,有10度的,</p>

<p>还有温度有+-1度,+-0.5度的,+-0.1度的,好几个级别呢,</p>

<p>我这个是最普通的,</p>

kangkls 发表于 2021-2-9 08:22

<p>国产的测温计很多卖20块钱,不知道用的 那个测温芯片,速度快,但是不准</p>

joeymm 发表于 2021-2-9 10:57

<p>1.用614测温应该使用医疗级别的型号,而不是工业级别的型号</p>

<p>2.测体表温度与实际值偏差大,是因为你缺少一个值换算的经验公式~</p>

fxyc87 发表于 2021-2-9 11:13

joeymm 发表于 2021-2-9 10:57
1.用614测温应该使用医疗级别的型号,而不是工业级别的型号

2.测体表温度与实际值偏差大,是因为你缺少 ...

<p>对,实际上就是校准</p>

xuc26 发表于 2023-12-5 10:05

<p>不用转换模块,直接串口UART通讯的数字红外温度传感器,硬件上还与MLX90614 pin to pin</p>

<p> &nbsp;</p>
页: [1]
查看完整版本: 【树莓派Pico测评】-制作红外体温计( I2C接口测试+MLX90614)