STM32
直播中

qjqb

8年用户 1302经验值
擅长:5762
私信 关注
[问答]

怎样去设计一种基于MLX90614和OpenMV-H7的温度传感器呢

MLX90614系列模块是什么?OpenMV-H7又是什么?

怎样去设计一种基于MLX90614和OpenMV-H7的温度传感器呢?

回帖(1)

李璐

2021-11-10 09:51:26
  使用RT1064作为主控,用的之前的车赛板子
  不得不说逐飞的库真滴好用 ^ ^
  测温传感器——MLX90614红外测温模块
  MLX90614 系列模块是一组通用的红外测温模块。在出厂前该模块已进行校验及线性化,具有非接触、体积小、精度高,成本低等优点。被测目标温度和环境温度能通过单通道输出,并有两种输出接口,适合于汽车空调、室内暖气、家用电器、手持设备以及医疗设备应用等。MLX90614温度传感器是一个标准IIC通信协议的温度传感器。它具有体积小,成本低,易集成等优异性能。温宽范围在-40℃~+125℃,最为重要的是它的精度可达到±0.5℃,被广泛的应用于现代医疗领域。做为本设计温度传感器效果极佳。
  物体红外辐射能量的大小和波长的分布与其表面温度关系密切。因此,通过对物体自身红外辐射的测量,能准确地确定其表面温度,红外测温就是利用这一原理测量温度的。红外测温器由光学系统、光电探测器、信号放大器和信号处理及输出等部分组成。
  光学系统汇聚其视场内的目标红外辐射能量,视场的大小由测温仪的光学零件及其位置确定。红外能量聚焦在光电探测器上并转变为相应的电信号。该信号经过放大器和信号处理威廉希尔官方网站 ,并按照仪器内的算法和目标发射率校正后转变为被测目标的温度值。
  PWM 的全称是 Pulse Width Modulation(脉冲宽度调制)即通过调节脉冲的周期、宽度,以达到变压、变频的目的,数字式脉宽调制方式中,数字是控制信号,通过改变高低电平数的比值达到改变占空比的目的, PWM 控制威廉希尔官方网站 在开关稳压电源、不间断电源(UPS)以及直流电机调速,交流电机变频调速等控制威廉希尔官方网站 中有着广泛应用。
  SMBus (System Management Bus,)是 1995 年由 intel 公司提出的一种高效同步串行总线,SMBus 只有两根信号线:双向数据线和时钟信号线,容许 CPU 与各种外围接口器件以串行方式进行通信、交换信息,即可以提高传输速度也可以减小器件的资源占用,另外即使在没有SMBus 接口的单片机上也可利用软件进行模拟。
  Melexis 公司生产的 MLX90614 系列测温模块是应用非常方便的红外测温装置,其所有的模块都在出厂前进行了校验,并且可以直接输出线性或准线性信号,具有很好的互换性,免去了复杂的校正过程。该模块以 81101 热电元件作为红外感应部分。输出是被测物体温度(TO)与传感器自身温度(Ta)共同作用的结果,理想情况下热电元件的输出电压为:
  Vir = A(to)
  其中温度单位均为 Kelvin, A 为元件的灵敏度常数。目标温度和环境温度由 81101 内置的热电偶测定测量,从 81101 中输出的两路温度信号分别经内部 MLX90302 器件上高性能、低噪声的斩波稳态放大器放大再经一个 17-bit 的模数转换器(ADC)和强大的数字信号处理(DSP)单元后输出。该系列模块的温度解析度可达 0.01°C,体积小巧,被测目标和环境温度能通过单通道(由 MLX90302 内的状态机控制)输出,有两种输出方式: PWM 输出、可编程 SMBus 输出,适于多种应用环境。
  读取数据:
  
  写入数据:
  
  摄像头——Openmv4H7
  
  OpenMV-H7是低功耗的Python3可编程机器视觉硬件,结合摄像头可以支持一系列广泛的图像处理功能和神经网络。OpenMV-H7使用跨平台 IDE 进行编程,该 IDE 允许查看摄像机的帧缓冲器、访问传感器控件、通过 USB 串行(或 WiFi/BLE(如果可用)将脚本上传到摄像机。OpenMV-H7 基板基于在 400MHz 下运行的STM32H743 MCU,具有 1MB SRAM、2MB 闪存、FPU、DSP 和硬件 JPEG 编码器。基板采用模块化传感器设计,将传感器与摄像机分离。模块化传感器设计使摄像机能够支持多个传感器,包括 OV7725、MT9V03x 全球快门传感器和 FLIR Lepton 1、2 和 3 热传感器。它的机器视觉算法包括寻找色块、边缘检测、标志跟踪等。我们可以利用其寻找色块算法进行防疫检测识别。它在本设计中可以充分发挥出非常好的作用。
  电子信息专业,视觉小白,泪目了。。。
  C语言部分代码
  #include “headfile.h”
  //串口接线 openmv: 红色线在上
  //按下实行人脸识别和
  #define KEY1 C25
  #define KEY2 C27
  //板子上左编码器处
  #define KEY3 C0
  #define KEY4 C1
  //板子上右编码器
  #define KEY5 C2
  #define KEY6 C24 //温度开启按键
  #define JIGUANG C3026
  float temperature22;
  //开关状态变量
  uint8 key1_status = 1;
  uint8 key2_status = 1;
  //温度阈值加减
  uint8 key3_status = 1;
  uint8 key4_status = 1;
  //进入口罩检测
  uint8 key5_status = 1;
  //返回人脸检测
  uint8 key6_status = 1;
  //上一次开关状态变量
  uint8 key1_last_status;
  uint8 key2_last_status;
  uint8 key3_last_status;
  uint8 key4_last_status;
  uint8 key5_last_status; //切换到口罩追踪识别
  uint8 key6_last_status; //切换回人脸追踪
  //开关标志位
  uint8 key1_flag;
  uint8 key2_flag;
  uint8 key3_flag;
  uint8 key4_flag;
  uint8 key5_flag;
  uint8 key6_flag;
  /
  uint8 rec_val;27
  int8 rec_display[2];
  int8 temp_str[]=“Temperature:”;
  uint8 led_flag;
  uint8 temp_yuzhi=30;
  uint8 buzzer_flag=1;
  u8 key5_index=0;
  u8 temp_key6_count=0; //1 开启测温 2 停止测温
  u8 temp_start_flag=0;
  int main(void)
  {
  DisableGlobalIRQ();
  board_init();//务必保留,本函数用于初始化 MPU 时钟 调试串口
  //此处编写用户代码(例如:外设初始化代码等)
  oled_init();
  simiic_init();
  pit_init();
  //串口初始化
  uart_init(USART_4,115200,UART4_TX_C16,UART4_RX_C17);
  gpio_init(KEY1, GPI, 0, GPIO_PIN_CONFIG);
  gpio_init(KEY2, GPI, 0, GPIO_PIN_CONFIG);
  gpio_init(KEY3, GPI, 0, GPIO_PIN_CONFIG);
  gpio_init(KEY4, GPI, 0,GPIO_PIN_CONFIG);
  gpio_init(KEY5, GPI, 0,GPIO_PIN_CONFIG);
  gpio_init(KEY6, GPI, 0,GPIO_PIN_CONFIG);
  //LED,BUZZER INIT
  gpio_init(B9, GPO, 1, GPIO_PIN_CONFIG);28
  gpio_init(B15, GPO, 1, GPIO_PIN_CONFIG);
  //JIGUANG INIT
  gpio_init(C30, GPO,0,GPIO_PIN_CONFIG); //不亮
  oled_p6x8str(0,0,temp_str); //temperature
  oled_print_chinese(96,0,16,oled_16x16_chinese[26],1); //℃
  //显示报警温度阈值
  oled_print_chinese(0,2,16,oled_16x16_chinese[16],5);
  pit_interrupt_ms(PIT_CH0,200);
  NVIC_SetPriority(PIT_IRQn,15);
  //uart_putchar(USART_4,‘1’);
  //总中断最后开启
  EnableGlobalIRQ(0);
  while (1)
  {
  oled_int16(75,3,temp_yuzhi);
  //保存按键状态
  key1_last_status = key1_status;
  key2_last_status = key2_status;
  key3_last_status = key3_status;
  key4_last_status = key4_status;
  key5_last_status = key5_status;
  key6_last_status = key6_status;
  //读取当前按键状态
  key1_status = gpio_get(KEY1);
  key2_status = gpio_get(KEY2);
  key3_status = gpio_get(KEY3);
  key4_status = gpio_get(KEY4);
  key5_status = gpio_get(KEY5);
  key6_status = gpio_get(KEY6);
  //检测到按键按下之后 并放开置位标志位
  if(key1_status && !key1_last_status) key1_flag = 1;
  if(key2_status && !key2_last_status) key2_flag = 1;
  if(key3_status && !key3_last_status) key3_flag = 1;
  if(key4_status && !key4_last_status) key4_flag = 1;
  if(key5_status && !key5_last_status) key5_flag = 1;29
  if(key6_status && !key6_last_status) key6_flag = 1;
  //标志位置位之后,可以使用标志位执行自己想要做的事件
  //按键逻辑:
  //进入人脸识别
  if(key1_flag)
  {
  key1_flag = 0;//使用按键之后,应该清除标志位
  uart_putchar(USART_4,‘1’);
  systick_delay_ms(1000);
  }
  //进入人脸采集
  if(key2_flag)
  {
  key2_flag = 0;//使用按键之后,应该清除标志位
  uart_putchar(USART_4,‘2’);
  systick_delay_ms(1000);
  }
  if(key3_flag)
  {
  key3_flag = 0;//使用按键之后,应该清除标志位
  if(temp_yuzhi《46)
  {
  temp_yuzhi++;
  }
  //systick_delay_ms(1000);
  }
  if(key4_flag)
  {
  key4_flag = 0;//使用按键之后,应该清除标志位
  if(temp_yuzhi》30)
  {
  temp_yuzhi--;
  }
  //systick_delay_ms(1000);
  }
  //进入口罩识别
  if(key5_flag)
  {30
  key5_flag = 0;//使用按键之后,应该清除标志位
  key5_index++;
  uart_putchar(USART_4,‘3’);
  if(key5_index==2) //0 口罩 1 人脸
  {
  key5_index=0;
  }
  if(key5_index==1)
  {
  kouzhao_flag=2;
  gpio_set(B9,1);
  oled_print_chinese(0,6,16,oled_16x16_chinese[66],2); // 三个空格
  oled_print_chinese(32,6,16,oled_16x16_chinese[108],6); //前面空三个汉字
  的显示
  }
  systick_delay_ms(1000);
  }
  if(key6_flag) //控制测温是否开启
  {
  key6_flag = 0;//使用按键之后,应该清除标志位
  temp_key6_count++;
  if(temp_key6_count==2)
  {
  temp_key6_count=0;
  }
  if(temp_key6_count==1)
  {
  temp_start_flag=1;
  }
  else
  {
  temp_start_flag=0;
  }
  systick_delay_ms(1000);
  }
  if(mm_flag2==1)
  {
  oled_print_chinese(0,4,16,oled_16x16_chinese[40],8); // 身份待识别
  }
  if(mm_flag2==2)
  {
  oled_print_chinese(0,4,16,oled_16x16_chinese[56],8); //识别失败31
  }
  if(kouzhao_flag==2) //未识别到口罩
  {
  oled_print_chinese(0,6,16,oled_16x16_chinese[66],2); // 三个空格
  oled_print_chinese(32,6,16,oled_16x16_chinese[108],6); //前面空三个汉字的
  显示
  }
  if(kouzhao_flag==1) //识别到口罩
  {
  oled_print_chinese(0,6,16,oled_16x16_chinese[66],3); // 三个空格
  oled_print_chinese(48,6,16,oled_16x16_chinese[110],5); //前面空三个汉字的显
  示
  }
  // 单片机接受 openmv 发的串口数据
  if(uart_query(USART_4,&rec_val))
  {
  rec_display[0]=rec_val;
  if(rec_display[0]==‘1’) //任世豪
  {
  mm_flag2=0;
  oled_print_chinese(0,4,16,oled_16x16_chinese[28],5); //识别成功:
  oled_print_chinese(70,4,16,oled_16x16_chinese[0],3);
  }
  if(rec_display[0]==‘2’) //周进
  {)
  oled_print_chinese(0,4,16,oled_16x16_chinese[28],5); //识别成功:
  oled_print_chinese(70,4,16,oled_16x16_chinese[12],2);
  oled_print_chinese(102,4,16,oled_16x16_chinese[38],1);
  mm_flag2=0;
  }
  if(rec_display[0]==‘3’) //伍郭成
  {
  oled_print_chinese(0,4,16,oled_16x16_chinese[28],5); //识别成功:
  oled_print_chinese(70,4,16,oled_16x16_chinese[6],3);
  mm_flag2=0;
  }
  if(rec_display[0]==‘4’) //识别失败
  {
  if(buzzer_flag)
  {
  buzzer_flag=0;32
  gpio_set(B15,0);
  systick_delay_ms(500);
  gpio_set(B15,1);
  systick_delay_ms(500);
  gpio_set(B15,0);
  systick_delay_ms(500);
  gpio_set(B15,1); //关
  systick_delay_ms(500);
  }
  }
  if(rec_display[0]==‘5’) //新人员
  {
  oled_print_chinese(0,4,16,oled_16x16_chinese[28],5); //识别成功:
  oled_print_chinese(70,4,16,oled_16x16_chinese[120],3);
  mm_flag2=0;
  }
  if(rec_display[0]==‘6’) //识别失败
  {
  mm_flag2=2;
  systick_delay_ms(1);
  if(buzzer_flag)
  {
  gpio_set(B15,0);
  systick_delay_ms(500);
  gpio_set(B15,1);
  systick_delay_ms(500);
  gpio_set(B15,0);
  systick_delay_ms(500);
  gpio_set(B15,1); //关
  systick_delay_ms(500);
  }
  }
  if(rec_display[0]==‘a’) //口罩识别通过,,显示已佩戴口罩
  {
  gpio_set(B9,0);
  kouzhao_flag=1;
  }
  if(rec_display[0]==‘b’) //口罩识别失败, LED 熄灭,显示未佩戴
  口罩
  {33
  gpio_set(B9,1);
  kouzhao_flag=2;
  }
  }
  if(temp_start_flag)
  {
  if(temp_flag)
  {
  temp_flag=0;
  temperature22 = MLX90614_Get_Temperature();
  }
  gpio_set(C30,1);
  }
  else
  {
  gpio_set(C30,0);
  }
  if(temperature22》=temp_yuzhi)
  {
  gpio_set(B9,0);
  systick_delay_ms(500);
  gpio_set(B9,1);
  systick_delay_ms(500);
  gpio_set(B15,0);
  }
  else
  {
  gpio_set(B15,1);
  }
  oled_printf_float(53,1,temperature22,2,3);
  }
  }在这里插入代码片
  使用Openmv进行身份识别和口罩佩戴的判断
  from pyb import millis
  from math import pi, isnan
  import sensor, time, image, pyb
  from pyb import UART
  from pyb import Servo
  from pid import PID
  from pyb import Servo
  import os
  pan_servo=Servo(1)
  tilt_servo=Servo(2)
  red_threshold =[(1, 74, 4, 27, 27, 8), #人脸颜色
  (0, 86, -10, -128, -10, -40)]
  #(0, 100, -128, 127, -128, -9)]
  # #
  (59, 80, -14, -74, -29, 75)] #blue
  #(0, 86, -10, -128, -10, -40) 对着白墙得到的数值,下午 14:23
  threshold_index = 1
  #blue_threshold =(59, 80, -14, -74, -29, 75)
  pan_pid = PID(p=0.07, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个 PID
  tilt_pid = PID(p=0.05, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个 PID
  NUM_SUBJECTS = 3 #图像库中不同人数,一共 6 人
  import sensor, image, time
  RED_LED_PIN = 1
  BLUE_LED_PIN = 3
  #sensor.set_vflip(True)
  uart = UART(3, 115200)35
  num=0
  ‘’‘
  def mkdir(path):
  folder = os.path.exists(path)
  uos.path.e
  if not folder: #判断是否存在文件夹如果不存在则创建为文件夹
  os.makedirs(path) #makedirs 创建文件时如果路径不存在会创建这个路径
  print(“--- new folder.。. ---”)
  print(“--- OK ---”)
  else:
  print(“--- There is this folder! ---”)
  ’‘’
  class collect_face:
  def collect(self):
  sensor.reset() # Initialize the camera sensor.
  sensor.set_pixformat(sensor.GRAYSCALE) # or sensor.GRAYSCALE
  sensor.set_framesize(sensor.B128X128) # or sensor.QQVGA (or others)
  sensor.set_windowing((92,112))
  sensor.skip_frames(10) # Let new settings take affect.
  sensor.skip_frames(time = 2000)
  num = 4 #设置被拍摄者序号,第一个人的图片保存到 s1 文件夹,第二个人的
  图片保存到 s2 文件夹,以此类推。每次更换拍摄者时,修改 num 值。
  n = 17 #设置每个人拍摄图片数量。
  #连续拍摄 n 张照片,每间隔 3s 拍摄一次。
  while(n):
  #红灯亮
  pyb.LED(RED_LED_PIN).on()
  sensor.skip_frames(time = 3000) # Give the user time to get ready.等待 3s,准备
  一下表情。
  #红灯灭,蓝灯亮
  pyb.LED(RED_LED_PIN).off()
  pyb.LED(BLUE_LED_PIN).on()
  #保存截取到的图片到 SD 卡
  print(n)36
  sensor.snapshot().save(“singtown/s%s/%s.pgm” % (num, n) ) # or “example.bmp”
  (or others)
  n -= 1
  pyb.LED(BLUE_LED_PIN).off()
  print(“Done! Reset the camera to see the saved image.”)
  num+=1
  class face_rendering:
  #def __init__(self)
  #self.num =0
  def min(self,pmin, a, s):
  if a《pmin:
  pmin=a
  self.num=s
  return pmin
  def start_face_rendering(self):
  sensor.reset() # Initialize the camera sensor.
  sensor.set_pixformat(sensor.GRAYSCALE) # or sensor.GRAYSCALE
  sensor.set_framesize(sensor.B128X128) # or sensor.QQVGA (or others)
  sensor.set_windowing((92,112))
  sensor.skip_frames(10) # Let new settings take affect.
  sensor.skip_frames(time = 5000) #等待 5s
  s3 = Servo(3) # servo on position 1 (P7)
  #将蓝灯赋值给变量 led
  led = pyb.LED(3) # Red LED = 1, Green LED = 2, Blue LED = 3, IR LEDs = 4.
  #SUB = “s1”
  #NUM_SUBJECTS = 3 #图像库中不同人数,一共 6 人
  NUM_SUBJECTS_IMGS = 17 #每人有 20 张样本图片
  # 拍摄当前人脸。
  img = sensor.snapshot()
  #img = image.Image(“singtown/%s/1.pgm”%(SUB))
  d0 = img.find_lbp((0, 0, img.width(), img.height()))
  #d0 为当前人脸的 lbp 特征
  img = None
  pmin = 999999
  self.num=037
  for s in range(1, NUM_SUBJECTS+1):
  dist = 0
  for i in range(2, NUM_SUBJECTS_IMGS+1):
  img = image.Image(“singtown/s%d/%d.pgm”%(s, i))
  d1 = img.find_lbp((0, 0, img.width(), img.height()))
  #d1 为第 s 文件夹中的第 i 张图片的 lbp 特征
  dist += image.match_descriptor(d0, d1)#计算 d0 d1 即样本图像与被检测人脸
  的特征差异度。
  print(“Average dist for subject %d: %d”%(s, dist/NUM_SUBJECTS_IMGS))
  pmin = self.min(pmin, dist/NUM_SUBJECTS_IMGS, s)#特征差异度越小,被检测
  人脸与此样本更相似更匹配。
  print(pmin)
  print(self.num) # num 为当前最匹配的人的编号。
  if pmin《=6000:
  if self.num==1: #任世豪
  uart.write(‘1’)
  if self.num==2: #周进
  uart.write(‘2’)
  if self.num==3: #伍郭成
  uart.write(‘3’)
  if self.num==4:
  uart.write(‘5’) #新添加人员
  #uart.write(“a”)
  led.on() #亮灯
  led1.off()
  time.sleep(3500) #延时 1500ms
  led.off()
  else:
  uart.write(‘6’) #识别失败
  t = collect_face()
  y= face_rendering(0)
  sensor.reset()
  sensor.set_pixformat(sensor.RGB565)
  sensor.set_framesize(sensor.QVGA)38
  sensor.skip_frames(time = 2000)
  #sensor.skip_frames(10) # Let new settings take affect.
  sensor.set_auto_whitebal(False) # turn this off.
  def find_max(blobs):
  max_size=0
  for blob in blobs:
  if blob[2]*blob[3] 》 max_size:
  max_blob=blob
  max_size = blob[2]*blob[3]
  return max_blob
  led1 = pyb.LED(1)
  c= “hg”
  while(1):
  #sensor.reset()
  sensor.set_pixformat(sensor.RGB565)
  sensor.set_framesize(sensor.QVGA)
  #sensor.skip_frames(time = 2000)
  #uart.write(‘k’)
  #clock.tick()
  #uart.write(‘2’)
  img = sensor.snapshot() # Take a picture and return the image.
  if uart.any():
  c=uart.readline()
  print(c[0])
  #c= ‘2’ 接收单片机的串口信息来执行相应功能
  if c[0]== 49: #‘1’
  print(“Face recognition”)
  led1.on()
  y.start_face_rendering()
  led1.off()
  if c[0]== 50: #‘2’39
  print(“Face acquisition”)
  NUM_SUBJECTS+=1
  t.collect()
  # led.on()
  if c[0]== 51: #‘3’ //转到人脸
  print(“change”)
  text=2
  threshold_index=threshold_index+1
  if threshold_index==2:
  threshold_index=0
  #clock.tick()
  ‘’‘count=0
  for i in range(1000):
  img = sensor.snapshot()
  blob = img.find_blobs([red_threshold[1]], area_threshold=300)
  if blob:
  count+=1
  if count《=10:
  uart.write(“b”)
  else:
  uart.write(“a”)’‘’
  c=“52”
  blobs = img.find_blobs([red_threshold[threshold_index]],area_threshold=2500)
  if blobs:
  text=1
  if threshold_index==1:
  if text==1:
  uart.write(“a”) #识别到口罩
  max_blob = find_max(blobs)
  pan_error = max_blob.cx()-img.width()/2
  tilt_error = max_blob.cy()-img.height()/2
  #print(“pan_error: ”, pan_error)
  img.draw_rectangle(max_blob.rect()) # rect
  img.draw_cross(max_blob.cx(), max_blob.cy()) # cx, cy
  pan_output=pan_pid.get_pid(pan_error,1)/2
  tilt_output=tilt_pid.get_pid(tilt_error,1)40
  #print(“pan_output”,pan_output)
  pan_servo.angle(pan_servo.angle()+pan_output)
  tilt_servo.angle(tilt_servo.angle()-tilt_output)
  else:
  text=2
  if threshold_index==1:
  if text==2:
  uart.write(“b”) #未识别到口罩
  #if threshold_index==1:
  #print(text)
  #print(text)
  #口罩判断
  img = sensor.snapshot()
  for blob in img.find_blobs([red_threshold[threshold_index]], pixels_threshold=200, ar
  ea_threshold=2500, merge=True):
  # These values depend on the blob not being circular - otherwise they will be shaky.
  #if blob.elongation() 》 0.5:
  #img.draw_edges(blob.min_corners(), color=(255,0,0))
  #img.draw_line(blob.major_axis_line(), color=(0,255,0))
  #img.draw_line(blob.minor_axis_line(), color=(0,0,255))
  # These values are stable all the time.
  img.draw_rectangle(blob.rect())
  img.draw_cross(blob.cx(), blob.cy())
  # Note - the blob rotation is unique to 0-180 only.
  # img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size
  =20)
  #print(clock.fps())
  #print(blob.code())
举报

更多回帖

发帖
×
20
完善资料,
赚取积分