开发者成长激励计划-基于TencentOS Tiny的植物土壤湿度监测机

2023-07-01 23:31:40 浏览数 (2)

一、总体设计

本次有幸参与开放原子开源基金会举办的开发者成长激励计划,植物土壤湿度监测机基于TencentOS Tiny CH32V_EVB RISC-V开发套件(采用WCH的RISC-V CH32V307VCT6 MCU)开发套件,外接WiFi模组及土壤湿度传感器监测植物生长环境湿度数据上传至云端,支持本地自动水泵运行,也可以通过腾讯云IoT实现云端手动控制水泵。

二、硬件设计

  • 开发板采用沁恒RISC-V MCU CH32V307VCT6芯片,CH32V305/7系列是基于沁恒自研RISC-V架构微处理器青稞V4系列设计的32位工业级互联型微控制器,配备了硬件堆栈区、快速中断入口,在标准RISC-V基础上大大提高了中断响应速度。加入单精度浮点指令集,扩充堆栈区,具有更高的运算性能。扩展串口UART数量到8组,定时器到10组,其中4组高级定时器。提供USB2.0高速接口(480Mbps)并内置了PHY收发器,以太网MAC升级到千兆并集成了10M-PHY模块。

硬件外设选择了土壤湿度传感器、一个板载的ESP8266模块直接用上了。水泵手头暂时没有,先LED顶上吧,板子上UESR LED 3/4权当水泵。

三、软件设计

借助于TencentOS Tiny系统和各种软件模块,整个软件比较简洁,相关硬件的驱动也直接从WCH的软件包下载,直接进行搭积木使用,效果很赞。

(一)ADC task

主要实现了ADC设备数据周期性读取,相关代码如下:

代码语言:javascript复制
void ADC_Function_Init(void)
{
    ADC_InitTypeDef ADC_InitStructure={0};
    GPIO_InitTypeDef GPIO_InitStructure={0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );

    ADC_DeInit(ADC1);
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_Cmd(ADC1, ENABLE);

    ADC_BufferCmd(ADC1, DISABLE);   //disable buffer
    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));
    Calibrattion_Val = Get_CalibrationValue(ADC1);

    ADC_BufferCmd(ADC1, ENABLE);   //enable buffer

    ADC_TempSensorVrefintCmd(ENABLE);
}

u16 Get_ADC_Val(u8 ch)
{
    u16 val;

    ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);

    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));

    val = ADC_GetConversionValue(ADC1);

    return val;
}


u16 Get_ADC_Average(u8 ch,u8 times)
{
    u32 temp_val=0;
    u8 t;
    u16 val;

    for(t=0;t<times;t  )
    {
        temp_val =Get_ADC_Val(ch);
        tos_task_delay(5);
    }

    val = temp_val/times;

    return val;
}

void ADC_entry(void *arg)
{
    u16 val;

    ADC_Function_Init();
    printf("CalibrattionValue:%dn", Calibrattion_Val);

    while(1)
    {
        val = Get_ADC_Average( ADC_Channel_8, 10 );
        tos_task_delay(1000);

        ADC_val = Get_ConversionVal(val);
        printf( "ADC-Val:%dn", ADC_val);
        
        //local ctrl
        if (autoMode == true)
        {
            if (ADC_val < 50)
            {
                GPIO_WriteBit(GPIOE, GPIO_Pin_4|GPIO_Pin_5, 0);
                printf("LOCAL ACTION: Humidity = %d%%,PUMP ONn", ADC_val);
            }
            else
            {
                GPIO_WriteBit(GPIOE, GPIO_Pin_4|GPIO_Pin_5, 1);
                printf("LOCAL ACTION: Humidity = %d%%,PUMP OFFn", ADC_val);
            }
        }
        
        tos_task_delay(1000);
    }
}

因为该土壤湿度传感器没法精确读取湿度,只能人工取到从干燥到泡入水中的取值范围,再用%量化:

代码语言:javascript复制
u16 Get_ConversionVal(s16 val)
{
    if(val < 3500) val = 3500;
    if(val > 4090 ) val = 4000;

    return ((4000 - val)/5);
}

本地水泵控制逻辑,低于50%启动水泵,1s监测一次土壤湿度:

代码语言:javascript复制
        //local ctrl
        if (autoMode == true)
        {
            if (ADC_val < 50)
            {
                GPIO_WriteBit(GPIOE, GPIO_Pin_4|GPIO_Pin_5, 0);
                printf("LOCAL ACTION: Humidity = %d%%,PUMP ONn", ADC_val);
            }
            else
            {
                GPIO_WriteBit(GPIOE, GPIO_Pin_4|GPIO_Pin_5, 1);
                printf("LOCAL ACTION: Humidity = %d%%,PUMP OFFn", ADC_val);
            }
        }     

