# 嵌入式系统 阿里 Haas EDU 开发记录 嵌入式系统 阿里 Haas EDU 开发记录 ## 缘起 >笔者所学物联网专业,有一门课是嵌入式系统。我们的嵌入式老师以个人名义为我们提供了阿里的Haas EDU教育开发版用于嵌入式系统实验课。并且留了一些任务给我们。本文记录相关流程供学习经验。 这块板子默认烧录的是 [HaaS EDU K1教育开发案例合集](https://gitee.com/alios-things/eduk1_demo)。开源地址:[https://gitee.com/alios-things/eduk1_demo](https://gitee.com/alios-things/eduk1_demo)。 系统是AliOS Things 3.3,内核 rhino,硬件名 Haas EDU K1 。 创建好之后就是这样了。 {{< image src="https://cdn.ftls.xyz/images/2021/11/1.jpg" caption="正面照" >}} {{< image src="https://cdn.ftls.xyz/images/2021/11/2.jpg" caption="背面照" >}} ## 搭建环境 1. 需要 Vscode 和 C/C++ Extension Pack 插件。 2. 安装 haas-studio v1.0.24,安装之后会跳出 aos-tools 的安装提示。同样也是一键安装。 状态栏可以看到编译,烧录等 {{< image src="https://cdn.ftls.xyz/images/2021/11/haas/haas1.png" caption="安装好插件之后" >}} ## 创建项目,编译和烧录程序 笔者是在原[HaaS EDU K1教育开发案例合集](https://gitee.com/alios-things/eduk1_demo)基础之上进行开发的,实际上也只是调用封装好的东西。 {{< image src="https://cdn.ftls.xyz/images/2021/11/haas/haas2.png" caption="创建教育开发案例合集项目" >}} {{< image src="https://cdn.ftls.xyz/images/2021/11/haas/haas3.png" caption="教育开发案例合集目录" >}} {{< image src="https://cdn.ftls.xyz/images/2021/11/haas/haas4.png" caption="用户代码目录solutions,红色是上云用的" >}} 第一次创建项目大约需要 5min。然后点击 VSCode 下面状态栏的编译。第一次编译大约需要 5min。编译之后这个文件夹大约 1G 左右。 编译成功后大概这样: ``` bash cp -f ../release_bin/pub_otp.bin ../write_flash_tool/ota_bin/ cp -f ../release_bin/pub_otp.bin ../write_flash_gui/ota_bin/ all files done. run external script success Run script 'python "C:\Users\icer\Desktop\lab3\hardware\chip\haas1000\release/auto_build_tool/build_bin.py" --target="C:\Users\icer\Desktop\lab3\solutions\lab3\aos.bin" ' success scons: done building targets. AOS SDK Done Build takes 0 Minutes 45 Seconds. ``` {{< image src="https://cdn.ftls.xyz/images/2021/11/haas/haas6.png" caption="编译之后" >}} 电脑需要装一个 cp210x.drivers 驱动。连接开发板到电脑,选择对应的串口,baudrate选择1500000,如果选错了可以修改配置文件。这些配置文件位于 `.vscode` 文件夹。然后点击 Vscode 状态栏的烧录,就可以看到大约 1700kb 的文件烧录进入了单片机。这时候单片机会显示一个出厂测试页面,会提示你按下K1,K2,K3, K4 , K1&K2 进行各种测试。看到这个测试说明我们的程序烧录成功了。 ### 关闭测试模式 首先我们想要看到是[HaaS EDU K1教育开发案例合集](https://gitee.com/alios-things/eduk1_demo)的图片中的各种功能。这时候我们需要关闭测试模式。 solutions\lab3\maintask.c 增加一行 ``` c #define ENABLE_FACTORY_TEST 0 ``` 然后我们就能看到[HaaS EDU K1教育开发案例合集](https://gitee.com/alios-things/eduk1_demo)提供的案例了。也就是出厂自带的程序。 ### 添加一个页面程序 我们可以看到,官方样例中每一个页面都是一个程序。这时,我们要添加自己的页面程序。 打开`solutions\lab3\k1_apps`文件夹。然后创建`solutions\lab3\k1_apps\test3`文件夹。创建两个文件 [test3.c]() 和 [test3.h]()。修改 `solutions\lab3\k1_apps\menu.c`。这里的代码我都会贴在最后。 {{< image src="https://cdn.ftls.xyz/images/2021/11/haas/haas5.png" caption="创建test3" >}} > 所需要的代码 >
[test3.c](#test3c)
[test3.h](#test3h)
[menu.c](#menuc)
代码变量说明:tem 温度 ,hum 湿度 ,xyz[3] 六轴传感器传出数据。 #### 烧录之后 {{< image src="https://cdn.ftls.xyz/images/2021/11/3.jpg" caption="正常显示数据和传感器信息" >}} #### 注意 创建文件之后,一定要修改solutions\lab3\package.yaml的source_file。 增加代码 ``` YAML source_file: <略> - "k1_apps/test3/test3.c" - "k1_apps/test4/test4.c" - "data_model_basic_demo.c" <略> ``` 实验效果如下。 六轴传感器传的是 float 类型,显示不下于是强转为 short 类型。 目前效果不是很好,六轴传感器显示需要先运行官方陀螺仪示例之后才可以正常显示。待修复此特性。 ### 配网WIFI 点击 VScode 状态栏的串口,选择对应的串口,选择1500000。这时候连接开发板并且开机能够看到一堆文字闪过。等待文字稳定后按下回车,能看到`(ash:/data)#`。这时候我们就可以输入CLI命令了。 输入`netmgr -t wifi -c ssid password`就可以配网了。ssid替换为WIFI网络名,password替换为WIFI密码。 ``` [ 44.975]eduk1_demo aos_task_delete test3_task [ 44.976]eduk1_demo aos_task_new homepage_task (ash:/data)#netmgr -t wifi -c ssid password ``` 配网之后开发板主页面会显示IP右上角会显示WIFI图标。还能看到 IP。 {{< image src="https://cdn.ftls.xyz/images/2021/11/4.jpg" caption="配网WIFI" >}} ## 数据上云 基于[HaaS EDU K1教育开发案例合集](https://gitee.com/alios-things/eduk1_demo)和[Wi-Fi设备连接阿里云示例](https://gitee.com/alios-things/linksdk_demo)。复制[Wi-Fi设备连接阿里云示例](https://gitee.com/alios-things/linksdk_demo)下的 data_model_basic_demo.c 到 lab3\solutions\lab3\data_model_basic_demo.c。 修改三元组为自己设备的三元组,具体步骤键[Wi-Fi设备连接阿里云示例 4.2 软件实现](https://gitee.com/alios-things/linksdk_demo#42-%E8%BD%AF%E4%BB%B6%E5%AE%9E%E7%8E%B0)。 修改data_model_basic_demo.c内的demo_main()为demo_main2()。 为了让这段程序在连接WIFI后运行,修改solutions\lab3\app_start.c,代码后面有。主要修改 wifi_event_cb 。 > 被修改的代码:
> [app_start.c](#app_startc)
为了上传传感器数据,为data_model_basic_demo.c增加头文件 ``` c // 传感器数据 #include "drv_temp_humi_si_si7006.h" #include "drv_temp_humi_sensylink_cht8305.h" #include "drv_acc_gyro_inv_mpu6050.h" #include "drv_acc_gyro_qst_qmi8610.h" ``` 修改data_model_basic_demo.c主循环上传温湿度传感器和六轴传感器数据,abc 为计数,temp 温度,hump 湿度,xyz为六轴传感器数据。 ``` c short int abc = 0; float temp, hump,xyz[3]; uint8_t info[30]; /* 主循环进入休眠 */ cht8305_init(); FisImu_init(); while (1) { if(abc>=100) { abc=0;} FisImu_read_acc_xyz(xyz); cht8305_getTempHumidity(&hump, &temp); /* TODO: 以下代码演示了简单的属性上报和事件上报, 用户可取消注释观察演示效果 */ sprintf(info, "{\"LightSwitch\": %d,\"tem\": %.1f,\"hum\": %.1f,\"rax\": %d,\"ray\": %d,\"raz\": %d}", abc,temp,hump,(short)xyz[0],(short)xyz[1],(short)xyz[2]); demo_send_property_post(dm_handle, info); demo_send_event_post(dm_handle, "Error", "{\"ErrorCode\": 0}"); abc+=1; aos_msleep(10000); } ``` 连接WIFI成功后,数据就可以上云了。在日志服务选择刚刚创建的设备就可以看到是否成功了,其次在也可以查看设备是否在线查看是否上云成功。 {{< image src="https://cdn.ftls.xyz/images/2021/11/haas/haas8.png" caption="上云日志" >}} {{< image src="https://cdn.ftls.xyz/images/2021/11/haas/haas9.png" caption="云平台收到的传感器信息" >}} 阿里云在产品栏目,功能定义,编辑草稿,可以定义物模型。阿里云物联网平台会匹配demo_send_property_post里的tem,hum,rax,ray,raz 等信息。编辑物模型之后,方便了后续的开发。 {{< image src="https://cdn.ftls.xyz/images/2021/11/haas/haas7.png" caption="物模型" >}} #### 注意 创建文件之后,一定要修改solutions\lab3\package.yaml的source_file。 增加代码 ``` YAML source_file: <略> - "data_model_basic_demo.c" <略> ``` 增加 ## 相关资料 [HaaS EDU K1快速开始](https://g.alicdn.com/alios-things-3.3/doc/haas_edu_k1_quick_start.html) [Python轻应用开发手册](https://g.alicdn.com/HaaSAI/PythonDoc/index.html) [HaaS EDU K1 学习路径图(从新手到专家)](https://blog.csdn.net/HaaSTech/article/details/114288702) [一站式开发工具HaaS Studio使用说明](https://blog.csdn.net/HaaSTech/article/details/119257352) {{< bilibili BV1sf4y137Fn 1 >}} ## 代码 ### test3.c ``` c #include "test3.h" #include "drv_temp_humi_si_si7006.h" #include "drv_temp_humi_sensylink_cht8305.h" #include "drv_acc_gyro_inv_mpu6050.h" #include "drv_acc_gyro_qst_qmi8610.h" #include "../menu.h" // mqtt 头文件 #include "aiot_state_api.h" #include "aiot_sysdep_api.h" #include "aiot_mqtt_api.h" MENU_COVER_TYP test3_cover = {MENU_COVER_NONE}; MENU_TASK_TYP test3_tasks = {test3_init, test3_uninit}; MENU_TYP test3 = {"test3", &test3_cover, &test3_tasks, NULL, NULL}; static int running = 1; // 定义三轴加速器的x,y,z // 使用开发板为 k1c g_haasboard_is_k1c = 1 static short r_ax = 0, r_ay = 0, r_az = 0; static aos_task_t test3_task_handle; int test3_init(void) { if (g_haasboard_is_k1c) { cht8305_init(); FisImu_init(); LOGI(EDU_TAG, "cht8305_init done\n"); LOGI(EDU_TAG, "FisImu_init done\n"); } else { si7006_init(); MPU_Init(); LOGI(EDU_TAG, "si7006_init done\n"); LOGI(EDU_TAG, "MPU_Init done\n"); } LOGI(EDU_TAG, "MPU_Init done\n"); // OLED_Clear(); OLED_Refresh_GRAM(); running = 1; aos_task_new_ext(&test3_task_handle, "test3_task", test3_task, NULL, 1024, AOS_DEFAULT_APP_PRI); LOGI(EDU_TAG, "aos_task_delete test3_task\n"); return 0; } void test3_task(void) { float temp, hump,xyz[3]; uint8_t temp_str[10]; uint8_t hump_str[10]; uint8_t info[10]; uint8_t six_str[30]; uint8_t six_info[10]; unsigned char c = 0; while (running) { if (g_haasboard_is_k1c) { FisImu_read_acc_xyz(xyz); cht8305_getTempHumidity(&hump, &temp); strcpy(info,"cht8305:"); } else { MPU_Get_Accelerometer(&r_ax, &r_ay, &r_az); si7006_getTempHumidity(&hump, &temp); strcpy(info,"si7006:"); } sprintf(temp_str, "W:%5.1fC", temp); sprintf(hump_str, "S:%5.1f%%", hump); if(g_haasboard_is_k1c) { strcpy(six_info,"FisImu"); // sprintf(six_str,"x:%2.1f,y:%2.1f,z:%2.1f",xyz[0],xyz[1],xyz[2]); sprintf(six_str,"x:%d,y:%d,z:%d",(short)xyz[0],(short)xyz[1],(short)xyz[2]); printf("FisIum: \n%f\n%f\n%f\n",xyz[0],xyz[1],xyz[2]); } else{ strcpy(six_info,"MPU"); sprintf(six_str,"x:%d,y:%d,z:%d",r_ax,r_ay,r_az); printf("MPU: \n%d\n%d\n%d\n",r_ax,r_ay,r_az); } // LOGD(EDU_TAG, "%s %s", temp_str, hump_str); // 绘制左右的图标 OLED_Icon_Draw(2, 24, &icon_skip_left, 0); OLED_Icon_Draw(122, 24, &icon_skip_right, 0); OLED_Show_String(20, 5, info, 12, 1); OLED_Show_String(20, 20, temp_str, 12, 1); OLED_Show_String(20, 35, hump_str, 12, 1); OLED_Show_String(20, 50, six_str ,12,1); OLED_Refresh_GRAM(); aos_msleep(500); } running = 1; } int test3_uninit(void) { running = 0; while (!running) { aos_msleep(50); } if (g_haasboard_is_k1c) { cht8305_deinit(); FisImu_deinit(); LOGI(EDU_TAG, "cht8305_deinit done\n"); LOGI(EDU_TAG, "FisImu_deinit done\n"); } else { si7006_deinit(); MPU_Deinit(); LOGI(EDU_TAG, "si7006_deinit done\n"); LOGI(EDU_TAG, "MPU_Deinit done\n"); } aos_task_delete(&test3_task_handle); LOGI(EDU_TAG, "aos_task_delete test3_task\n"); return 0; } ``` ### test3.h ```c #ifndef __TEST3_H__ #define __TEST3_H__ #include "../menu.h" extern MENU_TYP test3; int test3_init(void); int test3_uninit(void); void test3_task(void); #endif ``` ### menu.c ``` c #include #include #include "aos/kernel.h" #include "menu.h" // 添加离自己最近的子级目录 #include "aircraftBattle/aircraftBattle.h" #include "barometer/barometer.h" #include "compass/compass.h" #include "greedySnake/greedySnake.h" #include "gyroscope/gyroscope.h" #include "homepage/homepage.h" #include "humiture/humiture.h" #include "lightmeter/lightmeter.h" #include "musicbox/musicbox.h" #include "shakeshake/shakeshake.h" #include "kws/kws.h" // add path #include "test3/test3.h" #define KEY_CODE_BACK (EDK_KEY_1 | EDK_KEY_2) #define KEY_CODE_LEFT EDK_KEY_1 #define KEY_CODE_RIGHT EDK_KEY_3 #define KEY_CODE_DOWN EDK_KEY_4 MENU_TYP *Menus[] = { &homepage,&test3, &humiture, &gyroscope, &shakeshake, &compass, &barometer, &lightmeter, &musicbox, &greedySnake, &aircraftBattle, &kws, }; MENU_LIST_TYP MenuList = {Menus, sizeof(Menus)/sizeof(Menus[0])}; MENU_TYP *pCurMenu = NULL; key_code_cb app_key_code_cb = NULL; <略> 余下没有修改 ``` ### app_start.c ```c /* * Copyright (C) 2015-2020 Alibaba Group Holding Limited */ #include "aos/init.h" #include "board.h" #include "k1_apps/menu.h" #include #include #include #include #include #include // #include "drivers/lcd/st7789v/st7789v_vfs.h" // #include "drivers/lcd/st7789v/st7789v.h" #include "netmgr.h" extern int board_test(void); extern void vendor_cli_register_init(void); extern int demo_main2(int argc, char *argv[]); int g_haasboard_is_k1c = 0; int bt_connected = 0; int wifi_connected = 0; int ip_got_finished = 0; char eduk1_ip_addr[IPADDR_STR_LEN] = {0}; int demo_main(int argc, char *argv[]) { int ret = 0; while (1) { if (wifi_connected && !ip_got_finished) { ret = netmgr_wifi_get_ip_addr(&eduk1_ip_addr); if (ret ==0) ip_got_finished = 1; } aos_msleep(1000); } } static void entry_func(void *data) { demo_main(0 , NULL); } static void entry_func2(void *data) { demo_main2(0 , NULL); } static void wifi_event_cb(uint32_t event_id, const void *param, void *context) { aos_task_t task; aos_status_t ret2; switch (event_id) { case EVENT_NETMGR_DHCP_SUCCESS: wifi_connected = 1; aos_task_new("link_dmeo", entry_func, NULL, 6*1024); ret2 = aos_task_create(&task, "linksdk_demo", entry_func2, NULL, NULL, 6048, AOS_DEFAULT_APP_PRI, AOS_TASK_AUTORUN); if (ret2 < 0) { printf("create linksdk demo task failed, ret = %ld \r\n", ret2); } break; case EVENT_NETMGR_WIFI_DISCONNECTED: wifi_connected = 0; break; default: break; } return; } extern int haasedu_is_k1c(); int application_start(int argc, char **argv) { int ret; aos_set_log_level(AOS_LL_INFO); event_service_init(NULL); netmgr_service_init(NULL); /*enable network auto reconnect*/ netmgr_set_auto_reconnect(NULL, true); /*enable auto save wifi config*/ netmgr_wifi_set_auto_save_ap(true); event_subscribe(EVENT_NETMGR_DHCP_SUCCESS, wifi_event_cb, NULL); g_haasboard_is_k1c = haasedu_is_k1c(); sh1106_init(); menu_init(); ret = BleCfg_run(); if (ret) { return ret; } aos_msleep(100); (void)BleCfg_recovery_wifi(); (void)BleCfg_recovery_devinfo(); return 0; } ``` > 作者: 恐咖兵糖
> 版权声明: 本博客所有文章除特别声明外,均采用[CC BY-NC-SA 4.0 许可协议](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)。