基于51单片机和ADXL345震动检测模块检测震动;用LED灯和蜂鸣器表示超限报警,用LCD显示模拟检测结果。
主要选用ADXL345三轴振动传感器结合微分电路测得加速度,并且利用LCD显示震动信号。
程序运行图:
部分程序:
#include "system.h"
uint8 buffer[16];
int16 XAxisDegree,YAxisDegree,ZAxisDegree;
int16 XAxisDegreeTemp,YAxisDegreeTemp,ZAxisDegreeTemp;
int16 temp0,temp1; //int int16
int8 XAlarmL=-90,XAlarmH=90; //char int8
int8 YAlarmL=-90,YAlarmH=90;
int8 ZAlarmL=-90,ZAlarmH=90;
uint8 SystemSet; //unsigned char uint8
bit tab;
void LcdDisplay(void)
{
int16 temp;
if(SystemSet==0)
{
if(XAxisDegree==0) LCD1602_DisStr(0,0,"X: ");
else if(XAxisDegree>0) LCD1602_DisStr(0,0,"X:+");
else LCD1602_DisStr(0,0,"X:-");
if(XAxisDegree<0) temp=(-1)*XAxisDegree; // 转化为正数,显示需要
else temp=XAxisDegree;
sprintf(buffer,"%02d.%d",temp/10,temp%10);
LCD1602_DisStr(0,3,buffer);
if(YAxisDegree==0) LCD1602_DisStr(0,9,"Y: ");
else if(YAxisDegree>0) LCD1602_DisStr(0,9,"Y:+");
else LCD1602_DisStr(0,9,"Y:-");
if(YAxisDegree<0) temp=(-1)*YAxisDegree;
else temp=YAxisDegree;
sprintf(buffer,"%02d.%d",temp/10,temp%10);
LCD1602_DisStr(0,12,buffer);
if(ZAxisDegree==0) LCD1602_DisStr(1,0,"Z: ");
else if(ZAxisDegree>0) LCD1602_DisStr(1,0,"Z:+");
else LCD1602_DisStr(1,0,"Z:-");
if(ZAxisDegree<0) temp=(-1)*ZAxisDegree;
else temp=ZAxisDegree;
sprintf(buffer,"%02d.%d",temp/10,temp%10);
LCD1602_DisStr(1,3,buffer);
}
else
{
if(SystemSet==1) LCD1602_DisStr(0,4,"<X Set>");
else if(SystemSet==2) LCD1602_DisStr(0,4,"<Y Set>");
else if(SystemSet==3) LCD1602_DisStr(0,4,"<Z Set>");
if(DataVal0==0) LCD1602_DisStr(1,0,"L: ");
else if(DataVal0>0) LCD1602_DisStr(1,0,"L:+");
else LCD1602_DisStr(1,0,"L:-");
if(temp0<0) temp=(-1)*DataVal0; //
else temp=DataVal0;
sprintf(buffer,"%02d",temp);
LCD1602_DisStr(1,3,buffer);
if(DataVal1==0) LCD1602_DisStr(1,9,"H: ");
else if(DataVal1>0) LCD1602_DisStr(1,9,"H:+");
else LCD1602_DisStr(1,9,"H:-");
if(temp1<0) temp=(-1)*DataVal1;
else temp=DataVal1;
sprintf(buffer,"%02d",temp);
LCD1602_DisStr(1,12,buffer);
}
}
// 角度测量
void DegreeMeasure(void)
{
uint16 temp;
int32 temp0;
int16 XTemp,YTemp,ZTemp;
double temp1;
ADXL345_ReadBytes();
temp=((uint16)XyzDataBuf[1]<<8)|XyzDataBuf[0]; // 合成数据
XTemp=(int16)temp; // 由于是以二进制补码的形势存放的数据,所以要编制转换成带符号的值
temp=((uint16)XyzDataBuf[3]<<8)|XyzDataBuf[2];
YTemp=(int16)temp;
temp=((uint16)XyzDataBuf[5]<<8)|XyzDataBuf[4];
ZTemp=(int16)temp;
temp0 = (int32)YTemp*YTemp;
temp0 += (int32)ZTemp*ZTemp;
temp1 = sqrt(temp0);
temp1 = atan(XTemp/temp1); // 计算倾角的弧度值
XAxisDegreeTemp= temp1*1800/PI; // 弧度值变为角度值,放大10倍,保留1位小数
temp0 = (int32)XTemp*XTemp;
temp0 += (int32)ZTemp*ZTemp;
temp1 = sqrt(temp0);
temp1 = atan(YTemp/temp1);
YAxisDegreeTemp= temp1*1800/PI;
temp0 = (int32)YTemp*YTemp;
temp0 += (int32)XTemp*XTemp;
temp1 = sqrt(temp0);
temp1 = atan(ZTemp/temp1);
ZAxisDegreeTemp= temp1*1800/PI;
}
void CalcAvrgDegree(void)
{
static int16 XSum=0,XMin=900,XMax=-900;
static int16 YSum=0,YMin=900,YMax=-900;
static int16 ZSum=0,ZMin=900,ZMax=-900;
static uint8 i=0;
if(XMin>XAxisDegreeTemp) XMin=XAxisDegreeTemp; //求最小值
if(XMax<XAxisDegreeTemp) XMax=XAxisDegreeTemp; //求最大值
XSum += XAxisDegreeTemp; //累加
if(YMin>YAxisDegreeTemp) YMin=YAxisDegreeTemp; //求最小值
if(YMax<YAxisDegreeTemp) YMax=YAxisDegreeTemp; //求最大值
YSum += YAxisDegreeTemp; //累加
if(ZMin>ZAxisDegreeTemp) ZMin=ZAxisDegreeTemp; //求最小值
if(ZMax<ZAxisDegreeTemp) ZMax=ZAxisDegreeTemp; //求最大值
ZSum += ZAxisDegreeTemp; //累加
i++;
if(i>=10) //采样10次求平均
{
XSum = XSum-XMax-XMin; // 去除极值
XAxisDegree=XSum/(i-2); // 求出平均AD值(因为去除了极值,所以次数要减2)
XSum=0;XMin=900;XMax=-900; // 变量复位,准备下一次计算
YSum = YSum-YMax-YMin;
YAxisDegree=YSum/(i-2);
YSum=0;YMin=900;YMax=-900;
ZSum = ZSum-ZMax-ZMin;
ZAxisDegree=ZSum/(i-2);
ZSum=0;ZMin=900;ZMax=-900;
i=0;
}
}