提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
目录
腰带简介
腰带的主要功能是跌倒判断和LORA通信。我们通过MPU6050传感器获取运动数据,结合跌倒检测算法判断佩戴者是否发生跌倒。同时,我们使用JS跳频算法实现LORA自组网通信,腰带能够把检测数据通过LORA传输到网关,能够在不同环境中实现应急通信,给跌倒者给予尽快的救助。
一、主控芯片
我们采用Hi3861芯片作为腰带的主控芯片, Hi3861V100是一款高度集成的2.4GHz SoC WiFi芯片,集成IEEE 802.11b/g/n基带和RF电路,RF电路包括功率放大器PA、低 噪声放大器LNA、RF balun、天线开关以及电源管理等模块;支持20MHz标准带宽和5MHz/10MHz窄带宽,提供最大72.2Mbit/s 物理层速率。 Hi3861V100 WiFi基带支持正交频分复用(OFDM)技术,并向下兼容直接序列扩频(DSSS)和补码键控(CCK)技术,支 持IEEE 802.11 b/g/n协议的各种数据速率。 Hi3861V100芯片集成高性能32bit微处理器、硬件安全引擎以及丰富的外设接口,外设接口包括SPI、UART、I2C、PWM、 GPIO和多路ADC,同时支持高速SDIO2.0 Slave接口,最高时钟可达50MHz;芯片内置SRAM和Flash,可独立运行,并支持 在Flash上运行程序。 Hi3861V100支持HUAWEI LiteOS和第三方组件,并配套提供开放、易用的开发和调试运行环境。 Hi3861V100芯片适应于智能家电等物联网智能终端领域。
二、JS信道调频算法
为了确保系统良好的通信质量(例如,鲁棒性和永久性) ,我们将跳频信道集成到 LoRa 中,并应用了我们之前的工作,即Jump-Stay(JS)跳频算法[1]。JS算法允许节点(终端或网关)在网络中通过特定的信道跳转序列在不同的信道之间跳转。JS中的信道跳转序列由多个回合组成,每个回合由一个“跳转模式”和一个“停止模式”组成。每个节点可以在跳跃模式下连续跳转到不同的可用通道,但是在停止模式下保持在一个通道中。因此,JS算法可以帮助多个节点同时通过不同的通道进行通信,从而提高通信效率。
三、LoRa模块
1.使用说明
我们选择的LoRa模块为正点原子ATK-LORA-02,该模块采用高效的ISM 频段射频SX1278 扩频芯片,模块的工作频率在410Mhz~441Mhz,以1Mhz 频率为步进信道,共32 个信道。可通过AT 指令在线修改串口速率,发射功率,空中速率,工作模式等各种参数。
2.常用AT指令
四、传感器
1.六轴传感器MPU6050
MPU6050 是 InvenSense 公司推出的整合性 6 轴运动处理组件,其内部整合了 3 轴陀螺仪和 3 轴加速度传感器,并且含有一个IIC 接口, 可用于连接外部磁力传感器,并利用自带的数字运动处理器(DMP: Digital Motion Processor) 硬件加速引擎,通过主 IIC 接口,向应用端输出完整的 9 轴融合演算数据。
五、PCB设计
为了减少主板面积方便使用者佩戴,PCB板采用双层板设计,顶层主要放置Hi3861WiFi芯片模块(Hi-12F)和MPU6050传感器组件。传感器和主控芯片之间使用I2C串口进行连接通信。此外,我们在主板上设计了稳压电路,稳定电压,减少干扰。
主板底层主要放置LORA模块和EPPROM。LORA模块和主控芯片之间使用UART串口通信,LORA模块的MD0和AUX引脚连接到主控芯片的GPIO引脚,从而实现LORA通信时的JS信道跳跃。存储器则连接I2C,保证即使主板掉电后数据不会丢失。
实物图如下:
五、代码实现
1.更换信道
代码如下(示例):
#define SEED 1346354787//随机种子
#define N 32//全局信道数
/**可用信道数改变时需改变下面代码**/
#define U 32//当前可用信道数
char *Ck[32]={"0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16",
"17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"};//可用信道集合
/**********************************/
int M=U;//所有可用信道的数量
int P=17;//大于M的最小素数,在每一轮算法中保持不变
int r=1;//跳跃步长,是[1,M]的中一个数
int i=0;//信道索引,是[1,P]中的一个数
int t=0;//时隙计数器,每个时隙为20ms。1s=1000000
int s=0;//随机数
//判断是否为质数
int isPrime(int num){
if (num<2) return 0;
int k=2;
int s=sqrt(num);
while(k<=s){
if(num%k==0) return 0;
k++;
}
return 1;
}
//得到一个大于M的最小素数
int getLargestPrime(int M){
int isPrime(int num);
int k=M+1;
int flag=1;
while(flag){
if (isPrime(k)){
return k;
}
k++;
}
return 0;
}
//获取时隙t时的调频信道
int JSHopping (int M,int P,int r,int i,int t){
int j=0;//可用信道
t%=(3*P);
if (t<(2*P)) j=(i+(t*r)-1)%P+1;
else j=r;
if(j>M) j=(j-1)%M+1;
return j;//返回可用信道
}
//连接字符串
char *join(char *a, char *b) {
char *c = (char *) malloc(strlen(a) + strlen(b) + 1);
//局部变量,用malloc申请内存,strlen不算'\0',所以需要+1
if (c == NULL) exit (1);
char *tempc = c; //把首地址存下来
while (*a != '\0') {
*c++ = *a++;
}
while ((*c++ = *b++) != '\0') {
;
}
return tempc;
}
//发送AT指令进行JS跳信道
void JS_2(void){
GPIO(0);//设置为配置模式
uint32_t ret;
WifiIotUartAttribute uart_attr = {
//baud_rate: 115200
.baudRate = 115200,
//data_bits: 8bits
.dataBits = 8,
.stopBits = 1,
.parity = 0,
};
//Initialize uart driver
ret = UartInit(WIFI_IOT_UART_IDX_1, &uart_attr, NULL);
if (ret != WIFI_IOT_SUCCESS)
{
printf("Failed to init uart! Err code = %d\n", ret);
return;
}
int r0,i0;
P=getLargestPrime(M);
r0=rand()%M+1;//随机选取
i0=rand()%P+1;//随机选取
int n=t/(3*P);
int m=t/(3*M*P);
r=((r0+n-1)%M)+1;
i=((i0+m-1)%P);
int c=JSHopping (M,P,r,i,t);
t++;
char *aa="AT+WLRATE=";
char *bb=",5\r\n";
char *packed=join(join(aa,(char *)Ck[c]),bb);//AT+WLRATE=Ck[c],5\r\n
UartWrite(WIFI_IOT_UART_IDX_1, (unsigned char *)packed, strlen(packed));
printf("(更换信道中)发送的数据: %s\r\n", (unsigned char *)packed);
usleep(500000);
}
3.根据传感器回调的数据判断是否摔倒
代码如下(示例):
static void AXIS_Task(void)
{
E53_SC2_Init();
short *gyroData;
while (1)
{
int sum_x=0,sum_y=0,sum_z=0;
int gyro_x=0,gyro_y=0,gyro_z=0;
int count = 10;//取10次的均值
for(int i=count;i>0;i--)//均值滤波
{
E53_SC2_Read_Data();
MPU6050ReadGyro(*gyroData);
sum_x += (int)E53_SC2_Data.Accel[0];
sum_y += (int)E53_SC2_Data.Accel[1];
sum_z += (int)E53_SC2_Data.Accel[2];
gyro_x += (int)gyroData[0];
gyro_y += (int)gyroData[1];
gyro_z += (int)gyroData[2];
}
Temperature = (int)E53_SC2_Data.Temperature;
x = sum_x/count/2048*G;
y = sum_x/count/2048*G;
z = sum_x/count/2048*G;
dx = gyro_x/count;
dy = gyro_y/count;
dz = gyro_z/count;
smv = sqrt(x*x+y*y+z*z);
//printf("x=%d\ty=%d\tz=%d\tm/s^2\n",x,y,z);
//printf("三轴加速度和:%lf m/s^2\r\n",smv);
if(smv < 5 || smv >13)
{
FALL = 1;
f = 1;
osThreadYield();
LED_D1_StatusSet(OFF);
LED_D2_StatusSet(ON);
itoa(x+99900,str_x);
X_axisdata = str_x;
itoa(y+88800,str_y);
Y_axisdata = str_y;
itoa(z+77700,str_z);
Z_axisdata = str_z;
itoa(Temperature+66600,str_t);
Temperaturedata = str_t;
}
else
{
if(FALL==0)
{
itoa(x+99900,str_x);
X_axisdata = str_x;
itoa(y+88800,str_y);
Y_axisdata = str_y;
itoa(z+77700,str_z);
Z_axisdata = str_z;
itoa(Temperature+66600,str_t);
Temperaturedata = str_t;
}
f = 0;
LED_D1_StatusSet(ON);
LED_D2_StatusSet(OFF);
}
osDelay(100);
}
}
总结
该腰带仍处于开发调试阶段,更多功能也在逐步添加完善,本篇文章记录当前开发进度。
参考文献