请选择 进入手机版 | 继续访问电脑版

狗趴(GodPub),开源硬件学习与实践

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 4083|回复: 1

【JoyTag Arduino/Genuion 101 亲密接触】 查看芯片温度

[复制链接]

84

主题

143

帖子

721

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
721
QQ
发表于 2016-4-12 14:14:16 | 显示全部楼层 |阅读模式
原文信息

标题:【JoyTag Arduino/Genuion 101 亲密接触】 查看芯片温度
连接:http://forum.godpub.com/thread-118-1-1.html
备注:狗趴论坛首发,转载请注明出处。


简介

阅读Arduino/Genuion 101的库资料,偶然发现Intel Curie中竟然内置了温度传感器。
温度传感器隶属6轴加速度计/陀螺仪(BMI160),它包含在Intel Curie核心中。
本文介绍如何读取Intel Curie内置温度传感器获取芯片的温度。并在使用过程中发现官网手册中的一处失误,并予以纠正。


温度传感器资料

以下资料来自BMI160数据手册

BMI160.PNG

Arduino/Genuion 101  BMI160代码中读取温度的片段
/** Get current internal temperature as a signed 16-bit integer.
*  The resolution is typically 1/2^9 degrees Celcius per LSB, at an
*  offset of 23 degrees Celcius.  For example:
*
* <pre>
* Value    | Temperature
* ---------+----------------
* 0x7FFF   | 87 - 1/2^9 degrees C
* ...      | ...
* 0x0000   | 23 degrees C
* ...      | ...
* 0x8001   | -41 + 1/2^9 degrees C
* 0x8000   | Invalid
*
* @return Temperature reading in 16-bit 2's complement format
* @see BMI160_RA_TEMP_L
*/
int16_t BMI160Class::getTemperature() {
    uint8_t buffer[2];
    buffer[0] = BMI160_RA_TEMP_L;
    serial_buffer_transfer(buffer, 1, 2);
    return (((int16_t)buffer[1]) << 8) | buffer[0];
}

Arduino官网的函数手册

在Intel CurieIMU 库中,对上述函数进行了简单的封装
int CurieIMUClass::readTemperature()
{
    return getTemperature();
}

Arduino站上关于此函数链接:
http://www.arduino.cc/en/Reference/CurieIMUreadTemperature

所以我们不必去了解寄存器的信息,直接调用上述函数就可以得到原始的温度信息。
因为读出的是原始的温度数据,我们需要对其进行转换,才能变成我们所熟悉的摄氏温度,转换公式如下:
Celsius=(raw/32767.0)+23

(***注***:来自上述链接函数手册,这里有个巨大的坑!)


读取芯片温度的程序

根据上述信息,我们可以实现一个简单的程序通过串口读取芯片的温度。
代码如下:
  1. // http://forum.godpub.com/thread-118-1-1.html
  2. #include "CurieIMU.h"

  3. void setup() {
  4.   Serial.begin(9600); // initialize Serial communication
  5.   while (!Serial);    // wait for the serial port to open

  6.   // initialize device
  7.   Serial.println("Initializing IMU device...");
  8.   CurieIMU.begin();
  9. }


  10. void loop() {
  11.   // Returns the raw value of the temperature value read by the built-in motion sensor
  12.   int  rawTemp = CurieIMU.readTemperature() ;
  13.   
  14.   <font color="Red">float Temp = (rawTemp/32767.0)+23 ;</font>
  15.   Serial.println(Temp);
  16.   delay(5000);
  17. }
复制代码

打开串口监视器,可以看到每五秒输出当前芯片的温度值。效果如下:
Capture.PNG


掉进大坑里

看起来似乎很完美呢,23度,基本上和我当前室温相当。看来Curie发热很低啊,几乎不发热啊。
用手摸摸Curie的芯片,果然不是很热。
等等,哪里不对?按说体温36-7度,摸芯片,温度该有些变化呀,总不能我体温也23度吧?
到底差哪呢?好吧,姑且怀疑是我体表温度太低了吧,冷血动物

那么就想办法提高一下芯片温度试试。
本来想拿电烙铁烙丫一下,又怕烙坏,搞个温柔的方式,用电吹风吹吹吧
找来电吹风,调成高档,一顿吹呀,手都要烫掉了,发现温度只上升了零点几度,这不科学。

到底哪里出错了呢,官方的库,官方的算法。

对照文档,回头一步一步追查。
寄存器地址没错
  1. #define BMI160_RA_TEMP_L            0x20
  2. #define BMI160_RA_TEMP_H            0x21
复制代码

读取寄存器的值代码没错
  1. int16_t BMI160Class::getTemperature() {
  2.     uint8_t buffer[2];
  3.     buffer[0] = BMI160_RA_TEMP_L;
  4.     serial_buffer_transfer(buffer, 1, 2);
  5.     return (((int16_t)buffer[1]) << 8) | buffer[0];
  6. }
复制代码

CurieIMU的封装更是直接返回:
  1. int CurieIMUClass::readTemperature()
  2. {
  3. return getTemperature();
  4. }
复制代码

那么除了硬件本身不对,就是以下转换有可能出错啦:
  1. float Temp = (rawTemp/32767.0)+23 ;
复制代码

硬件一般很少有问题即便有问题我也没法调试不是,而这个温度转换是Arduino官网手册中提供的,那么就看看它有没有错误吧。
那么我们来分析为什么这么转换呢?
让我们回头看温度传感器的资料:
  1. * Value | Temperature
  2. * ---------+----------------
  3. * 0x7FFF | 87 - 1/2^9 degrees C
  4. * ... | ...
  5. * 0x0000 | 23 degrees C
  6. * ... | ...
  7. * 0x8001 | -41 + 1/2^9 degrees C
  8. * 0x8000 | Invalid
复制代码
当数值为0 温度为23,所以转换公式后边+23,这没问题。
0x0000到0x7FFF总计为32767步,那么原始数据/32767表达的啥意思?!大坑原来在这里。
看上边引用的内容,0x0000到0x7FFF对应的温度变化从23度到(87 - 1/2^9)度,也就是说大致变化了87-23 = 64度
那么由原始数据变化成温度的计算公式应该为:(rawTemp/(32767.0/64))+23 ; 亦即:(rawTemp/512.0)+23;

再回头看BMI160的手册,人家都说了解析度是 1/2^9,Arduino官网手册害死人,浪费我大量精力。


修正后的代码与效果

针对上述结论,对代码进行修改。
修正后的代码如下:
  1. // http://forum.godpub.com/thread-118-1-1.html
  2. #include "CurieIMU.h"

  3. void setup() {
  4.   Serial.begin(9600); // initialize Serial communication
  5.   while (!Serial);    // wait for the serial port to open

  6.   // initialize device
  7.   Serial.println("Initializing IMU device...");
  8.   CurieIMU.begin();
  9. }


  10. void loop() {
  11.   // Returns the raw value of the temperature value read by the built-in motion sensor
  12.   int  rawTemp = CurieIMU.readTemperature() ;

  13.   float Temp = (rawTemp/512.0)+23 ;
  14.   Serial.println(Temp);
  15.   delay(5000);
  16. }
复制代码

执行效果如下:
Capture2.PNG
这还是比较合理的,用电吹风一吹数值变化明显,电吹风吹的就不截图啦,累了。

亲爱的读者,这里还有个无比巨大的坑,你们能否看出来?
这个大坑说严重很严重的哦,会导致一些条件下数据完全出错。
(小提示,和数据类型有关)


总结

本文介绍如何读取Intel Curie内置温度传感器获取芯片的温度。并在使用过程中发现官网手册中的一处失误,并予以纠正。
文末作者挖了一个大坑,希望细心的读者能够发现,猜对没有奖励哦。
谨以本文抛砖引玉,希望大家折腾出更好玩的东西。

后续更多精彩内容,请关注狗趴论坛:http://www.godpub.com

天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

84

主题

143

帖子

721

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
721
QQ
 楼主| 发表于 2016-4-12 14:17:18 | 显示全部楼层
埋了个大坑,看看谁能找到。
天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|狗趴(GodPub) Arduino&Raspberry Pi开源硬件学习与实践[QQ群:20085629]  

GMT+8, 2020-4-2 23:09 , Processed in 0.097233 second(s), 38 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表