查看: 1618|回复: 15

[项目] 肺炎疫情期间,在家自制红外测温枪

[复制链接]
疫情期间在家自制一把红外测温枪,每天给家人量体温

——使用Arduino Nano和MLX90614红外测温模块



新冠肺炎疫情已经爆发一个多月了,各位老铁想必在家也快憋疯了。先前是口罩被抢购一空,现在测温枪也是不太好买,正好在家“自我隔离”,突然想起库存里还有一个红外测温模块,碰巧看到之前一位大神自制的红外测温枪,就借用了下大神设计的模型稍加改动(物理破坏),加上手边的一些元器件,做了一个测温枪。屏幕可显示体温(目标温度),室温(环境温度)、电量和体温情况,内置锂电池,可充电。

2.jpg

主控使用了Arduino Nano 328p(因为是手头最小的板子了),传感器使用了MLX90614红外测温模块(测温)和Gravity: I2C 3.7V锂电池电量计 (电量检测),显示屏使用了常见的0.96寸OLED屏(IIC)。因为制作之前没有拍照片,只有制作完成后的照片,所以各位看官老爷凑合看吧。

2020_02_16_10_23_IMG_1066.JPG
材料清单:
1.Arduino Nano 328p  1只
2.MLX90614非接触式红外温度传感器  1只
3.Gravity: I2C 3.7V锂电池电量计  1只
4.MP2636充电升压模块  1只
5.0.96寸OLED显示屏  1只
6.3.7V 1800mAh 锂电池 1只
7.USBType-A 公头、Micro USB公头、Micro USB母头 各1只
8.5V 6MM激光头 1只
9.拨动开关 1只
10.3D打印外壳
11.电子线、热缩管  若干
12.PH2.0公头2只、母头1只
工具:
1.TS100  烙铁
2.ANYCUBIC i3 Mega
3.热熔胶枪
软件:
1.Arduino IDE(我用的是1.6.6版本的)
2.PCtoLCD2002取模软件
3.Cura 15.04.6切片软件
制作过程:
第一步:将Nano板的排针全部拆下

第二步:将测温模块、OLED屏、电量计、激光头通过电子线焊接到主控板上
2020_02_16_10_35_IMG_1075.JPG

第三步:制作锂电池一分二电源线、Micro USB延长线和USBA插头线
2020_02_16_10_31_IMG_1072.JPG
一分二电源线用于分别给升压模块供电和电量计检测电量(拨动开关焊接到电源线上)

2020_02_16_10_31_IMG_1073.JPG
USB延长线用于连接升压模块

2020_02_16_10_32_IMG_1074.JPG
USBA插头线给主板供电

第四步:上传程序(有一部分多余代码懒得删了)
[C] 纯文本查看 复制代码
#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);        // I2C / TWI 

