前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >开发者成长激励计划-基于TencentOS Tiny的植物土壤湿度监测机

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

原创
作者头像
不爱吃胡萝卜
修改2023-07-01 23:31:40
6900
修改2023-07-01 23:31:40
举报

一、总体设计

本次有幸参与开放原子开源基金会举办的开发者成长激励计划,植物土壤湿度监测机基于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:%d\n", Calibrattion_Val);

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

        ADC_val = Get_ConversionVal(val);
        printf( "ADC-Val:%d\n", 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 ON\n", ADC_val);
            }
            else
            {
                GPIO_WriteBit(GPIOE, GPIO_Pin_4|GPIO_Pin_5, 1);
                printf("LOCAL ACTION: Humidity = %d%%,PUMP OFF\n", 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 ON\n", ADC_val);
            }
            else
            {
                GPIO_WriteBit(GPIOE, GPIO_Pin_4|GPIO_Pin_5, 1);
                printf("LOCAL ACTION: Humidity = %d%%,PUMP OFF\n", ADC_val);
            }
        }     

(二)DISP task

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

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

    printf("***display TASK\r\n");
    while (1)
    {
        sprintf(dispStr, "Humidity = %3d%%", ADC_val);
        printf("%s\n", 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:\r\n");
    printf("---------------------------------------------------------\r\n");
    printf("\ttopic:%s\r\n", msg->topic);
    printf("\tpayload:%s\r\n", msg->payload);
    printf("---------------------------------------------------------\r\n");

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

    printf("CJSON %s \r\n", (char*)msg->payload);

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

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

    if (status == 1)
    {
        printf("CLOUD ACTION: PUMP ON\n");
        GPIO_WriteBit(GPIOE, GPIO_Pin_4|GPIO_Pin_5, 0);
        autoMode = 0;
    }else if(status == 0)
    {
        printf("CLOUD ACTION: PUMP OFF\n");
        GPIO_WriteBit(GPIOE, GPIO_Pin_4|GPIO_Pin_5, 1);
        autoMode = 1;
    }else
    {
        printf("error parameter\n");
    }

    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 TASK\r\n");
    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!

最后,感谢阅读。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、总体设计
  • 二、硬件设计
  • 三、软件设计
    • (一)ADC task
      • (二)DISP task
        • (三)CONN task
          • (四)blink task
            • (五)MounRiver IDE
            • 四、实际运行效果
            • 五、总结
            • 最后,感谢阅读。
            相关产品与服务
            TencentOS Server
            TencentOS Server 是腾讯云推出的 Linux 操作系统,它旨在为云上运行的应用程序提供稳定、安全和高性能的执行环境。它可以运行在腾讯云 CVM 全规格实例上,包括黑石物理服务器2.0。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档