
简易拍立得设计
简介
这个一个可以将三维空间降到二维的装置,任何被他捕捉到的空间,都会被降维到一张小纸条上,人们称他为“二向箔”,哦不,拍立得。
简介:这个一个可以将三维空间降到二维的装置,任何被他捕捉到的空间,都会被降维到一张小纸条上,人们称他为“二向箔”,哦不,拍立得。开源协议
:GPL 3.0
(未经作者授权,禁止转载)描述
项目说明
- 主控使用STM32,并移植LVGL8.2。
- 200万像素摄像头,实现照片拍摄功能。
- 2.8寸TFT液晶显示屏,分辨率240×320。实现照片显示、打印、删除等功能。
- 内置热敏打印单元,可实现拍摄照片打印功能。
- 内置500mAh锂电池,并设计有锂电池充放电管理单。无需外部电源,体积小巧,方便携带。
- 使用波轮按键方便操作,同时提供电源开关键和拍摄按键。
- 支持定时休眠,一键休眠和唤醒,降低功耗。
开源协议
GPL3.0
开源网址:https://gitee.com/liangzili/camera
项目属性
提示:本项目为首次公开,为本人原创项目。项目未曾在别的比赛中获奖。
更新日志
master
- 固件程序修复摄像头清晰度差的问题。
20240720_V2.1
- 固件程序优化热敏打印速度。
- PCB调整DCMI为等长布线。
- PCB调整热敏打印头和摄像头供电部分线宽。
- PCB修复部分丝印被遮挡的问题。
- PCB修复左下角固定孔位置。
20240521_V2.0
- 新增LVGL8.2适配,实现更好的UI效果。
- 新增摄像头驱动电路,减小因摄像模组带来的空间占用。
- 优化RGB565转灰度算法,实现更合理的灰度值输出。
- 修改电源开关位置,解决因电源开关关闭导致无法充电的问题。
- PCB版型修改,下方开槽,方便打印纸卷放置,减小机身厚度。
- 修复LCD FSMC_D1引脚错误。
- 修复因VDDA、VSSA导致的STM32启动失败问题。
- 修复STM32外围滤波电容接地问题。
20240409_V1.0
- 项目首次发布,基本功能实现,完成验证。
硬件设计

主控:STM32F407ZG
选用这款微控制器,是因为STM32F4系列提供了出色的计算能力和实时响应能力。可以为项目中摄像头、屏幕、存储卡、热敏打印头、电池管理、按键控制等提供足够的IO支持及资源支持。
屏幕:2.8寸TFT液晶屏
这款2.8寸的屏幕采用240*320的分辨率,尺寸小巧的同时也能提供不错的显示效果。通过FSMC连接STM32控制器,简化了电路设计和布线,降低了系统成本和复杂度。
摄像头:OV2640摄像头模组
这款200万像素的摄像头,不仅具有极高的性价比,而且完全满足本项目的图像采集需求。通过DCMI连接STM32控制器,提供了高速的数据传输能力。
热敏打印头:精芯 JX-700-48R
设计一款拍立得设备,图像的打印是关键,不仅要体积小巧、重量轻,还要功耗低,而热敏打印就是不错的选择。
电池管理:TP4056
TP4056采用恒定电流/恒定电压(CCCV)充电模式,能够自动完成整个充电过程,包括涓流预充、恒流快速充电和恒压充电阶段,有效保证电池的健康和长寿命。
软件设计
软件界面:

受篇幅限制,这里只针对部分关键代码进行讲解。
热敏打印功能实现:
当系统检测到打印键按下时,将获取当前图片的路径,并调用如下函数,此函数用于从给定路径读取一个BMP图像文件,并将其转换为热敏打印机的数据格式进行打印。
static void PrintFile(char *path)
{
FRESULT res;
FIL file; // 文件对象
UINT br; // 实际读取的字节数
uint16_t line = 0; // 当前打印行号
uint16_t lineDateTemp[384]; // 文件内容缓存,保存一行图片数据
res = f_open(&file, path, FA_READ);
if (res != FR_OK)
{
printe("文件打开失败\n");
}
/* 从bmp头 获取图片信息 */
BITMAPINFO hbmp;
res = f_read(&file, &hbmp, sizeof(BITMAPINFO), &br);
if (res != FR_OK)
{
printe("文件读取失败\n");
}
uint32_t bfOffBits = hbmp.bmfHeader.bfOffBits; // 位图数据偏移量
uint16_t w = hbmp.bmiHeader.biWidth; // 图象的宽度,以象素为单位
uint16_t h = hbmp.bmiHeader.biHeight; // 图象的高度,以象素为单位
printi("位图数据偏移量:%d,宽度:%d,高度:%d。\n",bfOffBits,w,h);
f_lseek(&file, bfOffBits); // 移动文件指针跳过bmp文件头
memset(lineDateTemp, 0xFF, sizeof(lineDateTemp)); // 行数据点默认为白色
do{
res = f_read(&file, lineDateTemp, w*2, &br); // 一次读取1行像素,16bit,一个像素2个字节
if(w < 384) // 图片宽度小于打印宽度
{
memmove(lineDateTemp + (384 - w)/2, lineDateTemp, w*2); // 数据整体移动,使图像保持居中
memset(lineDateTemp,0xFF, (384 - w)/2); // 填充白色
}
if(res != FR_OK)
{
printf("文件读取失败\n");
break;
}
uint8_t printLine[48]; // 一行打印数据48字节DotS
for(uint16_t i = 0;i < 384;i+=8) // 对当前 DOT点 进行处理,打印宽度
{
uint8_t packedByte = 0; // 将8个二值化像素合并为一个字节
for(uint8_t j = 0;j < 8;j++) // 3.将8个二值化后的像素(每个像素1位)合并成一个字节
{
uint8_t gray = RGB565ToGray(lineDateTemp[384 - i - j]);// 1.RGB565格式转灰度图,uint16_t => uint8_t
packedByte |= GrayToBinary(gray, 127) << (7 - j); // 2.根据灰度值设定阈值进行二值化处理,阈值为128
if(j == 7)
{
printLine[i/8] = packedByte; // 4.将处理好的数据添加到打印数组,等待打印
}
}
}
printf("打印line%d\n",line);
LinePrint(printLine);
if (res != FR_OK)
{
printf("f_lseek err\n");
}
line++;
}while(br > 0);
PrinterStep(80);//打印完成的出纸长度
StopPrint();
f_close(&file);
}
// RGB565转灰度
uint8_t RGB565ToGray(uint16_t rgb565)
{
uint32_t gray;
uint8_t r = (rgb565 >> 11) & 0x1F; // R 5 bits
uint8_t g = (rgb565 >> 5) & 0x3F; // G 6 bits
uint8_t b = rgb565 & 0x1F; // B 5 bits
gray = (r*30*8 + g*59*4 + b*11*8 + 50) / 100; // 注意,这里使用的是近似的人眼感知权重:R*30%, G*59%, B*11%。加50是为了四舍五入。
return (uint8_t)gray; // 确保结果在0-255范围内,尽管这里计算的结果自然就在该范围内
}
// 二值化处理
uint8_t GrayToBinary(uint8_t gray, uint8_t threshold) {
return (gray >= threshold) ? 0 : 1;
}
结构设计


实物展示


物料采购
可下载附件中的表格

设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程知识产权声明&复刻说明
本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。
请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。










