小车跟随行驶系统(基于MSP-EXP430F5529LP系统板)

news/2025/2/22 23:00:37/

选用材料:主控板MSP-EXP430F5529LP、陀螺仪、直流减速电机(可以选用光电编码器,霍尔电机不好调节PID)、TB6612电机驱动、超声波测距模块、灰度传感器、无线透传/蓝牙模块(便于两辆小车相互发送信息)、OLED屏等。

总体思路:使用灰度传感器巡线,超声波检测前后车距,通过调节PID的位置环,控制两辆小车前后的距离,运用JY901进行陀螺仪矫正。

2022TI_C1_JY901.c

#include "2022TI_C1_JY901.h"struct SAngle Mpu_angle;//串口0初始化
void Usart0Init(void)
{GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3, GPIO_PIN4);GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3, GPIO_PIN3);//Baudrate = 115200, clock freq = 25MHz//在线计算器//https://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.htmlUSCI_A_UART_initParam param = {0};param.selectClockSource = USCI_A_UART_CLOCKSOURCE_SMCLK;param.clockPrescalar = 13;param.firstModReg = 9;param.secondModReg = 0;param.parity = USCI_A_UART_NO_PARITY;param.msborLsbFirst = USCI_A_UART_LSB_FIRST;param.numberofStopBits = USCI_A_UART_ONE_STOP_BIT;param.uartMode = USCI_A_UART_MODE;param.overSampling = USCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION;if (STATUS_FAIL == USCI_A_UART_init(USCI_A0_BASE, &param)){return;}//Enable UART module for operationUSCI_A_UART_enable(USCI_A0_BASE);//Enable Receive InterruptUSCI_A_UART_clearInterrupt(USCI_A0_BASE,USCI_A_UART_RECEIVE_INTERRUPT);USCI_A_UART_enableInterrupt(USCI_A0_BASE,USCI_A_UART_RECEIVE_INTERRUPT);
}#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A0_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(USCI_A0_VECTOR)))
#endif
void USCI_A0_ISR (void)
{
//    uint8_t receivedData = 0;switch (__even_in_range(UCA0IV,4)){//Vector 2 - RXIFGcase 2:CopeSerial2Data(USCI_A0_BASE);
//            receivedData = USCI_A_UART_receiveData(USCI_A0_BASE);break;default: break;}
}//发送N个字节长度的数据
void USART0_Send(uint8_t *pui8Buffer, uint32_t ui32Count)
{while(ui32Count--){USCI_A_UART_transmitData(USCI_A0_BASE, *pui8Buffer++);}
}void CopeSerial2Data(uint16_t baseAddress)
{static unsigned char ucRxBuffer[250];static unsigned char ucRxCnt = 0;unsigned char i,sum;ucRxBuffer[ucRxCnt++]=USCI_A_UART_receiveData(baseAddress);;   //将收到的数据存入缓冲区中if (ucRxBuffer[0]!=0x55) //数据头不对,则重新开始寻找0x55数据头{ucRxCnt=0;return;}if (ucRxCnt<11) {return;}//数据不满11个,则返回else{switch(ucRxBuffer[1])//三轴角度{case 0x53:memcpy(&Mpu_angle,&ucRxBuffer[2],8);for(i=0; i<10; i++)sum += ucRxBuffer[i];if(sum == ucRxBuffer[10]){Mpu_angle.angle_z=  (float)Mpu_angle.Angle[2]/32768*180;//ZMpu_angle.angle_y = (float)Mpu_angle.Angle[0]/32768*180;//YMpu_angle.angle_x = (float)Mpu_angle.Angle[1]/32768*180;//X}
//                memcpy(&Mpu_angle,&ucRxBuffer[2],8);
//                Mpu_angle.angle_z=  (float)Mpu_angle.Angle[2]/32768*180;//Z
//                Mpu_angle.angle_y = (float)Mpu_angle.Angle[0]/32768*180;//Y
//                Mpu_angle.angle_x = (float)Mpu_angle.Angle[1]/32768*180;//Xbreak;default:break;}ucRxCnt=0;//清空缓存区}
}

2022TI_C1_JY901.h

#ifndef __2022TI_C1_JY901_H_
#define __2022TI_C1_JY901_H_#include <includes.h>struct SAngle
{short Angle[3];short T;float angle_x;float angle_y;float angle_z;
};extern struct SAngle Mpu_angle;//串口0初始化
void Usart0Init(void);
void USART0_Send(uint8_t *pui8Buffer, uint32_t ui32Count);void CopeSerial2Data(uint16_t baseAddress);#endif /* JY901_H_ */

2022TI_C1_SR04.c

