首页 > 技术知识 > 正文

原文引自电子发烧友论坛 HarmonyOS技术社区 《基于OpenHarmony的智慧牧场》

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app

前文回顾

《智慧牧场之生物姿态检测篇》

《智慧牧场之生物心率检测篇》

1. 背景知识

1.1牧场定位的意义

在智慧牧场解决方案中,实时检测牲畜的活动状况是非常重要的环节。现在已经不是放牛和牧羊犬的时代了。面临大范围牧场上牲畜走失,寻找困难,过度放牧导致草场退化等问题,通过穿戴式的生物跟踪部件,可以有效解决以上的问题。

当大量牲畜散布在地面上时,牧场管理员往往发现很难跟踪正在发生的事情。需要一个系统来确定牲畜在任何给定时间的位置和行驶的距离。此外,跟踪系统也会防止任何类型的盗窃,因为牧场管理员可以使用跟踪报告来定位被盗牲畜。

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app1

1.2室外定位技术比较

目前的室外定位技术,大体上分为如下几种类别:

信号载体 典型定位方式 定位精度 不足 北斗/GPS卫星民用领域 3个观测方程式求解位置 10米级 遮挡影响较大 蜂窝移动网络GSM 基于TC-OFODM信号进行测距定位 100米级 对基站依赖程度较高 5G 超密集组网下的定位技术/面向5C的TDOA和AOA定位技术、面向5G网络上行定位和下行定位 100米级 抗干扰有局限性 惯性导航 基于航位推算方法 米级 存在累计漂移误差 地球磁场 基于信号场强定位或与其他技术组合应用 米级 地球指纹特征差异小

基于GPS和GSM的定位在全世界被广泛使用,可以用来确定其所连接生物的精确位置。这种器件成本低、可靠性高,并具有精确跟踪功能。可以提供有效、实时的物体、生物的位置报告和时间信息。

2. 解决方案概要

该方案采用基于全球移动通信系统(GSM)技术和GPS技术的嵌入式系统。该系统安装在生物穿戴设备中。接口GSM模块连接到Hi3861。该系统提供以下功能:a)位置信息,b)使用短信进行实时跟踪。

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app2

3. 硬件设计

3.1SIM808模块调制解调器模块

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app3

可以选用GSM、GPRS、GPS三合一功能的SIM808模块。支持GSM/GPRS Quad-Band网络,结合GPS技术进行卫星导航。它具有睡眠模式下的超低功耗,并集成了锂离子电池充电电路,使其具有超长的待机时间,方便使用可充电锂离子电池的项目。它具有高 GPS 接收灵敏度,具有 22 个跟踪和 66 个采集接收器通道。模块通过 UART(编者注:Universal Asynchronous Receiver/Transmitter 通用异步接收器/发送器的英文缩写) 由 AT 指令控制,支持 3.3V 和 5V 逻辑电平。

GSM调制解调器的工作基于命令,命令始终以“AT开头”(表示注意),以“<CR>字符结束”,例如拨号命令是ATD<number>;ATD7814629081;这里,拨号命令以分号(;)结束。在Hi3861的帮助下,该AT命令被提供给GSM调制解调器。GSM调制解调器在MAX 232 IC的帮助下与微控制器串行连接。GSM指定的频率范围为1850到1990 MHz(移动台到基站)。

3.2 Hi3861

Hi3861开发板模组大小约2cm*5cm,是一款高度集成的2.4GHz WLAN SoC。

Hi3861芯片集成高性能32bit微处理器、拥有丰富的外设接口,芯片内置SRAM(编者注:Static Random-Access Memory 静态随机存取存储器的英文缩写)和Flash,并支持在Flash上运行程序。

Hi3861模组有2MB FLASH,352KB RAM。但我们编写代码时,要注意对有限资源的合理利用。

Hi3861可以说是麻雀虽小,五脏俱全。Hi3861的外设接口包括(外部主晶振为40M或者24M):

2个SPI(Synchronous Peripheral Interface)

3个UART(Universal Asynchronous Receiver & Transmitter)