static const unsigned char shiwen[3][32] PROGMEM={
{0x40,0x00,0x80,0x00,0xFE,0x7F,0x02,0x40,0x01,0x20,0xFC,0x1F,0x20,0x00,0x10,0x04,
0xF8,0x0F,0x80,0x08,0x80,0x00,0xFC,0x1F,0x80,0x00,0x80,0x00,0xFF,0x7F,0x00,0x00},/*"室",0*/
/* (16 X 16 , 宋体 )*/

{0x00,0x00,0xC4,0x1F,0x48,0x10,0x48,0x10,0xC1,0x1F,0x42,0x10,0x42,0x10,0xC8,0x1F,
0x08,0x00,0xE4,0x3F,0x27,0x25,0x24,0x25,0x24,0x25,0x24,0x25,0xF4,0x7F,0x00,0x00},/*"温",1*/
/* (16 X 16 , 宋体 )*/

{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00},/*":",2*/
/* (16 X 16 , 宋体 )*/
};
static const unsigned char tiwen[3][32] PROGMEM={
  {0x10,0x02,0x10,0x02,0x10,0x02,0x08,0x02,0xE8,0x3F,0x0C,0x02,0x0C,0x07,0x0A,0x07,
  0x89,0x0A,0x88,0x0A,0x48,0x12,0xA8,0x2F,0x18,0x42,0x08,0x02,0x08,0x02,0x08,0x02},/*"体",0*/
/* (16 X 16 , 宋体 )*/

{0x00,0x00,0xC4,0x1F,0x48,0x10,0x48,0x10,0xC1,0x1F,0x42,0x10,0x42,0x10,0xC8,0x1F,
0x08,0x00,0xE4,0x3F,0x27,0x25,0x24,0x25,0x24,0x25,0x24,0x25,0xF4,0x7F,0x00,0x00},/*"温",1*/
/* (16 X 16 , 宋体 )*/

{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00},/*":",2*/
/* (16 X 16 , 宋体 )*/
};
static const unsigned char sheshidu[1][32] PROGMEM={
  {0x06,0x00,0x89,0x2F,0x69,0x30,0x36,0x20,0x10,0x20,0x18,0x00,0x18,0x00,0x18,0x00,
  0x18,0x00,0x18,0x00,0x18,0x00,0x10,0x00,0x30,0x20,0x60,0x10,0x80,0x0F,0x00,0x00},/*"℃",0*/
/* (16 X 16 , 宋体 )*/
};
static const unsigned char zhengchang[2][32] PROGMEM={
  
{0x00,0x00,0xFE,0x3F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x88,0x00,0x88,0x1F,
0x88,0x00,0x88,0x00,0x88,0x00,0x88,0x00,0x88,0x00,0x88,0x00,0xFF,0x7F,0x00,0x00},/*"正",0*/
/* (16 X 16 , 宋体 )*/

{0x80,0x00,0x88,0x08,0x90,0x04,0xFE,0x7F,0x02,0x40,0xF9,0x2F,0x08,0x08,0xF8,0x0F,
 0x80,0x00,0xFC,0x1F,0x84,0x10,0x84,0x10,0x84,0x14,0x84,0x08,0x80,0x00,0x80,0x00},/*"常",1*/
/* (16 X 16 , 宋体 )*/
};

static const unsigned char yichang[2][32] PROGMEM={
  {0x00,0x00,0xFC,0x0F,0x04,0x08,0x04,0x08,0xFC,0x0F,0x04,0x20,0x04,0x20,0xF8,0x3F,
0x00,0x00,0x10,0x04,0x10,0x04,0xFF,0x7F,0x10,0x04,0x08,0x04,0x04,0x04,0x02,0x04},/*"异",0*/
/* (16 X 16 , 宋体 )*/

{0x80,0x00,0x88,0x08,0x90,0x04,0xFE,0x7F,0x02,0x40,0xF9,0x2F,0x08,0x08,0xF8,0x0F,
0x80,0x00,0xFC,0x1F,0x84,0x10,0x84,0x10,0x84,0x14,0x84,0x08,0x80,0x00,0x80,0x00},/*"常",1*/
/* (16 X 16 , 宋体 )*/
};
static const unsigned char dl[4][32] PROGMEM={
{0x80,0x00,0x80,0x00,0x80,0x00,0xFC,0x1F,0x84,0x10,0x84,0x10,0x84,0x10,0xFC,0x1F,
0x84,0x10,0x84,0x10,0x84,0x10,0xFC,0x1F,0x84,0x50,0x80,0x40,0x80,0x40,0x00,0x7F},/*"电",0*/
/* (16 X 16 , 宋体 )*/

{0x00,0x00,0xF8,0x0F,0x08,0x08,0xF8,0x0F,0x08,0x08,0xFF,0x7F,0x00,0x00,0xF8,0x0F,
0x88,0x08,0xF8,0x0F,0x88,0x08,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xFE,0x3F},/*"量",1*/
/* (16 X 16 , 宋体 )*/

{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00},/*":",2*/
/* (16 X 16 , 宋体 )*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x08,0x62,0x04,0x63,0x04,0x63,0x02,0x62,0x01,
0x9C,0x3C,0x40,0x62,0x20,0x42,0x20,0x42,0x10,0x62,0x08,0x3C,0x00,0x00,0x00,0x00},/*"%",0*/
/* (16 X 16 , @宋体 )*/
};

