智能语音垃圾桶——设备端.md 18 KB

智能语音垃圾桶——设备端

搭建好开发环境后,就可以开始编写代码

一、设备功能代码

1、初始化设备

(1)智能语音垃圾桶需要四个舵机,所以我们需要对GPIO6、GPIO7、GPIO9、GPIO10做初始化设置pwm功能

void SmartdustbinInit(void)
{
    GpioInitOperation(HAL_WIFI_IOT_IO_NAME_GPIO_10, 0, IOT_GPIO_DIR_OUT, IOT_GPIO_VALUE0);
    GpioInitOperation(HAL_WIFI_IOT_IO_NAME_GPIO_9, 0, IOT_GPIO_DIR_OUT, IOT_GPIO_VALUE0);
    GpioInitOperation(HAL_WIFI_IOT_IO_NAME_GPIO_7, 0, IOT_GPIO_DIR_OUT, IOT_GPIO_VALUE0);
    GpioInitOperation(HAL_WIFI_IOT_IO_NAME_GPIO_6, 0, IOT_GPIO_DIR_OUT, IOT_GPIO_VALUE0);
}
2、舵机功能

可将GPIO10、GPIO9、GPIO7、GPIO6分别用作可回收垃圾、不可回收垃圾、厨余垃圾、其他垃圾的开关功能

(1)设置舵机旋转角度及方向
//舵机正转
void set_engine_angle_R(hi_s32 duty)
{   
    uint32 count = duty/THE_PARM_OF_CACL_CYCLE;
    for (int i = 1; i <= count; i++) {
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_10, IOT_GPIO_VALUE1);
        hal_udelay(duty - i*THE_PARM_OF_CACL_CYCLE);
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_10, IOT_GPIO_VALUE0);
        hal_udelay(THE_CYCLES_OF_PWM_CONTROL - (duty - i*THE_PARM_OF_CACL_CYCLE));
    }
}
void set_engine_angle_U(hi_s32 duty)
{
    uint32 count = duty/THE_PARM_OF_CACL_CYCLE;
    for (int i = 1; i <= count; i++) {
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_9, IOT_GPIO_VALUE1);
        hal_udelay(duty - i*THE_PARM_OF_CACL_CYCLE);
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_9, IOT_GPIO_VALUE0);
        hal_udelay(THE_CYCLES_OF_PWM_CONTROL - (duty - i*THE_PARM_OF_CACL_CYCLE));
    }
}
void set_engine_angle_K(hi_s32 duty)
{
    uint32 count = duty/THE_PARM_OF_CACL_CYCLE;
    for (int i = 1; i <= count; i++) {
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_7, IOT_GPIO_VALUE1);
        hal_udelay(duty - i*THE_PARM_OF_CACL_CYCLE);
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_7, IOT_GPIO_VALUE0);
        hal_udelay(THE_CYCLES_OF_PWM_CONTROL - (duty - i*THE_PARM_OF_CACL_CYCLE));
    }
}
void set_engine_angle_O(hi_s32 duty)
{
    uint32 count = duty/THE_PARM_OF_CACL_CYCLE;
    for (int i = 1; i <= count; i++) {
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_6, IOT_GPIO_VALUE1);
        hal_udelay(duty - i*THE_PARM_OF_CACL_CYCLE);
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_6, IOT_GPIO_VALUE0);
        hal_udelay(THE_CYCLES_OF_PWM_CONTROL - (duty - i*THE_PARM_OF_CACL_CYCLE));
    }
}
//舵机反转
void set_engine_angle_reversal(hi_s32 duty)
{

    uint32 count = duty/THE_PARM_OF_CACL_CYCLE;
    for (int i = 1; i <= count; i++) {
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_10, IOT_GPIO_VALUE1);
        hal_udelay(i*THE_PARM_OF_CACL_CYCLE);
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_10, IOT_GPIO_VALUE0);
        hal_udelay(THE_CYCLES_OF_PWM_CONTROL - i*THE_PARM_OF_CACL_CYCLE);
    }
}
void set_engine_angle_reversal_U(hi_s32 duty)
{
    uint32 count = duty/THE_PARM_OF_CACL_CYCLE;
    for (int i = 1; i <= count; i++) {
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_9, IOT_GPIO_VALUE1);
        hal_udelay(i*THE_PARM_OF_CACL_CYCLE);
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_9, IOT_GPIO_VALUE0);
        hal_udelay(THE_CYCLES_OF_PWM_CONTROL - i*THE_PARM_OF_CACL_CYCLE);
    }
}
void set_engine_angle_reversal_K(hi_s32 duty)
{
    uint32 count = duty/THE_PARM_OF_CACL_CYCLE;
    for (int i = 1; i <= count; i++) {
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_7, IOT_GPIO_VALUE1);
        hal_udelay(i*THE_PARM_OF_CACL_CYCLE);
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_7, IOT_GPIO_VALUE0);
        hal_udelay(THE_CYCLES_OF_PWM_CONTROL - i*THE_PARM_OF_CACL_CYCLE);
    }
}
void set_engine_angle_reversal_O(hi_s32 duty)
{
    uint32 count = duty/THE_PARM_OF_CACL_CYCLE;
    for (int i = 1; i <= count; i++) {
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_6, IOT_GPIO_VALUE1);
        hal_udelay(i*THE_PARM_OF_CACL_CYCLE);
        IoTGpioSetOutputVal(HAL_WIFI_IOT_IO_NAME_GPIO_6, IOT_GPIO_VALUE0);
        hal_udelay(THE_CYCLES_OF_PWM_CONTROL - i*THE_PARM_OF_CACL_CYCLE);
    }
}

