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

开发者成长激励计划-基于TencentOS Tiny环境监测小车

原创
作者头像
用户9951948
修改2022-08-11 11:43:24
5250
修改2022-08-11 11:43:24
举报
文章被收录于专栏:自己的原创自己的原创
开发者成长激励计划TencentOS Tiny 的环境监测小车.ppt

一.前言

随着国家对环境大气监测越来越重视,一种新型移动监测车出现了,他满足了可以随处走动,随时随地的监测数据,本次就是在此方案的影响下完成本次的环境监测小车。当然这里我只是做了一个简单的模型,已经做到了采集温湿度传感器上云,后续可以自己添加一些传感器,真实采集大气的环境的TVOC传感器,还可以加入GPS上传小车行进轨迹。

二.方案框架

本次方案主要使用的是沁恒的CH32V307开发板,外接温度湿度传感器,使用板载TFT,LCD显示,板载的ESP8266作为上云连接,对接腾讯云上传温湿度数据小车状态数据,同时通过其控制了小车,但是稍微有点延时,所以我添加了一块ESP32开发板,通过蓝牙控制小车。

三.硬件方案介绍

这是本次官方的开发板,板载资源十分丰富,有摄像头,SPI falsh。TF卡,wifi模块同时外拓了很多的IO口。还有自带一个网口。可以说这些板载资源已经够开发了,可以实现很多的功能,本次由于时间关系我有一个功能未添加,后续可以添加上,就是把记录数据全部保存到本地的SD卡中,这样再win平台也能查询,本地也可以根据这个完成曲线显示。

本次为了不联网下也能控制小车,我使用了一款乐鑫开发板,ESP32,其集成经典蓝牙和低功耗蓝牙,我用来开发了蓝牙接收数据通过串口发送给CH32V307开发板,从而很快的控制小车动作。

SHT20温湿度传感器,数字式传感器,IIC接口,通过移植我们很好的就获取了其中的温湿度数值,由于手上缺少一些传感器,所以就没做TVOC,PM2.5这些传感器获取,使用这个替代下。

小车底盘我们选择最通用的亚克力板拼成的小车模型,直流电机驱动。

四.软件方案介绍

首先此次开发板是RISC-V内核的单片机,所以沁恒有自己的一套IDE而且不收费的,所以我们直接去官网下载即可。此款IDE名称是MounRiver Studio。使用起来还是有很方便之处的。

首先就是看下我们的Drivers目录,这里添加了我们的小车控制代码,json数据解析代码,还有温湿度传感器的代码。