#include "2022TI_C1_SR04.h"float sr04_dist = 0.0;
uint32_t Sign_Counts = 0;//脉冲宽度(高) us//启动测量
void SR04_Start(void)
{GPIO_setOutputHighOnPin(GPIO_PORT_P7, GPIO_PIN4);delay_us(50);GPIO_setOutputLowOnPin(GPIO_PORT_P7, GPIO_PIN4);
}//SR04 trig p7.4
//SR04 echo p2.5
void Timer_A2_Capture_Init(void)
{Timer_A_initContinuousModeParam htim = {0};htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1;htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE;htim.timerClear = TIMER_A_DO_CLEAR;htim.startTimer = true;Timer_A_initContinuousMode(TIMER_A2_BASE, &htim);GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN5);Timer_A_initCaptureModeParam capture_htim = {0};capture_htim.captureRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2;capture_htim.captureMode = TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE;capture_htim.captureInputSelect = TIMER_A_CAPTURE_INPUTSELECT_CCIxA;capture_htim.synchronizeCaptureSource = TIMER_A_CAPTURE_SYNCHRONOUS;capture_htim.captureInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE;capture_htim.captureOutputMode = TIMER_A_OUTPUTMODE_OUTBITVALUE;Timer_A_initCaptureMode(TIMER_A2_BASE,&capture_htim);GPIO_setAsOutputPin(GPIO_PORT_P7, GPIO_PIN4);GPIO_setOutputLowOnPin(GPIO_PORT_P7, GPIO_PIN4);GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN5);
}#pragma vector=TIMER2_A1_VECTOR
__interrupt
void TIMER2_A1_ISR (void)
{static uint16_t Overflow_Times = 0;static uint16_t Sign_Begin = 0, Sign_End = 0;switch(TA2IV){case TA2IV_TACCR2:if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)){Sign_Begin = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);}else{Sign_End = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);if(!Overflow_Times)Sign_Counts = Sign_End - Sign_Begin;else{Sign_Counts = (uint32_t)65536 * Overflow_Times + Sign_End - Sign_Begin;Overflow_Times = 0;}//25MHZ//计数周期 1/25 us 340M/Ssr04_dist = 0.04 *0.34 * Sign_Counts / 2.0;//mm}Timer_A_clearCaptureCompareInterrupt(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);break;case TA2IV_TAIFG:if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)){++Overflow_Times;}elseOverflow_Times = 0;Timer_A_clearTimerInterrupt(TIMER_A2_BASE);break;default:break;}
}

2022TI_C1_SR04.h

#ifndef __2022TI_C1_SR04__H
#define __2022TI_C1_SR04__H#include <includes.h>extern float sr04_dist;
extern uint32_t Sign_Counts;void SR04_Start(void);void Timer_A2_Capture_Init(void);#endif 

2022TI_C1_PID.c

#include "2022TI_C1_PID.h"PID M3508_spid[2];
PID ANGLE;
PID distance;
float abs_limit(float a, float ABS_MAX)
{if(a > ABS_MAX)a = ABS_MAX;if(a < -ABS_MAX)a = -ABS_MAX;return a;
}void PID_Position_Calc( PID *pp,  float  CurrentPoint,  float NextPoint )  
{   pp->Error =  NextPoint -  CurrentPoint;          pp->SumError += pp->Error;                      pp->DError = pp->Error - pp->LastError;pp->output =  pp->Proportion * pp->Error +   \abs_limit(pp->Integral * pp->SumError, pp->Integralmax ) +   \pp->Derivative * pp->DError ;  if(pp->output > pp->outputmax )  pp->output = pp->outputmax;if(pp->output < - pp->outputmax )  pp->output = -pp->outputmax;
//	pp->PrevError = pp->LastError;  pp->LastError = pp->Error;
}void PID_Incremental_Calc( PID *pp,  float  CurrentPoint,  float NextPoint )  
{  pp->Error =  NextPoint -  CurrentPoint;          pp->SumError += pp->Error;                      pp->DError = pp->Error - pp->LastError;pp->output +=  pp->Proportion * ( pp->Error - pp->LastError )+   \abs_limit(pp->Integral * pp->Error, pp->Integralmax ) +   \pp->Derivative * ( pp->Error +  pp->PrevError - 2*pp->LastError);  if(pp->output > pp->outputmax )  pp->output = pp->outputmax;if(pp->output < - pp->outputmax )  pp->output = -pp->outputmax;pp->PrevError = pp->LastError;  pp->LastError = pp->Error;
}void PIDInit(PID *pp, float Kp , float Ki , float Kd ,  float outputmax, float Integralmax)  
{  pp->Integralmax = Integralmax;pp->outputmax  = outputmax;pp->Proportion = Kp;pp->Integral   = Ki;pp->Derivative = Kd;pp->DError = pp->Error = pp->output = pp->LastError = pp->PrevError = 0; 
}  

