【STM32】利用姿态传感器实现倾斜报警器

目录

认识STM32

姿态传感器

项目:【STM32】利用姿态传感器实现倾斜报警器

实现功能:

开发板:野火STM32F429

编程软件:Keil uVision5

编程语言:C语言

代码部分

main部分

姿态传感器代码部分

MadgwickAHRS.C

MadgwickAHRS.H

效果实现

vofa+软件使用方法

总结 


这篇博客是我上《ARM嵌入式》课程的学习总结分享。(如有错误欢迎私信评论补充纠正)

认识STM32

STM32是一系列由STMicroelectronics(意法半导体)公司推出的32位RISC微控制器产品线。这些微控制器广泛应用于各种嵌入式系统中,包括工业控制、消费类电子、汽车电子等领域。STM32系列微控制器具有高性能、低功耗、丰富的外设接口和广泛的软件支持等特点,因此备受工程师和开发者青睐。STM32系列微控制器基于ARM Cortex-M架构,适用于各种不同规模和复杂度的嵌入式系统设计。

(个人理解:集成了许多复杂模块的控制芯片,能实现的功能比AT89C52芯片更加多。应用范围广且价格实惠,更满足了小白对嵌入式的学习需求。)

姿态传感器

姿态传感器是一种能够检测物体在空间中的姿态(即倾斜、旋转等)的传感器。姿态传感器通常包括加速度计、陀螺仪和磁力计等传感器,通过这些传感器检测物体的加速度、角速度和磁场信息,从而确定物体的姿态。姿态传感器在许多应用中被广泛使用,如无人机、机器人、导航系统等领域,可以帮助控制系统准确地感知和理解物体的姿态信息,从而实现精确的控制和导航。
(个人理解:类似手机打游戏里的陀螺仪,可以监测到搭载此传感器物体的空间位置。姿态传感器已经集成在野火STM32F429开发板中,无需接线。)

项目:【STM32】利用姿态传感器实现倾斜报警器

 利用姿态传感器实现倾斜报警器的应用范围非常广泛。

1. 工程建筑领域:在建筑工地或者工程施工过程中,姿态传感器可以用来监测建筑物或者工程设备的倾斜情况,及时发现倾斜情况并进行警告,以避免出现安全事故。

2. 车辆领域:姿态传感器可以用来监测车辆的倾斜情况,特别是在越野行驶或者爬坡时,可以帮助驾驶员了解车辆的倾斜角度,以确保安全驾驶。

3. 航空领域:在飞机或者其他航空器上安装姿态传感器,可以实时监测飞机的倾斜角度和姿态,帮助飞行员及时调整飞行姿态,确保飞行安全。

4. 工业自动化领域:姿态传感器可以用来监测工业机器人或者自动化设备的倾斜情况,及时发现异常情况并进行报警,避免设备损坏或者生产事故。

总的来说,利用姿态传感器实现倾斜报警器的应用范围非常广泛,可以在各个领域中帮助监测和预警倾斜情况,保障设备和人员的安全。
 

实现功能:

制作做一个倾倒报警器,当pitch角或者roll角度大于60度时,蜂鸣器发出“嘀嘀嘀”报警声,角度在正常范围内报警声关闭。

开发板:野火STM32F429

编程软件:Keil uVision5

编程语言:C语言

代码部分

main部分

#include "stm32F4xx.h"
#include "stm32f4xx_conf.h"
#include "stdio.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "uart.h"
#include "adc.h"
#include "bsp_lcd.h"
#include "lcd_show_zn.h"
#include "lcd_show_zn_font.h"
#include "gt9xx.h"
#include "MadgwickAHRS.h"
#include "mpu6050.h"



uint16_t select_index = 0;  //表明当前选中哪一个菜单项
uint8_t  beep_state = 0;    //表示蜂鸣器的开关状态  0表示关闭  
uint8_t  led_state = 0;    //表示LED的开关状态  0表示关闭  
uint8_t	 system_time=0;