#include <Wire.h>
#include <IR_Thermometer_Sensor_MLX90614.h>
#include "DFRobot_MAX17043.h"

IR_Thermometer_Sensor_MLX90614 MLX90614 = IR_Thermometer_Sensor_MLX90614();

//电量检测模块初始化
#ifdef __AVR__
  #define ALR_PIN       2
#else
  #define ALR_PIN       D2
#endif

#define PRINT_INTERVAL        2000

DFRobot_MAX17043        gauge;
uint8_t       intFlag = 0;

void interruptCallBack()
{
  intFlag = 1;
}

void draw(void) {
  // graphic commands to redraw the complete screen should be placed here  
  u8g.setFont(u8g_font_fub14);
  //u8g.setFont(u8g_font_osb21);
  //u8g.drawStr( 0, 20, "Hello World!");
  //体温显示
   u8g.drawXBMP( 0, 4,16, 16, tiwen[0]);
  u8g.drawXBMP( 16, 4,16, 16, tiwen[1]);
  u8g.drawXBMP( 32, 4,16, 16, tiwen[2]);
  float O = MLX90614.GetObjectTemp_Celsius();
  u8g.setPrintPos(40,19); 
  u8g.print(O);
  u8g.drawXBMP( 92, 4,16, 16, sheshidu[0]);
  //室温显示
   u8g.drawXBMP( 0, 24,16, 16, shiwen[0]);
  u8g.drawXBMP( 16, 24,16, 16, shiwen[1]);
  u8g.drawXBMP( 32, 24,16, 16, shiwen[2]);
  float A = MLX90614.GetAmbientTemp_Celsius();
  u8g.setPrintPos(40,39); 
  u8g.print(A);
  u8g.drawXBMP( 92, 24,16, 16, sheshidu[0]);
  //电量显示  
   u8g.drawXBMP( 0, 44,16, 16, dl[0]);
  u8g.drawXBMP( 16, 44,16, 16, dl[1]);
  u8g.drawXBMP( 32, 44,16, 16, dl[2]);
  u8g.setPrintPos(40,59); 
  u8g.print(gauge.readPercentage());
  u8g.drawXBMP( 92, 44,16, 16, dl[3]);
  //体温判断
  u8g.drawXBMP( 111, 0,16, 16, tiwen[0]);
    u8g.drawXBMP( 111, 16,16, 16, tiwen[1]);
    u8g.drawXBMP( 111, 48,16, 16, zhengchang[1]);
  if(32 <= O && O <37.3){
    u8g.drawXBMP( 111, 32,16, 16, zhengchang[0]);
    }
    else{
      u8g.drawXBMP( 111, 32,16, 16, yichang[0]);
      }
}

void setup(void) {
  // flip screen, if required
  // u8g.setRot180();
  
  // set SPI backup if required
  //u8g.setHardwareBackup(u8g_backup_avr_spi);

  // assign default color value
  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255,255,255);
  }

 MLX90614.begin(); 

  Serial.begin(115200);
  while(!Serial);
  Serial.println();
  Serial.println();
  pinMode(ALR_PIN, INPUT_PULLUP);
  attachInterrupt(ALR_PIN, interruptCallBack, FALLING);  //default alert is 32%
  
  while(gauge.begin() != 0) {
    Serial.println("gauge begin faild!");
    delay(2000);
  }
  delay(2);
  Serial.println("gauge begin successful!");
  //gauge.setInterrupt(32);  //use this to modify alert threshold as 1% - 32% (integer)
  
}

