资讯详情

牙刷消毒架设计思路

# 消毒架是集杀菌干燥功能和时间显示功能于一体的日常家用小电器。它的原理相对简单,在32位ARM Cortex-M时钟芯片读取在0核的微处理器上,通过与读取的时钟信息进行比较,在固定时间内微处理器驱动灭菌和干燥模块。这样,最基本的消毒架可以按时消毒干燥。如有必要,可添加时间显示模块(数码管,LCD1602、OLED或LCD12864可以)、时间调整模块、电源状态监测模块等。,最后用户可以在程序中设置自己的消毒时间和报警监控,从而实现高档消毒架。

#

根据总体思路,消毒架暂时分为四个大型模块:电源检测模块、时间显示模块(包括时间采集、时间显示)、时间调整模块(包括系统时间、用户自定义时间)、消毒架工作模块(消毒、干燥、除湿),如果你想让每个模块更简洁,你可以细分括号中的所有内容(尽管程序组织更清晰,但每个模块.c、.h文件内容不多,只有一两百行代码,看起来会给人一种代码少的错觉,就是弟弟)。

##

电源检测模块主要适用于想要将消毒架制成电池供电的类型。考虑到电池待机时间和电池容量(这是一个小产品,不可能在数万毫安的内部)。为了增加电池供电时的待机时间,电池供电时必须切断或优化一些高能耗功能,如显示部分可以降低显示亮度等级(这里使用的数字管显示时间),降低除湿风扇的驱动频率,如果干燥模块功率过高,可以直接切断或优化(但市场上的产品基本上切断了此功能)等。只要思维不滑,方法总是比困难多。根据自己的需要优化这些东西。我关闭了干燥功能,降低了显示数字管的亮度等级。

其实电源检测模块很简单,只要外部电源和电池电源有明显的区别,就可以实现。我相信你已经想到了,好的是充电宝。充电宝充电不充电不就是这样吗?此外,充电宝方案如此成熟,充电宝的电源芯片并不昂贵,这是最完美的选择。至于选择何种芯片就看你自己了。以前用的是坏充电宝的电源芯片IP5306,它的数据在互联网上很多,它的数据手册不仅有各种各样的电气信息,而且还给出了一个典型的应用原理图,最重要的是,它的灯亮了PWM控制也太方便检测状态,简直不太舒服。我使用双灯显示模式。在程序中,在固定时间检测两个灯的电平变化次数,然后通过次数确定状态。