3、写dustbin_open()和dustbin_close()函数方便调用
void Dustbin_close_R(void)
{
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "           ", 1);
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "Dustbin:close_R", 1);
    set_engine_angle_reversal(THE_ANGLE_OF_dustbin_WROK);
    g_dustbinIsOpen = FALSE;
}
void Dustbin_close_U(void)
{
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "           ", 1);
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "Dustbin:close_U", 1);
    set_engine_angle_reversal_U(THE_ANGLE_OF_dustbin_WROK);
    g_dustbinIsOpen = FALSE;
}
void Dustbin_close_K(void)
{
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "           ", 1);
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "Dustbin:close_K", 1);
    set_engine_angle_reversal_K(THE_ANGLE_OF_dustbin_WROK);
    g_dustbinIsOpen = FALSE;
}
void Dustbin_close_O(void)
{
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "           ", 1);
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "Dustbin:close_O", 1);
    set_engine_angle_reversal_O(THE_ANGLE_OF_dustbin_WROK);
    g_dustbinIsOpen = FALSE;
}
void Dustbin_open_R(void)
{
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "           ", 1);
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "Dustbin:open_R ", 1);
    set_engine_angle_R(THE_ANGLE_OF_dustbin_WROK);
    g_dustbinIsOpen = TRUE;
}
void Dustbin_open_U(void)
{
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "           ", 1);
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "Dustbin:open_U ", 1);
    set_engine_angle_U(THE_ANGLE_OF_dustbin_WROK);
    g_dustbinIsOpen = TRUE;
}
void Dustbin_open_K(void)
{
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "           ", 1);
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "Dustbin:open_K ", 1);
    set_engine_angle_K(THE_ANGLE_OF_dustbin_WROK);
    g_dustbinIsOpen = TRUE;
}
void Dustbin_open_O(void)
{
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "           ", 1);
    OledShowStr(0, Y_SHOW_SMART_CAN_SHOW_OPEN, "Dustbin:open_O ", 1);
    set_engine_angle_O(THE_ANGLE_OF_dustbin_WROK);
    g_dustbinIsOpen = TRUE;
}

二、容量上报

我们需要一个包含四个垃圾桶容量上报的函数,上报属性可参考profile文件

