视频链接:基于zigbee的无线传输(患者监护系统)_哔哩哔哩_bilibili
可以通过视频更加清晰地了解项目。
程序不完善,但是基本可以完成无线传输的目的。
1.项目要求:
跟着步骤一步一步来,基本可以完成此次项目,所用程序全部开源。项目总体要求为利用Arduino采集两个传感器的数据,通过Arduino的串口发送给终端(就是其中一个zigbee),然后终端利用无线传输发送给协调器。
1.1补充:
以下展示其主要目的为展示zigbee的无线传输,arduino采集的传感器数据可以通过我们自身去模拟,下面会有段落描述怎样模拟产生arduino产生的串口数据给终端zigbee。
2.项目所用硬件模块:
1.两台zigbee模块,一台充当协调器(收集数据),一台充当终端(发送数据)。
2.一个arduino模块用来采集传感器信息,主要利用arduino上的IIC模块,其实不用arduino也可以,我们可以采用其他的的硬件模块采集传感器数据或者就用zigbee。补充一下:在模拟的时候,我们完全可以不采用arduino采集的数据,可以通过串口助手给终端发数据。
3.所用的传感器型号为:MX30205和MAX30102。
心率传感器部分的接线:
VIN- 3.3V
SDA-SDA
SCL-SCL
GND-GND
人体温度传感器部分的接线:
VCC- 3.3V
SDA-SDA
SCL-SCL
OS-GND(模块的中断引脚,任意)
A2-GND
A1-VCC
A0-GND
3.arduino程序
#include <Wire.h>
#include "Protocentral_MAX30205.h"
#include "MAX30105.h"
#include "heartRate.h"
MAX30205 tempSensor; //体温传感器
MAX30105 particleSensor; //心率传感器
byte SendPack[3]={0x00,0x00,0x00}; //串口发送协议帧缓存,首尾字节为帧头和帧尾,有效数据分别为体温、心率
int timer1_counter;
const byte RATE_SIZE = 4; //定义多少次心率数据取平均值
byte rates[RATE_SIZE]; //用于存放心率数据
byte rateSpot = 0;
long lastBeat = 0; //存储上次心跳发生的时间
float beatsPerMinute;
int beatAvg;
void setup()
{
// put your setup code here, to run once:
Wire.begin();
Serial.begin(9600);
tempSensor.begin(); //初始化体温传感器为连续模式
// 初始化心率传感器
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
{
Serial.println("MAX30105 was not found. Please check wiring/power. ");
while (1);
}
particleSensor.setup(); //使用默认设置来配置心率传感器
particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running
particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
//配置定时器,用于串口定时发送数据包
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
// timer1_counter = 65536-(62500*0.5); //0.5s 定时器中断
timer1_counter = 34286; //预加载timer1 65536-16Mhz/256/2Hz
TCNT1 = timer1_counter;
TCCR1B |= (1 << CS12);
TIMSK1 |= (1<< TOIE1);
interrupts();
}
void loop()
{
//温度处理
unsigned int temp = tempSensor.getTemperature()*100; // 读取温度值并放大100倍
SendPack[0]=temp / 100; //更新体温值整数部分
SendPack[1]=temp % 100; //更新体温值小数部分
//心率处理
long irValue = particleSensor.getIR();
if ((checkForBeat(irValue) == true)&&(irValue > 50000)) //检测到一次心跳
{
long delta = millis() - lastBeat;
lastBeat = millis();
beatsPerMinute = 60 / (delta / 1000.0); //根据两次心跳时间差来计算心率值
if (beatsPerMinute < 255 && beatsPerMinute > 40) //小于40BPM或大于255BPM视为无效
{
rates[rateSpot++] = (byte)beatsPerMinute; //将心跳数据存入缓存以便求平均
rateSpot %= RATE_SIZE; //循环存储
beatAvg = 0;
for (byte x = 0 ; x < RATE_SIZE ; x++) //计算平均心率
beatAvg += rates[x];
beatAvg /= RATE_SIZE;
if(beatAvg<40) //小于40BPM视为无效
beatAvg = 0;
}
if(beatsPerMinute < 40)
beatsPerMinute=0;
}
else if(irValue < 50000)
{
beatsPerMinute=0;
beatAvg = 0;
}
SendPack[2]=beatAvg; //更新心跳值
}
//定时器中断服务函数
ISR(TIMER1_OVF_vect)
{
TCNT1 = timer1_counter;
for(char i=0;i<3;i++) //通过串口将协议帧发送出去
{
Serial.write(SendPack[i]);
}
}
4.终端程序
#include <iocc2530.h>
#define LED1 P1_0
#define LED2 P1_1
#define LED3 P0_4
#define KEY1 P0_1
#define SENDVAL 5
unsigned char RX0_Buffer[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //UART0接收缓冲
unsigned char DataGet_Flag = 0; //串口0接收到协议帧标志
unsigned char ReceiveData = 0;
unsigned char ReceiveIndex = 0;
char SendPacket[]={0x0E,0x61,0x88,0x00,0x07,0x20,0xEF,0xBE,0x20,0x50,0x00,0x00,0x00,'\r','\n'};
void ConfigGPIO(void);
void Init32M(void);
void halRfInit(void);
void RFSend(char *pstr,char len);
void Uart0_Cfg(void);
void Uart0_PrintASCII(unsigned char c);
void DelayMS(unsigned int ms)
{
unsigned int i,j;
for (i=0; i<ms; i++)
for (j=0; j<605; j++);
}
void main()
{
char backup = 1;
ConfigGPIO();
Init32M();
halRfInit();
Uart0_Cfg();
SHORT_ADDR0=0x50;
SHORT_ADDR1=0x20;//设置本模块地址 设置本模块的网络地址0x2050
for(;;)
{
DelayMS(1010);
SendPacket[10] = RX0_Buffer[0];
SendPacket[11] = RX0_Buffer[1];
SendPacket[12] = RX0_Buffer[2];
RFSend(SendPacket,15);
Uart0_PrintASCII(RX0_Buffer[0]);
Uart0_PrintASCII(RX0_Buffer[1]);
Uart0_PrintASCII(RX0_Buffer[2]);
Uart0_PrintASCII(SendPacket[10]);
Uart0_PrintASCII(SendPacket[11]);
Uart0_PrintASCII(SendPacket[12]);
}
}
void Uart0_PrintASCII(unsigned char c)
{
UTX0IF = 0;
U0DBUF = c;
while(UTX0IF==0);
UTX0IF = 0;
}
void Init32M(void)
{
SLEEPCMD &=0xFB;//1111 1011 开启2个高频时钟源
while(0==(SLEEPSTA & 0x40));// 0100 0000 等待32M稳定
DelayMS(1);
CLKCONCMD &=0xF8;//1111 1000 不分频输出
CLKCONCMD &=0XBF;//1011 1111 设置32M作为系统主时钟
while(CLKCONSTA & 0x40); //0100 0000 等待32M成功成为当前系统主时钟
}
void ConfigGPIO(void)
{
P1SEL &= ~0x03;
P0SEL &= ~0x10;
P1DIR |= 0x03;
P0DIR |= 0x10;
P0SEL &= ~0x02;
P0DIR &= ~0x02;
P0INP &= ~0x02;
}
void halRfInit(void)
{
EA=0;
FRMCTRL0 |= 0x60;
// Recommended RX settings
TXFILTCFG = 0x09;
AGCCTRL1 = 0x15;
FSCAL1 = 0x00;
// enable RXPKTDONE interrupt
RFIRQM0 |= 0x40;//把射频接收中断打开
// enable general RF interrupts
IEN2 |= 0x01;
FREQCTRL =(11+(25-11)*5);//(MIN_CHANNEL + (channel - MIN_CHANNEL) * CHANNEL_SPACING);
//设置载波为2475M
PAN_ID0=0x07;
PAN_ID1=0x20; //0x2007
//halRfRxInterruptConfig(basicRfRxFrmDoneIsr);
RFST = 0xEC;//清接收缓冲器
RFST = 0xE3;//开启接收使能
EA=1;
}
void RFSend(char *pstr,char len)
{
char i;
RFST = 0xEC; //确保接收是空的
RFST = 0xE3; //清接收标志位
while (FSMSTAT1 & 0x22);//等待射频发送准备好
RFST = 0xEE;//确保发送队列是空
RFIRQF1 &= ~0x02;//清发送标志位
for(i=0;i<len;i++)
{
RFD=pstr[i];
}
RFST = 0xE9;
while(!(RFIRQF1 & 0x02) );
RFIRQF1 = ~0x02;
}
void Uart0_Cfg()
{
PERCFG&=~0x01; //有2个备用位置,0使用备用位置1;1使用备用位置2
P0SEL |= 0x0C; //P0_2 RXD P0_3 TXD 外设功能 0000 1100
U0CSR |= 0xC0; //串口接收使能 1100 0000 工作UART模式+允许接受
U0UCR |= 0x00; //无奇偶校验,1位停止位
U0GCR |= 0x08;
U0BAUD = 0x3b; //波特率:9600bps
IEN0 |= 0X04; //开串口接收中断 'URX0IE = 1',也可以写成 URX0IE=1;
EA=1;
}
#pragma vector=URX0_VECTOR
__interrupt void URX0_IRQ(void)
{
URX0IF=0;
if(ReceiveIndex == 3)
{
ReceiveIndex = 0;
}
RX0_Buffer[ReceiveIndex++] = U0DBUF;
}
#pragma vector=RF_VECTOR
__interrupt void RF_IRQ(void)
{
EA=0;
if( RFIRQF0 & 0x40 )
{
RFIRQF0&= ~0x40;
}
S1CON= 0;
RFST = 0xEC;//清接收缓冲器
RFST = 0xE3;//开启接收使能
EA=1;
}
5.协调器程序
#include <iocc2530.h>
#include "stdio.h"
#include "string.h"
#define LED1 P1_0
#define LED2 P1_1
#define LED3 P0_4
#define KEY1 P0_1
#define SENDVAL 5
void ConfigGPIO(void);
void Init32M(void);
void ConfigGPIO(void);
void Uart0_Cfg();
void Uart0SendByte(char SendByte);
void halRfInit(void);
void Uart0_Printf(unsigned char *p);
char RF_RecData[3] = {0, 0, 0};
double Temperature=0.0;
unsigned char HeartRate=0;
__near_func int putchar(int c)
{
UTX0IF = 0;
U0DBUF = (char)c;
while(U0DBUF == 0);
return c;
}
void DelayMS(unsigned int ms)
{
unsigned int i,j;
for (i=0; i<ms; i++)
for (j=0; j<605; j++);
}
void main()
{
char buf[100];
int repleacedatatemphigh;
int repleacedatatemplow;
int repleacedataheart;
ConfigGPIO();
Init32M();
halRfInit();
Uart0_Cfg();
SHORT_ADDR0=0xEF;
SHORT_ADDR1=0xBE;//设置本模块地址 0xBEEF
for(;;)
{
DelayMS(1200);
Uart0_Printf("temp: ");
repleacedatatemphigh = RF_RecData[0];
sprintf(buf, "%d",repleacedatatemphigh);
Uart0_Printf(buf);
Uart0_Printf(".");
repleacedatatemplow = RF_RecData[1];
sprintf(buf, "%d",repleacedatatemplow);
Uart0_Printf(buf);
Uart0_Printf("\r\n");
Uart0_Printf("heart: ");
repleacedataheart = RF_RecData[2];
sprintf(buf, "%d",repleacedataheart);
Uart0_Printf(buf);
Uart0_Printf("\r\n");
}
}
void Init32M(void)
{
SLEEPCMD &=0xFB;//1111 1011 开启2个高频时钟源
while(0==(SLEEPSTA & 0x40));// 0100 0000 等待32M稳定
DelayMS(1);
CLKCONCMD &=0xF8;//1111 1000 不分频输出
CLKCONCMD &=0XBF;//1011 1111 设置32M作为系统主时钟
while(CLKCONSTA & 0x40); //0100 0000 等待32M成功成为当前系统主时钟
}
void ConfigGPIO(void)
{
P1SEL &= ~0x03;
P0SEL &= ~0x10;
P1DIR |= 0x03;
P0DIR |= 0x10;
P0SEL &= ~0x02;
P0DIR &= ~0x02;
P0INP &= ~0x02;
}
void Uart0_Cfg()
{
PERCFG &=0xFE;
P0SEL |=0x0C;
U0CSR |=0xC0;
U0UCR =0;
U0GCR =11;
U0BAUD =216;
IEN0 |=0x04;
EA=1;
}
void Uart0_Printf(unsigned char *p) //发送字符串
{
while(*p)
{
U0DBUF=*(p++);
while(UTX0IF == 0);
UTX0IF = 0;
}
}
void Uart0SendByte(char SendByte)
{
U0DBUF=SendByte; //把我们收到的数据通过串口再返回发出去
while(UTX0IF==0);
UTX0IF=0;
}
void halRfInit(void)
{
EA=0;
FRMCTRL0 |= 0x60;
// Recommended RX settings
TXFILTCFG = 0x09;
AGCCTRL1 = 0x15;
FSCAL1 = 0x00;
// enable RXPKTDONE interrupt
RFIRQM0 |= 0x40;
// enable general RF interrupts
IEN2 |= 0x01;
FREQCTRL =(11+(25-11)*5);//(MIN_CHANNEL + (channel - MIN_CHANNEL) * CHANNEL_SPACING);
PAN_ID0=0x07;
PAN_ID1=0x20;
//halRfRxInterruptConfig(basicRfRxFrmDoneIsr);
RFST = 0xEC;//清接收缓冲器
RFST = 0xE3;//开启接收使能
EA=1;
}
void RevRFProc()
{
static char len;
static int ch;
static char Alllen;
static char index = 0;
len=ch=0;
RFIRQM0 &= ~0x40;
IEN2 &= ~0x01;
EA=1;
len=RFD;
//len=0x0C 12
Alllen=len;
while (len>0)
{
ch=RFD;
if(3==len)
{
}
if((len>=3)&&(Alllen-len>=9))
{
if(index == 3)
index = 0;
RF_RecData[index++] = ch;
//Uart0SendByte(ch);
}
len--;
}
EA=0;
// enable RXPKTDONE interrupt
RFIRQM0 |= 0x40;
// enable general RF interrupts
IEN2 |= 0x01;
}
#pragma vector=RF_VECTOR
__interrupt void RF_IRQ(void)
{
EA=0;
if( RFIRQF0 & 0x40 )
{
RevRFProc();
RFIRQF0&= ~0x40; // Clear RXPKTDONE interrupt
}
S1CON= 0; // Clear general RF interrupt flag
RFST = 0xEC;//清接收缓冲器
RFST = 0xE3;//开启接收使能
EA=1;
}