1

基于OpenHarmony的智能喝水提醒器 - xioahuboke

 1 year ago
source link: https://www.cnblogs.com/xiaohuzaixue/p/16711677.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

基于OpenHarmony的智能喝水提醒器

一、硬件说明
Neptune OpenHarmony物联网IOT模组Wi-Fi&蓝牙双模开发板、超声波模块、蜂鸣器模块、杜邦线若干
开发板相关资料:https://gitee.com/hihope_iot/docs/tree/master/Neptune

2776504-20220920162100606-1305173178.png

实现效果
将水杯放到超声波传感器前,实现15分钟提示一次喝水。

2776504-20220921115235418-1475127032.jpg

二、项目开发流程

2776504-20220920162352239-1805876192.png
2776504-20220920162426237-1052427359.png
  1. 编写C语言代码
    主要完成以下逻辑:
    (1)编写蜂鸣器、超声波测距的代码
    (2)不断获取水杯的位置
    (3)对获取到的水杯距离做判断
    (4)如果超过时间阈值,开始报警,否则关闭报警

task_drink_Water.h

 #ifndef _TASK_DRINK_WATER_H
  #define _TASK_DRINK_WATER_H

  #include "los_compiler.h"

  #ifdef __cplusplus
  #if __cplusplus
  extern "C" {
  #endif /* __cplusplus */
  #endif /* __cplusplus */

  VOID CreateDrinkWaterTask(VOID);

  #ifdef __cplusplus
  #if __cplusplus
 }
  #endif /* __cplusplus */
  #endif /* __cplusplus */

  #endif /* _TASK_DRINK_WATER_H */

task_drink_water.c

 #include "task_drink_water.h"
 #include "stdio.h"
 #include "los_task.h"
 #include "utils_file.h"
 #include "wm_gpio.h"

 #define TASK_DRINK_WATER_PRIORITY        6  //喝水提醒任务的优先级

 #define TRIG_GPIO WM_IO_PB_00    //超声波触发检测IO口,PB0
 #define ECHO_GPIO WM_IO_PB_05		 //超声波响应检测IO口,PB5,高电平时间就是超声波发送出去到被接收器接受的时间
 #define BUZZER_GPIO WM_IO_PB_01  //蜂鸣器控制IO口,PB1

/**
 * @brief  开启和关闭蜂鸣器,开启时提醒用户喝水
 * @param[in] value : 1:开启,0:关闭
 * @retval
 */
VOID RemindToDrinkWater(u8 value) {
	tls_gpio_cfg(WM_IO_PB_01, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLLOW);
	tls_gpio_write(WM_IO_PB_01, value);
}

/**
 * @brief  通过超声波测距启动一次测距,返回测量的距离,单位mm
 * @retval 返回单位mm
 */
INT64 GetDistanceMM(VOID) {
	UINT64 checkStart;
	UINT64 timeCount;
	UINT64 waitStart;

	tls_gpio_cfg(TRIG_GPIO, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLLOW); //设置触发脚为输出
	tls_gpio_cfg(ECHO_GPIO, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLLOW); //设置检测距离IO口为输入

	//控制触发脚超过10us的方波启动检测
	tls_gpio_write(TRIG_GPIO, 1);
	(VOID)LOS_TaskDelay(10);
	tls_gpio_write(TRIG_GPIO, 0);

	waitStart = LOS_SysCycleGet();
	//等待ECHO IO口高电平
	while (tls_gpio_read(ECHO_GPIO) == 0);

	//高电平后开始启动计时
	checkStart = LOS_SysCycleGet();

	//等待ECHO IO口低电平
	while (tls_gpio_read(ECHO_GPIO) == 1);

	//计时结束
	timeCount = LOS_SysCycleGet() - checkStart;
	printf("timeCount = %lld\n", timeCount);

	//根据CPU的频率,将时钟周期转换成ns
	timeCount = (timeCount / OS_SYS_CLOCK) * OS_SYS_NS_PER_SECOND +
	            (timeCount % OS_SYS_CLOCK) * OS_SYS_NS_PER_SECOND / OS_SYS_CLOCK;

	//计算距离  340 米/s * timeCount(ns) * 1000  / 1000000000 / 2
	return (170 * timeCount / 1000000);

}
/**
 * @brief  喝水提醒任务主函数
 * @retval 无
 */
