蜜袋鼯 第⑦贴 基于RSL10的蜜袋鼯--运动奖励系统之软件设计
[复制链接]
前要简介
上一贴介绍了基于RSL10的蜜袋鼯健康监测项目中的运动奖励系统,运动奖励子系统主要可以实现 主机端通过蓝牙协议 与其通讯,当有奖励指令下达后,该系统则驱动电磁阀导通,推出装有小虫的盒子,已达到给蜜袋鼯奖励食物的作用。
本帖正文
上一贴讲解了运动奖励子系统的结构设计和硬件设计部分。
本帖主要讲下软件设计部分内容。
这个子系统的软件实现相对比较简单,首先是要控制电磁铁的通断只需要实现几个IO的功能,
我选择了ble_peripheral_server_bond作为基础工程
在app.h中定义了输出引脚号
app.h
........
/* 喂食继电器 DIO 端口定义 */
#define TS1_DIO_NUM 0
#define TS2_DIO_NUM 1
#define TS3_DIO_NUM 2
#define TS4_DIO_NUM 3
#define TS5_DIO_NUM 4
........
在app_config.c中做了初始化
void Device_Initialize(void)
{
.........
Sys_DIO_Config(TS1_DIO_NUM, DIO_MODE_GPIO_OUT_0);
Sys_DIO_Config(TS2_DIO_NUM, DIO_MODE_GPIO_OUT_0);
Sys_DIO_Config(TS3_DIO_NUM, DIO_MODE_GPIO_OUT_0);
Sys_DIO_Config(TS4_DIO_NUM, DIO_MODE_GPIO_OUT_0);
Sys_DIO_Config(TS5_DIO_NUM, DIO_MODE_GPIO_OUT_0);
Sys_GPIO_Set_Low(TS1_DIO_NUM);
Sys_GPIO_Set_Low(TS2_DIO_NUM);
Sys_GPIO_Set_Low(TS3_DIO_NUM);
Sys_GPIO_Set_Low(TS4_DIO_NUM);
Sys_GPIO_Set_Low(TS5_DIO_NUM);
...........
}
然后是通讯方面,使用customss协议定义好uuid实现上下位机双向通讯,BLE最大可发送的包大小为20字节,
因为这部分控制也很简单,只要控制对应奖励盒弹出即可,所以协议只用了两个字节,如下
其中 第一个字节为指令,固定为0XFF
第二个字节 按位控制对应奖励器开关,例如0x01为第一个盒子,0x02为第二个盒子,0x04为第三个盒子…
然后在app_customss.c中修改接收、和发送的订阅协议,如下所示
发送给上位机的订阅实现
// 订阅的内容修改为当前奖励器的触发状态
void CUSTOMSS_MsgHandler(ke_msg_id_t const msg_id, void const *param,
ke_task_id_t const dest_id, ke_task_id_t const src_id)
{
.........
case CUSTOMSS_NTF_TIMEOUT:
{
uint8_t conidx = KE_IDX_GET(dest_id);
app_env_cs.to_air_buffer[0] = 0xff;
app_env_cs.to_air_buffer[1] = 0x00;
for(int i=0;i<5;i++)
{
if(DIO->CFG&0x01)
app_env_cs.to_air_buffer[1] |= 1<<i;
}
if ((app_env_cs.to_air_cccd_value[0] == ATT_CCC_START_NTF &&
app_env_cs.to_air_cccd_value[1] == 0x00)
&& GAPC_IsConnectionActive(conidx))
{
/* Send notification to peer device */
GATTC_SendEvtCmd(conidx, GATTC_NOTIFY, 0, GATTM_GetHandle(CS_TX_VALUE_VAL0),
2 , app_env_cs.to_air_buffer);
}
........
}
上位机发送给下位机的接收实现
//接收到消息后,判断帧数据是否为指令,并执行操作
uint8_t CUSTOMSS_RXCharCallback(uint8_t conidx, uint16_t attidx, uint16_t handle,
uint8_t *to, const uint8_t *from, uint16_t length,
uint16_t operation)
{
memcpy(to, from, length);
#if RSL10_DEBUG
PRINTF("RXCharCallback (%d): (%d) ", conidx, length);
for (int i = 0; i < length; i++)
{
PRINTF("%02x ", app_env_cs.from_air_buffer);
}
PRINTF("\n\r");
#endif /* if RSL10_DEBUG */
/* 判断协议是否正确
* 协议简易设置为 0xff 0xxx 第二个字节 按位控制IO开关 */
if(length == 2 && to[0] == 0xff)
{
ke_timer_set(APP_FSIO_TIMEOUT, TASK_APP, TIMER_SETTING_MS(200));
for(int i=0; i < 5; i++)
{
if(((to[1]>>i)&0x01) == 1)
{
Sys_GPIO_Set_High(i);
#if RSL10_DEBUG
PRINTF("Open TS%d.\r\n", i);
#endif /* if RSL10_DEBUG */
}
else
{
Sys_GPIO_Set_Low(i);
#if RSL10_DEBUG
PRINTF("Close TS%d.\r\n", i);
#endif /* if RSL10_DEBUG */
}
}
}
return ATT_ERR_NO_ERROR;
}
需要注意的是,奖励系统的电磁铁只要通电一下就能弹出来并且自己维持
所以为了避免浪费电量,增加了个软件定时器,来执行关闭电磁铁的操作,代码修改如下:
//新增奖励IO触发超时定时回调函数
void APP_FSio_Timeout_Handler(ke_msg_id_t const msg_id, void const *param,
ke_task_id_t const dest_id, ke_task_id_t const src_id)
{
Sys_GPIO_Set_Low(TS1_DIO_NUM);
Sys_GPIO_Set_Low(TS2_DIO_NUM);
Sys_GPIO_Set_Low(TS3_DIO_NUM);
Sys_GPIO_Set_Low(TS4_DIO_NUM);
Sys_GPIO_Set_Low(TS5_DIO_NUM);
}
并在app.c中注册上述函数的回调
app.c
int main(void)
{
........
MsgHandler_Add(APP_FSIO_TIMEOUT, APP_FSio_Timeout_Handler);
.......
}
以上就是运动奖励子系统上的代码实现过程。
别急啦,下一贴零件就到啦,给你装起来~ 要不你给我写个上位机吧?
|