2个I2C(The Inter-Integrated Circuit)

6路PWM(Pulse Width Modulation)

15个GPIO(General Purpose Input/Output)

7路ADC(Analog to Digital Converter)

1个I2S接口

1个高速SDIO2.0(Secure Digital Input/Output)接口,最高时钟可达50MHz;

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app4

Hi3861主控功能框架图如下:

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app5

在该系统中,它用于同步GSM和GPS的操作。GPS连续向微控制器发送位置数据,即车辆位置的纬度和经度,而GSM从微控制器发送和接收数据。GPS调制解调器连续提供许多参数作为输出,但只有NMEA(编者注:National Marine Electronics Association国家海洋电子协会的英文缩写)数据被读取并“显示在OLED上”。将相同的数据发送给移动用户,以便可以知道车辆的确切位置。用户的移动号码存储在EEPROM(编者注:Electrically Erasable Programmable read only memory 带电可擦可编程只读存储器 的英文缩写)中。

4. 软件设计

软件编程是用C语言完成的。GPS从卫星接收的数据(坐标)在软件中定义。解码NMEA(国家海洋电子协会)协议是开发该软件的主要目的。软件程序中应包含用户的手机号码,以便从我们在GSM调制解调器中使用的SIM卡接收位置值。NMEA协议由一组ASCII字符集的消息组成。GPS接收数据并以ASCII逗号分隔的消息字符串的形式显示。$在每条消息的开头使用符号。位置(纬度和经度)的格式为ddmm。mmmm(度数分钟和十进制分钟)。软件协议由GGA(编者注:Global Positioning System Fix Data 全球定位系统固定数据)和GLL(编者注:Geographic Position 地理位置-纬度/经度)组成。但在这个系统中,我们只使用GGA。系统流程图如下所示:

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app6

具体代码实现:

