基於OpenHarmony的智慧喝水提醒器

一、硬體說明
Neptune OpenHarmony物聯網IOT模組Wi-Fi&藍牙雙模開發板、超聲波模組、蜂鳴器模組、杜邦線若干
開發板相關資料://gitee.com/hihope_iot/docs/tree/master/Neptune

實現效果
將水杯放到超聲波感測器前,實現15分鐘提示一次喝水。

二、項目開發流程

  1. 接線

  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. 做好配置,開始燒寫步驟