0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于STM32设计的自动刹车灯

DS小龙哥-嵌入式技术 来源:DS小龙哥-嵌入式技术 作者:DS小龙哥-嵌入式技 2023-06-28 09:07 次阅读

一、项目介绍

随着科技的发展,人们对低碳环保的认知和需求不断提高。骑自行车既能够低碳环保,又能够锻炼身体,成为了很多人出行的首选。然而,由于自行车本身没有带指示灯,比如刹车指示灯等,所以自行车的安全性并不是很好,如果人们在骑自行车时紧急刹车,后车无法及时判断前方自行车的行为,容易造成交通事故。因此,设计一款自动刹车灯系统具有十分重要的意义。

本项目实现了通过安装ADXL345陀螺仪和四枚LED灯还有STM32F103C8T6主控芯片来实现自行车自动刹车灯的功能。当自行车上安装了该设备后,ADXL345通过IIC通信协议将X,Y,Z三轴的加速度实时值发送给SMT32F103C8T6主控芯片,并结合STM32高级定时器的PWM功能,输出不同占空比的脉冲,控制不同的LED灯输出多种亮度等级,从而控制不同的LED的开关以及明暗,并且通过不同亮度的红光和绿光混合,能够得到黄色的LED灯光。这样,在自行车急刹或者加速时,实时地控制LED灯的亮度和颜色,让后方车辆能够更清楚地了解前方自行车的行为,从而做出快速的反应,保障骑行者以及后车的安全。同时,该系统也能够提高自行车的可见性,并且对于追求低碳环保的人群来说,让自行车既能低碳环保,又能够锻炼身体。

image-20230618184936424

二、设计思路

2.1 项目目标

本项目通过安装ADXL345陀螺仪和四枚LED灯还有STM32F103C8T6主控芯片来实现自行车自动刹车灯的功能,使得自行车在急刹或者加速时,实时地控制LED灯的亮度和颜色,提高其可见性,降低交通事故的风险。同时,该系统还能够使自行车既能低碳环保,又能够锻炼身体。

2.2 项目硬件构成

(1)自行车:作为安装系统的物体,需要有一个固定的位置来安装ADXL345陀螺仪和四枚LED灯。

(2)ADXL345陀螺仪:通过IIC通信协议与STM32F103C8T6主控芯片通信,并将X、Y、Z三轴的加速度实时值发送给SMT32F103C8T6主控芯片。

(3)四枚LED灯:使用不同亮度的红光和绿光混合,能够得到黄色的LED灯光。通过控制其亮度和颜色来提高自行车的可见性。

(4)STM32F103C8T6主控芯片:根据接收到的ADXL345数据,结合STN32的高级定时器的PWM功能,输出不同占空比的脉冲,控制不同的LED灯输出多种亮度等级。

2.3 项目功能实现

(1)自行车加速度监测:ADXL345陀螺仪通过IIC通信协议与STM32F103C8T6主控芯片通信,实时地感知自行车的加速度变化。

(2)LED灯亮度和颜色控制:STM32F103C8T6主控芯片运用高级定时器的PWM功能,能够输出不同占空比的脉冲,并控制不同的LED灯输出多种亮度等级,通过不同亮度的红光和绿光混合,能够得到黄色的LED灯光,提高自行车的可见性。

(3)系统安装和调试:需要将ADXL345陀螺仪和四枚LED灯与STM32F103C8T6主控芯片连接起来,并进行系统测试和调试。

三、系统测试

3.1 功能样机安装与焊接

绘制好电路原理图之后,按照原理图将自动刹车灯系统的各个模块安装在事先购买好的洞洞板上,然后用导线将他们连接在一起,最后再焊接在一起,做成完整的自动刹车灯电路板。

image-20230618184608787

3.2 ADXL345模块调试

当上电后,将自动刹车灯电路的串口2外设引脚连接至PC端,将加速度解算后的实际值发送至PC端,通过PC端串口调试助手显示出具体数值,再观察数值是否符合常理。

image-20230618184700297

通过显示的数据信息,可以推测出ADXL345陀螺仪能够正常工作。

3.3 实物调试

最后阶段,将对自行车自动刹车灯进行实物调试,确定其基本功能能够正常实现。

当系统上电后,左右各一枚LED发出低亮黄色灯光,如下图。

image-20230618184801135

静置30S后,所有LED均熄灭,如下图。

image-20230618184825767