int IotProfile_Report_ALL(int dev_status,int recyclables_Capacity,int unrecyclable_Capacity,int kitchenGarbage_Capacity,int otherRubbish_Capacity)
{
    int ret = -1;
    cJSON *root;
    char *jsonString;
    IotProfileService    service;
    IotProfileKV  kvDev_status;//dev
    IotProfileKV  kvRecyclables_Capacity;//可回收垃圾桶
    IotProfileKV  kvUnrecyclable_Capacity;//不可回收垃圾桶
    IotProfileKV  kvKitchenGarbage_Capacity;//厨余垃圾垃圾桶
    IotProfileKV  kvOtherRubbish_Capacity;//其他垃圾

    /* package the data */
    service.eventTime = NULL;
    service.serviceID = "SmartDustbin_DATA";
    service.propertyLst = &kvDev_status;
    service.nxt = NULL;

    kvDev_status.key = "Dev_Status";
    kvDev_status.value = &dev_status;
    kvDev_status.type = IOT_PROFILE_KEY_DATATYPE_INT;
    kvDev_status.nxt = &kvRecyclables_Capacity;

    kvRecyclables_Capacity.key = "Recyclables_Capacity";
    kvRecyclables_Capacity.value = &recyclables_Capacity;
    kvRecyclables_Capacity.type = IOT_PROFILE_KEY_DATATYPE_INT;
    kvRecyclables_Capacity.nxt = &kvUnrecyclable_Capacity;

    kvUnrecyclable_Capacity.key = "Unrecyclable_Capacity";
    kvUnrecyclable_Capacity.value = &unrecyclable_Capacity;
    kvUnrecyclable_Capacity.type = IOT_PROFILE_KEY_DATATYPE_INT;
    kvUnrecyclable_Capacity.nxt = &kvKitchenGarbage_Capacity;

    kvKitchenGarbage_Capacity.key = "KitchenGarbage_Capacity";
    kvKitchenGarbage_Capacity.value = &kitchenGarbage_Capacity;
    kvKitchenGarbage_Capacity.type = IOT_PROFILE_KEY_DATATYPE_INT;
    kvKitchenGarbage_Capacity.nxt = &kvOtherRubbish_Capacity;

    kvOtherRubbish_Capacity.key = "OtherRubbish_Capacity";
    kvOtherRubbish_Capacity.value = &otherRubbish_Capacity;
    kvOtherRubbish_Capacity.type = IOT_PROFILE_KEY_DATATYPE_INT;
    kvOtherRubbish_Capacity.nxt = NULL;

    jsonString = IoTProfilePackage(&service);
    if ( NULL != jsonString) {
        ret = CLOUD_ReportMsg(jsonString);
        free(jsonString);
    } else {
        RaiseLog(LOG_LEVEL_ERR, "format the report message error");
    }
    return ret;
}

三、接收及解析iot云命令

1、首先需要一个云端命令处理函数
int CLOUD_CommandCallBack(const char *jsonString)
{
    cJSON *objRoot = NULL;
    cJSON *objCmdName = NULL;
    int ret = -1;
    if (jsonString == NULL) {
        return ret;
    }
    if ((objRoot = cJSON_Parse(jsonString)) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "could not parse the payload\r\n");
        goto EXIT_JSONPARSE;
    }
    if ((objCmdName = cJSON_GetObjectItem(objRoot, "command_name")) == NULL) {     
        RaiseLog(LOG_LEVEL_ERR, "%s:could not get the cmd name from json\r\n");
        goto EXIT_CMDOBJ;
    }

    if (0 == strcmp(cJSON_GetStringValue(objCmdName), "Open_R")) {
        ret = DealMain_dustbinOpenRecyclables(objRoot);
    } else if(0 == strcmp(cJSON_GetStringValue(objCmdName), "Open_U")) {
        ret = DealMain_dustbinOpenUnrecyclable(objRoot);
    } else if(0 == strcmp(cJSON_GetStringValue(objCmdName), "Open_K")) {
        ret = DealMain_dustbinOpenKitchenGarbage(objRoot);
    }else if(0 == strcmp(cJSON_GetStringValue(objCmdName), "Open_O")) {
        ret = DealMain_dustbinOpenOtherRubbish(objRoot);
    }else {
        RaiseLog(LOG_LEVEL_ERR, "unresolved command:%d\r\n", cJSON_GetStringValue(objCmdName));
    }

