一、总体设计
本次有幸参与开放原子开源基金会举办的开发者成长激励计划,植物土壤湿度监测机基于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!