检测到震动后,重新亮起两盏黄色LED灯,如下图。

image-20230618184849795

当检测到刹车时,四枚LED灯均以高亮发出红色灯光,如下图。

image-20230618184910210

结合自行车自动刹车灯的功能需求和实物调试结果,可以发现,调试结果完全符合自动刹车灯的预期功能。

四、代码设计

4.1 主函数

#include "stm32f10x.h"
 #include "usart.h"
 #include "led.h"
 #include "RTC_Time.h" 
 #include < stdio.h >
 #include "delay.h"
 #include "sys.h"
 #include "stdlib.h"
 #include "stdio.h"
 #include "string.h"
 #include "adxl345.h"
 int main(void)
 {
       u32 flag=0;
       short x, y, z;
     float accelerated;
       LED_GPIO_Config();//初始化LED
     USART2_Config();
     delay_init(); //延时函数初始化
     PWM_LED_INIT();   //PWM   PA8-9
       LED_Init();    //PB7 LED-R
       PBout(7) = 1;     
       ADXL345_Init(); //PB 10,11
     ADXL345_Read_Average(&x, &y, &z, 20);
     ADXL345_AUTO_Adjust((char *)&x, (char *)&y, (char *)&z);
     TIM_SetCompare1(TIM1, 50); //设置TIMx捕获比较1寄存器(通道1)值(脉冲宽度)   占空比%20
     TIM_SetCompare2(TIM1, 50); //设置TIMx捕获比较2寄存器(通道2)值(脉冲宽度)   占空比%20
     while (1)
     {
         ADXL345_Read_Average(&x, &y, &z, 5);   //读加速度值
               accelerated=(x*3.9/1000*9.8);          //加速度实际值
             printf("X=%4.1f   Y=%4.1f  Z=%4.1f
",accelerated,(y*3.9/1000*9.8),(z*3.9/1000*9.8));
             while(flag >425)
             {
                  TIM_SetCompare1(TIM1, 0);          //通道2 占空比%0                         
                  TIM_SetCompare2(TIM1, 0);          //通道2 占空比%0 
                ADXL345_Read_Average(&x, &y, &z, 5);
                  accelerated=(x*3.9/1000*9.8);
                 if(accelerated< -5||accelerated >5) 
                 {
                     break;
                 }
             }
                 flag++; 
           if(accelerated< -4)
                 {
                     //四个LED低电平导通           
                     TIM_SetCompare1(TIM1, 0);            //GREEN不亮                          
                     TIM_SetCompare2(TIM1, 1000);         //RED高亮
                     PBout(7) = 0;   
                     flag=0;    
                 }
                 if(accelerated >0)
                 {
                     PBout(7) = 1;
                     TIM_SetCompare1(TIM1, 50);           //RED低亮  
                     TIM_SetCompare2(TIM1, 50);           //GREEN低亮
          }
                 if(accelerated >5)
                 {
                 flag=0; 
                 }
     }   
 }

4.2 LED灯控制

#include "led.h"
 #include "delay.h"
 void LED_GPIO_Config(void)
 {   
     //定义一个GPIO_InitTypeDef 类型的结构体,名字叫GPIO_InitStructure 
     GPIO_InitTypeDef  GPIO_InitStructure;
     //使能GPIOC的外设时钟
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
     //选择要用的GPIO引脚       
     GPIO_InitStructure.GPIO_Pin =GPIO_Pin_13;
     ///设置引脚模式为推免输出模式             
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         
     //设置引脚速度为50MHZ
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     //调用库函数,初始化GPIO
     GPIO_Init(GPIOC, &GPIO_InitStructure);
 }
 void TIME_INIT()
 {
     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
     TIM_OCInitTypeDef TIM_OCInitStructure; //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
     //TIM1定时器初始化  10ms
     TIM_TimeBaseInitStructure.TIM_Period = 999; 
     TIM_TimeBaseInitStructure.TIM_Prescaler = 719;
     TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;
     TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
     TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure);
     //TIM1的PWM配置     
     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
     TIM_OCInitStructure.TIM_Pulse = 0;//设置初始PWM脉冲宽度为0
     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //PWM输出使能
     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//当定时器计数值小于CCR_Val时为低电平
       //通道的使能
     TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //通道1
     TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); 
         TIM_OC2Init(TIM1, &TIM_OCInitStructure);  //通道2
     TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);   
         TIM_ARRPreloadConfig(TIM1, ENABLE);   //使能TIM1重载寄存器ARR
     TIM_Cmd(TIM1, ENABLE);                //使能
     TIM_CtrlPWMOutputs(TIM1, ENABLE);     //高级定时器必须加
 }
 void PWM_LED_INIT(void)
 {
     GPIO_InitTypeDef GPIO_InitStructure;
       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);  //GPIOA8,9,10是TIM1的通道1,2,3
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 ;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
     GPIO_Init(GPIOA, &GPIO_InitStructure);
     TIME_INIT();
 }
 void LED_Init(void)
 {
     GPIO_InitTypeDef GPIO_InitStructure;
   //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
 }
 ​