(二)DISP task

显示task功能较简单,就是将获得的土壤湿度数据进行显示。

代码语言:javascript复制
void disp_entry(void *arg)
{
    char dispStr[20] = {0};

    printf("***display TASKrn");
    while (1)
    {
        sprintf(dispStr, "Humidity = =%%", ADC_val);
        printf("%sn", dispStr);
        LCD_ShowString(0,20,dispStr,RED,WHITE,32,0);
        tos_task_delay(1000);
    }
}

(三)CONN task

实现了端侧数据上云,使用TencentOS Tiny已有的代码框架,加上自己的业务逻辑,简单好用还牢靠。

收到云端水泵控制命令,人工接管水泵控制权。

代码语言:javascript复制
void default_message_handler(mqtt_message_t* msg)
{
    cJSON* cjson_root   = NULL;
    cJSON* cjson_status = NULL;
    cJSON* cjson_ctrl = NULL;
    int  status = 0xff;

    printf("callback:rn");
    printf("---------------------------------------------------------rn");
    printf("ttopic:%srn", msg->topic);
    printf("tpayload:%srn", msg->payload);
    printf("---------------------------------------------------------rn");

    char *p = ((char*)msg->payload) 1;
    cjson_root = cJSON_Parse(p);
    if (cjson_root == NULL) {
        printf("report reply message parser failrn");
        goto exit;
    }

    printf("CJSON %s rn", (char*)msg->payload);

    cjson_status = cJSON_GetObjectItem(cjson_root, "params");
    if (cjson_status == NULL)
    {
        printf("report reply status parser params failrn");
        goto exit;
    }

    cjson_ctrl = cJSON_GetObjectItem(cjson_status, "ctrl");
    status = cJSON_GetIntValue(cjson_ctrl);
    if (cjson_ctrl == NULL)
    {
        printf("report reply status parser ctrl failrn");
        goto exit;
    }

    if (status == 1)
    {
        printf("CLOUD ACTION: PUMP ONn");
        GPIO_WriteBit(GPIOE, GPIO_Pin_4|GPIO_Pin_5, 0);
        autoMode = 0;
    }else if(status == 0)
    {
        printf("CLOUD ACTION: PUMP OFFn");
        GPIO_WriteBit(GPIOE, GPIO_Pin_4|GPIO_Pin_5, 1);
        autoMode = 1;
    }else
    {
        printf("error parametern");
    }

    exit:
        cJSON_Delete(cjson_root);
        cjson_root = NULL;
        status = 0;
        return;
}

(四)blink task

实现LED的周期性闪烁。

代码语言:javascript复制
void blink_entry(void *arg)
{
    u8 pin_Set = false;

    printf("***blink TASKrn");
    while (1)
    {
        if (pin_Set)
        {
            GPIO_WriteBit(GPIOE, GPIO_Pin_2|GPIO_Pin_3, 0);
            pin_Set = false;
        }
        else
        {
            GPIO_WriteBit(GPIOE, GPIO_Pin_2|GPIO_Pin_3, 1);
            pin_Set = true;
        }
        tos_task_delay(1000);
    }
}

(五)MounRiver IDE

第一次用MounRiver,毫无违和感,支持点赞,点名表扬。

MounRiver Studio是一款面向RISC-V内核单片机的集成开发环境。为用户提供专业嵌入式项目所需的开发、调试环境,烧录工具及完善的项目管理功能。代码编辑,工程模板导入、导出,单步调试,代码烧录,IDE在线、离线升级…MounRiver Studio为单片机开发提供了完整的解决方案。

四、实际运行效果

开机后的LOG,来自TencentOS Tiny 2.4.5。

来到腾讯云IoT,可以看到设备在线 数据上云。

最后,真实环境出场。

IPS LCD太亮,来个特写,起码显示弄清楚吧。

实现了本地数据读取并上报云端,云端命令端侧执行的功能。

五、总结

1.其实可以做的更好点(update,增加了云端控制、腾讯连连小程序等功能,基本完整了);

2.RISC-V发展趋势不可阻拦,一年前用的RISC-V跟现在这个完全不能比;

3.TencentOS Tiny资料很好,可以直接上手;

4.培训的授课大佬们都很用心,能感受到;

5.最后,感谢开放原子开源基金会!感谢WCH和TencentOS Tiny!

最后,感谢阅读。

0 人点赞