2022TI_C1_PID.h

#ifndef __2022TI_C1_PID_H
#define __2022TI_C1_PID_Htypedef struct PID {float  Proportion;         //  Proportional Const  float  Integral;           //  Integral Const  float  Derivative;         //  Derivative Const  float  PrevError;          //  Error[-2]float  LastError;          //  Error[-1]  float  Error;float  DError;float  SumError;           //  Sums of Errors  float  Integralmax;float  output;float  outputmax;
} PID;extern PID M3508_spid[2];
extern PID ANGLE;
extern PID distance;float abs_limit(float a, float ABS_MAX);
void PID_Position_Calc( PID *pp,  float  CurrentPoint,  float NextPoint);
void PID_Incremental_Calc( PID *pp,  float  CurrentPoint,  float NextPoint);
void PIDInit(PID *pp, float Kp , float Ki , float Kd ,  float outputmax, float Integralmax);#endif


http://www.ppmy.cn/news/352766.html

相关文章

汽车中控IVI及解决方案

中控IVI(In-Vehicle Infotainment )过去常称为车载信息娱乐系统,前装选配或后装加装,现在还有个智能座舱系统的名字,也有叫cluster IVI,IVI的作用可以说是越来越强大,人送新绰号:车机。想想手机,就知道车机有多强大了。它都涉及哪些功能呢? 1、音频:麦克风输入、扬声…

迅为RK3568核心板车载中控AVM一体机应用

RK3568M车载中控&AVM一体机方案搭载4核A55 CPU&#xff0c;G52-2EE GPU架构&#xff0c;1Tops算力NPU&#xff0c;支持1路4K 60fps或8路1080P 30fps的多格式解码和高达1080P 100fps的H.265编码&#xff0c;具备双千兆GMAC、三路CAN以及USB3.0/SATA3.0/PCIE3.0等丰富接口&am…

汽车中控芯片开发板入门及开发进阶

后续将会在中控开发板上研究一些具体应用,现罗列如下: 中控屏显示摄像头视频:这个应用也是很平常的,将涉及不同格式的视频解码和大屏显示。利用蓝牙模块实现中控屏的手机投屏功能:很多车机靠这个应用增加用户粘性,比如鸿蒙车机投屏效果就不错,如手机互连:HiCar、CarPla…

xt6使用技巧_凯迪拉克XT6中控屏幕功能使用操作图解

2020款昂克赛拉在外部配置上&#xff0c;全系标配远近光一体式LED大灯、LED尾灯、双边共两出式排气。而1.5L和2.0L车型不同之处在于前格栅配色&#xff0c;同时轮圈规格分别为16英寸和18英寸。此外&#xff0c;中高配车型将提供电动天窗、外后视镜电折叠/记忆、自动雨刷、自动大…

SimFAS(深克斯)中控编程入门培训教程笔记

近日学习了 SimFAS中控系统的编程培训&#xff0c;总体来说很简单&#xff0c;现在把PPT简单记录一下&#xff1a; 总体概况&#xff1a;完成整个完完成整个项目实施&#xff0c; 简单&#xff1a;涉及到编程的地方&#xff0c;都是 输入中文关键字&#xff0c;然后出来参数让…

「大屏」上车跑出加速度,哪些供应商在「领跑」娱乐中控

全景大屏、8155、座舱域控制器、游戏引擎HMI设计、沉浸式交互体验&#xff0c;这些越来越多出现在新车上的软硬件功能配置&#xff0c;正在让座舱零部件供应商享受到前所未有的市场红利。 这其中&#xff0c;备受争议的大屏、多屏配置&#xff0c;还在加速推进。 高工智能汽车…

中控服务器总结

经过了2个月的开发&#xff0c;中控基本可以运行。 1、安卓可下发数据 2、客户端C#可以运行播放视频、音频 3、服务器可以转发数据到客户端、并可控制电源、电路的开、关 4、采用的设备有8口网络电源中继器、2路网络串口服务器。 串口服务器的配置主要是在主服务器运行&#xf…

HTML <embed> 标签

定义和用法 <embed> 标签定义嵌入的内容&#xff0c;比如插件。 实例 <embed src"helloworld.swf" />浏览器支持 元素ChromeIEFirefoxSafariOpera<embed>YesYesYesYesYes 所有主流浏览器都支持 <embed> 标签。 HTML 4.01 与 HTML 5 之…