复制/***** 获取电压值函数 *****/ static float GetVoltage(void) { unsigned int ret; unsigned short data; ret = AdcRead(WIFI_IOT_ADC_CHANNEL_5, &data, WIFI_IOT_ADC_EQU_MODEL_8, WIFI_IOT_ADC_CUR_BAIS_DEFAULT, 0xff); if (ret != WIFI_IOT_SUCCESS) { printf(“ADC Read Fail “); } return (float)data * 1.8 * 4 / 4096.0; } /* input:AT+CGNSINF Command Response * output:struct GGPS_DATA */ static void GPS_CGNSINF_Analyze(char *origin, GGPS_DATA *gpsdata) { int counter = 0; char tmp[150] = {0}; char *lptr = NULL; char *localptr = NULL; lptr = (char *)strstr(origin, “+CGNSINF”); if (lptr == NULL) { return; } else { lptr += 10; } while (*lptr != ) { if (*lptr == , && *(lptr + 1) == ,) { tmp[counter] = *lptr; counter++; tmp[counter] = 0; } else if (*lptr == && *(lptr + 1) == && counter < 148) { tmp[counter] = 0; tmp[counter + 1] = ,; tmp[counter + 2] = 0; break; } else { tmp[counter] = *lptr; } lptr++; counter++; /* avoid array out of range */ if (counter >= GNSINF_MSG_MAX_LEN){ return; } } /* Clear struct data */ memset(gpsdata, 0, sizeof( GGPS_DATA)); localptr = (char *)strtok(tmp, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->GNSSrunstatus, localptr, sizeof(gpsdata->GNSSrunstatus)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->Fixstatus, localptr, sizeof(gpsdata->Fixstatus)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->UTCdatetime, localptr, sizeof(gpsdata->UTCdatetime)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->latitude, localptr, sizeof(gpsdata->latitude)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->logitude, localptr, sizeof(gpsdata->logitude)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->altitude, localptr, sizeof(gpsdata->altitude)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->speedOTG, localptr, sizeof(gpsdata->speedOTG)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->course, localptr, sizeof(gpsdata->course)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->fixmode, localptr, sizeof(gpsdata->fixmode)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->Reserved1, localptr, sizeof(gpsdata->Reserved1)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->HDOP, localptr, sizeof(gpsdata->HDOP)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->PDOP, localptr, sizeof(gpsdata->PDOP)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->VDOP, localptr, sizeof(gpsdata->VDOP)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->Reserved2, localptr, sizeof(gpsdata->Reserved2)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->satellitesinview, localptr, sizeof(gpsdata->satellitesinview)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->GNSSsatellitesused, localptr, sizeof(gpsdata->GNSSrunstatus)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->GLONASSsatellitesused, localptr, sizeof(gpsdata->GLONASSsatellitesused)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->Reserved3, localptr, sizeof(gpsdata->Reserved3)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->CN0max, localptr, sizeof(gpsdata->CN0max)); localptr = (char *)strtok(NULL, “,”); if (localptr == NULL) { return; } strncpy(gpsdata->HPA, localptr, sizeof(gpsdata->HPA)); localptr = (char *)strtok(NULL, ” “); if (localptr == NULL) { return; } strncpy(gpsdata->VPA, localptr, sizeof(gpsdata->VPA)); } static void GsmCheckRingAndHanupMessage(void) { if (strstr(g_uart_buff, “RING”) != NULL) { printf(“ring. “); if (GsmGetConnectSts() == false) { GsmSetRingSts(true); } } if (strstr(g_uart_buff, “NO CARRIER”) != NULL) { printf(“hang up. “); GsmSetHungUpSts(true); if (GsmGetConnectSts() == true) { GsmSetConnectSts(false); } } } static uint32_t GsmSendCmd(char *cmd, int len) { if (cmd == NULL || len <= 0) { return HI_ERR_FAILURE; } uint32_t ret = HI_ERR_FAILURE; static uint32_t count = 0; uint8_t *uart_buff_ptr = g_uart_buff; ret = hi_uart_write(DEMO_UART_NUM, (hi_u8 *)cmd, len); if (ret == HI_ERR_FAILURE) { return HI_ERR_FAILURE; } printf(” SendData%d,cmd:%s. “, len, cmd); while (g_uartController.isReadBusy) { count++; if (count > UART_WAIT_COUNT_MAX) { break; } } if (g_uartController.isReadBusy) { printf(“GsmSendCmd hi_uart_read busy return”); return HI_ERR_FAILURE; } if (!g_uartController.isReadBusy){ usleep(100000); /* sleep 100ms */ } g_uartController.isReadBusy = true; g_ReceivedDatalen = hi_uart_read(DEMO_UART_NUM, uart_buff_ptr, UART_BUFF_SIZE); if (g_ReceivedDatalen > 0) { printf(” rcvData len:%d,msg:%s. “, g_ReceivedDatalen, g_uart_buff); if (strstr(g_uart_buff, “OK”) != NULL) { GsmCheckRingAndHanupMessage(); memset(g_uart_buff, 0, sizeof(g_uart_buff)); g_ReceivedDatalen = 0; g_uartController.isReadBusy = false; return HI_ERR_SUCCESS; } else { printf(” received error cmd “); GsmCheckRingAndHanupMessage(); memset(g_uart_buff, 0, sizeof(g_uart_buff)); g_ReceivedDatalen = 0; g_uartController.isReadBusy = false; return HI_ERR_FAILURE; } } else { g_uartController.isReadBusy = false; printf(” SendCmd no cmd return! “); return HI_ERR_FAILURE; } return HI_ERR_SUCCESS; } uint32_t GpsGetLocation(GGPS_INFO *gpsInfo) { uint32_t ret = HI_ERR_FAILURE; static uint32_t count = 0; uint8_t *uart_buff_ptr = g_uart_buff; ret = hi_uart_write(DEMO_UART_NUM, (hi_u8 *)”AT+CGNSINF “, strlen(“AT+CGNSINF “)); if (ret == HI_ERR_FAILURE) { return NULL; } while (g_uartController.isReadBusy) { count++; if (count > UART_WAIT_COUNT_MAX) { break; } usleep(100000); /* sleep 100ms */ } if (g_uartController.isReadBusy) { printf(“GpsGetLocation hi_uart_read busy return”); return HI_ERR_FAILURE; }else{ usleep(100000); /* sleep 100ms */ } g_uartController.isReadBusy = true; g_ReceivedDatalen = hi_uart_read(DEMO_UART_NUM, uart_buff_ptr, UART_BUFF_SIZE); if (g_ReceivedDatalen > 0) { printf(” rcvData len:%d,msg:%s. “, g_ReceivedDatalen, g_uart_buff); uint8_t *strLocation = (uint8_t *)strstr(g_uart_buff, “+CGNSINF: 1,1”); if (strLocation != NULL) { GGPS_DATA gpsData; GPS_CGNSINF_Analyze((char *)g_uart_buff, &gpsData); printf(“latitude:%s. “, gpsData.latitude); printf(“logitude:%s. “, gpsData.logitude); memcpy_s(gpsInfo->UTCdatetime, sizeof(gpsInfo->UTCdatetime), gpsData.UTCdatetime, sizeof(gpsData.UTCdatetime)); memcpy_s(gpsInfo->logitude, sizeof(gpsInfo->logitude), gpsData.logitude, sizeof(gpsData.logitude)); memcpy_s(gpsInfo->latitude, sizeof(gpsInfo->latitude), gpsData.latitude, sizeof(gpsData.latitude)); memcpy_s(gpsInfo->satellitesinview, sizeof(gpsInfo->satellitesinview), gpsData.satellitesinview, sizeof(gpsData.satellitesinview)); GsmCheckRingAndHanupMessage(); memset(g_uart_buff, 0, sizeof(g_uart_buff)); g_ReceivedDatalen = 0; g_uartController.isReadBusy = false; return HI_ERR_SUCCESS; } else { GsmCheckRingAndHanupMessage(); memset(g_uart_buff, 0, sizeof(g_uart_buff)); g_ReceivedDatalen = 0; g_uartController.isReadBusy = false; return HI_ERR_FAILURE; } } else { printf(” SendCmd no cmd return! “); g_uartController.isReadBusy = false; return HI_ERR_FAILURE; } } uint32_t GsmCallCellPhone(char *cellPhoneNumeber) { uint32_t ret = HI_ERR_FAILURE; char sendCmd[32] = “”; uint8_t cPhoneNumLength = strlen(cellPhoneNumeber); if (cPhoneNumLength < PHONE_NUMB_LEN) { return HI_ERR_FAILURE; } /* Send AT+CSQ. */ strncpy(sendCmd, “AT+CSQ “, strlen(“AT+CSQ “)); printf(” sendCmd=%s “, sendCmd); ret = GsmSendCmd(sendCmd, strlen(sendCmd)); if (ret == HI_ERR_FAILURE) { return HI_ERR_FAILURE; } memset(sendCmd, 0, strlen(sendCmd)); /* Call cellPhone Number:ATD+cellPhoneNumber. */ snprintf(sendCmd, sizeof(sendCmd), “ATD%s; “, cellPhoneNumeber); printf(” sendCmd=%s “, sendCmd); ret = GsmSendCmd(sendCmd, strlen(sendCmd)); if (ret == HI_ERR_FAILURE) { return HI_ERR_FAILURE; } return HI_ERR_SUCCESS; } 玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app7

未完待续……

后期预告《智慧牧场之室内管理系统篇》 写在最后我们最近正带着大家玩嗨OpenHarmony。如果你有好玩的东东,欢迎投稿,让我们一起嗨起来!有点子,有想法,有Demo,立刻联系我们:合作邮箱:zzliang@atomsource.org 玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app8

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app9

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app10玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app11玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app12

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app13

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app14

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app15

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app16

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app17

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app18

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app19

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app20

玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇-智能牧场app21

原文标题:玩嗨OpenHarmony:基于OpenHarmony的智慧牧场方案 3/4 生物运动轨迹跟踪篇

文章出处:【微信公众号:开源技术服务中心】欢迎添加关注!文章转载请注明出处。

猜你喜欢