电源检测参考程序:

        Flip_Level_1=GPIOC_ReadPortPin(GPIO_Pin_1);   Flip_Level_2=GPIOC_ReadPortPin(GPIO_Pin_2);   while(Computing_Time(Get_Time(),Time_Power_LED)<2000)   {    if(Flip_Level_1!=GPIOC_ReadPortPin(GPIO_Pin_1))     {i  ;}     if(Flip_Level_2!=GPIOC_ReadPortPin(GPIO_Pin_2))  {j  ;}    Flip_Level_1=GPIOC_ReadPortPin(GPIO_Pin_1);    Flip_Level_2=GPIOC_ReadPortPin(GPIO_Pin_2); //   PRINT("电平变化次数:i=%ld j=%ld\r\n",i,j);   }         ///数值供参考,以实际测量为准   if((i>40)&&(i<160)) POWER_LED1=2;   if(i>200)   POWER_LED1=1;    if(i==0)    POWER_LED1=0;          ///数值供参考,以实际测量为准   if((j>40)&&(j<160)) POWER_LED2=2;     if(j>200)   POWER_LED2=1;     if(j==0)    POWER_LED2=0;        if(POWER_LED2==0)                       POWER_Flag=3;    ///充电状态(包括充满状态)   if((POWER_LED1==0)&&(POWER_LED2==1))  POWER_Flag=2;    //放电未充状态   if((POWER_LED1==0)&&(POWER_LED2==2))    POWER_Flag=1;    ///低电报警状态

##

时间显示模块是时钟芯片 显示模块。

时钟芯片是一种具有时钟特性的芯片,可以获得现实时间。时钟芯片是一种集成电路,主要由可充电锂电池、充电电路和晶体振荡电路组成。时钟芯片大致分为平行接口、串行接口和三线接口三类DS1302、DS属串行接口的1307。

在我看来,时钟芯片的主要功能是提供准确的时间和记录时间,记录数据和断电保护(我目前只使用过这两个功能,但我没有使用过)。

  • 提供准确时间和记录时间的功能是时钟芯片最基本的功能,时钟芯片的时钟功能非常强大,可以提供准确的年、月、日、周、时、分、秒所有时间单元(这需要硬件电路没有问题,我遇到的运行基本上是硬件电路的原因),时钟芯片也具有闰年补充功能。时钟芯片具有数据记录和断电保护功能。
  • 记录数据和断电保护是时钟芯片的神来之笔。意外电源不能丢失数据,电源也可以直接读取准确的时间信息,更不用说有多麻烦了。时钟芯片的功能来自内部 RAM 单元,此 RAM 部分单元用于控制时钟显示,大部分用于存储单元数据。锂电池是时钟芯片电路的重要组成部分之一。时钟芯片断电或关机后,锂电池可通过芯片内部电路为芯片供电,使时钟芯片断电后仍能运行,确保时钟芯片内记录的数据不丢失。

时钟芯片的介绍到此为止,芯片是随机选择的。这是一件在业余时间制作的小工艺品。按照不浪费的原则,时钟芯片也从其他地方拆下。我在这里用的是DS1307,DS1307和DS1302在功能上差不多,主要是通信上面有一些区别()。至于谁使用得更好,两者都是一样的。网上有很多相关的例程。基本上,改变例程中定义的引脚可以读取数据,然后处理数据。事实上,这里的程序没有太多的技术内容,主要是在硬件电路上(跑步时很难解决,很长一段时间后,我看到很多博客仍然没有很好地解决这个问题)。

DS读写参考程序1307:

//DS1307写数据 void Write1307(unsigned char add,unsigned char dat) {   unsigned char temp;   temp=dat/10;    temp<<=4;   temp=dat temp;   IIC_Start_DS1307();   IIC_Send_Byte_DS1307(0xD0);   ///呼叫芯片DS1307,并定义为写作动作     IIC_Wait_Ack_DS1307();   IIC_Send_Byte_DS1307(add);    //发送起始地址   IIC_Wait_Ack_DS1307();       IIC_Send_Byte_DS1307(temp);   //发送待写入数据   IIC_Wait_Ack_DS1307();    IIC_Stop_DS1307();  }  //DS1307读数据 unsigned char Read1307(unsigned char add) {   unsigned char temp;   unsigned char dat;   IIC_Start_DS1307();            IIC_Send_Byte_DS1307(0xD0); ///呼叫芯片DS1307,并定义为写作动作   IIC_Wait_Ack_DS1307();  //等待信号响应   IIC_Send_Byte_DS1307(add); //发送起始地址   IIC_Wait_Ack_DS1307();     IIC_Stop_DS1307();     IIC_Start_DS1307();   IIC_Send_Byte_DS1307(0xD1); ///呼叫芯片DS1307,并定义为读动作   IIC_Wait_Ack_DS1307();   dat=IIC_Read_Byte_DS1307(0);    IIC_Stop_DS1307();   temp=dat/16;   dat=dat;   dat=dat temp*10;   return(dat); }

显示模块,这些都是泛滥的东西。随便搜索时间显示模块,各种万年历就出来了(不仅有各种电路图,还有完整的例程)。显示模块的原理相似,都在显示设备中(LCD12864、LCD1602、OLED、数字在数字管上循环显示。唯一的区别是每个显示器的通信方式不同。事实上,显示模块的技术含量并不大。有各种显示程序和电路图,基本上可以直接移植。

参考程序:

     
      
//此段选编码为根据实际硬件线路做出的编码,分别对应0-9、全灭
UINT8 Data_Code[]={0xdd,0x09,0xd3,0x5b,0x0f,0x5e,0xde,0x19,0xdf,0x5f,0x00};

void AiP650_Set(UINT8 add,UINT8 dat) //数码管显示
{
	//写显存必须从高地址开始写
	IIC_Start_AIP650();
	IIC_Send_Byte_AIP650(add); //第一个显存地址
	IIC_Wait_Ack_AIP650();
	IIC_Send_Byte_AIP650(dat);
	IIC_Wait_Ack_AIP650();
	IIC_Stop_AIP650();
}

//小时+中间点亮灭间隔1s
void AiP650_HourAdd_Display(UINT8 hour,UINT8 sec)
{
    //小时
    UINT8 data=(hour%24)/10;
	AiP650_Set(0x68,Data_Code[data]);//十位
	data=(hour%24)%10;
	if(sec%2==0)
    {
		AiP650_Set(0x6a,Data_Code[data]|(UINT8)(1<<5));//个位	
	}
	else
	{
		AiP650_Set(0x6a,Data_Code[data]);//个位
	}
}

//分钟单独显示
void AiP650_Min_Display(UINT8 min)
{
	//分钟
    UINT8 data=(min%60)/10;
	AiP650_Set(0x6c,Data_Code[data]);//十位
	data=(min%60)%10;
	AiP650_Set(0x6e,Data_Code[data]);//个位
}

//小时: 分钟同时显示
void AiP650_DisPlay(UINT8 hour, UINT8 min,UINT8 sec)
{ 
    //小时+中间点亮灭间隔1s
	AiP650_HourAdd_Display(hour,sec);
     //分钟
	AiP650_Min_Display(min);
}

void Light_Level_Set(UINT8 Level)//设置亮度等级 1-8级
{
	Level&=0x07;	//Level = (0x0111 & Level) 
	Level<<=4;		//Level = (0x0111 & Level) 0000
	Level++;		//Level = (0x0111 & Level) 0000 + 0x0000 0001
	AiP650_Set(0x48,Level);
}
     

##

时间调整模块算是这个里面比较有技术含量的了,两个按键实现系统时间修改,自定义消杀时间设定供能。老实说这个模块花费时间最长但到现在为止只能说实现了功能。两个按键要实现五个功能(系统时间和设定时间小时、分钟的加减以及设定时间的保存),最开始的时候打算用四个按键实现这个功能,后来看见了一篇介绍多功能按键的博客,https://www.cnblogs.com/mcumagic/p/5892995.html,之前有了解过多功能按键但一直没有用过,本着学习的原则直接将四个按键改成两个按键,然后参考这篇博客开始了艰难的调试之旅(此处调试过程省略,自己动手调试一下真的很有收获)。

        按键状态参考程序:只有长按和短按功能

//按键状态检测
Key_Mode_Typedef Button_Scan(Whitch_Button_Typedef Button_Count)
{
    static UINT8 Button_Sta[Button_Sum]={0,0};
	UINT32 Button[Button_Sum]=  {GPIOC_ReadPortPin(GPIO_Pin7),GPIOC_ReadPortPin(GPIO_Pin_6)};
	Button_Mode_Typedef keyStatus;
	switch(Button_Sta[Button_Count])
	{
	    case 0:
			if(Button[Button_Count]==0)
			{
				Button_Sta[Button_Count]=1;
				Set_Delay(Button_Long_Time,Long_Press_Time);
			}
			else
			{
				Button_Sta[Button_Count]=0;
			}
			ButtonStatus=No_Press;
		break;

		case 1:
			if(Button[Button_Count]==0)
		    {
				if(Delay(Button_Long_Time,Long_Press_Time))
				{
					Button_Sta[Button_Count]=2;
					ButtonStatus=Long_Press;
				}
				else
				ButtonStatus=No_Press;
			}
			else
			{
				Button_Sta[Key_Count]=0;
				ButtonStatus=Short_Press;
			}
		break;
		    
        case 2:
			if(Button[Button_Count]==0)
			{
				if(Delay(Button_Long_Time,Long_Press_Time))    ButtonStatus=Long_Press;
				else    ButtonStatus=No_Press;
			}
			else
			{
				Button_Sta[Button_Count]=0;
				ButtonStatus=No_Press;
			}
		break;

		default:
		break;
	}
    return ButtonStatus;
}

        按键状态能检测出来短按和长按,就基本能实现功能了。长短按区分时间设定还是系统时间修改,按键位置辅助确定调节的是小时还是分钟——>左右短按分别对应时间加减——>长按保存(无触发2秒后返回不保存)。但调试双击的时候一直不理想,所以没法用上。后续有时间再改进吧!

##

消毒架工作模块其实说白了就是通过IO驱动相关模块通断,就像点灯一样。加热模块、消杀模块、风扇这些都是买的成品,网上都有,成本也比高(主要是时间不充足)。这里需要注意的是理清工作逻辑和异常处理而已。

        这个部分的工作逻辑不算复杂。系统走时到设定时间点或系统定义的消杀时间点,先启动杀菌然后烘干和除湿工作——>杀菌时间到关闭杀菌,继续烘干和除湿工作——>烘干和除湿时间到,关闭烘干除湿——>循环检测是否到下一个时间点。

        异常处理主要是断电后过了时间点但又没过多久,这里就可以把到时间点后左右检测时间放宽一些(2分钟、5分钟、10分钟)自己设定即可,如果满足还是可以继续工作。当然肯定还有其他更好的方案。

        这部分程序太杂了,就不每个都贴出来了,主逻辑参考程序:

void main()
{
	Syserm_Init();
	Syserm_Power_off();    //系统掉电检测
	Syserm_Power_Check();
    while(1)	
    {
        low_voltage_state();
		Key_Set();
		if(Key_flag==0)		
		{
			Syserm_Power_Check();	
			Time_Display();	
		}	
		if(POWER_Flag!=1)
		{	
			Sterilization(); 
			Heating(); 
			Dehumidify(); 	
		}
    }	
}

#

        逻辑理清才算起步,调试才是问题的重灾区。真的是不调试以为都是些现成的没什么难度,So easy。一调试真的就是各种牛鬼蛇神都出来了(大部分都是细节错误)。关于调试部分的硬件就不说了(硬件太菜,遇到的问题基本都是请教认识的硬件大佬们解决的)。软件调试就几个遇到的比较感觉很容易踩坑的点给大家参考一下。

        1、数码管显示乱码?

        这种问题很常见但也很好解决;首先确认数码管是共阴极还是共阳极——>确定位选,段选全打开看所有段显示是否正常——>段选正常,分别修改每一段的显示值确定各段的排序(一定要做,我这里就是因为几个段顺序错了,导致显示乱码,导致我熬了一个夜都没解决还是第二天才想到可能是这个问题)——>根据段选确定数字0—9的编码值。这样走下来数码管显示基本上就不会再出现乱码问题了(除非硬件变化)。

        2、DS1307读数异常?(包括但不限于读不到数、读数不变、读数不准、上电时读数有延迟等)

        DS1307读不到数:调试时,用串口打印读数但串口没有反应,这种情况一般是通信没成功,通信成功始终有数值的只是不会变而已(我只遇到过这种情况下没有输出,但不排除还有其他情况);通信不成功包括串口通信不成功(在程序里用串口1打印数据却在串口2上读数据或者串口通信没调)、时钟芯片IIC没调通(完全读不到东西)。遇到这种问题先检查串口,确定串口无误后再检查时钟芯片IIC通信。

        3、DS1307读数不变:如果避过了上面那个坑能读到数据,但是数据没有变化,那恭喜你进入了一个大坑。数据读到但没变化这个我看了一下,大家都遇到过这种问题但是原因又各不相同(但终归是芯片没工作和读取数据的地址不对这两种)。下面主要说明我觉得可能存在的几个方向:

        时钟芯片供电部分:供电一般使用3.3~5.0V左右(供电要超过3.2V),前期由于没注意导致DS1307供电只有3.1V左右,串口打印出来的数据会存在不变的情况,推测是时钟芯片供电电压太低导致芯片没工作所以读不到数据,但有时候重启后又能正常变化。所以具体是不是这个原因不确定。

        时钟芯片晶振部分:读数不变还有可能是晶振不起振导致芯片不工作。晶振不起振的原因就不深究了,我们可以用示波器检测晶振是否工作正常。用示波器测量芯片的晶振接口,如果有正常的方波说明晶振是能起振的。如果晶振起振但读数还是不变,那就可能是晶振接反了(有的晶振是有正反的)、芯片挂了或IIC没接上拉电阻(可优先考虑)。

        时钟芯片读数不准确:时钟芯片跑时有误差只能是晶振电路电容不匹配。可以适当改变晶振电容(网上有相关计算公式公式但我换了按照公式计算出来的电容也还是没改进,好在跑时问题不是很严重大概两三天会有1分钟的误差)。

        时钟芯片上电时读数有延迟:用示波器监测发现上电时晶振起振响应很慢(大概要2~3s才能波形才稳定,每次断电重启时都这样),在网上查了一些资料都说这个好像是芯片本身的原因,没有办法改善。那就只能在每次初始化的时候加个延时函数了。

        3、其他问题

        其他调试问题都是一些粗心大意惹的祸,像引脚定义不正确、引脚模式设置错误、模块通断控制时置1和复位弄错、ADC采集时通道号定义错误、AD采集时模块和单片机没共地等。这些常见的错误不注意的话都容易出现而且没考虑到这些细节出问题的话很难找到解决方法,。所以为了在调试的时候更快速更高效,在调试前最好先检查一下电路主控和各模块是否接地、确认一下模块控制引脚的连接和定义情况,只要细节做得到位调试一般不会出什么问题。

#总结

        消毒架虽不是个很复杂的东西,但还是有很多可以学习的地方。最深的感受就是软件一定要会一些硬件知识。不说精通至少要能找到是哪里除了问题,就算去问大佬也不至于受很多白眼。

        就这样吧!看模电和电路去了... ...

标签: 如何用电容延迟断电双灯指示固态继电器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台