void loop(void) {
  // picture loop
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );
  
  // rebuild the picture after some delay
  delay(500);
  static unsigned long lastMillis = 0;
  if((millis() - lastMillis) > PRINT_INTERVAL) {
    lastMillis = millis();
    Serial.println();

    Serial.print("voltage: ");
    Serial.print(gauge.readVoltage());
    Serial.println(" mV");

    Serial.print("precentage: ");
    Serial.print(gauge.readPercentage());
    Serial.println(" %");

  }

  if(intFlag == 1) {
    intFlag = 0;
    gauge.clearInterrupt();
    Serial.println("Low power alert interrupt!");
    //put your battery low power alert interrupt service routine here
  }·
}

第五步:安装各模块(使用热熔胶和美纹纸包裹端点,防止短路),完成组装
2020_02_16_10_21_IMG_1064.jpg

2020_02_15_20_22_IMG_1063.JPG

2020_02_16_10_45_IMG_1086.JPG


资料下载:
0.96寸OLED屏相关资料:示例程序、库文件、取模软件等 网盘链接 提取码:vktz

项目附件下载:
Project file.zip (1.69 MB, 下载次数: 11)

rzyzzxw  版主

发表于 2020-2-16 15:37:44

这个项目很棒啊
回复

使用道具 举报

aliteamer  中级技师
 楼主|

发表于 2020-2-16 16:03:03

rzyzzxw 发表于 2020-2-16 15:37
这个项目很棒啊

谢谢版主的认可
回复

使用道具 举报

glwz007  中级技师

发表于 2020-2-16 21:00:00

请问环境温度怎么取得?
回复

使用道具 举报

glwz007  中级技师

发表于 2020-2-16 21:23:33

知道了,传感器自身输出两个温度。
回复

使用道具 举报

rzegkly  版主

发表于 2020-2-17 09:33:39

喜欢,好文章!
回复

使用道具 举报

aliteamer  中级技师
 楼主|

发表于 2020-2-17 15:20:24

rzegkly 发表于 2020-2-17 09:33
喜欢,好文章!

哈哈,第一次写,没什么经验,请前辈们多多指教
回复

使用道具 举报

aliteamer  中级技师
 楼主|

发表于 2020-2-17 15:47:12

glwz007 发表于 2020-2-16 21:23
知道了,传感器自身输出两个温度。

对的,这个传感器可以测量目标温度和环境温度
回复

使用道具 举报

kylinpoet  中级技匠

发表于 2020-2-17 21:53:34

又是一篇好文,支持。
回复

使用道具 举报

DFrJ5KYVQaH  初级技匠

发表于 2020-2-18 08:32:51

太棒了,一定好好学习
回复

使用道具 举报

chenhanzhong  高级技师

发表于 2020-2-18 13:22:28

很赞!!!
回复

使用道具 举报

laai  初级技师

发表于 2020-2-26 19:14:57

顶起~好帖,用MIND+编程可以实现同样效果吗
回复

使用道具 举报

想成为蟑螂恶霸  见习技师

发表于 2020-3-3 11:45:48

啊哈哈哈 这个可以 非常实用
回复

使用道具 举报

aliteamer  中级技师
 楼主|

发表于 2020-3-28 22:39:14

laai 发表于 2020-2-26 19:14
顶起~好帖,用MIND+编程可以实现同样效果吗

用MIND+的话就得用DF的OLED屏了~
回复

使用道具 举报

Vibranium  高级技师

发表于 2020-3-31 18:12:52

好评大佬,电量显示很实用呢
回复

使用道具 举报

aliteamer  中级技师
 楼主|

发表于 2020-4-1 00:59:03

Vibranium 发表于 2020-3-31 18:12
好评大佬,电量显示很实用呢

哈哈,不然没电了就尴尬了
回复

使用道具 举报

高级模式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2020 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail