目录
1、项目说明
此项目参与嘉立创的“星火计划”外包赛道,由武汉芯源半导体公司和嘉立创共同发布题目,本项目耗时两个月,自主设计一款便携、可充电的环境辐射检测仪。
该工程所用到的电子元器件均可在某宝购买到,同时贴片规格均采用0805的封装便于焊接(除充电部分的热敏电阻)。
该工程分为1.0和2.0版本,1.0版本是单独电路的调试,适合项目初期,2.0版本是集成到一起的。
2、开源协议
- LGPL 3.0
- 禁止用于商业和复刻者售卖
3、项目相关功能
- 可根据辐射值的大小进行声光提示
- 可通过手机充电器进行充电,无须频繁更换电池,保护环境。
- 丰富的UI界面,使用者可以直观的看到当前的辐射量的相关参数
- 当TYPE-C接口被插入时,会自动更换供电电路,整个电路的供电为充电器供电,同时为电池充电。
4、项目属性
- 原创作品,禁止用作商业用途和谋取利益
5、项目进度
- 2023.9.1开始项目的制作,同时开始仿真电路的搭建。
- 2023.9.4PCB板绘制完成,但是考虑到焊接难度和复刻难度,果断放弃。
- 2023.9.17PCB板绘制完成,此次的PCB布局为模块布局,方便调试。
- 2023.10.10 PCB调试成功,开始正式画V2.0版本。
- 2023.11.07 V2.0版本绘制完成,开始编写程序,并且开始打印外壳。
- 2023.11.17 完结
6、设计原理
- 利用MOS管的导通实现一个开关电路,即当有外部电源供电时自动切断电池的输出,由外部电源对整个电路供电同时对电池进行充电。
- 采用TP4056X 锂电池充电芯片,对电池进行充电,并且本工程采用的充电电路带有温度反馈,过热自动断开充电,避免危险发生。并且相对TP4056,TP4056X自带反接保护,这使得外部电路更加简洁。
- 采用SX1308 升压芯片将锂电池4.2V升压到5V,避免了因为电池电压过低造成芯片的不正常工作,同时这样的设计使得盖革管的工作电压稳定,避免了因为电池电量低造成的计数异常。
- 采用Boost升压电路配合TLC555实现升压,通过调节可调电阻改变定时器的占空比,实现对升压的可调。
- 采用AMS-117 3.3V LDO线性降压芯片,将稳压后的5V降压到3.3V给单片机供电。
- 采用LCD_TFT 1.8寸屏幕,可对采集到的数据进行显示。
- 通过一个三极管实现计数,当有辐射源时,其释放出的射线穿过盖革管会被电离,此时会产生一个脉冲信号,此时三极管导通,同时将单片机的GPIO口配置为上拉输入,当三极管导通时GPIO口为低电平则进入中断一次,实现一次计数。
- 数值的换算,通过配置定时器实现1S的计时,即每1S读取一次GPIO的中断次数,在主循环里面进行判断定时器标志位是否改变,来实现每1S 的读取数据,并且换算成相应的辐射值,这样通过判断标志位的方法可以避免在定时器中断里面执行太多的函数造成程序的堵塞。
- 蜂鸣器报警声音频率随辐射值的变化而声音频率不同,我采用的是直接写死这部分代码,即分为多个等级,每个等级对应不同的频率,频率的改变是通过延时实现的,但是传统的蜂鸣器鸣叫大多数用的是延时函数,那样会阻塞程序的正常运行,所以我采取的方法是通过配置一个1MS的定时器,在定时器内实现延时,即判断给定的时间长短,然后在中断内用 if语句去判断有没有到时间。此部分的内容较为绕口,要多读几遍。
- 屏幕的刷新采用标志位的形式,即在第9点中提到的多个等级,不同等级对应的标志位不同,从而去判断需不需要刷新屏幕的背景颜色。
7、软件说明
int on_time = 0,off_time = 0,last_on_time=0,last_off_time = 0;
/**
* @brief This funcation handles BTIM2
*/
void BTIM2_IRQHandler(void)
{
/* USER CODE BEGIN */
if(BTIM_GetITStatus(CW_BTIM2,BTIM_IT_OV)==SET)
{
if(on_time>0)
{
on_time--;
Bozzer_on;//蜂鸣器响
}
else if(off_time>0)
{
off_time--;
Bozzer_off;//蜂鸣器关
}
else
{
on_time = last_on_time;
off_time = last_off_time;
}
}
BTIM_ClearITPendingBit(CW_BTIM2,BTIM_IT_OV);
/* USER CODE END */
}
这部分代码是在1MS的定时器的中断中需要执行的任务,on_time和off_time是蜂鸣器响和关的时间,例如把on_time设置为100,即蜂鸣器响100ms,
last_on_time和last_off_time是为保存上一次设置的时间,这样用处是蜂鸣器可以一直重复的响,不然就是每设置一次值蜂鸣器才会响。
while(1)
{
sprintf(temp1, "%.4f", InstVal);
sprintf(temp2, "%.4f", Cumval);
sprintf(temp3, "%.4f", Aveval);
sprintf(temp4, "%d", count);
Gui_DrawFont_GBK24(10,64,WHITE,BLUE,temp2); //累计值
Gui_DrawFont_GBK24(80,64,WHITE,BLUE,"uSv/h");
Gui_DrawFont_GBK24(10,102,WHITE,BLACK,temp3); //平均值
Gui_DrawFont_GBK24(80,102,WHITE,BLACK,"uSv/h");
Gui_DrawFont_GBK24(70,130,WHITE,BLACK,temp4); //计数值
switch(color_Flag)
{
case 0 : Gui_DrawFont_GBK16(40,3,BLACK,GREEN,"瞬时值");
Gui_DrawFont_GBK24(10,24,BLACK,GREEN,temp1); //瞬时值
Gui_DrawFont_GBK24(80,24,BLACK,GREEN,"uSv/h");
if(color_Flag == last_color_flag) {}
else Lcd_Clear_1(2,2,126,38,GREEN); //瞬时值背景
break;
case 1 : Gui_DrawFont_GBK16(40,3,BLACK,YELLOW,"瞬时值");
Gui_DrawFont_GBK24(10,24,BLACK,YELLOW,temp1); //瞬时值
Gui_DrawFont_GBK24(80,24,BLACK,YELLOW,"uSv/h");
if(color_Flag == last_color_flag) {}
else Lcd_Clear_1(2,2,126,38,YELLOW); //瞬时值背景
break;
case 2 : Gui_DrawFont_GBK16(40,3,BLACK,RED,"瞬时值");
Gui_DrawFont_GBK24(10,24,BLACK,RED,temp1); //瞬时值
Gui_DrawFont_GBK24(80,24,BLACK,RED,"uSv/h");
if(color_Flag == last_color_flag) {}
else Lcd_Clear_1(2,2,126,38,RED); //瞬时值背景
break;
}
last_color_flag = color_Flag;
if(Flag == 1)
{
count ++;
BTIM_Cmd(CW_BTIM1,DISABLE); //停止定时器
Flag = 0; //清除标志位
InstVal = (float)value * 210/3600; //瞬时值
Cumval+=InstVal; //累加值
Aveval = Cumval/count; //平均值
if(InstVal>=0.5) //报警值
{
last_on_time = 1;
last_off_time = 0;
color_Flag = 2;
}
else if (InstVal == 0) //正常值
{
last_on_time = 0;
last_off_time = 1;
color_Flag = 0;
}
else if(InstVal>=0.4)
{
//蜂鸣器报警
on_time = 50;
off_time = 50;
last_on_time = on_time;
last_off_time = off_time;
color_Flag = 1;
}
else if(InstVal>=0.3)
{
//蜂鸣器报警
on_time = 150;
off_time = 150;
last_on_time = on_time;
last_off_time = off_time;
color_Flag = 1;
}
else if(InstVal>=0.2)
{
//蜂鸣器报警
on_time = 300;
off_time = 300;
last_on_time = on_time;
last_off_time = off_time;
color_Flag = 1;
}
else if(InstVal>=0)
{
//蜂鸣器报警
on_time = 500;
off_time = 500;
last_on_time = on_time;
last_off_time = off_time;
color_Flag = 1;
}
value = 0;
BTIM_Cmd(CW_BTIM1,ENABLE); //打开定时器
}
}
这部分代码是整个程序的核心,通过判断FLAG的值,来判断是否1S定时结束,之后就是数值的换算。
同时color_flag是用来判断数值背景需不需要改变的,同时在case里面的判断是为了避免一直处于刷新背景的情况下,因为一直刷新背景会造成屏幕的闪烁。
RCC_Configuration(); //初始化时钟
LED_init(); //指示灯初始化
Bozzer_Init(); //蜂鸣器初始化
Lcd_Init(); //屏幕初始化
Lcd_Clear(BLUE); //清屏
//显示开机标语
Gui_DrawFont_GBK16(50,30,WHITE,BLUE,"世界");
Gui_DrawFont_GBK16(26,50,WHITE,BLUE,"可以没有XX,");
Gui_DrawFont_GBK16(50,70,WHITE,BLUE,"地球");
Gui_DrawFont_GBK16(18,90,WHITE,BLUE,"不能失去海洋!");
Delay_s(3);
Lcd_Clear(BLACK); //清屏
// //设置背景
Lcd_Clear_1(2,2,126,38,GREEN); //瞬时值背景
Lcd_Clear_1(2,41,126,78,BLUE); //累加值背景
//矩形边框
Gui_DrawLine(0,1,128,1,WHITE);
Gui_DrawLine(128,1,128,160,WHITE);
Gui_DrawLine(128,160,1,160,WHITE);
Gui_DrawLine(2,160,2,0,WHITE);
Gui_DrawLine(0,40,128,40,WHITE);
Gui_DrawLine(0,80,128,80,WHITE);
Gui_DrawLine(0,120,128,120,WHITE);
//显示提示语
Gui_DrawFont_GBK16(40,42,WHITE,BLUE,"累计值");
Gui_DrawFont_GBK16(40,82,WHITE,BLACK,"平均值");
Gui_DrawFont_GBK16(5,130,WHITE,BLACK,"计数次数");
Gui_DrawFont_GBK16(104,130,WHITE,BLACK,"次");
Timer_BTIM1_Init(); //定时器初始化
GeiGer_Init(); //中断初始化
这部分是UI界面的设计
8、实物展示
9、展望
未来如果有机会的话,还会加入电池的电压检测,并优化电路的涉及,让他的尺寸更小,但是由于盖革管的价格偏贵,可能会搁置,感兴趣的小伙伴可以加个关注
10、设计注意事项
- 注意焊接时的安全
- 在焊接结束要先调节5V稳压电路,将电压调节到5V之后,再进行400V的调节,
- 400V升压调节时,不可将盖革管接入电路,避免因为电压过高损坏盖革管(一根也不便宜,坏了心疼)
- 在调节电压的时候,需要用万用表边测量便调节,同时万用表的量程需要选择正确
- 万用便需要保证测量高压时没有误差,之前我个人在测量时就遇到过这种情况,测量低压准,高压不准。
- 本工程的电路都经过本人测试,可直接下单。
- 由于5V升400V的电路中使用到的电感现在某宝的价格偏贵,也可以使用对应数值的工字电感进行代替(本人未测试过,只是建议)