MLX90640作为传感器的热成像仪,主控stm32f401ccu6,板载flash当个u盘存图片,锂电池供电,2寸屏幕,测试电路板是否发烫小工具
mlx90640,虽然价格并不便宜,不过相比于成品产品的便宜不少(功能也对应少一点),主控stm32f401ccu6,充电芯片ip2312,外置flash焊接了一个8m的“大”flash,感觉存图片足够了,屏幕使用的是2寸的spi的屏,没用并口功能已经后悔了,刷新有点慢(能用),懒得改了,电路板图片如下
solidworks绘制外壳:
程序部分使用双线性插值,把传感器像素对应转到屏幕显示大小减去边缘留的一点空,拿来写界面用,用了dsp库中的现成函数,实测和手写的处理速度没差 加了文件系统,存图片有点慢,要好几秒
dsp代码主要如下(总体代码在工程链接中):
// 双线性插值
uint8_t Besize_draw(BMP_8 input_bmp8[],uint8_t method,uint8_t ifsavefile)
{//注释的是自己的插值,现在使用dsp库中提供的
// BMP_8 bmp8[IMG_INITIAL_HEIGHT][IMG_INITIAL_WIDTH];
BMP_8 temp;
BMP_24 temp_24;
RGB565 TEMP_RGB565;
uint16_t color[1];
char filename[20];
int i, j;
int w = IMG_INITIAL_WIDTH;
int h = IMG_INITIAL_HEIGHT;
int iw = IMG_WIDTH;
int ih = IMG_HEIGHT;
float dx=((float)IMG_INITIAL_WIDTH-2.0f)*1.0f/(IMG_WIDTH-1);
float dy=((float)IMG_INITIAL_HEIGHT-2.0f)*1.0f/(IMG_HEIGHT-1);
// for(int a=0;a<IMG_INITIAL_HEIGHT;a++)
// {
// for(int b=0;b<IMG_INITIAL_WIDTH;b++)
// bmp8[a][b].gray_val=input_bmp8[a*IMG_INITIAL_WIDTH+b].gray_val;
// }
arm_bilinear_interp_instance_f32 bilinear_data;
bilinear_data.numCols=IMG_INITIAL_WIDTH;
bilinear_data.numRows=IMG_INITIAL_HEIGHT;
float data[IMG_INITIAL_WIDTH*IMG_INITIAL_HEIGHT];
for(int a=0;a<IMG_INITIAL_HEIGHT*IMG_INITIAL_WIDTH;a++)
{
data[a]=(float)input_bmp8[a].gray_val;
}
bilinear_data.pData=data;
if(ifsavefile)
{
sprintf(filename,"photo%d.bmp",get_filenum());
retSD = f_mount(&spi_fs, "", 1);
if(retSD != FR_OK)
{
if(retSD == FR_NO_FILESYSTEM)
{
//f_mount 没有文件系统,开始格式化spi-flash
retSD = f_mkfs("",FM_FAT32,0,work,sizeof(work));
if(retSD != FR_OK)
{
//f_mkfs 格式化失败
return 1;
}
else
{
//格式化成功,开始重新挂载spi-flash
retSD = f_mount(&spi_fs, "", 1);
if(retSD != FR_OK)
{
return 1;
;//f_mount 发生错误
}
else
{
save_bmp_header(&fil,&bmpinfo);
f_lseek(&fil,66);
}//spi-flash文件系统挂载成功
}
}
else
{
return 1;
}
}
else
{//spi-flash文件系统挂载成功
retSD = f_open(&fil, filename, FA_OPEN_ALWAYS | FA_WRITE);
if(retSD == FR_OK)
{
save_bmp_header(&fil,&bmpinfo);
f_lseek(&fil,66);
}
else
{
return 1;
}
}
}
ST7789_SetAddressWindow((320-IMG_WIDTH)/2, (240-IMG_HEIGHT)/2, IMG_WIDTH+(320-IMG_WIDTH)/2-1, IMG_HEIGHT+(240-IMG_HEIGHT)/2-1);
ST7789_Select();
ST7789_DC_Set();
uint16_t imgdata[IMG_WIDTH*IMG_HEIGHT/4];
uint32_t index=0;
for (j = 0; j < ih; j++)
{
// float fy = ((float)j + 0.5f) * dy - 0.5f;
float fy=(float)j * dy+1 ;
for (i = 0; i < iw; i++)
{
// float fx = ((float)i + 0.5f) * dx - 0.5f;
float fx = (float)i * dx+1 ;
temp.gray_val=(uint8_t)arm_bilinear_interp_f32(&bilinear_data,fx,fy);
// // 四邻域
// int Lx = (int)fx;
// int Rx = Lx + 1;
// int Ly = (int)fy;
// int Ry = Ly + 1;
// Lx = Lx > w - 2 ? w - 2 : Lx < 0 ? 0 : Lx;
// Rx = Rx > w - 1 ? w - 1 : Rx < 0 ? 0 : Rx;
// Ly = Ly > h - 2 ? h - 2 : Ly < 0 ? 0 : Ly;
// Ry = Ry > h - 1 ? h - 1 : Ry < 0 ? 0 : Ry;
// float u = (float)Rx - fx;
// float v = (float)Ry - fy;
// float r1=u*(float)bmp8[Ly][Lx].gray_val+(1-u)*(float)bmp8[Ly][Rx].gray_val;
// float r2=u*(float)bmp8[Ry][Lx].gray_val+(1-u)*(float)bmp8[Ry][Rx].gray_val;
// temp.gray_val=(uint8_t)(v * r1 + (1 - v) * r2);
bmp8_to_color(method,temp.gray_val,&temp_24);
TEMP_RGB565.r_bit =temp_24.r_val>>3;
TEMP_RGB565.g_bit =temp_24.g_val>>2;
TEMP_RGB565.b_bit =temp_24.b_val>>3;
color[0] =(TEMP_RGB565.r_bit << 11 |TEMP_RGB565.g_bit << 5 |TEMP_RGB565.b_bit);
color[0] =( color[0] >> 8) | ((color[0] & 0xFF) << 8);
if(index<IMG_WIDTH*(IMG_HEIGHT/4))
imgdata[index++]=color[0];
else
{
index=0;
imgdata[index++]=color[0];
}
}
if((j+1)%(IMG_HEIGHT/4)==0)
{
HAL_SPI_Transmit(hspi, (uint8_t*)imgdata, sizeof(uint16_t)*IMG_WIDTH*(IMG_HEIGHT/4), HAL_MAX_DELAY);
if(ifsavefile)
{
for(int y=0;y<IMG_HEIGHT/4;y++)
{
for(int x=0;x<IMG_WIDTH;x++)
{
imgdata[y*IMG_WIDTH+x] =( imgdata[y*IMG_WIDTH+x] >> 8) | ((imgdata[y*IMG_WIDTH+x] & 0xFF) << 8);
}
}
f_write(&fil,(uint8_t*)imgdata,sizeof(uint16_t)*IMG_WIDTH*(IMG_HEIGHT/4),&count);
// UART_printf(&huart1,"count=%d\n",count);
}
}
}
ST7789_UnSelect();
if(ifsavefile)
{
if(retSD != FR_OK)
{
f_close(&fil);
return 1;
}
f_close(&fil);
}
return 0;
}
实际效果
电路原理图:
pcb图: