今日播报!基于STM32设计的自动刹车灯
随着科技的发展,人们对低碳环保的认知和需求不断提高。骑自行车既能够低碳环保,又能够锻炼身体,成为了很多人出行的首选。然而,由于自行车本身没有带指示灯,比如刹车指示灯等,所以自行车的安全性并不是很好,如果人们在骑自行车时紧急刹车,后车无法及时判断前方自行车的行为,容易造成交通事故。因此,设计一款自动刹车灯系统具有十分重要的意义。
本项目实现了通过安装ADXL345陀螺仪和四枚LED灯还有STM32F103C8T6主控芯片来实现自行车自动刹车灯的功能。当自行车上安装了该设备后,ADXL345通过IIC通信协议将X,Y,Z三轴的加速度实时值发送给SMT32F103C8T6主控芯片,并结合STM32高级定时器的PWM功能,输出不同占空比的脉冲,控制不同的LED灯输出多种亮度等级,从而控制不同的LED的开关以及明暗,并且通过不同亮度的红光和绿光混合,能够得到黄色的LED灯光。这样,在自行车急刹或者加速时,实时地控制LED灯的亮度和颜色,让后方车辆能够更清楚地了解前方自行车的行为,从而做出快速的反应,保障骑行者以及后车的安全。同时,该系统也能够提高自行车的可见性,并且对于追求低碳环保的人群来说,让自行车既能低碳环保,又能够锻炼身体。
二、设计思路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 功能样机安装与焊接绘制好电路原理图之后,按照原理图将自动刹车灯系统的各个模块安装在事先购买好的洞洞板上,然后用导线将他们连接在一起,最后再焊接在一起,做成完整的自动刹车灯电路板。
3.2 ADXL345模块调试当上电后,将自动刹车灯电路的串口2外设引脚连接至PC端,将加速度解算后的实际值发送至PC端,通过PC端串口调试助手显示出具体数值,再观察数值是否符合常理。
通过显示的数据信息,可以推测出ADXL345陀螺仪能够正常工作。
3.3 实物调试最后阶段,将对自行车自动刹车灯进行实物调试,确定其基本功能能够正常实现。
当系统上电后,左右各一枚LED发出低亮黄色灯光,如下图。
静置30S后,所有LED均熄灭,如下图。
当检测到震动后,重新亮起两盏黄色LED灯,如下图。
当检测到刹车时,四枚LED灯均以高亮发出红色灯光,如下图。
结合自行车自动刹车灯的功能需求和实物调试结果,可以发现,调试结果完全符合自动刹车灯的预期功能。
四、代码设计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\\r\\n",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; }
审核编辑 黄宇
关键词:
下一篇:最后一页
- 国家移民管理局暂停签发韩国、日本公民来华口岸签证及72/144小时过境免签-环球滚动
- 港股异动 | 药明生物(02269)升7% 近三月北水增仓超5个百分点 机构料全年业绩持续高增
- 当前快报:美国小企业乐观度降至近十年来倒数第二
- 英文爱情的句子唯美句子大全(精选259句)
- 粤港澳大湾区中小企业报告:逾6成中小企业预期2023年将投放可观资金于大湾区_天天热文
- 山西泽州警方摧毁省级目标贩毒网络 17名毒贩累计贩毒超30公斤 今日热门
- 安逸花网贷8万逾期还不起我会不会被起诉 全球快播
- 有意思小周刊(2023.01.09):一文详解|影响成长的关键思考_世界消息
- 当前要闻:电子车牌板块1月9日跌0.11%,易华录领跌,主力资金净流出6738.9万元
- 省呗网贷逾期14年多久会上征信
-
今日观点!僵尸列车狂奔什么时候出 公测上线时间预告
导读:最近很多玩家都在关注僵尸列车狂奔这款手游,想知道具体的公测时
-
如果没有你这首歌是谁唱的_如果没有你 姚贝娜演唱歌曲
《如果没有你》是歌手姚贝娜演唱的歌曲,所属专辑《天生骄傲》发行于20
-
“过客”变“常客” 50余种候鸟落户科尔沁国家级自然保护区
国家一级保护鸟类丹顶鹤在湿地中觅食。 梁永峰 摄国家二级保护鸟类黑
-
全球今热点:以特斯拉为“母版”,小鹏G6预售22.5万,诚意不该被忽略
以特斯拉为“母版”,小鹏G6预售22 5万,诚意不该被忽略虽然新能源领域
-
河北266特派团助科技成长
“这批产品硬度要求高,我们试验了几次总不达标,您看看哪个环节有问题
-
【新华财经调查】一线调研:“点绿成金”,绿色保险如何高质量提速发展?
整体而言,绿色保险基础体系较为薄弱,目前仍然处于“摸着石头过河”的
-
瓦格纳事件后,俄国防部长绍伊古现身特别军事行动区
中新网6月26日电据塔斯社当地时间26日报道,俄罗斯国防部长绍伊古视察
-
宏达新材(002211.SZ)收到到期债务履行通知书 涉及债务4221.76万元
智通财经APP讯,宏达新材(002211)(002211 SZ)发布公告,公司收到上海市
-
公用事业行业今日净流出资金13.06亿元,桂东电力等10股净流出资金超5000万元
沪指6月27日上涨1 23%,申万所属行业中,今日上涨的有31个,涨幅居前的
-
两小学一幼儿园拟今秋投入使用!胶州李哥庄镇推进城市更新 “加码”百姓幸福感_今亮点
胶州市李哥庄镇投资近5000万元,建设航秀路、中达街等5条镇区道路,实
X 关闭
今日播报!基于STM32设计的自动刹车灯
大利好!四家房企公告再融资获批|天天速看
中金交运行业2023下半年展望:守正出奇 关注精选个股
火影忍者第622话 火影忍者第639话袭击_环球速看
山东山西的山是指哪一座山_山东山西的山是指
X 关闭
得知西安疫情防控“升级” 男子夜骑共享单车回咸阳淳化
中国医生将任SIU主席背后:从追随者同行者到引领者
海南省通报政法队伍教育整顿成果
云南两地发现核酸阳性人员 西安实行最严格的社会面管控
广东梅州大埔中央红色交通线沿线发现多株百岁古树