项目来源:
FastBond项目开展以来,自己一直在想做个什么项目,既要有意义能学到东西,还要有实用价值,并且是自己能力范围内能实现的。左思右想却想不出什么能做的东西……。某日和自家老爷子提起这个事情,老爷子提出一堆天马行空的想法,我都一一否决,告诉他我能力有限做不出来!然后就被严重鄙视了,自己也很郁闷。最后老爷子说,生活中有时其实不需要多高科技的东西。比如每天按时吃药这事,在生病时,根本不叫事;不舒服自然会提醒你吃药。可是人上了年纪,需要天天按时服药时,就很容易忘记。因为很多时候没有不舒服,可是药不能停。我说:您手机不是设定了有闹铃吗?可以按时提醒吃药啊!回答:没错,可是手机闹铃可以取消,万一被取消了,就麻烦大了!而且手机很容易让人分神,闹铃响了后,拿起手机关闭闹铃,就开始玩手机了,忘记要做什么了!由此打算给老爷子做一个提醒按时吃药的药盒。
项目介绍:
该项目是一个简单的随身携带的药盒。简单是指只有一个功能——定时提醒功能。对设计要求:首先药盒体积不敏感,能够携带1~3天的药物即可。其次用电池供电,能做到长时间待机(3天以上)。能够按时提醒用药。
具体设计实现:
- 硬件选择:
模块 数量 说明 MAX32660-EVSYS开发板 1 美信DARWIN产品系列 DS3232模块 1 美信RTC时钟芯片 ADP151AUJZ-3.3-R7 1 LDO芯片.用于锂电池线性降压。
MAX32660:属于美信DARWIN产品系列,是一款超低功耗、性价比突出、集成度非常高的32位控制器。芯片封装非常小,4mm x 4mm 的TQFN已经是这个系列里最大封装,非常适合电池供电。MAX32660采用了带浮点运算功能的Cortex-M4内核,最大主频96MHz, 带256KB Flash和96KB SRAM,性能很强劲。MAX32660-EVSYS是MAX32660评估系统提供结构紧凑的开发平台,在微小、易于使用的电路板实现对MAX32660全部特性的访问。主板上已安装基于MAX32625PICO的调试适配器;完成编程后,可将其直接拆卸。调试模块支持可选的10引脚Arm® Cortex®调试连接器,用于实现DAPLink功能。组合尺寸为0.65in x 2.2in,而主板独立尺寸为0.65in x 0.95in。外部连接采用双排连接头,兼容过孔和SMT应用。该电路板以非常小的空间提供强大的处理子系统,很容易集成到各种应用中。
DS3232是低成本温度补偿晶体振荡器(TCXO),内置精度极高的温度补偿实时时钟(RTC)以及236字节电池备份SRAM。此外,DS3232还具有电池输入,可在器件主电源掉电时保持精确计时。集成晶振提高了器件的长期精度,并减少了生产线的元件数量。DS3232具有商业级和工业级温度范围,并采用工业标准的20引脚、300mil SO封装。 RTC可以计数秒、分、时、星期、日期、月份和年份信息。对于少于31天的月份,月末日期自动调整,同时包括闰年修正功能。该时钟可以工作在24小时模式或带/AM/PM指示的12小时模式。提供两个可编程定时闹钟和可编程方波输出。地址和数据通过I2C双向总线串行传输。 精密的、经过温度补偿的电压基准和比较器电路用来监视VCC状态,以便检测电源失效,提供复位输出,并在必要时自动切换到备份电源。
LDO芯片:ADP151AUJZ-3.3-R7 厂家:ADI 用途:将输入电压转换为3.3V给单片机供电。 - 硬件连接:
要实现定制的功能,最终必须得自己制作PCB。目前还是个PCB制作小白,购买了KiCad的课程,还在学习。目前验证功能使用面包板作为模块的连接。MAX32660与DS3232之间用I2C协议通讯。闹钟的设置使用上位机通过串口与MAX32660通讯,硬件上使用microUSB口连接。 - 功能实现:
上位机使用PyQt5做界面,使用python来实现功能。药盒是没有任何显示界面,提醒用药时间是依赖DS3232的闹钟功能实现的,所以,当下位机与上位机连接时,上位机会通过互联网自动校正下位机时间。下位机定时将读取到的时间上送上位机,上位机定时刷新显示下位机时间。
@pyqtSlot() # 打开串口 关闭串口 def on_pushButtonSerCtl_clicked(self): if self.ui.pushButtonSerCtl.text().find('打开') >= 0: try: # 超时设置,None:永远等待操作,0为立即返回请求结果,其他值为等待超时时间(单位为秒) # 使用115200波特率 self.ser = serial.Serial(self.ui.comboBoxPort.currentText(), baudrate=115200, bytesize=8, parity='N', stopbits=1, timeout=1) except serial.SerialException: print('错误', '打开串口出错!') else: self.ser.flush() # 刷新缓存 self.ui.pushButtonSerCtl.setText('关闭') self.ui.pushButtonSet.setEnabled(True) # 允许设置闹铃 self.ui.comboBoxPort.setEnabled(False) self.findSerialPortThread.workstat = False # 让线程停止工作 self.timer.start(40) # 刷新界面开始 100ms间隔刷新 # 启动一次自动校时 nettime = getBeijinTime() # 获得网络标准时间 print(type(nettime), nettime) if len(nettime) == 7: buf = bytes( (int(nettime[0]) % 2000, int(nettime[1]), int(nettime[2]), int(nettime[3]), int(nettime[4]), int(nettime[5]), int(nettime[6]))) # print(buf) self.ser.write(buf) else: self.ser.flush() # 刷新缓存 self.ser.close() self.ui.pushButtonSerCtl.setText('打开') self.ui.pushButtonSet.setEnabled(False) self.ui.comboBoxPort.setEnabled(True) self.findSerialPortThread.workstat = True # 让线程工作 self.timer.stop() # 停止刷新
当上位机通过串口与下位机连接后,可以在上位机上设置闹铃。一共有两个闹铃。可以设置开启、关闭闹铃,可以修改闹铃的时间。闹铃允许设置时和分。使用两个字节保存数据,其中保存时的字节最高位用来保存闹铃的开启和关闭。
#处理时间函数 def timedeal(strtime,isopen=True): [hour,min]=strtime.split(":") if isopen==False: hour=int(hour)+128 return int(hour),int(min)
下位机使用官网的IIC例程作为基础。从美信官网找到DS3232的说明文档。DS3232控制起来很简单,这个芯片所有的控制操作都是通过操作寄存器来实现的。0x00H~0x06H是时间寄存器,时间的读写都是通过这7个寄存器来实现的。0x07H~0x0AH为闹铃1的寄存器。可以设定秒、分、时、天。我这里是需要每天重复,所以仅仅需要设定秒、分和时,其余不用设置的置最高位为1即可,这里直接填写0x80H。0x0BH~0x0DH为闹铃2,闹铃2仅仅比闹铃1少了个秒,其余都是一样的。0x0EH是控制寄存器,最低两位控制着闹铃的启动,要启动闹铃,对应位直接置1即可。0x0EH是状态寄存器,最低两位对应着两个闹铃的状态,当闹铃响起时,对应的状态位就会为1,并且DS3232的INT管脚也会变为低电平,我这里没有接INT管脚,直接通过读取状态位寄存器判断闹铃是否响起。闹铃响起后,重置状态位寄存器,然后通过LED 闪光提醒用药(老爷子耳朵背)。
当闹铃亮起后,目前是通过按键消除LED的闪光警告,未来希望能够和药盒联动,当打开药盒时触发按键事件,关闭闪光警告,保证药盒被打开。
后续:
目前仅仅实现了药盒的系统验证。要实现实物,准备使用3D打样药盒,将整个电路藏于药盒中,这样就必须自制电路板了。MAX32660这么小的芯片,真没把握手工焊接!还有MAX32660的低功耗还有待实现,目前尚未对低功耗进行优化。电源部分ADP151AUJZ-3.3-R7为贴片芯片,这里不做验证,在制作PBC时贴上。
心得体会:
经过这次实践,深刻体味到了知易行难,动手之初觉着应该很简单,可做起来才发现大大小小困难,都需要一一解决。感谢电子森林的这次活动,也感谢硬禾学堂的各位大佬的细心指导!