4.3 adxl345.c

#include "adxl345.h"
 #include "sys.h"
 #include "delay.h"
 #include "math.h"   
 u8 ADXL345_Init(void)
 {                 
     IIC_Init();                         //初始化IIC总线  
     if(ADXL345_RD_Reg(DEVICE_ID)==0XE5) //读取器件ID
     {  
         ADXL345_WR_Reg(0X31,0X2B);  //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程 
         ADXL345_WR_Reg(0X2C,0x0A);        //数据输出速度为100Hz
         ADXL345_WR_Reg(0X2D,0x28);    //链接使能,测量模式
         ADXL345_WR_Reg(0X2E,0x00);  //不使用中断      
         ADXL345_WR_Reg(0X1E,0x00);
         ADXL345_WR_Reg(0X1F,0x00);
         ADXL345_WR_Reg(0X20,0x00);  
         return 0;
     }           
     return 1;                                     
 }   
 //写ADXL345寄存器
 //addr:寄存器地址
 //val:要写入的值
 //返回值:无
 void ADXL345_WR_Reg(u8 addr,u8 val) 
 {
     IIC_Start();                 
     IIC_Send_Byte(ADXL_WRITE);  //发送写器件指令    
     IIC_Wait_Ack();    
   IIC_Send_Byte(addr);              //发送寄存器地址
     IIC_Wait_Ack();                                                        
     IIC_Send_Byte(val);             //发送值                      
     IIC_Wait_Ack();                    
   IIC_Stop();                             //产生一个停止条件       
 }
 //读ADXL345寄存器
 //addr:寄存器地址
 //返回值:读到的值
 u8 ADXL345_RD_Reg(u8 addr)      
 {
     u8 temp=0;       
     IIC_Start();                 
     IIC_Send_Byte(ADXL_WRITE);  //发送写器件指令    
     temp=IIC_Wait_Ack();       
     IIC_Send_Byte(addr);        //发送寄存器地址
     temp=IIC_Wait_Ack();                                                       
     IIC_Start();                //重新启动
     IIC_Send_Byte(ADXL_READ);   //发送读器件指令    
     temp=IIC_Wait_Ack();       
     temp=IIC_Read_Byte(0);      //读取一个字节,不继续再读,发送NAK               
     IIC_Stop();                 //产生一个停止条件      
     return temp;                //返回读到的值
 }  
 //读取ADXL的平均值
 //x,y,z:读取10次后取平均值
 void ADXL345_RD_Avval(short *x,short *y,short *z)
 {
     short tx=0,ty=0,tz=0;      
     u8 i;  
     for(i=0;i< 10;i++)
     {
         ADXL345_RD_XYZ(x,y,z);
         delay_ms(10);
         tx+=(short)*x;
         ty+=(short)*y;
         tz+=(short)*z;     
     }
     *x=tx/10;
     *y=ty/10;
     *z=tz/10;
 } 
 //自动校准
 //xval,yval,zval:x,y,z轴的校准值
 void ADXL345_AUTO_Adjust(char *xval,char *yval,char *zval)
 {
     short tx,ty,tz;
     u8 i;
     short offx=0,offy=0,offz=0;
     ADXL345_WR_Reg(POWER_CTL,0x00);     //先进入休眠模式.
     delay_ms(100);
     ADXL345_WR_Reg(DATA_FORMAT,0X2B);   //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程 
     ADXL345_WR_Reg(BW_RATE,0x0A);       //数据输出速度为100Hz
     ADXL345_WR_Reg(POWER_CTL,0x28);     //链接使能,测量模式
     ADXL345_WR_Reg(INT_ENABLE,0x00);    //不使用中断      
     ADXL345_WR_Reg(OFSX,0x00);
     ADXL345_WR_Reg(OFSY,0x00);
     ADXL345_WR_Reg(OFSZ,0x00);
     delay_ms(12);
     for(i=0;i< 10;i++)
     {
         ADXL345_RD_Avval(&tx,&ty,&tz);
         offx+=tx;
         offy+=ty;
         offz+=tz;
     }           
     offx/=10;
     offy/=10;
     offz/=10;
     *xval=-offx/4;
     *yval=-offy/4;
     *zval=-(offz-256)/4;      
     ADXL345_WR_Reg(OFSX,*xval);
     ADXL345_WR_Reg(OFSY,*yval);
     ADXL345_WR_Reg(OFSZ,*zval); 
 } 
 //读取3个轴的数据
 //x,y,z:读取到的数据
 void ADXL345_RD_XYZ(short *x,short *y,short *z)
 {
     u8 buf[6];
     u8 i;
     IIC_Start();                 
     IIC_Send_Byte(0X3A);    //发送写器件指令    
     IIC_Wait_Ack();    
   IIC_Send_Byte(0x32);          //发送寄存器地址(数据缓存的起始地址为0X32)
     IIC_Wait_Ack();             
     IIC_Start();                //重新启动
     IIC_Send_Byte(0X3B);    //发送读器件指令
     IIC_Wait_Ack();
     for(i=0;i< 6;i++)
     {
         if(i==5)buf[i]=IIC_Read_Byte(0);//读取一个字节,不继续再读,发送NACK  
         else buf[i]=IIC_Read_Byte(1);   //读取一个字节,继续读,发送ACK 
         delay_us(15);
       IIC_Start();                  //重新启动
         IIC_Send_Byte(0X3A);    //发送写器件指令
             IIC_Wait_Ack(); 
         IIC_Send_Byte(0x33+i);          //发送寄存器地址(数据缓存的起始地址为0X32)
       IIC_Wait_Ack();           
       IIC_Start();                  //重新启动
       IIC_Send_Byte(0X3B);  //发送读器件指令
       IIC_Wait_Ack();
     }                  
     IIC_Stop();                 //产生一个停止条件
     *x=(short)(((u16)buf[1]< < 8)+buf[0]);        
     *y=(short)(((u16)buf[3]< < 8)+buf[2]);        
     *z=(short)(((u16)buf[5]< < 8)+buf[4]);       
 }
 //读取ADXL345的数据times次,再取平均
 //x,y,z:读到的数据
 //times:读取多少次
 void ADXL345_Read_Average(short *x,short *y,short *z,u8 times)
 {
     u8 i;
     short tx,ty,tz;
     *x=0;
     *y=0;
     *z=0;
     if(times)//读取次数不为0
     {
         for(i=0;i< times;i++)//连续读取times次
         {
             ADXL345_RD_XYZ(&tx,&ty,&tz);
             *x+=tx;
             *y+=ty;
             *z+=tz;
             delay_ms(5);
         }
         *x/=times;
         *y/=times;
         *z/=times;
     }
 }
 //得到角度
 //x,y,z:x,y,z方向的重力加速度分量(不需要单位,直接数值即可)
 //dir:要获得的角度.0,与Z轴的角度;1,与X轴的角度;2,与Y轴的角度.
 //返回值:角度值.单位0.1°.
 short ADXL345_Get_Angle(float x,float y,float z,u8 dir)
 {
     float temp;
     float res=0;
     switch(dir)
     {
         case 0://与自然Z轴的角度
             temp=sqrt((x*x+y*y))/z;
             res=atan(temp);
             break;
         case 1://与自然X轴的角度
             temp=x/sqrt((y*y+z*z));
             res=atan(temp);
             break;
         case 2://与自然Y轴的角度
             temp=y/sqrt((x*x+z*z));
             res=atan(temp);
             break;
     }
     return res*1800/3.14;
 }

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 芯片
    +关注

    关注

    455

    文章

    50760

    浏览量

    423361
  • 通信协议
    +关注

    关注

    28

    文章

    881

    浏览量

    40304
  • 陀螺仪
    +关注

    关注

    44

    文章

    784

    浏览量

    98677
  • STM32
    +关注

    关注

    2270

    文章

    10897

    浏览量

    355831
  • IIC
    IIC
    +关注

    关注

    11

    文章

    300

    浏览量

    38321
  • ADXL345
    +关注

    关注

    14

    文章

    71

    浏览量

    33895
  • 刹车灯
    +关注

    关注

    0

    文章

    10

    浏览量

    4282