//编写中断服务函数
void EXTI0_IRQHandler()
{
    if(EXTI_GetITStatus(EXTI_Line0) != RESET)  //证明触发了中断
    {
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}
void EXTI15_10_IRQHandler()
{
    if(EXTI_GetITStatus(EXTI_Line13) != RESET)  //证明触发了中断
    {
        EXTI_ClearITPendingBit(EXTI_Line13);
    }
}


	
 uint8_t 	warnning_state=0;

int main(void)
{
    GPIO_InitTypeDef gpio_info;
 
    //GTP_Init_Panel();
    Delay_init();
    UART_init(115200);
    LED_init();
    MPU6050_Init();
  
 
    //PI11  蜂鸣器
    //初始化GPIO-I时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOI,ENABLE);
    
    gpio_info.GPIO_Mode = GPIO_Mode_OUT;
    gpio_info.GPIO_OType = GPIO_OType_PP;
    gpio_info.GPIO_Pin = GPIO_Pin_11;
    gpio_info.GPIO_PuPd = GPIO_PuPd_UP;
    gpio_info.GPIO_Speed = GPIO_Low_Speed;
    GPIO_Init(GPIOI,&gpio_info);

	
	
	
//作业:1. 通过VOFA+查看IMU6轴融合后得到的姿态角数据
//2. 制作做一个倾倒报警器,当pitch角或者roll角度大于60度时,蜂鸣器发出“嘀嘀嘀”报警声,角度在正常范围内报警声关闭


  while(1)
  {
		
    system_time+=10;  //计算系统时间
    Delay_ms(10); //每个循环延时10ms
    MadgwickAHRSupdateIMU(10);  //该函数的执行间隔是10ms
    if(system_time%100)      //每100ms通过串口打印一次数据
    {
      //printf("%d,%d,%d,%d,%d,%d\r\n",Acel[0],Acel[1],Acel[2],Gyro[0],Gyro[1],Gyro[2]);
			printf("%f,%f,%f\r\n",pitch,roll,yaw);
    }
		if(	pitch>60	||	pitch<-60 ||	roll>60	||	roll<-60	)
		{
			warnning_state = 1;
		}
		else 
		{
			warnning_state = 0;
		}
		
		if(system_time%1000 == 0 && warnning_state == 1)
		{
			if(beep_state ==1)
			{
				GPIO_ResetBits(GPIOI,GPIO_Pin_11);//关闭蜂鸣器
				beep_state =0;
			}
			else
			{
				GPIO_SetBits(GPIOI,GPIO_Pin_11);//开启蜂鸣器
				beep_state =1;
			}
		}
	
  }//while

}//mian

姿态传感器代码部分

MadgwickAHRS.C
#include "MadgwickAHRS.h"

#define ARM_MATH_CM4
#include "arm_math.h"


#define betaDef		      0.1f		// 2 * proportional gain

/*  敏感系数 */
#define ACC_SENSI    4095.9375f   //加速度敏感系数
#define GYRO_SENSI   16.38375f    //陀螺仪敏感系数
#define MAG_SENSI    6.66666667f  //磁力计敏感系数

/*  常用参数 */
#define DEG2RAD	   PI/180
//---------------------------------------------------------------------------------------------------
// Variable definitions

volatile float beta = betaDef;								// 2 * proportional gain (Kp)
volatile float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f;	// quaternion of sensor frame relative to auxiliary frame
volatile float pitch = 0.0f, roll = 0.0f, yaw = 0.0f;

volatile int tst_q0, tst_q1, tst_q2, tst_q3;
volatile int tst_yaw, tst_roll, tst_pitch;

short Acel[3];
short Gyro[3];

float invSqrt(float x);
void computeAngles(void);




void MadgwickAHRSupdateIMU(uint32_t period) 
{
	float recipNorm;
	float s0, s1, s2, s3;
	float qDot1, qDot2, qDot3, qDot4;
	float _2q0, _2q1, _2q2, _2q3, _4q0, _4q1, _4q2 ,_8q1, _8q2, q0q0, q1q1, q2q2, q3q3;
  float gx=0,  gy=0,  gz=0,  ax=0,  ay=0,  az=0;
  float sampleFreq;
  MPU6050ReadAcc(Acel);
  MPU6050ReadGyro(Gyro);
  
  gx = (float)Gyro[0]/GYRO_SENSI*DEG2RAD;
  gy = (float)Gyro[1]/GYRO_SENSI*DEG2RAD;
  gz = (float)Gyro[2]/GYRO_SENSI*DEG2RAD;
  
  ax = (float)Acel[0]/ACC_SENSI;
  ay = (float)Acel[1]/ACC_SENSI;
  az = (float)Acel[2]/ACC_SENSI;
  
	// Rate of change of quaternion from gyroscope
	qDot1 = 0.5f * (-q1 * gx - q2 * gy - q3 * gz);
	qDot2 = 0.5f * (q0 * gx + q2 * gz - q3 * gy);
	qDot3 = 0.5f * (q0 * gy - q1 * gz + q3 * gx);
	qDot4 = 0.5f * (q0 * gz + q1 * gy - q2 * gx);

	// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
	if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {

		// Normalise accelerometer measurement
		recipNorm = invSqrt(ax * ax + ay * ay + az * az);
		ax *= recipNorm;
		ay *= recipNorm;
		az *= recipNorm;   

		// Auxiliary variables to avoid repeated arithmetic
		_2q0 = 2.0f * q0;
		_2q1 = 2.0f * q1;
		_2q2 = 2.0f * q2;
		_2q3 = 2.0f * q3;
		_4q0 = 4.0f * q0;
		_4q1 = 4.0f * q1;
		_4q2 = 4.0f * q2;
		_8q1 = 8.0f * q1;
		_8q2 = 8.0f * q2;
		q0q0 = q0 * q0;
		q1q1 = q1 * q1;
		q2q2 = q2 * q2;
		q3q3 = q3 * q3;

		// Gradient decent algorithm corrective step
		s0 = _4q0 * q2q2 + _2q2 * ax + _4q0 * q1q1 - _2q1 * ay;
		s1 = _4q1 * q3q3 - _2q3 * ax + 4.0f * q0q0 * q1 - _2q0 * ay - _4q1 + _8q1 * q1q1 + _8q1 * q2q2 + _4q1 * az;
		s2 = 4.0f * q0q0 * q2 + _2q0 * ax + _4q2 * q3q3 - _2q3 * ay - _4q2 + _8q2 * q1q1 + _8q2 * q2q2 + _4q2 * az;
		s3 = 4.0f * q1q1 * q3 - _2q1 * ax + 4.0f * q2q2 * q3 - _2q2 * ay;
		recipNorm = invSqrt(s0 * s0 + s1 * s1 + s2 * s2 + s3 * s3); // normalise step magnitude
		s0 *= recipNorm;
		s1 *= recipNorm;
		s2 *= recipNorm;
		s3 *= recipNorm;

		// Apply feedback step
		qDot1 -= beta * s0;
		qDot2 -= beta * s1;
		qDot3 -= beta * s2;
		qDot4 -= beta * s3;
	}
  sampleFreq = 1000.0f/period;
	// Integrate rate of change of quaternion to yield quaternion
	q0 += qDot1 * (1.0f / sampleFreq);
	q1 += qDot2 * (1.0f / sampleFreq);
	q2 += qDot3 * (1.0f / sampleFreq);
	q3 += qDot4 * (1.0f / sampleFreq);

	// Normalise quaternion
	recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
	q0 *= recipNorm;
	q1 *= recipNorm;
	q2 *= recipNorm;
	q3 *= recipNorm;
  
  computeAngles();
}


float invSqrt(float x) {
	float halfx = 0.5f * x;
	float y = x;
	long i = *(long*)&y;
	i = 0x5f3759df - (i>>1);
	y = *(float*)&i;
	y = y * (1.5f - (halfx * y * y));
	return y;
}


void computeAngles(void)
{
	roll = atan2f(q0*q1 + q2*q3, 0.5f - q1*q1 - q2*q2) * 57.3f;
	pitch = asinf(-2.0f * (q1*q3 - q0*q2))* 57.3f;
	yaw = atan2f(q1*q2 + q0*q3, 0.5f - q2*q2 - q3*q3)* 57.3f;
	
	tst_q0 = q0 * 100;
	tst_q1 = q1 * 100;
	tst_q2 = q2 * 100;
	tst_q3 = q3 * 100;
	
	tst_pitch = pitch * 100;
	tst_roll = roll*100;
	tst_yaw = yaw*100;
	
}
MadgwickAHRS.H
#ifndef MadgwickAHRS_h
#define MadgwickAHRS_h

#include "mpu6050.h"

extern volatile float pitch, roll, yaw;   //pitch->绕Y轴旋转的角度    roll->绕X轴旋转的角度   
extern short Acel[3];          //x、y、z的加速度,其实就是重力加速度
extern short Gyro[3];          //x、y、z轴的角速度

//period  该函数执行的间隔,单位是ms
void MadgwickAHRSupdateIMU(uint32_t period);

#endif

效果实现

编写完成代码,下载至开发板后,即可通过"VOFA+"软件查看IMU6轴融合后得到的姿态角数据,超过指定位置后蜂鸣器发出警报。

vofa+软件使用方法

1.选择使用串口通信

2.选择连接开发板和本机的通信COM口(不知道COM口位置可去设备管理器查看)

3.波特率选择“115200”

4.点击蓝色圆形图标,开始连接

(以下图片是VOFA+软件主页面)

总结 

以上代码是针对STM32F4系列微控制器的嵌入式C代码。它包括了一系列头文件的引用,定义了一些全局变量和中断服务函数。在main函数中,初始化了一些硬件设备如LED、MPU6050等,并进入一个主循环。主要功能是通过IMU6轴融合计算姿态角数据,并监测pitch角和roll角是否超过±60度,如果超过则触发蜂鸣器报警。定时通过串口打印姿态角数据。

(说实话其实很多代码的编写都是复制粘贴的,但学会看懂别人的代码和在此基础上进行调用和改写,培养编程逻辑思维就算是学有所悟了吧。)

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值