肺炎疫情期间,在家自制红外测温枪
疫情期间在家自制一把红外测温枪,每天给家人量体温——使用Arduino Nano和MLX90614红外测温模块
新冠肺炎疫情已经爆发一个多月了,各位老铁想必在家也快憋疯了。先前是口罩被抢购一空,现在测温枪也是不太好买,正好在家“自我隔离”,突然想起库存里还有一个红外测温模块,碰巧看到之前一位大神自制的红外测温枪,就借用了下大神设计的模型稍加改动(物理破坏),加上手边的一些元器件,做了一个测温枪。屏幕可显示体温(目标温度),室温(环境温度)、电量和体温情况,内置锂电池,可充电。
主控使用了Arduino Nano 328p(因为是手头最小的板子了),传感器使用了MLX90614红外测温模块(测温)和Gravity: I2C 3.7V锂电池电量计 (电量检测),显示屏使用了常见的0.96寸OLED屏(IIC)。因为制作之前没有拍照片,只有制作完成后的照片,所以各位看官老爷凑合看吧。
材料清单:
1.Arduino Nano 328p1只
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屏、电量计、激光头通过电子线焊接到主控板上
第三步:制作锂电池一分二电源线、Micro USB延长线和USBA插头线
一分二电源线用于分别给升压模块供电和电量计检测电量(拨动开关焊接到电源线上)
USB延长线用于连接升压模块
USBA插头线给主板供电
第四步:上传程序(有一部分多余代码懒得删了)
#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0); // I2C / TWI
static const unsigned char shiwen 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 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 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 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 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 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);
u8g.drawXBMP( 16, 4,16, 16, tiwen);
u8g.drawXBMP( 32, 4,16, 16, tiwen);
float O = MLX90614.GetObjectTemp_Celsius();
u8g.setPrintPos(40,19);
u8g.print(O);
u8g.drawXBMP( 92, 4,16, 16, sheshidu);
//室温显示
u8g.drawXBMP( 0, 24,16, 16, shiwen);
u8g.drawXBMP( 16, 24,16, 16, shiwen);
u8g.drawXBMP( 32, 24,16, 16, shiwen);
float A = MLX90614.GetAmbientTemp_Celsius();
u8g.setPrintPos(40,39);
u8g.print(A);
u8g.drawXBMP( 92, 24,16, 16, sheshidu);
//电量显示
u8g.drawXBMP( 0, 44,16, 16, dl);
u8g.drawXBMP( 16, 44,16, 16, dl);
u8g.drawXBMP( 32, 44,16, 16, dl);
u8g.setPrintPos(40,59);
u8g.print(gauge.readPercentage());
u8g.drawXBMP( 92, 44,16, 16, dl);
//体温判断
u8g.drawXBMP( 111, 0,16, 16, tiwen);
u8g.drawXBMP( 111, 16,16, 16, tiwen);
u8g.drawXBMP( 111, 48,16, 16, zhengchang);
if(32 <= O && O <37.3){
u8g.drawXBMP( 111, 32,16, 16, zhengchang);
}
else{
u8g.drawXBMP( 111, 32,16, 16, yichang);
}
}
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
}·
}
第五步:安装各模块(使用热熔胶和美纹纸包裹端点,防止短路),完成组装
资料下载:
0.96寸OLED屏相关资料:示例程序、库文件、取模软件等 网盘链接 提取码:vktz
项目附件下载:
这个项目很棒啊{:6_215:} rzyzzxw 发表于 2020-2-16 15:37
这个项目很棒啊
谢谢版主的认可{:6_204:} 请问环境温度怎么取得? 知道了,传感器自身输出两个温度。 喜欢,好文章!{:6_213:} rzegkly 发表于 2020-2-17 09:33
喜欢,好文章!
哈哈,第一次写,没什么经验,请前辈们多多指教{:5_190:} glwz007 发表于 2020-2-16 21:23
知道了,传感器自身输出两个温度。
对的,这个传感器可以测量目标温度和环境温度 又是一篇好文,支持。 太棒了,一定好好学习 很赞!!! 顶起~好帖,用MIND+编程可以实现同样效果吗 啊哈哈哈 这个可以 非常实用 laai 发表于 2020-2-26 19:14
顶起~好帖,用MIND+编程可以实现同样效果吗
用MIND+的话就得用DF的OLED屏了~ 好评大佬,电量显示很实用呢 Vibranium 发表于 2020-3-31 18:12
好评大佬,电量显示很实用呢
哈哈,不然没电了就尴尬了
页:
[1]