收藏 人收藏

    评论

    相关推荐

    第三刹车灯:CHMSL设计方案

    CHMSL代表中央高位刹车灯,安装在车辆左侧和右侧制动车灯(也称为刹车灯)的上方。根据美国国家高速公路交通安全管理局的规定,当刹车系统工作时,CHMSL要向后方司机提供明显确切的信息,
    的头像 发表于 05-29 16:25 7588次阅读

    [求助]明锐16刹车灯自检原理??

    明锐16刹车灯断丝后,仪表盘灯故障指示亮,换新灯后仪表盘灯故障指示消除。基本情况介绍:钥匙旋转至加电位置,车计算机自检,若刹车灯有故障则仪表盘灯故障指示亮;若无,则不亮。继续转至发动机启动位,汽车
    发表于 03-31 13:30

    开源硬件-基于STM32自动刹车灯设计

    开源硬件-基于STM32自动刹车灯设计...
    发表于 03-25 19:59

    【云智易申请】基于stm32自动刹车灯

    申请理由:此项目具有很大的实用性,而且节能环保,应用范围广。另外,本人从事高校教学工作数年,期间不间断承接企业项目,具有较丰富的开发经验。项目描述:自动刹车灯由电池供电并内置加速度传感器,因此无需
    发表于 08-05 08:01

    基于STM32自动刹车灯设计

    自动刹车灯是一个小巧的电路板,在刹车减速时自动亮起。可以将其安装在自行车上,用于警示其他车辆和行人。自动
    发表于 08-29 11:51

    8.31【Elecfans社区好资料】想要学好STM32,必须弄懂这八个经典项目设计

    基于STM32自动刹车灯设计https://bbs.elecfans.com/jishu_1639073_1_1.html5.基于STM32示波器DDS信号发生器https
    发表于 08-31 14:32

    中央高位刹车灯CHMSL的散热性怎么考虑?

    CHMSL代表中央高位刹车灯,安装在车辆左侧和右侧制动车灯(也称为刹车灯)的上方。根据美国国家高速公路交通安全管理局的规定,当刹车系统工作时,CHMSL要向后方司机提供明显确切的信息,
    发表于 08-13 07:05

    智能车大作战,各类智能车开源资料,你更偏爱哪一款?

    `1、开源硬件-基于STM32自动刹车灯设计自动刹车灯是一个小巧的电路板,在刹车减速时
    发表于 10-23 15:20

    汽车刹车灯监视电路分析

    为克服以上缺点,笔者制作了一个电路(原理图见图1所示),巧妙地借用了原车仪表内的刹车灯/手刹报警灯作为附加电路的报警显示,且仅用1根线接至手刹开关上,就能完成对刹车灯的监控,并指示出可能出现的四种状态。
    发表于 04-26 07:06

    闪光式刹车灯电路

    闪光式刹车灯电路
    发表于 09-09 11:01 1421次阅读
    闪光式<b class='flag-5'>刹车灯</b>电路

    摩托车刹车灯延时熄灯电路

    摩托车刹车灯延时熄灯电路
    发表于 01-24 17:21 13次下载

    STM32经典项目设计实例分享

    学习参考意义的设计实例。尤其对于新手,是一个学习stm32单片机的活生生的范例。 1.开源硬件-基于STM32自动刹车灯设计 自动
    发表于 10-16 10:39 66次下载

    闪光刹车灯电路图

     刹车灯,一般安装在车辆尾部,主体颜色为红色的灯,以便后面行驶的车辆易于发现前方车辆刹车,起到防止追尾事故发生的目的。简单的车型就是电源通过保险,然后到刹车开关,踩下制动踏板进行刹车
    的头像 发表于 07-19 10:08 9761次阅读
    闪光<b class='flag-5'>刹车灯</b>电路图

    中央高位刹车灯——第三刹车灯

    中央高位刹车灯——第三刹车灯
    发表于 11-01 08:26 5次下载
    中央高位<b class='flag-5'>刹车灯</b>——第三<b class='flag-5'>刹车灯</b>

    汽车刹车灯故障报警装置介绍

    现有汽车刹车灯的控制电源为12蓄电池(汽油发动机),踩下刹车踏板时,电流从蓄电池正极流出,经过保险丝及刹车灯开关的闭合触点到达并联的2个刹车灯炮中,然后经过车身搭铁回到蓄电池负极。
    的头像 发表于 01-14 11:29 2928次阅读