EXIT_CMDOBJ:
EXIT_JSONPARSE:
    if (objRoot != NULL) {
        cJSON_Delete(objRoot);
    }
    return ret;
}
2、对命令进行解析处理,IoT云下发Open_R命令将会调用DealMain_dustbinOpenRecyclables()
static int DealMain_dustbinOpenRecyclables(cJSON *objCmd)//云端命令处理
{   int ret = -1;
    cJSON *objParas = NULL;
    cJSON *objPara = NULL;
    CommandParamSetOpen setOpen;
    if ((objParas = cJSON_GetObjectItem(objCmd, "paras")) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "Could not get paras in json");
        return ret;
    }
    if (Getcommand_dustbinOpenRecyclables(&setOpen, objParas) < 0) {
        RaiseLog(LOG_LEVEL_ERR, "GetCommandSetOpen failed!\n");
    }
    ret = IotProfile_CommandCallback(CLOUD_COMMAND_SETOPEN, &setOpen);
    return ret;
}
3、对IoT云命令进行响应回馈
int IotProfile_CommandCallback(int command, void *buf)
{
    CommandParamSetOpen setOpen;
    CLOUD_CommandType cmd = (CLOUD_CommandType)command;
    if (cmd == CLOUD_COMMAND_SETOPEN) {
        setOpen = *(CommandParamSetOpen *)buf;
        g_appController.recyclables_Capacity = setOpen.openStatus;
        return 0;
    } 
    return -1;
}
4、对Open命令的命令参数进行进一步解析
static int Getcommand_dustbinOpenRecyclables(CommandParamSetOpen *setOpen,cJSON *objCmd)
{
    cJSON *objPara = NULL;
    if (setOpen== NULL || objCmd == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "NULL POINT!\n");
        return -1;
    }
    memset(setOpen, 0x00, sizeof(CommandParamSetOpen));

    if ((objPara = cJSON_GetObjectItem(objCmd, "OpenRecyclables")) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "Could not get paras in json");
        return -1;
    }
        if (0 == strcmp(cJSON_GetStringValue(objPara), "ON")) {
            Dustbin_open_R();
        }
        else {
            Dustbin_close_R();
        }
    return 0;
}

static int Getcommand_dustbinOpenUnrecyclable(CommandParamSetOpen *setOpen,cJSON *objCmd)
{
    cJSON *objPara = NULL;
    if (setOpen== NULL || objCmd == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "NULL POINT!\n");
        return -1;
    }
    memset(setOpen, 0x00, sizeof(CommandParamSetOpen));

    if ((objPara = cJSON_GetObjectItem(objCmd, "OpenUnrecyclable")) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "Could not get paras in json");
        return -1;
    }
        if (0 == strcmp(cJSON_GetStringValue(objPara), "ON")) {
            Dustbin_open_U();
        }
        else {
            Dustbin_close_U();
        }
    return 0;
}

static int Getcommand_dustbinOpenKitchenGarbage(CommandParamSetOpen *setOpen,cJSON *objCmd)
{
    cJSON *objPara = NULL;
    if (setOpen== NULL || objCmd == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "NULL POINT!\n");
        return -1;
    }
    memset(setOpen, 0x00, sizeof(CommandParamSetOpen));

    if ((objPara = cJSON_GetObjectItem(objCmd, "OpenKitchenGarbage")) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "Could not get paras in json");
        return -1;
    }
        if (0 == strcmp(cJSON_GetStringValue(objPara), "ON")) {
            Dustbin_open_K();

        }
        else {
            Dustbin_close_K();
        }
    return 0;
}

static int Getcommand_dustbinOpenOtherRubbish(CommandParamSetOpen *setOpen,cJSON *objCmd)
{
    cJSON *objPara = NULL;

    if (setOpen== NULL || objCmd == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "NULL POINT!\n");
        return -1;
    }
    memset(setOpen, 0x00, sizeof(CommandParamSetOpen));
    if ((objPara = cJSON_GetObjectItem(objCmd, "OpenOtherRubbish")) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "Could not get paras in json");
        return -1;
    }
        if (0 == strcmp(cJSON_GetStringValue(objPara), "ON")) {
            Dustbin_open_O();
        }
        else {
            Dustbin_close_O();
        }
    return 0;
}

四、hi3861获取语音开发板命令

语音开发板识别一级命令:“你好,垃圾桶”成功后,说出第二级控制命令后,通过UART串口协议输出cJson包:Open_R、Open_U、Open_K、Open_O,需要hi3861对接口进行监听,以保证不会漏掉语音命令

