基于Arduino开发板的简易智能车项目介绍及源码
源码出处:😀
浙江师范大学第九届智能车校赛 啊对对队的比赛源码(菜的一笔,仅供思路参考)
说在前面:😝
这次的比赛还是有些遗憾的,只是跑完了全程,并没有取得太好的成绩,仅拿到了三等奖,确实也是因为自己太忙,没有把很多精力放在这个比赛上,然后还有一个不可控因素是我们车子的性能确实差。
在这里感谢啊对对队的队长梁驿能邀请我参加这个比赛,并且也在这个比赛中投入了很多激情;还要感谢队伍的另一名队员王晴雨,对这个比赛投入了很高的热情和很多的时间,并且也是一直在感染我,让我有继续做下去的动力。在这个比赛中我学到了很多的硬件的知识,也收获了很多东西。这次的智能车校赛是我在大学里参加的第一个比赛,我会一直记得我们曾在实验室奋斗的时光,这也会成为我人生中一段宝贵的经历。
主要技术点:🧠
车辆硬件的组装、OLED屏幕显示框架的使用,PID控制算法的简单实现(不考虑积分作用,不考虑积分限幅等作用),Arduino板数据存储函数库的使用,自研速度控制的代码(很菜,但很稳)
整体代码:🤑
/*
满电状态的代码
kp = 265
kd = 15
*/
#include <stdio.h>
#include <math.h>
#include <EEPROM.h>
//OLED使用头文件
#include<U8glib.h>
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI
const int led_Pin = 13; //LED控制引脚
const int left_Forward_PWM_Pin = 10; //左电机正转控制引脚
const int left_Backward_PWM_Pin = 5; //左电机反转控制引脚
const int right_Forward_PWM_Pin = 6; //右电机正转控制引脚
const int right_Backward_PWM_Pin = 9; //右电机反转控制电路
const int AD_Left_Pin = A0; //左电磁传感器AD引脚
const int AD_Right_Pin = A1; //右电磁传感器AD引脚
const int button_W_pin = 2; //方向↑键
const int button_S_pin = 4; //方向↓键
const int button_A_pin = 7; //方向←键
const int button_D_pin = 8; //方向→键
const int button_C_pin = 12; //中心键
//初始化
void setup() {
//---------初始化LED引脚-------------------
pinMode(led_Pin, OUTPUT);
//---------初始化电机引脚(默认直行)----------
analogWrite(left_Forward_PWM_Pin, 175);
analogWrite(left_Backward_PWM_Pin, 0);
analogWrite(right_Forward_PWM_Pin, 245);
analogWrite(right_Backward_PWM_Pin, 0);
//---------初始化传感器引脚------------------
pinMode(AD_Left_Pin, INPUT);
pinMode(AD_Right_Pin, INPUT);
//---------初始化按钮对应引脚----------------
pinMode(button_W_pin, INPUT_PULLUP);
pinMode(button_S_pin, INPUT_PULLUP);
pinMode(button_A_pin, INPUT_PULLUP);
pinMode(button_D_pin, INPUT_PULLUP);
pinMode(button_C_pin, INPUT_PULLUP);
}
//清除数据(只有前10位要用)
void ClearMsg()
{
for(int i=0;i<10;i++)
EEPROM.write(i,0);
}
//存入数据
void WriteMsg(int K,bool flag)
{
int i = 0; //flag == true 就是存储Kp,从第一个位置开始
if(flag == false) //否则就是存储Kd,从第六个位置开始
i = 5;
while(K > 255)
{
EEPROM.write(i,255);
K -= 255;
i++;
}
EEPROM.write(i,K);
}
//读取数据
int ReadMsg(bool flag)
{
int sum = 0;
int i = 0;
if(flag == false)
i = 5;
for(int j=0;j<5;j++)
sum += EEPROM.read(i++);
return sum;
}
//以下系数为定值,在具体实验中进行调整,切记从小到大进行调整
//以下定义为全局变量
int Kp = ReadMsg(true);//比例系数
int Kd = ReadMsg(false);//微分系数
float Error = 0;//误差
int Last_Error = 0;//上一次误差
int E_Left; //左边电感产生的电压
int E_Right; //右边电感产生的电压
int PID = 0;
int menu = 1;
unsigned long Now_Time = millis();
unsigned long nowTime = millis();
//bool isStraight = true; 思考了一下,isStraight 好像是不需要的, nowTime 已经做到了控制
void return_PID()
{
Error = (sqrt(E_Left) - sqrt(E_Right)) / (E_Left + E_Right);
PID = Kp * Error + Kd * (Error - Last_Error);
Last_Error = Error;
PID = PID * 2;
}
void loop() {
//电感定义
E_Left = analogRead(AD_Left_Pin);
E_Right = analogRead(AD_Right_Pin);
//按键
int buttonStateW = digitalRead(button_W_pin);
int buttonStateS = digitalRead(button_S_pin);
int buttonStateA = digitalRead(button_A_pin);
int buttonStateD = digitalRead(button_D_pin);
int buttonStateC = digitalRead(button_C_pin);
//按键的控制
/*menu=0 调节kp;menu=1 调节kd;menu=2
在这里我们利用W S即上下键来控制menu的加减
我们利用A D 来控制系数的加减
*/
if (buttonStateW == LOW) {
delay(300);
if (buttonStateW == LOW)
menu++;
}
if (buttonStateS == LOW) {
delay(300);
if (buttonStateS == LOW)
menu--;
}
if(menu > 2)
menu = 1;
else if(menu < 1)
menu = 2;
//控制kp
if (menu == 1) {
if (buttonStateA == LOW) {
delay(50);
if (buttonStateA == LOW)
Kp--;
}
if (buttonStateD == LOW) {
delay(50);
if (buttonStateD == LOW) {
Kp++;
}
}
}
//控制Kd
if (menu == 2) {
if (buttonStateA == LOW) {
delay(50);
if (buttonStateA == LOW)
Kd--;
}
if (buttonStateD == LOW) {
delay(50);
if (buttonStateD == LOW) {
Kd++;
}
}
}
if(buttonStateC == LOW)
{
delay(200);
if(buttonStateC == LOW)
{
ClearMsg();
WriteMsg(Kp,true);
WriteMsg(Kd,false);
u8g.firstPage();
do{
u8g.setFont(u8g_font_6x10);
u8g.drawStr(5, 30, "Save successfully!");
u8g.drawStr(5,40,"A duiduidui yyds!");
}while(u8g.nextPage());
delay(2000);
}
}
//OLED进行显示
u8g.firstPage();
do {
u8g.setFont(u8g_font_6x10);
//前两行显示电感的值如何实现
//左电感
u8g.drawStr(0, 10, " L=");
u8g.setPrintPos(20, 10);
u8g.print(E_Left);
//右电感
u8g.drawStr(40, 10, "R=");
u8g.setPrintPos(55, 10);
u8g.print(E_Right);
//PID
u8g.drawStr(80,10,"PID=");
u8g.setPrintPos(105,10);
u8g.print(PID);
u8g.drawStr(0,20," -------------");
//menu
u8g.drawStr(0, 30, " |menu =");
u8g.setPrintPos(70, 30);
u8g.print(menu);
//打印Kp的值
u8g.drawStr(0, 40, " |Kp =");
u8g.setPrintPos(70, 40);
u8g.print(Kp);
//打印Kd的值
u8g.drawStr(0, 50, " |Kd =");
u8g.setPrintPos(70, 50);
u8g.print(Kd);
u8g.drawStr(0,60," -------------");
u8g.drawStr(95,30,"|");
u8g.drawStr(95,40,"|");
u8g.drawStr(95,50,"|");
} while ( u8g.nextPage() );
//每 50ms 进行一次检测
if (millis() - Now_Time > 50)
{
E_Left = analogRead(AD_Left_Pin);
E_Right = analogRead(AD_Right_Pin);
return_PID();
//下述代码如果不太行,两个解决办法:
//1、减去除最大速度外最大的两段速度(或者再加两段)
//2、提高最小的电压差检测
if(fabs(E_Left - E_Right) > 750)//750
{
//满电状态left再减5 现属于测试
analogWrite(right_Forward_PWM_Pin, 77 + PID * 1.15);
analogWrite(left_Forward_PWM_Pin, 55 - PID);
nowTime = millis();
}
else if(fabs(E_Left - E_Right) > 550)//550
{
analogWrite(right_Forward_PWM_Pin, 91 + PID * 1.15);
analogWrite(left_Forward_PWM_Pin, 65 - PID);
nowTime = millis();
}
else if(fabs(E_Left - E_Right) > 350)//350
{
analogWrite(right_Forward_PWM_Pin, 119 + PID * 1.15);
analogWrite(left_Forward_PWM_Pin, 85 - PID);
nowTime = millis();
}
else if(fabs(E_Left - E_Right) > 200)//200
{
analogWrite(right_Forward_PWM_Pin, 147 + PID * 1.15);
analogWrite(left_Forward_PWM_Pin, 105 - PID);
nowTime = millis();
}
else
{
if(millis() - nowTime < 1000)//250应该还需要更改
{
analogWrite(right_Forward_PWM_Pin, 175 + PID * 1.15);
analogWrite(left_Forward_PWM_Pin, 125 - PID);
}
else
{
//细心的人应该已经发现了,我们的左右电机的电位是不一样的,这就是我说的我们的车子性能太差了,左右轮极度不对称。
analogWrite(right_Forward_PWM_Pin, 245 + PID * 1.15);
analogWrite(left_Forward_PWM_Pin, 175 - PID);
}
}
Now_Time = millis();
}
}
车辆图片:💯(拍摄手法拙劣)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!