代码语言:javascript
复制
#include  "car.h"
#include "lcd.h"
u8 car_state = 0;
s8 lcd_car_state = -1;
void car_gpio_init()
{
    GPIO_InitTypeDef  GPIO_InitStructure={0};
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
    GPIO_InitStructure.GPIO_Pin = left_advance_pin; /*  */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(left_advance_prot, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = left_retreat_pin; /*  */
    GPIO_Init(left_retreat_prot, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = right_advance_pin; /*  */
    GPIO_Init(right_advance_prot, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = right_retreat_pin; /*  */
    GPIO_Init(right_retreat_prot, &GPIO_InitStructure);

    car_stop();
}
//小车停止
void car_stop()
{
    car_state = 0;
    left_advance_off();
    left_retreat_off();
    right_advance_off();
    right_retreat_off();
}
//小车前进
void car_advance()
{
    car_state = 1;
    left_advance_on();
    right_advance_on();
}

//小车后退
void car_retreat()
{
    car_state = 2;
    left_retreat_on();
    right_retreat_on();
}

//小车左转
void car_left()
{
    car_state = 3;
    left_advance_on();
    right_retreat_on();
}
//小车右转
void car_right()
{
    car_state = 4;
    left_retreat_on();
    right_advance_on();
}

void car_uart_receive(u8 data)
{
    if(data == 0x00)
    {
        lcd_car_state = 0;
        car_stop();
    }
    else if(data == 0x01)
    {
        lcd_car_state = 1;
        car_advance();
    }
    else if(data == 0x02)
    {
        lcd_car_state = 2;
        car_retreat();
    }
    else if(data == 0x03)
    {
        lcd_car_state = 3;
        car_left();
    }
    else if(data == 0x04)
    {
        lcd_car_state = 4;
        car_right();
    }
}

小车代码,我是使用一款驱动芯片直接4个IO口就能控制两路电机,中间我添加了一个串口接收,这样ESP32蓝牙过来的串口数据也可以控制小车。

代码语言:javascript
复制
void lcd_display(void *arg)
{
    car_gpio_init();
    LCD_Init();
    LCD_Fill(0,0,LCD_W,LCD_H,BLACK);

    Draw_Circle(70,20,12,WHITE);   //前进圆
    Draw_Circle(20,70,12,WHITE);   //右转圆
    Draw_Circle(120,70,12,WHITE);   //左转圆
    Draw_Circle(70,70,12,WHITE);  //停止圆
    Draw_Circle(70,120,12,WHITE);  //后退圆

    LCD_Draw_ALLCircle(70,70,12,RED);  //停止圆


    LCD_ShowChinese(145,10,"温度",WHITE,BLACK,24,0);   //
    LCD_ShowString(195,10,":",WHITE,BLACK,24,0);   //
    LCD_ShowChinese(145,70,"湿度",WHITE,BLACK,24,0);   //
    LCD_ShowString(195,70,":",WHITE,BLACK,24,0);   //

    LCD_ShowString(210,35,"C",YELLOW,BLACK,24,0);
    LCD_ShowString(210,105,"%",LIGHTGREEN,BLACK,24,0);

    LCD_ShowChinese(0,140,"小车状态",WHITE,BLACK,24,0);
    LCD_ShowString(100,140,":",WHITE,BLACK,24,0);
    LCD_ShowChinese(115,140,"停止",BRED,BLACK,24,0);
//    LCD_ShowString(30,140,"TencentOS_Tiny V2.4.5",WHITE,BLACK,16,0);
//    LCD_ShowString(30,140+16,"CH32V_EVB_AIoT RevB02",WHITE,BLACK,16,0);
//    LCD_ShowString(30,140+16+16,"CH32V307",WHITE,BLACK,16,0);

    while (1)
    {
        if(lcd_car_state == 0)
        {

            lcd_car_state = -1;

            car_stop();
            LCD_Draw_ALLCircle(70,20,12,BLACK);   //前进圆
            LCD_Draw_ALLCircle(120,70,12,BLACK);   //右转圆
            LCD_Draw_ALLCircle(20,70,12,BLACK);   //左转圆
            LCD_Draw_ALLCircle(70,70,12,BLACK);  //停止圆
            LCD_Draw_ALLCircle(70,120,12,BLACK);  //后退圆

            Draw_Circle(70,20,12,WHITE);   //前进圆
            Draw_Circle(120,70,12,WHITE);   //右转圆
            Draw_Circle(20,70,12,WHITE);   //左转圆
            Draw_Circle(70,70,12,WHITE);  //停止圆
            Draw_Circle(70,120,12,WHITE);  //后退圆

            LCD_Draw_ALLCircle(70,70,12,RED);  //停止圆

            LCD_ShowChinese(115,140,"停止",BRED,BLACK,24,0);
        }
        else if(lcd_car_state == 1)
        {
            lcd_car_state = -1;

            LCD_Draw_ALLCircle(70,20,12,BLACK);   //前进圆
            LCD_Draw_ALLCircle(120,70,12,BLACK);   //右转圆
            LCD_Draw_ALLCircle(20,70,12,BLACK);   //左转圆
            LCD_Draw_ALLCircle(70,70,12,BLACK);  //停止圆
            LCD_Draw_ALLCircle(70,120,12,BLACK);  //后退圆

            Draw_Circle(70,20,12,WHITE);   //前进圆
            Draw_Circle(120,70,12,WHITE);   //右转圆
            Draw_Circle(20,70,12,WHITE);   //左转圆
            Draw_Circle(70,70,12,WHITE);  //停止圆
            Draw_Circle(70,120,12,WHITE);  //后退圆

//            LCD_Draw_ALLCircle(70,70,12,RED);  //停止圆

            LCD_Draw_ALLCircle(70,20,12,GREEN);   //前进圆
            LCD_ShowChinese(115,140,"前进",BLUE,BLACK,24,0);

        }
        else if(lcd_car_state == 2)
        {
            lcd_car_state = -1;

            LCD_Draw_ALLCircle(70,20,12,BLACK);   //前进圆
            LCD_Draw_ALLCircle(120,70,12,BLACK);   //右转圆
            LCD_Draw_ALLCircle(20,70,12,BLACK);   //左转圆
            LCD_Draw_ALLCircle(70,70,12,BLACK);  //停止圆
            LCD_Draw_ALLCircle(70,120,12,BLACK);  //后退圆

            Draw_Circle(70,20,12,WHITE);   //前进圆
            Draw_Circle(120,70,12,WHITE);   //右转圆
            Draw_Circle(20,70,12,WHITE);   //左转圆
            Draw_Circle(70,70,12,WHITE);  //停止圆
            Draw_Circle(70,120,12,WHITE);  //后退圆

            LCD_Draw_ALLCircle(70,120,12,GREEN);  //后退圆
            LCD_ShowChinese(115,140,"后退",BLUE,BLACK,24,0);
        }
        else if(lcd_car_state == 3)
        {
            lcd_car_state = -1;

            LCD_Draw_ALLCircle(70,20,12,BLACK);   //前进圆
            LCD_Draw_ALLCircle(120,70,12,BLACK);   //右转圆
            LCD_Draw_ALLCircle(20,70,12,BLACK);   //左转圆
            LCD_Draw_ALLCircle(70,70,12,BLACK);  //停止圆
            LCD_Draw_ALLCircle(70,120,12,BLACK);  //后退圆

            Draw_Circle(70,20,12,WHITE);   //前进圆
            Draw_Circle(120,70,12,WHITE);   //右转圆
            Draw_Circle(20,70,12,WHITE);   //左转圆
            Draw_Circle(70,70,12,WHITE);  //停止圆
            Draw_Circle(70,120,12,WHITE);  //后退圆

            LCD_Draw_ALLCircle(20,70,12,GREEN);   //左转圆
            LCD_ShowChinese(115,140,"左转",BLUE,BLACK,24,0);
        }
        else if(lcd_car_state == 4)
        {
            lcd_car_state = -1;

            LCD_Draw_ALLCircle(70,20,12,BLACK);   //前进圆
            LCD_Draw_ALLCircle(120,70,12,BLACK);   //右转圆
            LCD_Draw_ALLCircle(20,70,12,BLACK);   //左转圆
            LCD_Draw_ALLCircle(70,70,12,BLACK);  //停止圆
            LCD_Draw_ALLCircle(70,120,12,BLACK);  //后退圆

            Draw_Circle(70,20,12,WHITE);   //前进圆
            Draw_Circle(120,70,12,WHITE);   //右转圆
            Draw_Circle(20,70,12,WHITE);   //左转圆
            Draw_Circle(70,70,12,WHITE);  //停止圆
            Draw_Circle(70,120,12,WHITE);  //后退圆

            LCD_Draw_ALLCircle(120,70,12,GREEN);   //右转圆
            LCD_ShowChinese(115,140,"右转",BLUE,BLACK,24,0);
        }
        LCD_ShowFloatNum1(150,35,sht20Info.tempreture,4,YELLOW,BLACK,24);   //
        LCD_ShowFloatNum1(150,105,sht20Info.humidity,4,LIGHTGREEN,BLACK,24);   //
        tos_task_delay(1000);
    }
}

LCD显示我是直接专门开了一个任务,用于刷新LCD显示的,目前安排了连接wifi的提示,5个圆代表了我们小车的不同运行状态。侧面我做了温湿度数据显示。

代码语言:javascript
复制
void default_message_handler(mqtt_message_t* msg)
{

    cJSON* cjson_root   = NULL;
    cJSON* cjson_method = NULL;
    cJSON* cjson_status = NULL;
    cJSON* cjson_params = NULL;
    cJSON* cjson_switch = NULL;
    char* status = NULL;
    char* method = NULL;

    k_event_flag_t event_flag = report_fail;


    int StateOfTheCar;

    printf("callback:\r\n");
    printf("---------------------------------------------------------\r\n");
    printf("\ttopic:%s\r\n", msg->topic);
    printf("\tpayload:%s\r\n", msg->payload);
    printf("---------------------------------------------------------\r\n");
    /* 使用cjson解析上报响应数据 */
    cjson_root = cJSON_Parse(msg->payload+1);
    if (cjson_root == NULL) {
        printf("report reply message parser fail1\r\n");
        event_flag = report_fail;
        goto exit;
    }

    /* 提取method */
    cjson_method = cJSON_GetObjectItem(cjson_root, "method");
    method = cJSON_GetStringValue(cjson_method);
    if (cjson_method == NULL || method == NULL) {
        printf("report reply status parser fail2\r\n");
        event_flag = report_fail;
        goto exit;
    }

        if (strstr(method, "control"))
        {
            cjson_params = cJSON_GetObjectItem(cjson_root, "params");
            cjson_switch = cJSON_GetObjectItem(cjson_params, "StateOfTheCar");
            if (cjson_params == NULL || cjson_switch == NULL) {
                printf("control data parser fail4\r\n");
                cJSON_Delete(cjson_root);
                return;
            }

            StateOfTheCar = cjson_switch->valueint;

            printf("StateOfTheCar:%d\r\n",StateOfTheCar);
            if(StateOfTheCar == 0x00)
            {
                lcd_car_state = 0;
                car_stop();
            }
            else if(StateOfTheCar == 0x01)
            {
                lcd_car_state = 1;
                car_advance();
            }
            else if(StateOfTheCar == 0x02)
            {
                lcd_car_state = 2;
                car_retreat();
            }
            else if(StateOfTheCar == 0x03)
            {
                lcd_car_state = 3;
                car_left();
            }
            else if(StateOfTheCar == 0x04)
            {
                lcd_car_state = 4;
                car_right();
            }

            cJSON_Delete(cjson_root);
        return;
    }

exit:
    cJSON_Delete(cjson_root);
    cjson_root = NULL;
    status = NULL;
    method = NULL;

}

这个是腾讯平台下发控制小车解析JSON数据。

代码语言:javascript
复制
#define REPORT_DATA_TEMPLATE    "{\\\"method\\\":\\\"report\\\"\\,\\\"clientToken\\\":\\\"00000001\\\"\\,\\\"params\\\":{\\\"temperature\\\":\\\"%.2f\\\"\\,\\\"humidity\\\":\\\"%.2f\\\"\\,\\\"StateOfTheCar\\\":\\\"%d\\\"}}"

这个是上传的物模型,主要三种数据传输上去,一个是温度,一个湿度,一个小车状态。

至此底层的开发就这样了。

五.腾讯云物联网平台开发

腾讯云物联网平台开发,需要我们自己新建项目,产品。联网方式我们选择WIFI联网。数据使用腾讯云的物模型即可。

然后就是添加我们的功能,功能也是物模型,传输数据解析与这些都有关系的。尤其是标识符需要注意。

之后就是我们的H5面板,腾讯连连方便我们开发微信小程序控制小车。查阅数据。这里我使用的是标准面板。

最后就是新建设备,设备建好之后,设备内容需要我们自己更换,这个是在底层,不然也是通信不上的。

先看下我们腾讯连连的面板,上线后设备就是这样的。状态由于没有和按钮同步,所以我就在外面添加了,可以在外面看到小车各种状态。

六.演示视频

视频内容

七.总结

本次基于RISC-V开发过程很是顺利,得益于一个好的IDE,一个好的OS,TencentOS Tiny提供了完善的驱动,上云和下发数据解析都能直接完成。加上腾讯的物联网平台可以直接用小程序进行联控更加方便。本次的IDE主要在浮点数需要设置,其他地方,提示跳转都是很方便的,由于时间的关系,自己仅构想了这个简单的应用,最后的数据保存,可以利用两个,一个SPI Flash 和TF卡,保存数据这个功能,在实际中还是很有用的。本次开发就到这里了。

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.前言
  • 二.方案框架
  • 三.硬件方案介绍
  • 四.软件方案介绍
  • 五.腾讯云物联网平台开发
  • 六.演示视频
  • 七.总结
相关产品与服务
TencentOS Server
TencentOS Server 是腾讯云推出的 Linux 操作系统,它旨在为云上运行的应用程序提供稳定、安全和高性能的执行环境。它可以运行在腾讯云 CVM 全规格实例上,包括黑石物理服务器2.0。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档