1、hi3861初始化GPIO0和GPIO1用于UART串口协议传输
 void UartInit(void){
    RaiseLog(LOG_LEVEL_INFO,"[2022012x01] entry into UartInit");
    IoTGpioInit(HAL_WIFI_IOT_IO_NAME_GPIO_0);
    HalIoSetFunc(HAL_WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_UART1_TXD);
    IoTGpioInit(HAL_WIFI_IOT_IO_NAME_GPIO_1);
    HalIoSetFunc(HAL_WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_UART1_RXD);
    hi_uart_attribute uart_attr = {
        .baud_rate = UART_BAUD_RATE, /* baud_rate: 9600 */
        .data_bits = UART_DATA_BITS,      /* data_bits: 8bits */
        .stop_bits = UART_STOP_BITS,
        .parity = 0,
    };
    RaiseLog(LOG_LEVEL_INFO,"[2022012x01] uart_init success");
    /* Initialize uart driver */
    hi_u32 ret = hi_uart_init(HI_UART_IDX_1, &uart_attr, HI_NULL);
    if (ret != HI_ERR_SUCCESS)
    {
        printf("[220214x02]Failed to init uart! Err code = %d\n", ret);
        return;
    }
}
2、对UART串口程序创建线程
static void *uart_demo_task(void)
{
    static uint16_t countSendTimes = 0;
    static uint8_t countReceiveTimes = 0;
    g_uartController.isReadBusy = false;
    printf("[Initialize uart successfully\n");
    while (1)
    {
        osDelay(50); 
        UartReceiveMessage();//Collecting Serial Port Data
        hi_sleep(SMART_CAN_SLEEP_2500MS);  
    }
    return 0;
}
void uart_task_create(void)
{
    RaiseLog(LOG_LEVEL_INFO,"uart_task_create");
    osThreadAttr_t attr;
    attr.name = "uartTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = UART_DEMO_TASK_STAK_SIZE;
    attr.priority = CONFIG_TASK_UART_PRIOR;
    if (osThreadNew((osThreadFunc_t)uart_demo_task, NULL, &attr) == NULL)
    {
        printf("[220214x02]Falied to create uart_demo_task!\n");
    }
}
3、串口数据收集程序
static void UartReceiveMessage(void)
{
    char *recData;
    printf("----Listening----");
    RaiseLog(LOG_LEVEL_INFO,"Start Listening serial port");
    if (UartIsBufEmpty())
        {
            return;
        }
        if (g_uartController.isReadBusy)
        {
            return;
        }
        g_uartController.isReadBusy = true;
        g_ReceivedDatalen = hi_uart_read(DEMO_UART_NUM, g_uart_buff, UART_BUFF_SIZE);
        if (g_ReceivedDatalen > 0)
        {
            printf("UartReceiveMessage rcvData len:%d,msg:%s.\n", g_ReceivedDatalen, g_uart_buff);
            setVoiceCommand();//Setting voice Commands
            memset(g_uart_buff, 0, sizeof(g_uart_buff));
            g_ReceivedDatalen = 0;
        }
        g_uartController.isReadBusy = false;
}
4、语音命令解析程序
static void setVoiceCommand(void)
{  
    if (strstr(g_uart_buff, "Open_R") != NULL)
    {
        printf("[220214x02]listened Open_R\n");
        Dustbin_open_R();
        printf("[220214x02] Delay 10s close_R\n");
        osDelay(1000);
        Dustbin_close_R();
    }else if (strstr(g_uart_buff, "Open_U") != NULL)
    {
        printf("[220214x02]listened Open_U\n");
        Dustbin_open_U();
        printf("[220214x02] Delay 10s close_U\n");
        osDelay(1000);
        Dustbin_close_U();
    }else if (strstr(g_uart_buff, "Open_K") != NULL)
    {
        printf("[220214x02]listened Open_K\n");
        Dustbin_open_K();
        printf("[220214x02] Delay 10s close_K\n");
        osDelay(1000);
        Dustbin_close_K();
    }else if (strstr(g_uart_buff, "Open_O") != NULL)
    {
        printf("[220214x02]listened Open_O\n");
        Dustbin_open_O();
        printf("[220214x02] Delay 10s close_O\n");
        osDelay(1000);
        Dustbin_close_O();
    }

}