VOID TaskDrinkWaterEntry(VOID) {
	//UINT64 start = LOS_SysCycleGet();
	UINT64 distance;
	UINT64 lastTimeToDrink = 0;
	UINT64 noDrinkingTimeCount;
	u8 lastStatus = 0xFF;

	while (1) {
		distance = GetDistanceMM();
		if (distance > 50) { //杯子离开超声波检测范围超过50mm,当作喝水
			lastTimeToDrink = LOS_SysCycleGet(); //记录上次喝水的时间(杯子离开超声波测距模块即将放回去的时间)
		}
		noDrinkingTimeCount = LOS_SysCycleGet() - lastTimeToDrink;  //当前时间减去上次喝水的时间,算出未喝水的时间。

		//将时间转换成ms
		noDrinkingTimeCount = (noDrinkingTimeCount / OS_SYS_CLOCK) * 1000 +
		                      (noDrinkingTimeCount % OS_SYS_CLOCK) * 1000 / OS_SYS_CLOCK;

		printf("noDrinkingTimeCount = %lld\n", noDrinkingTimeCount);
		if (noDrinkingTimeCount > 10 * 1000) { //超过10秒未喝水进行提醒,时间可改,为了测试方便默认10s
			if (lastStatus != 1) { //如果上次已经开启蜂鸣器,状态未变化的情况下不再开启蜂鸣器。
				printf("Have a break and drink water!,tick = %lld\n", LOS_SysCycleGet());
				RemindToDrinkWater(1); //提醒喝水
				lastStatus = 1;
			}
		} else {
			if (lastStatus != 0) {
				RemindToDrinkWater(0); //杯子放回,关闭提醒。
				lastStatus = 0;
			}

		}
		printf("distance = %lld\n", distance);
		(VOID)LOS_TaskDelay(250); //适当延迟,给其他任务执行的机会
	}
}

/**
 * @brief  创建喝水提醒任务
 * @retval 无
 */
VOID CreateDrinkWaterTask(VOID) {
	UINT32 ret;
	UINT32 taskID1;
	UINT32 taskID2;
	TSK_INIT_PARAM_S stTask = {0};

	printf("TaskSample: DrinkWaterTask create start...\n");
	stTask.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskDrinkWaterEntry;
	stTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; //默认任务栈大小,根据需求配置,创建任务时,可以针对性设置
	stTask.pcName = "DrinkWaterTask";
	stTask.usTaskPrio = TASK_DRINK_WATER_PRIORITY;
	ret = LOS_TaskCreate(&taskID1, &stTask);
	if (ret != LOS_OK) {
		printf("DrinkWaterTask create failed\n");
	}
}

main.c

#include "devmgr_service_start.h"
#include "task_drink_water.h"


void UserMain(void) {
	printf("\n user task \n");

#if DEMO_CONSOLE
	CreateDemoTask();
#endif
	CreateDrinkWaterTask();

#if defined(LOSCFG_KERNEL_TEST_FULL) || defined(LOSCFG_KERNEL_TEST)
	LosAppInit();
#else
	if (DeviceManagerStart()) {
		printf("[%s] No drivers need load by hdf manager!", __func__);
	}
#endif
}
  1. 搭建软件开发环境,在Ubuntu下编译OpenHarmony系统源码
    在windows上写完代码后,在linux下中进行OpenHarmony代码编译
    (1)安装docker desktop,如果打开软件出现Docker Desktop stopping就需要安装 wsl_update_x64.msi
    (2)使用windows命令行,执行以下命令,以便在docker中准备一个集成好Neptune开发环境的Ubuntu(linux)系统
    路径替换成自己的!
    docker load -i D:\NeptuneOpenHarmony\software\neptune_openharmony_docker.tar

(3)将OpenHarmony源码包所在路径映射到linux下,路径替换成自己的!

docker run -it --rm -v D:\NeptuneOpenHarmony\software\Neptune:/home/Neptune
neptune_openharmony_docker:latest

(4)进入到/home/Neptune
cd /home/Neptune

(6)解压源码
tar -xvf openharmony_master.tar.gz

(7)将代码文件移动至如下位置
device\soc\winnermicro\wm800\board\app

(8)进入源码目录
cd /home/Neptune/openharmony_master`

(9)启动编译
hb build -f

  1. 烧写代码到Neptune开发板
    烧写
  2. 编译好的文件会被存放在如下目录
    out/neptune100/neptune_iotlink_demo/bin/hihope_neptune100.fls
  3. 将开发板连接到电脑上
  4. 打开Upgrade_Tools_V1.4.13下载工具
  5. 做好配置,开始烧写步骤
    2776504-20220921110003663-1594848963.png

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK