当前位置:网站首页>技能梳理[email protected]+adxl345+电机震动+串口输出
技能梳理[email protected]+adxl345+电机震动+串口输出
2022-06-30 09:37:00 【Sky_Lannister】
基于f103zet6单片机,使用adxl345检测电机振动频率,串口打印,程序模板是正点原子
1、项目简介

2、实现逻辑
#对adxl345初始化
#检测电机的震动(加速度),通过串口打印
3、应用场景
#检测电机或其它物品的震动
4、核心代码梳理
#define SlaveAddress 0xA6 //定义器件在IIC总线中的从地址,根据ALT ADDRESS地址引脚不同修改 //ALT ADDRESS引脚接地时地址为0xA6,接电源时地址为0x3A
unsigned char BUF[8]; //接收数据缓存区
unsigned char ge,shi,bai,qian,wan; //显示变量
unsigned char err;
float temp_X,temp_Y,temp_Z;
float Acc_X,Acc_Y,Acc_Z,q;
short Frequency;
void SCL_Set_Output(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SCL_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SCL_GPIO, &GPIO_InitStructure);
}
void SDA_Set_Output(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SDA_GPIO, &GPIO_InitStructure);
}
void SDA_Set_Input(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SDA_GPIO, &GPIO_InitStructure);
}
/************************************** 起始信号 **************************************/
void ADXL345_Start(void)
{
SCL_OUT();
SDA_OUT();
SET_SDA();//SDA = 1; //拉高数据线
SET_SCL();//SCL = 1; //拉高时钟线
delay_us(2);//Delay5us(); //延时
CLE_SDA();//SDA = 0; //拉低数据线
delay_us(2);//Delay5us(); //延时
CLE_SCL();//SCL = 0; //拉低时钟线
}
/************************************** 停止信号 **************************************/
void ADXL345_Stop(void)
{
SCL_OUT();
SDA_OUT();
CLE_SDA();//SDA = 0; //拉低数据线
SET_SCL();//SCL = 1; //拉高时钟线
delay_us(2);//Delay5us(); //延时
SET_SDA();//SDA = 1; //产生上升沿
delay_us(2);//Delay5us(); //延时
CLE_SCL();
}
/************************************** 发送应答信号 入口参数:ack (0:ACK 1:NAK) **************************************/
void ADXL345_SendACK(uchar ack)
{
SCL_OUT();
SDA_OUT();
if(ack==0)//SDA = ack; //写应答信号
{
CLE_SDA();
}
else
{
SET_SDA();
}
SET_SCL();//SCL = 1; //拉高时钟线
delay_us(2);//Delay5us(); //延时
CLE_SCL();//SCL = 0; //拉低时钟线
delay_us(5);//Delay5us(); //延时
}
/************************************** 接收应答信号 **************************************/
uchar ADXL345_RecvACK(void)
{
SDA_INT();
SCL_OUT();
SET_SCL();//SCL = 1; //拉高时钟线
delay_us(2);// Delay5us(); //延时
SET_SCL();
if(SDA_VAL()== Bit_SET) //CY = SDA; //读应答信号
{
err = 1;
}
else
{
err = 0;
}
CLE_SCL() ;//SCL = 0; //拉低时钟线
delay_us(5);// Delay5us(); //延时
SDA_OUT();
return err;
}
/************************************** 向IIC总线发送一个字节数据 **************************************/
void ADXL345_SendByte(unsigned char dat)
{
unsigned char i;
SCL_OUT();
SDA_OUT();
for (i=0; i<8; i++) //8位计数器
{
delay_us(5); //延时
if(dat&0x80) //SDA = CY; //送数据口
{
SET_SDA();}
else
{
CLE_SDA();}
delay_us(5); //延时
SET_SCL();//SCL = 1; //拉高时钟线
delay_us(5); //延时
CLE_SCL();//SCL = 0; //拉低时钟线
dat <<= 1; //移出数据的最高位
}
ADXL345_RecvACK();
}
/************************************** 从IIC总线接收一个字节数据 **************************************/
unsigned char ADXL345_RecvByte(void)
{
unsigned char i;
unsigned char Mid;
unsigned char dat = 0;
SDA_INT();
SCL_OUT();
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
delay_us(5); //延时
SET_SCL();
if(SDA_VAL()== Bit_SET) //CY = SDA; //读应答信号
{
Mid = 1;
}
else
{
Mid = 0;
}
if(Mid) dat++;
delay_us(5);
CLE_SCL();//SCL = 0; //拉低时钟线
}
return dat;
}
//******单字节写入*******************************************
void Single_Write_ADXL345(uchar REG_Address,uchar REG_data)
{
ADXL345_Start(); //起始信号
ADXL345_SendByte(SlaveAddress); //发送设备地址+写信号
ADXL345_SendByte(REG_Address); //内部寄存器地址,请参考中文pdf22页
ADXL345_SendByte(REG_data); //内部寄存器数据,请参考中文pdf22页
ADXL345_Stop(); //发送停止信号
}
//********单字节读取*****************************************
uchar Single_Read_ADXL345(uchar REG_Address)
{
uchar REG_data;
ADXL345_Start(); //起始信号
ADXL345_SendByte(SlaveAddress); //发送设备地址+写信号
ADXL345_SendByte(REG_Address); //发送存储单元地址,从0开始
ADXL345_Start(); //起始信号
ADXL345_SendByte(SlaveAddress+1); //发送设备地址+读信号
REG_data=ADXL345_RecvByte(); //读出寄存器数据
ADXL345_SendACK(1);
ADXL345_Stop(); //停止信号
return REG_data;
}
//*********************************************************
//
//连续读出ADXL345内部加速度数据,地址范围0x32~0x37
//
//*********************************************************
void Multiple_Read_ADXL345(void)
{
uchar i;
ADXL345_Start(); //起始信号
ADXL345_SendByte(SlaveAddress); //发送设备地址+写信号
ADXL345_SendByte(0x32); //发送存储单元地址,从0x32开始
ADXL345_Start(); //起始信号
ADXL345_SendByte(SlaveAddress+1); //发送设备地址+读信号
for (i=0; i<6; i++) //连续读取6个地址数据,存储中BUF
{
BUF[i] = ADXL345_RecvByte(); //BUF[0]存储0x32地址中的数据
if (i == 5)
{
ADXL345_SendACK(1); //最后一个数据需要回NOACK
}
else
{
ADXL345_SendACK(0); //回应ACK
}
}
ADXL345_Stop(); //停止信号
delay_us(5);
}
//*****************************************************************
//初始化ADXL345,根据需要请参考pdf进行修改************************
void Init_ADXL345(void)
{
//
Single_Write_ADXL345(0x31,0x0B); //测量范围,正负16g,13位模式
Single_Write_ADXL345(0x2C,0x08); //速率设定为25 参考pdf13页
Single_Write_ADXL345(0x2D,0x08); //选择电源模式 参考pdf24页 //参考14页表7进行修改
Single_Write_ADXL345(0x2E,0x80); //使能 DATA_READY 中断
Single_Write_ADXL345(0x38,0x00);
Single_Write_ADXL345(0x2F,0x00);
Single_Write_ADXL345(0x1E,0x00); //X 偏移量 根据测试传感器的状态写入pdf29页
Single_Write_ADXL345(0x1F,0x00); //Y 偏移量 根据测试传感器的状态写入pdf29页
Single_Write_ADXL345(0x20,0x05); //Z 偏移量 根据测试传感器的状态写入pdf29页
}
//***********************************************************************
//显示x轴
void ReadData_x(void)
{
int Acc_dis_data,dis_data,Acc_speed,Dis; //变量
Multiple_Read_ADXL345(); //连续读出数据,存储在BUF中
/*获取syz轴加速度*/
Acc_dis_data=(BUF[1]<<8)+BUF[0]; //合成数据
Acc_X=(float)Acc_dis_data*3.9/1000*9.8; //计算数据和显示,查考ADXL345快速入门第4页
Acc_dis_data=(BUF[3]<<8)+BUF[2]; //合成数据
Acc_Y=(float)Acc_dis_data*3.9/1000*9.8; //计算数据和显示,查考ADXL345快速入门第4页
Acc_dis_data=(BUF[5]<<8)+BUF[4]; //合成数据
Acc_Z=(float)Acc_dis_data*3.9/1000*9.8; //计算数据和显示,查考ADXL345快速入门第4页
/*获取syz轴坐标*/
dis_data=(BUF[1]<<8)+BUF[0]; //合成数据
temp_X=(float)dis_data*3.9; //计算数据和显示,查考ADXL345快速入门第4页
dis_data=(BUF[3]<<8)+BUF[2]; //合成数据
temp_Y=(float)dis_data*3.9; //计算数据和显示,查考ADXL345快速入门第4页
dis_data=(BUF[5]<<8)+BUF[4]; //合成数据
temp_Z=(float)dis_data*3.9; //计算数据和显示,查考ADXL345快速入门第4页
}
int main(void)
{
#define ACC_X_FIL 500
#define TEMP_X_FIL 50
#define LINE_FIL_N 10
u8 time=0,j;
u8 fil_count;
uint16_t value_buf[LINE_FIL_N];
u8 i;
u8 t=0;
uint16_t Acc_X_hex, TEMP_X_hex, Acc_X_hex_last, TEMP_X_hex_last;
uint32_t count_num = 0, fre = 0, fre_sum_fil = 0, fre_sum[10] = {
0}, fre_sum_num = 0, fil_sum = 0;
uart_init(115200); //串口初始化为115200
delay_init(); //延时初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
LED_Init(); //初始化与LED连接的硬件接口
usart3_init(115200); //初始化串口3
KEY_Init();
BEEP_Init();
OLED_Clear();
TIM2_Int_Init(4999,7199);
TIM6_Int_Init(2499,7199);
OLED_Init(); //初始化OLED
Init_ADXL345(); //adxl345初始化
DS18B20_Init(); //DS18B20初始化
printf("start !!!\r\n");
OLED_ShowString(0,0,"Electric machinery",12);
OLED_ShowString(0,52,"ASCII:",12);
OLED_ShowString(64,52,"CODE:",12);
OLED_Refresh_Gram(); //更新显示到OLED
u8 ret;
ret=atk_8266_wifista_test();
delay_ms(1500);
if(ret==2)
{
printf("wifi init ok !!!\r\n");
_mqtt.Init(rxbuf,0,txbuf,0);//MQTT初始化
//MQTT连接
ret=_mqtt.Connect("gl8dRlBcJhj.ESP8266|securemode=2,signmethod=hmacsha256,timestamp=2524608000000|",
"ESP8266&gl8dRlBcJhj",
"223d122ec212698603b5c2af5b73c9d0936e1c1e6327c566ea938089e56452ff");
delay_ms(1500);
delay_ms(1500);//这两段延时可以适当减少,但删掉好像会出问题
}
_mqtt.Init(rxbuf,0,txbuf,0);//MQTT初始化
ret=_mqtt.SubscribeTopic("/sys/a1e8HLT2lBT/test/thing/service/property/set",0,1);
delay_ms(3000);//可以删掉试试
char * string=NULL;
if(Single_Read_ADXL345(0X00)==0xe5)
{
delay_ms(5);
}
else
{
delay_ms(3);
}
j=' ';
while(1)
{
count_num++;
OLED_ShowChar(48,48,j,16,1);//显示ASCII字符
OLED_Refresh_Gram();
j++;
if(j>'~')j=' ';
OLED_ShowNum(103,48,j,3,16);//显示ASCII字符的码值
if(time%100==0){
temperature=DS18B20_Get_Temp();
ReadData_x(); //三轴检测函数
}
//printf("\r\nTemp:%d.%d .C\n",temperature/10,temperature%10);
// printf(" X=%4.3f m/s2 Y=%4.3f m/s2 Z=%4.3f m/s2\r\n",Acc_X,Acc_Y,Acc_Z);
// printf("x轴的值:%.1f y轴的值:%.1f Z轴的值:%.1f\r\n",temp_X,temp_Y,temp_Z);
// printf("%4.3f\r\n",Acc_X);
Acc_X_hex = Acc_X * 1000;
TEMP_X_hex = temp_X;
if((abs(Acc_X_hex - Acc_X_hex_last) > ACC_X_FIL))//滤波
{
fre++;
}
if((abs(TEMP_X_hex - TEMP_X_hex_last) > TEMP_X_FIL))
{
fre++;
}
Acc_X_hex_last = Acc_X_hex;
TEMP_X_hex_last = TEMP_X_hex;
if(count_num % 100 == 0)//经校准此时为1s
{
fre_sum[(fre_sum_num++) % 10] = fre;
for(i=0; i<10; i++)
{
fre_sum_fil += fre_sum[i];
}
fre_sum_fil = fre_sum_fil/10;
printf("\r\nTemp:%d.%d .C\n",temperature/10,temperature%10);
printf("fre is: %d HZ\r\n",fre_sum_fil);
Fre_sum_fil = fre_sum_fil;
fre_sum_fil = 0;
fre = 0;
LED0=!LED0;
}
if(count_num % 10 == 0)
{
printf("%c",0XFF);
printf("%c",0XFF);
printf("%c",(uint16_t)(Acc_X_hex/255));
printf("%c",(uint16_t)Acc_X_hex);
value_buf[fil_count++] = Acc_X_hex;
if(fil_count == LINE_FIL_N)
{
fil_count = 0;
}
for (u8 count=0; count<LINE_FIL_N; count++)
{
fil_sum += value_buf[count];
}
fil_sum = fil_sum / LINE_FIL_N;
printf("%c",(uint16_t)(fil_sum/255));
printf("%c",(uint16_t)fil_sum);
fil_sum = 0;
}
if(alarm_is_free == 10)//alarm_is_free=10,初始值为10
{
if(temperature/10 < 25 && Fre_sum_fil < 40)alarmFlag=0;//蜂鸣器报警
else alarmFlag =1;
}
if(alarm_is_free<10)
{
alarm_is_free++;
}
t=KEY_Scan(0); //得到按键值
if(t == KEY0_PRES)LED0=!LED0;
else if(t == KEY1_PRES){
alarmFlag=!alarmFlag;
delay_ms(20000);
alarm_is_free=0;
}
delay_ms(10);
_mqtt.Init(rxbuf,0,txbuf,0);//MQTT初始化
string=MyCreatJson( );
_mqtt.PublishData("/sys/gl8dRlBcJhj/ESP8266/thing/event/property/post", //具有发布权限的TOPIC
string, //符合json数据格式的消息串
0); //消息等级
free(string);//!!!!发布完要释放空间 ?
}
}
5、部分参考资料
6、注意事项
#这款模块检测的精度不是特别准,几乎可以认为是一个震动传感器,为了出来一个电机其它不突然数据变大的情况,用的一个累加值
完整可运行项目地址
边栏推荐
- Koreano essential creates a professional style
- Eth is not connected to the ore pool
- 移植完整版RT-Thread到GD32F4XX(详细)
- 【C语言快速上手】带你了解C语言,零基础入门③
- 调试方法和技巧详解
- MySQL index, transaction and storage engine of database (1)
- 6. Redis new data type
- G 代码解释|最重要的 G 代码命令列表
- C语言实现扫雷游戏,附详解及完整代码
- Great Wall digital art digital collection platform releases the creation Badge
猜你喜欢

UAV project tracking record 83 -- PCB diagram completion

Yixian e - commerce publie un rapport trimestriel: adhérer à la R & D et à l’investissement de la marque, réaliser un développement durable et de haute qualité

机器人系统动力学——惯性参数

Yixian e-commerce released its first quarterly report: adhere to R & D and brand investment to achieve sustainable and high-quality development

Appium automation test foundation - ADB shell command

“昆明城市咖啡地圖”活動再度開啟

Guolin was crowned the third place of global popularity of perfect master in the third quarter of 2022

Robot system dynamics - inertia parameters

郭琳加冕 2022第三季完美大师 全球人气季军

“昆明城市咖啡地图”活动再度开启
随机推荐
MySQL log management, backup and recovery of databases (2)
鼠标右键打开cmd(命令行)
GNN动手实践(二):复现图注意力网络GAT
keras ‘InputLayer‘ object is not iterable
OSError: [Errno 28] No space left on device
Some domestic image sources
G 代码解释|最重要的 G 代码命令列表
机器人系统动力学——惯性参数
Highlight display of Jinbei LB box, adhering to mini special effects
Launch of Rural Revitalization public welfare fund and release of public welfare bank for intangible cultural heritage protection of ancient tea tree
MIT-6874-Deep Learning in the Life Sciences Week4
Robot system dynamics - inertia parameters
Yixian e - commerce publie un rapport trimestriel: adhérer à la R & D et à l’investissement de la marque, réaliser un développement durable et de haute qualité
1033 To Fill or Not to Fill
Description of event object
South China Industrial Group launched digital economy and successfully held the city chain technology conference
Tooltips in the era of touch
Jinbei LT6 is powerful in the year of the tiger, making waves
戴森设计大奖,以可持续化设计改变世界
What is the real performance of CK5, the king machine of CKB?