最新动态
制作一款用于座位管理的墨水屏
2024-11-14 21:46  浏览:59

完成上述步骤后正式开始墨水屏 Demo 的应用功能开发。

制作一款用于座位管理的墨水屏

功能描述 详细说明 屏幕显示
  • 座位号
  • 座位状态
  • 提醒信息
  • 二维码 复位按键 长按 3 秒,设备重新配网 信息下发
  • 正常:预定/无预定
  • 异常:暂不开放 预约信息记录 后台记录近 30 天座位占用信息 低电量报警 设备电池电量低于 10%上报至管理端(云端)
  • lc

    
    

    首先是硬件部分的配置,本次硬件部分主要在于墨水屏幕的显示和字库芯片的读取,字库芯片与屏使用同一块 SPI 驱动,所以首先将 SPI 进行初始化配置,另外 MCU 与 Zigbee 模组通过串口进行通信,所以也要将串口进行初始化。

    
    
    
    
    
    

    下面是电子屏的显示部分,屏幕初始化完成后可以直接在主程序中调用显示函数,另外如果 SPI 初始化有问题可以将模拟 SPI 改为硬件 SPI 再进行驱动。

    屏幕显示也可以显示图片,采用取模软件将图片里的像素点数据放进 picture.h 文件中就可以显示图片。

    注意

    • 注意输出图片大小不能超过屏幕的尺寸大小,屏幕显示完成后调用局刷与全刷函数可以实现屏幕的局部刷新与全局刷新。
    • 注意屏幕每次刷新完后需要进入休眠模式,否则会对设备的整机功耗造成较大影响。

    • 屏幕刷新函数(全刷/局刷)

      屏幕刷新函数 描述 优点 缺点 全屏刷新 整个页面全部刷新一次,整个屏幕要闪几次 没有残影 需要多刷几下屏幕 局部刷新 每一次刷新显示内容时,不会整个屏幕都刷新,仅刷新有画面和字的地方 优势是屏幕不会闪烁 会有残影,但残影问题多刷几次白屏就能清除掉或者执行一次全刷也可以清除

      注意:在实现墨水屏的全局刷新与局部刷新功能时, 从局刷转到全刷时休眠后一定要先进入初始化再刷新。

      
      
    • 屏幕显示函数

      
      
    • 屏幕刷白屏函数

      
      
    • 硬件复位函数

      当需要清掉局部信息并重新显示新的信息时就可以用硬件复位函数来实现;

      
      
    • 屏幕休眠函数

      
      

      注意:屏幕刷新完后必须进入休眠模式。

    在使用字库芯片时,用户只要知道字符的内码,就可以计算出该字符点阵在芯片中的地址,然后就可从该地址连续读出点阵信息用于显示。本次屏幕显示信息主要通过从字库芯片中读取数据从而显示在屏幕上,从字库中读到的数据一个字符就是一个数组数据,然后电子屏再将每一位数组数据显示在屏幕上。

    • 字库芯片初始化

      
      
    • 字库芯片休眠

      
      
    • 字库芯片唤醒

      以低电平作为起始位,高电平作为停止位;

      
      
    • 矢量文字读取函数

      调用方式:通过指定参数进行调用,获取点阵数据到 pBits[]数组中

      
      

      如果有需要固定显示的文字部分,可在程序中将固定文字信息写在数组中从而直接显示固定信息,一个 ASCII 码对应 2 位 GBK 内码占一个字节,一个中文字符对应 4 位 GBK 内码占两个字节。

      
      

      将固定信息通过文字读取函数 get_font()与屏幕显示函数 EPD_Dis_Part()进一步显示在墨水屏上。

      
      

    由于墨水屏需要连接到 涂鸦 IoT 开发平台,依靠平台来实现自动化、App 端操控,以及设备之间的相互联动,所以需要有 Zigbee 网关来帮助设备连接上智能平台。Zigbee 网关的作用就是负责连接智能平台,间接地把 Zigbee 设备接入我们的智能平台,确保手机和 Zigbee 网关处于同一个 WiFi 网络,以保证手机与智能网关之间有效连接。

    1. 将网关与电源连接,并通过网线与家庭 2.4GHz 频段路由器相连。
    2. 确认配网指示灯(绿灯)常亮(若指示灯处于其他状态,长按复位键,至绿灯常亮)。
    3. 确保手机连接家庭 2.4GHz 频段路由器,此时手机、网关处于同一个局域网。
    4. 打开涂鸦智能 APP 首页,点击页面右上角添加按钮 +
    5. 选择网关中控/有线网关(zigbee),依照提示操作设备入网。
    6. 添加成功后,即可在列表中找到网关设备。

    Zigbee 网关配网成功后,即可在网关里添加子设备。依据涂鸦智能 App 首页配网提示操作子设备配网,配网成功后即可在涂鸦智能 App 上进行调试。

    除了在程序里写入配网指令实现配网,还可以通过涂鸦调试助手发送配网指令来操作设备入网。更多详情,请查看 Zigbee 串口协议。

    注意:配网之前必须先在 涂鸦 IoT 开发平台 添加 DP,否则配网会一直失败。

    定义一个结构体数组来存放 MCU 接收网关下发或上报的 DP value。

    
    

    调试过程可使用调试面板来下发 DP,MCU 收到指令后回复并执行对应的操作。

    • 座位信息设置

      1. 下发 DP101 ,DP 数据格式为{“n”:“seat number”,“st”:“state”}
      DP ID 内容 备注 101 “query” 设备发送,同步座位号信息 格式 {“n”:“seat number”,“st”:“state”} n:座位编码字段 seat number:编码内容 st:座位状态字段 state:座位真实状态 (enable disable repairing)

      下发 DP 后 MCU 接收并解析出座位编码、座位状态等字段信息,然后驱动屏幕将座位编号信息显示在墨水屏上;

      1. 定义一个结构体,用来表示墨水屏的三种工作状态:
      
      

      DP 解析及处理函数:

      
      

      以座位 S-1234 为例,当座位状态为 enable 时才可以执行预约的动作,如果是 disable 和 repairing 则显示该座位暂不开放(可根据自己需求修改)。

      座位状态 DP 格式 显示内容 enable {“n”:“S-1234”,“st”:"enable "} 显示座位编号,若有预约信息则显示预约信息,无预约信息显示空白 disable {“n”:“S-1234”,“st”:"disable "} 显示座位编号以及“暂不开放” repairing {“n”:“S-1234”,“st”:"repairing "} 显示座位编号以及“暂不开放”

      MCU 接收到 value 后将解析出的信息存放在 中并通过修改显示函数 中的横纵坐标来调整在屏幕中的位置。

      注意:显示函数完成后,屏幕和字库芯片都需要进入休眠。

      座位编号显示函数:

      
      
    • 座位二维码链接

      可通过调试面板下发 DP102 生成对应座位二维码信息,DP 存放字节长度最大为 62 字节,若 URL 超过了最大限长,可将二维码链接分为两段 DP 来下发;这里以长度为 80 的 URL 为例,单条 DP 可以不固定长度,但不能超过限长,开发者可以按照自身的长度自行分配分两段还是三段。

      DPID 内容 备注 102 “query” 设备发送,同步座位链接信息 格式 {“qr”:“url”,“d”:“th”,“a”:“all”} qr:二维码链接字段;url:座位链接长度不超过 255 设备通过 url 本地生成二维码 d:二维码条目字段 th:第几段二维码链接信息 a:二维码字段总量 all:共有几段二维码

      示例:座位 1111 URL 地址为 https://seat-reservation-mobile.tuyacn.com/weapp?a=1&seat_id=1435857125099298816

      故 DP 格式: {“qr”:“https://seat-reservation-mobile.tuyacn.com”,“d”:“1”,“a”:“2”} {“qr”:"/weapp?a=1&seat_id=1435857125099298816",“d”:“2”,“a”:“2”}

      下发 DP 102 后 MCU 接收并解析出 URL 并存放在 FlashBuffer.st_qrcode 中,进一步调用二维码生成函数将座位二维码显示在墨水屏上。

      DP 解析及处理函数:

      
      

      二维码显示函数

      
      

      开发者可以根据自己需求修改 URL 信息,另外如果 URL 前半部分固定不变的话可以将其写在程序中,通过 DP 只下发后半部分 URL,可以简化很多步骤。

    DP ID 内容 备注 103 {“st”:time,“et”:time,“n”:“name”,“t”:“type”,“d”:“th”} st:预约起始时间字段 et:预约结束时间字段 time:时间 n:预约者名字字段 name:名字内容 t:类型字段 type:add:增加 del:删除 d:第几条预约信息

    DP 103 是预约信息的更新,更新类型包括新增与删除,更新的前提是设备已经从服务端同步过才有更新。

    例如当前显示两条预约信息,当需要更新第一条预约信息时先下发更新 DP,并且第一条更新完成的同时需将第二条信息删除,下面为更新与删除的举例;

    类型 举例 新增 {“st”:“10:00”,“et”:“12:00”,“n”:“无施”,“t”:“add”,“d”:“1”} 删除 {“st”:“10:00”,“et”:“12:00”,“n”:“无施”,“t”:“del”,“d”:“2”}

    DP 解析及处理函数:

    
    

    MCU 接收到 Value 后将解析出的起始时间存放在 FlashBuffer.st_add,将终止时间存放在 FlashBuffer.et_add,姓名字段存放在 gbk_n 中,并通过修改显示函数 EPD_Dis_Part() 中的横纵坐标来调整在屏幕中的位置。

    • 更新函数:

      
      
    • 删除函数:

      
      
    DP ID 内容 备注 104 “query” 设备发送,同步预约信息(全量) {“st”:time,“et”:time,“n”:“name”,“d”:“th”,“a”:“all”} st:预约起始时间字段 et:预约结束时间字段 time:时间 n:预约者姓名字段 name:姓名 d:单条预约信息 a:预约信息总量

    DP 104 是预约信息的同步,设备上电后同步所有数据,若查询到几条预约信息就对应显示几条预约信息,如查询到有三条信息则依次三条预约信息,下发格式。

    预约信息全量 举例 第一条 {“st”:“10:00”,“et”:“12:30”,“n”:“一一”,”d”:”1”,”a”:”3”} 第二条 {“st”:“14:10”,“et”:“16:30”,“n”:“一二”,”d”:”2”,”a”:”3”} 第三条 {“st”:“18:30”,“et”:“20:00”,“n”:“一三”,”d”:”3”,”a”:”3”}
    • DP 解析及处理函数:

      
      

      MCU 接收到 Value 后将解析出的起始时间存放在 FlashBuffer.st_all,将终止时间存放在 FlashBuffer.et_all,姓名字段存放在 gbk_1 中,并通过修改显示函数 EPD_Dis_Part() 中的横纵坐标来调整在屏幕中的位置。

    • 显示函数:

      
      

    当设备电池电量低于 10% 时将低电量状态上报至后台端,由于电池的电量和电压不是线性关系,若要通过电压来做电量指示的话需要多做几组充电放电的曲线测试,程序中也需要分三种情况处理:空载时、负载时、以及充电时将三种情况分别表示出来,用电压做电量指示才会更准确一些。

    本次设计在计量电池电量时采用设备功耗来计算电池电量,如设备休眠状态(80ms)电流 10uA,接收状态(600us)5mA,则可以算出平均电流,已知电池总电量,就可以计算出设备可工作时间。当电池电量低于 10%,上报至后台端。

    MCU 与模组唤醒逻辑如下:

    TX/RX:通讯串口

    IO1:Zigbee 唤醒 MCU 引脚,拉低唤醒,电平持续时间 10ms 以上。

    IO2:MCU 唤醒 Zigbee 引脚,拉低唤醒,电平持续时间 10ms 以上。

    MCU 与模组唤醒的引脚为 PB4、PB5,对应 MCU 的 P B0、PC13。

    Zigebee 模组烧录的固件为低功耗固件,可通过配置 Zigbee 网络策略参数来调节模组的功耗,以下为 Zigbee 模组的常用参数。

    Zigbee 网络策略参数 默认值 心跳时间 17000 配网时间 180 poll 时间 5000 上电持续 poll 30 poll 失败次数 4 应用触发 rejion 1 rejion 间隔 180 rejion 次数 1 发送功率 11

    下面是对各个参数的详细描述,

    • 心跳时间:是用来维护设备和网关之间的数据链路是否正常的手段,强电设备的心跳时间默认为 150+random(30)秒,低功耗设备的心跳时间默认为 4 小时,设置范围为 10~5*3600 秒,且网关判定 12 小时内没有收到心跳则认为设备离线。

    • 配网时间:当 MCU 发送配网指令之后,模组会执行一段时间的配网操作,并发送当前网络状态为配网状态。在一段时间内由于某些原因(例如附近没有开启配网的网络或者距离较远)导致模组没有加入到合适网络,则配网超时。配网超时之后,模组将处于未配网状态,同时也会将此状态发送给 MCU。配网超时时间默认为 180 秒,设置范围为 30~600 秒。

    • poll 时间(唤醒周期):poll 时间是指已经加入到网络的低功耗模组会在周期内唤醒,唤醒之后低功耗模组会发送数据请求(Data request)至其父节点,用于告知父节点,其当前处于唤醒状态,父节点是否为其缓存数据。如果存在缓存数据,则父节点可以将数据发送给低功耗模组。

      :Poll 值主要是影响功耗。唤醒周期越短,功耗越大。poll 最小值为 200ms,小于最小值按照最小值处理。建议取值小于等于 8s,这里 poll 时间默认为 5,000ms,设置范围为 200~10,000ms。

    • 上电持续 poll:通常上电之后,设置一段时间的快速 poll,可以在这个时间窗内将网关的配置命令下发。上电之后的快速 Poll 的时间默认为 30 秒,设置范围为 30~600s。

    • poll 失败次数:低功耗模块发送 Data request 之后,父节点首先是需要回复 ack,该 ack 是对 Data request 的应答。如果有缓存数据则将数据发送给模块,如果没有数据发送,则仅需回复 ack。如果模块发送了 Data request,但由于环境、距离、父节点断电等因素导致模块没有收到 ack,则模块的 poll 失败次数会加 1,如果在累加的过程中重新收到父节点的 ack,则累加清零,当累加到的一定的值时(Poll 失败次数),认为模块丢失父节点,需要触发 rejion。默认值为 4 次,设置范围为 3~40 次。

    • rejoin(重连):即重新加入到网络,但无须网关开启配网模式,是一种专门用于低功耗设备在父节点丢失时,重新加入网络的一种机制。

    • rejoin 间隔: 周期触发 rejion 的间隔时间。低功耗模块触发 rejion 之后,发送 beacon request 的周期间隔。默认值为 180s,即当设备丢失父节点时,会间隔 180 秒尝试 rejion。

    • rejoin 次数:低功耗模块触发 rejion 之后,发送 beacon request 的次数,默认值为 1,可设置范围为 1~10 次。

    • 发送功率:发送功率越大,功耗越高,默认值为 11dB,可设置范围为 3~19dB。

    以上几个参数为模组较常用的几个参数,模组网络参数调节完之后测出模组休眠状态功耗约为 2.4uA,以上参数满足低功耗要求故开发者无须再次修改调节。

    MCU 有多种低功耗模式:睡眠模式、低功耗运行模式、低功耗睡眠模式、停止模式、待机模式。

    待机模式电流最低,但是待机模式时的 MCU 处于不受控制的状态,所有的 IO 口都工作在高阻抗的状态下,只有专门的几个引脚能将 MCU 唤醒,而每次唤醒后相当于系统复位,RAM 中的数据全部丢失,在外部器件连接的情况下,器件的引脚可能会吸收大量的电流,反而达不到低功耗的要求。

    停止模式的功耗仅次于待机模式。在 STOP 模式下,PLL、HSL、HSE 都被停止,RAM 和寄存器的值保留。

    本次方案采用 STOP2 模式为功耗最低的睡眠模式,且 STOP2 模式只能从运行模式进入,开发者可根据自身应用场景选择相应的模式,下面是 MCU 在几种模式下的功耗大小,

    低功耗模式 电流消耗 唤醒时间 STOP0 100 µA 0.7 µs STOP1 4.6 µA 4 µs STOP2 2.7µA 5 µs

    下面为 MCU 进入低功耗模式的流程步骤