一、总体设计
本次有幸参与国民技术N32项目移植,植物生长仪基于国民技术推出的N32G45XVL-STB开发套件,外接WiFi模组及土壤湿度传感器,监测植物生长环境湿度并上传至云端,同时利用支持云端下发控制命令实现远程控制。
二、硬件设计
系统硬件基于N32G45XVL-STB,MCU为N32G457,采用32-bit
ARM Cortex-M4内核,集成高达512KB片内FLASH,144KB SRAM,多达17个高性能模拟器件,18个数字通讯接口,同时集成10/100M以太网接口,数字摄像头接口,内置10余种密码算法硬件加速引擎,支持存储加密、用户分区保护、安全启动等多种安全特性,可广泛应用于网络打印机、3D打印机、门禁考勤系统、LED户外显示屏、工业小型网关、DTU、PLC、充电桩等消费及工业互联应用领域。此外,板载祖传miniUSB接口CMSIS DAP仿真器。
硬件外设选择了ESP8266模块、土壤湿度传感器、一个板载的LED权当水泵了(反正都是PIN控制,又不是不能用),具体接口见下表。
三、软件设计和实现
借助于RT-Thread系统的各种软件模块,整个软件比较简洁,因为本来需要开发者自己实现的驱动和功能,RT-Thread都通过基础驱动和组件模块实现了,而且效果很赞。
通过RT-Studio,配置如下组件:
具体软件架构如下:
端侧软件主要4个task:
1.main task:主要初始化环境,譬如LED配置,MQ的init,并且启动两大业务task,MQTT task和ADC task,之后便控制LED2不断闪烁。
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO,ENABLE);
GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE);
rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT);
rt_thread_mdelay(1000);
ret = rt_mq_init(&mq, "MsgQ", &msg_pool[0], 1, sizeof(msg_pool), RT_IPC_FLAG_PRIO);
if (ret != RT_EOK)
{
rt_kprintf("init message queue failed: %d.\n", ret);
return -1;
}
rt_thread_mdelay(1000);
onenet_mqtt_init();
rt_thread_mdelay(1000);
onenet_upload_cycle();
while (1)
{
rt_pin_write(LED1_PIN, PIN_LOW);
rt_thread_mdelay(1000);
rt_pin_write(LED1_PIN, PIN_HIGH);
rt_thread_mdelay(1000);
}
2.ADC task:采集ADC1的数据,并且在自动模式下根据土壤湿度传感器的度数是否超过阈值决定是否启动水泵(亮LED3),同时将具体数值通过消息队列发送给MQTT task。
adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
while(1)
{
rt_thread_mdelay(2000);
value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
if (value > 30) value = 30;
tmp = 30 - value;
if (iMode == 0)
{
if(tmp <15)
{
rt_pin_write(LED2_PIN, PIN_HIGH);
}
else
{
rt_pin_write(LED2_PIN, PIN_LOW);
}
}
rt_kprintf("rt_adc_read :%d \n",value);
result = rt_mq_send(&mq, (char *)&tmp, sizeof(tmp));
if (result != RT_EOK)
{
rt_kprintf("rt_mq_send ERR(%d)\n", result);
}
else
{
rt_kprintf("ADC_task: send message - %d\n", tmp);
}
}
3.MQTT task:基于pahoMQTT模块,注册处理MQTT下发信息的回调函数,接收中移物联网平台云端下发手动操作命令,启动/关停水泵(LED3)。
static void onenet_cmd_rsp_cb(uint8_t *recv_data, size_t recv_size, uint8_t **resp_data, size_t *resp_size)
{
char res_buf[] = { "cmd is received!\n" };
LOG_D("recv data is %.*s\n", recv_size, recv_data);
if (strstr(recv_data, "ON") != NULL)
{
iMode = 1;
rt_pin_write(LED2_PIN, PIN_HIGH);
}
else if (strstr(recv_data, "OFF") != NULL)
{
iMode = 0;
rt_pin_write(LED2_PIN, PIN_LOW);
}
*resp_data = (uint8_t *) ONENET_MALLOC(strlen(res_buf));
strncpy((char *)*resp_data, res_buf, strlen(res_buf));
*resp_size = strlen(res_buf);
}
4.upLoadX task:通过消息队列接收来自ADC task的湿度数据,通过onenet MQTT传输至中移物联网平台。
while (1)
{
if (rt_mq_recv(&mq, (char *)&value, sizeof(value), RT_WAITING_FOREVER) == RT_EOK)
{
rt_kprintf("UpLoadX: recv msg from msg queue, the content:%d\n", value);
}
if (onenet_mqtt_upload_digit("humidity", value) < 0)
{
LOG_E("upload has an error, stop uploading");
break;
}
else
{
LOG_D("buffer : {\"humidity\":%d}", value);
}
rt_thread_delay(rt_tick_from_millisecond(1000));
}
最后RT-Thread Studio编译好的固件如下图,内存占用太少了,N32G457的144KB表示毫无压力。
四、运行效果
最熟悉的配方、最熟悉的画面。
来个ps cmd。
再来看看Onenet云端的数据。
最后本尊压轴出场(模拟干燥环境,水泵抽水,把那个绿灯LED3就是水泵)。
<最后,感谢国民技术 & 发烧友>