
目录绪论 11.1 研究意义及背景 11.2 本文主要研究内容及任务 1系统概述 22.1 控制系统要求分析 22.2 平衡小车控制原理分析 22.3 自平衡小车PID控制器分析 42.3.1 PID控制原理 42.3.2 PID控制器设计 4系统硬件电路设计 53.1 硬件电路整体框架 53.2 电源供电部分 53.3 STM32F103C8T6最小系统 73.3.1 复位电路 83.3.2 Boot选择部分 83.3.3晶振部分 93.3.4 指示灯部分 93.3.5 st-link下载部分 93.4 九轴姿态角度传感器部分 103.4.1 九轴姿态角度传感器基本介绍 103.4.2 九轴姿态角度传感器性能 103.4.3 实物图 103.4.4 引脚说明 113.4.5 通信方式 113.5 电机驱动编码器部分 123.5.1电机编码器基本介绍 123.5.2 电机实物图 123.5.3 电机编码器引脚说明 123.5.4 电机驱动A4950 133.6 巡线避障部分 143.6.1 传感器介绍 143.7 蓝牙通信部份 15软件设计部分 164.1 操作系统RTOS(RtThread) 164.1.1简介RtThread 164.1.2 系统任务的划分 174.2 电机驱动 184.2.1 流程图 184.2.2 主要API函数 184.3 九轴姿态角度传感器数据读取 194.3.1 数据格式 194.3.2 程序流程 204.4 编码器数据读取 224.4.1 数据格式 224.4.2 程序流程 224.5 直立PID功能实现 234.5.1 控制策略 234.5.2 流程图 234.5.3 直立环 244.5.4 速度环 254.5.5 转向环 264.6 蓝牙遥控部分 264.6.1 数据协议 264.7 循迹避障部分 274.7.1 主要API解析 27系统PID调试部分 285.1 直立环 295.2 速度环 305.3 转向环 305.4 角度锁死 31总结 31参考文献 32致谢 32附录 33附录一 主要代码 33附录二 原理图 40附录三 实物图 41设计一款两轮自平衡小车通过对陀螺仪的数据的读取处理从而识别出车身姿态根据车身姿态计算PID通过对小车进行实时的PID控制使得小车可以按照要求实现自主平衡根据遥控可以实现平稳前进后退根据灰度传感器数据可以实现循迹和避障。具体内容分为以下几个部分1.平衡小车机械设计部分主要是机械重心调整电气设计部分。2.信号处理部分九轴陀螺仪数据的读取和处理灰度传感器的读取和处理电机编码器的数据读取和处理。3.控制算法PID根据输入的信息完成直立环速度环转向环的计算控制。4.遥控传输部分采用蓝牙无线模块接收手机的遥控数据。2.系统概述2.1 控制系统要求分析要使小车在干扰的情况下实现自平衡自恢复干扰并且能够在遥控下实现前进后退左转右转功能。结合系统分析可知自平衡小车需要维持原地不倒和运动运动的动力来自自平衡车的两轮两轮由两个直流电机驱动。因此自平衡小车可以作为被控制对象自平衡小车的两轮可以作为控制系统的控制量。整个系统划分为三个部分1.自平衡小车的站立控制直立环以小车的倾斜角度和角速度作为输入参数通过计算直立环的PD控制器得到电机的输出大小控制电机的速度来保持小车的自平衡。2.自平衡小车的速度控制速度环在站立环的基础上通过改变自平衡小车电机的编码器数值来调整车体的实际运动速度。通过计算PI通过调整电机的运行速度改变小车的实际运行速度。当速度环的速度设置为的时候小车可以实现在原地保持不动当人为干扰推动小车小车可以自动回到原地。设置为某一数值的时候可以实现前进后退。3.自平衡小车转向调整转向环通过调整自平衡小车两轮的速度利用差速转弯采用P控制器。可以实现左右转弯。#includemain.hu16 imuCorrectCount0,imuErrorCount0,readEncodeCount0,sendDataCount0,controlMotorCount0;//记录hz数 s32 leftEncoder0,rightEncoder0;/* 线 程readEncode 作 用读取左右电机编码器脉冲数 频 率100Hz */void readEncode(void* parameter){while(1){readEncodeCount;leftEncoder Read_Encoder(2);rightEncoder - Read_Encoder(4);rt_thread_delay(1);rt_timer_check();}}/* 线 程sendData 作 用使用printf通过串口3打印数据也可使用rt_kprintf,通过串口1打印数据 频 率10Hz */void sendData(void* parameter){//printf(d %.2f\r\n\r\n,m[2]);// rt_thread_delay(1000);//do something // rt_timer_check();}/* 线 程controlMotor 作 用控制电机 频 率1000Hz 日 期2019年1月26日 作 者meetwit */void controlMotor(void* parameter){float temp1,temp2,temp3;float get_angle,get_gyro;temp1 32768/180.0;//角度 temp2 32768/2000.0;//角速度 temp3 32768/16.0;//角加速度 int finalPwm 0,finalPwm2 0;u8 time0;while(1){time;controlMotorCount;finalPwm 0;get_angle stcAngle.Angle[0]/temp1;get_gyro stcGyro.w[0]/temp2;if(get_angle40||get_angle-40){//角度过大锁住 motor_run(0,0);stop_flag 1;}if(stop_flag){if(get_angle-5get_angle5){//角度适合解锁 rt_thread_delay(RT_TICK_PER_SECOND*2);//扶正后等待x秒 stop_flag 0;//解锁}velocity_mw();//执行一次清除积分 motor_run(0,0);}else{//10和300 进行PID控制 finalPwm balance_mw(get_angle,get_gyro);finalPwm velocity_mw();finalPwm2 finalPwmFlag_turn;if(finalPwm20){motor_run(3,finalPwm2);}else{motor_run(4,-finalPwm2);}if(finalPwm0){motor_run(2,finalPwm);}else{motor_run(1,-finalPwm);}if(time%200){Flag_v 0;Flag_turn 0;}}rt_thread_delay(5);rt_timer_check();}}void timer1_f(void* parameter){Rx_Tm3--;if(Rx_Tm31)Task_Pc3();}/* 线 程time_thread 作 用通过串口1打印系统时间 频 率1Hz 日 期2019年1月26日 作 者meetwit */void time_thread(void* parameter){rt_tick_t tick_temp;rt_uint8_t h0,m0,s0;while(1){tick_temp rt_tick_get();stick_temp/RT_TICK_PER_SECOND%60;mtick_temp/RT_TICK_PER_SECOND/60%60;htick_temp/RT_TICK_PER_SECOND/60/60%24;rt_kprintf(\r\nThe system runtime is %d:%d:%d.%d\r\n,h,m,s,tick_temp%RT_TICK_PER_SECOND);rt_kprintf(imuCorrectCount%d,imuErrorCount%d,readEncodeCount%d,sendDataCount%d,controlMotorCount%d\r\n,imuCorrectCount/3,imuErrorCount,readEncodeCount,sendDataCount,controlMotorCount);imuCorrectCount0;imuErrorCount0;readEncodeCount0;sendDataCount0;controlMotorCount0;rt_thread_delay(RT_TICK_PER_SECOND);}}