|
采用arduino單片機(jī),MPU6050模塊,L298n電機(jī)驅(qū)動(dòng)模塊,HC06藍(lán)牙模塊進(jìn)行參數(shù)調(diào)節(jié),
一個(gè)KEY鍵連IO3,用于保存當(dāng)前參數(shù)與讀取參數(shù)。
代碼下載后可直接使用,可根據(jù)你機(jī)器工況調(diào)整PID即可。
blanCar.jpg (22.58 KB, 下載次數(shù): 73)
下載附件
2019-12-21 23:17 上傳
單片機(jī)源程序如下:
- /****************************************************************************
- Minibalance For Arduino
- ****************************************************************************/
- #include <DATASCOPE.h> //這是PC端上位機(jī)的庫(kù)文件
- #include <PinChangeInt.h> //外部中斷
- #include <MsTimer2.h> //定時(shí)中斷
- #include <KalmanFilter.h> //卡爾曼濾波
- #include "I2Cdev.h"
- #include "MPU6050_6Axis_MotionApps20.h"//MPU6050庫(kù)文件
- #include "Wire.h"
- #include <EEPROM.h>
- MPU6050 Mpu6050; //實(shí)例化一個(gè) MPU6050 對(duì)象,對(duì)象名稱為 Mpu6050
- DATASCOPE data;//實(shí)例化一個(gè) 上位機(jī) 對(duì)象,對(duì)象名稱為 data
- KalmanFilter KalFilter;//實(shí)例化一個(gè)卡爾曼濾波器對(duì)象,對(duì)象名稱為 KalFilter
- int16_t ax, ay, az, gx, gy, gz; //MPU6050的三軸加速度和三軸陀螺儀數(shù)據(jù)
- #define KEY 3 //按鍵引腳
- #define IN1 11 //TB6612FNG驅(qū)動(dòng)模塊控制信號(hào) 共6個(gè)
- #define IN2 12
- #define IN3 7
- #define IN4 6
- #define PWMA 10
- #define PWMB 9
- #define ENCODER_L 2 //編碼器采集引腳 每路2個(gè) 共4個(gè)
- #define DIRECTION_L 5
- #define ENCODER_R 4
- #define DIRECTION_R 8
- #define ZHONGZHI -4.2//小車的機(jī)械中值 DIFFERENCE
- #define DIFFERENCE 2
- int Balance_Pwm, Velocity_Pwm, Turn_Pwm; //直立 速度 轉(zhuǎn)向環(huán)的PWM
- int Motor1, Motor2; //電機(jī)疊加之后的PWM
- float Battery_Voltage; //電池電壓 單位是V
- volatile long Velocity_L, Velocity_R = 0; //左右輪編碼器數(shù)據(jù)
- int Velocity_Left, Velocity_Right = 0; //左右輪速度
- int Flag_Qian, Flag_Hou, Flag_Left, Flag_Right; //遙控相關(guān)變量
- int Angle, Show_Data,PID_Send; //用于顯示的角度和臨時(shí)變量
- unsigned char Flag_Stop = 1,Send_Count,Flash_Send; //停止標(biāo)志位和上位機(jī)相關(guān)變量
- float Balance_Kp=15,Balance_Kd=0.4,Velocity_Kp=2,Velocity_Ki=0.01;
- //***************下面是卡爾曼濾波相關(guān)變量***************//
- float K1 = 0.05; // 對(duì)加速度計(jì)取值的權(quán)重
- float Q_angle = 0.001, Q_gyro = 0.005;
- float R_angle = 0.5 , C_0 = 1;
- float dt = 0.005; //注意:dt的取值為濾波器采樣時(shí)間 5ms
- int addr = 0;
- /**************************************************************************
- 函數(shù)功能:檢測(cè)小車是否被拿起
- 入口參數(shù):Z軸加速度 平衡傾角 左輪編碼器 右輪編碼器
- 返回 值:0:無(wú)事件 1:小車被拿起
- **************************************************************************/
- int Pick_Up(float Acceleration, float Angle, int encoder_left, int encoder_right){
- static unsigned int flag, count0, count1, count2;
- if (flag == 0) //第一步
- {
- if (abs(encoder_left) + abs(encoder_right) < 15) count0++; //條件1,小車接近靜止
- else count0 = 0;
- if (count0 > 10) flag = 1, count0 = 0;
- }
- if (flag == 1) //進(jìn)入第二步
- {
- if (++count1 > 400) count1 = 0, flag = 0; //超時(shí)不再等待2000ms
- if (Acceleration > 27000 && (Angle > (-14 + ZHONGZHI)) && (Angle < (14 + ZHONGZHI))) flag = 2; //條件2,小車是在0度附近被拿起
- }
- if (flag == 2) //第三步
- {
- if (++count2 > 200) count2 = 0, flag = 0; //超時(shí)不再等待1000ms
- if (abs(encoder_left + encoder_right) > 300) //條件3,小車的輪胎因?yàn)檎答佭_(dá)到最大的轉(zhuǎn)速
- {
- flag = 0; return 1;
- }
- }
- return 0;
- }
- /**************************************************************************
- 函數(shù)功能:檢測(cè)小車是否被放下 作者:平衡小車之家
- 入口參數(shù): 平衡傾角 左輪編碼器 右輪編碼器
- 返回 值:0:無(wú)事件 1:小車放置并啟動(dòng)
- **************************************************************************/
- int Put_Down(float Angle, int encoder_left, int encoder_right){
- static u16 flag, count;
- if (Flag_Stop == 0) return 0; //防止誤檢
- if (flag == 0)
- {
- if (Angle > (-10 + ZHONGZHI) && Angle < (10 + ZHONGZHI) && encoder_left == 0 && encoder_right == 0) flag = 1; //條件1,小車是在0度附近的
- }
- if (flag == 1)
- {
- if (++count > 100) count = 0, flag = 0; //超時(shí)不再等待 500ms
- if (encoder_left > 12 && encoder_right > 12 && encoder_left < 80 && encoder_right < 80) //條件2,小車的輪胎在未上電的時(shí)候被人為轉(zhuǎn)動(dòng)
- {
- flag = 0;
- flag = 0;
- return 1; //檢測(cè)到小車被放下
- }
- }
- return 0;
- }
- /**************************************************************************
- 函數(shù)功能:異常關(guān)閉電機(jī) 作者:平衡小車之家
- 入口參數(shù):傾角和電池電壓
- 返回 值:1:異常 0:正常
- **************************************************************************/
- unsigned char Turn_Off(float angle, float voltage)
- {
- unsigned char temp;
- if (angle < -40 || angle > 40 || 1 == Flag_Stop || voltage < 11.1) //電池電壓低于11.1V關(guān)閉電機(jī) //===傾角大于40度關(guān)閉電機(jī)//===Flag_Stop置1關(guān)閉電機(jī)
- {
- temp = 1;
- analogWrite(PWMA, 0); //PWM輸出為0
- analogWrite(PWMB, 0); //PWM輸出為0
- }
- else temp = 0; //不存在異常,返回0
- return temp;
- }
- /**************************************************************************
- 函數(shù)功能:虛擬示波器往上位機(jī)發(fā)送數(shù)據(jù) 作者:平衡小車之家
- 入口參數(shù):無(wú)
- 返回 值:無(wú)
- **************************************************************************/
- void DataScope(void)
- {
- int i;
- data.DataScope_Get_Channel_Data(Angle, 1); //顯示第一個(gè)數(shù)據(jù),角度
- data.DataScope_Get_Channel_Data(Velocity_Left, 2);//顯示第二個(gè)數(shù)據(jù),左輪速度 也就是每40ms輸出的脈沖計(jì)數(shù)
- data.DataScope_Get_Channel_Data(Velocity_Right, 3);//顯示第三個(gè)數(shù)據(jù),右輪速度 也就是每40ms輸出的脈沖計(jì)數(shù)
- data.DataScope_Get_Channel_Data(Battery_Voltage, 4);//顯示第四個(gè)數(shù)據(jù),電池電壓,單位V
- Send_Count = data.DataScope_Data_Generate(4);
- for ( i = 0 ; i < Send_Count; i++)
- {
- Serial.write(DataScope_OutPut_Buffer[i]);
- }
- delay(50); //上位機(jī)必須嚴(yán)格控制發(fā)送時(shí)序
- }
- /**************************************************************************
- 函數(shù)功能:按鍵掃描 作者:平衡小車之家
- 入口參數(shù):無(wú)
- 返回 值:按鍵狀態(tài),1:?jiǎn)螕羰录?:無(wú)事件。
- **************************************************************************/
- unsigned char My_click(void){
- static unsigned char flag_key = 1; //按鍵按松開標(biāo)志
- unsigned char Key;
- Key = digitalRead(KEY); //讀取按鍵狀態(tài)
- if (flag_key && Key == 0) //如果發(fā)生單擊事件
- {
- flag_key = 0;
- return 1; // 單擊事件
- }
- else if (1 == Key) flag_key = 1;
- return 0;//無(wú)按鍵按下
- }
- /**************************************************************************
- 函數(shù)功能:直立PD控制 作者:平衡小車之家
- 入口參數(shù):角度、角速度
- 返回 值:直立控制PWM
- **************************************************************************/
- int balance(float Angle, float Gyro)
- {
- float Bias;
- int balance;
- Bias = Angle - ZHONGZHI; //===求出平衡的角度中值 和機(jī)械相關(guān)
- balance = Balance_Kp * Bias + Gyro * Balance_Kd; //===計(jì)算平衡控制的電機(jī)PWM PD控制 kp是P系數(shù) kd是D系數(shù)
- return balance;
- }
- /**************************************************************************
- 函數(shù)功能:速度PI控制 作者:平衡小車之家
- 入口參數(shù):左輪編碼器、右輪編碼器
- 返回 值:速度控制PWM
- **************************************************************************/
- int velocity(int encoder_left, int encoder_right)
- {
- static float Velocity, Encoder_Least, Encoder, Movement;
- static float Encoder_Integral, Target_Velocity;
- float kp = 2, ki = kp / 200; //PI參數(shù)
- if ( Flag_Qian == 1)Movement = 600;
- else if ( Flag_Hou == 1)Movement = -600;
- else //這里是停止的時(shí)候反轉(zhuǎn),讓小車盡快停下來(lái)
- {
- Movement = 0;
- if (Encoder_Integral > 300) Encoder_Integral -= 200;
- if (Encoder_Integral < -300) Encoder_Integral += 200;
- }
- //=============速度PI控制器=======================//
- Encoder_Least = (encoder_left + encoder_right) - 0; //===獲取最新速度偏差==測(cè)量速度(左右編碼器之和)-目標(biāo)速度(此處為零)
- Encoder *= 0.7; //===一階低通濾波器
- Encoder += Encoder_Least * 0.3; //===一階低通濾波器
- Encoder_Integral += Encoder; //===積分出位移 積分時(shí)間:40ms
- Encoder_Integral = Encoder_Integral - Movement; //===接收遙控器數(shù)據(jù),控制前進(jìn)后退
- if (Encoder_Integral > 21000) Encoder_Integral = 21000; //===積分限幅
- if (Encoder_Integral < -21000) Encoder_Integral = -21000; //===積分限幅
- Velocity = Encoder * Velocity_Kp + Encoder_Integral * Velocity_Ki; //===速度控制
- if (Turn_Off(KalFilter.angle, Battery_Voltage) == 1 || Flag_Stop == 1) Encoder_Integral = 0;//小車停止的時(shí)候積分清零
- return Velocity;
- }
- /**************************************************************************
- 函數(shù)功能:轉(zhuǎn)向控制 作者:平衡小車之家
- 入口參數(shù):Z軸陀螺儀
- 返回 值:轉(zhuǎn)向控制PWM
- **************************************************************************/
- int turn(float gyro)//轉(zhuǎn)向控制
- {
- static float Turn_Target, Turn, Turn_Convert = 3;
- float Turn_Amplitude = 80, Kp = 2, Kd = 0.001; //PD參數(shù)
- if (1 == Flag_Left) Turn_Target += Turn_Convert; //根據(jù)遙控指令改變轉(zhuǎn)向偏差
- else if (1 == Flag_Right) Turn_Target -= Turn_Convert;//根據(jù)遙控指令改變轉(zhuǎn)向偏差
- else Turn_Target = 0;
- if (Turn_Target > Turn_Amplitude) Turn_Target = Turn_Amplitude; //===轉(zhuǎn)向速度限幅
- if (Turn_Target < -Turn_Amplitude) Turn_Target = -Turn_Amplitude;
- Turn = -Turn_Target * Kp + gyro * Kd; //===結(jié)合Z軸陀螺儀進(jìn)行PD控制
- return Turn;
- }
- /**************************************************************************
- 函數(shù)功能:賦值給PWM寄存器 作者:平衡小車之家
- 入口參數(shù):左輪PWM、右輪PWM
- 返回 值:無(wú)
- **************************************************************************/
- void Set_Pwm(int moto1, int moto2)
- {
- if (moto1 > 0) digitalWrite(IN1, HIGH), digitalWrite(IN2, LOW); //TB6612的電平控制
- else digitalWrite(IN1, LOW), digitalWrite(IN2, HIGH); //TB6612的電平控制
- analogWrite(PWMA, abs(moto1)); //賦值給PWM寄存器
- if (moto2 < 0) digitalWrite(IN3, HIGH), digitalWrite(IN4, LOW); //TB6612的電平控制
- else digitalWrite(IN3, LOW), digitalWrite(IN4, HIGH); //TB6612的電平控制
- analogWrite(PWMB, abs(moto2));//賦值給PWM寄存器
- }
- /**************************************************************************
- 函數(shù)功能:限制PWM賦值 作者:平衡小車之家
- 入口參數(shù):無(wú)
- 返回 值:無(wú)
- **************************************************************************/
- void Xianfu_Pwm(void)
- {
- int Amplitude = 250; //===PWM滿幅是255 限制在250
- if(Flag_Qian==1) Motor2-=DIFFERENCE; //DIFFERENCE是一個(gè)衡量平衡小車電機(jī)和機(jī)械安裝差異的一個(gè)變量。直接作用于輸出,讓小車具有更好的一致性。
- if(Flag_Hou==1) Motor2-=DIFFERENCE-2;
- if (Motor1 < -Amplitude) Motor1 = -Amplitude;
- if (Motor1 > Amplitude) Motor1 = Amplitude;
- if (Motor2 < -Amplitude) Motor2 = -Amplitude;
- if (Motor2 > Amplitude) Motor2 = Amplitude;
- }
- /**************************************************************************
- 函數(shù)功能:5ms控制函數(shù) 核心代碼 作者:平衡小車之家
- 入口參數(shù):無(wú)
- 返回 值:無(wú)
- **************************************************************************/
- void control()
- {
- static int Velocity_Count, Turn_Count, Encoder_Count;
- static float Voltage_All,Voltage_Count;
- int Temp;
- sei();//全局中斷開啟
- Mpu6050.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); //獲取MPU6050陀螺儀和加速度計(jì)的數(shù)據(jù)
- KalFilter.Angletest(ax, ay, az, gx, gy, gz, dt, Q_angle, Q_gyro, R_angle, C_0, K1); //通過(guò)卡爾曼濾波獲取角度
- Angle = KalFilter.angle;//Angle是一個(gè)用于顯示的整形變量
- Balance_Pwm = balance(KalFilter.angle, KalFilter.Gyro_x);//直立PD控制 控制周期5ms
- if (++Velocity_Count >= 8) //速度控制,控制周期40ms
- {
- Velocity_Left = Velocity_L; Velocity_L = 0; //讀取左輪編碼器數(shù)據(jù),并清零,這就是通過(guò)M法測(cè)速(單位時(shí)間內(nèi)的脈沖數(shù))得到速度。
- Velocity_Right = Velocity_R; Velocity_R = 0; //讀取右輪編碼器數(shù)據(jù),并清零
- Velocity_Pwm = velocity(Velocity_Left, Velocity_Right);//速度PI控制,控制周期40ms
- Velocity_Count = 0;
- }
- if (++Turn_Count >= 4)//轉(zhuǎn)向控制,控制周期20ms
- {
- Turn_Pwm = turn(gz);
- Turn_Count = 0;
- }
- Motor1 = Balance_Pwm - Velocity_Pwm + Turn_Pwm; //直立速度轉(zhuǎn)向環(huán)的疊加
- Motor2 = Balance_Pwm - Velocity_Pwm - Turn_Pwm; //直立速度轉(zhuǎn)向環(huán)的疊加
- Xianfu_Pwm();//限幅
- if (Pick_Up(az, KalFilter.angle, Velocity_Left, Velocity_Right)) Flag_Stop = 1; //===如果被拿起就關(guān)閉電機(jī)//===檢查是否小車被那起
- if (Put_Down(KalFilter.angle, Velocity_Left, Velocity_Right)) Flag_Stop = 0; //===檢查是否小車被放下
- if (Turn_Off(KalFilter.angle, Battery_Voltage) == 0) Set_Pwm(Motor1, Motor2);//如果不存在異常,賦值給PWM寄存器控制電機(jī)
- if (My_click()) Flag_Stop = !Flag_Stop; //中斷剩余的時(shí)間掃描一下按鍵狀態(tài)
- Temp = analogRead(0); //采集一下電池電壓
-
- Voltage_Count++; //平均值計(jì)數(shù)器
- Voltage_All+=Temp; //多次采樣累積
- if(Voltage_Count==200) Battery_Voltage=11.1,Voltage_All=0,Voltage_Count=0;//求平均值 =Voltage_All*0.05371/200
- }
- /**************************************************************************
- 函數(shù)功能:初始化 相當(dāng)于STM32里面的Main函數(shù) 作者:平衡小車之家
- 入口參數(shù):無(wú)
- 返回 值:無(wú)
- **************************************************************************/
- void setup() {
- pinMode(IN1, OUTPUT); //TB6612控制引腳,控制電機(jī)1的方向,01為正轉(zhuǎn),10為反轉(zhuǎn)
- pinMode(IN2, OUTPUT); //TB6612控制引腳,
- pinMode(IN3, OUTPUT); //TB6612控制引腳,控制電機(jī)2的方向,01為正轉(zhuǎn),10為反轉(zhuǎn)
- pinMode(IN4, OUTPUT); //TB6612控制引腳,
- pinMode(PWMA, OUTPUT); //TB6612控制引腳,電機(jī)PWM
- pinMode(PWMB, OUTPUT); //TB6612控制引腳,電機(jī)PWM
- digitalWrite(IN1, 0); //TB6612控制引腳拉低
- digitalWrite(IN2, 0); //TB6612控制引腳拉低
- digitalWrite(IN3, 0); //TB6612控制引腳拉低
- digitalWrite(IN4, 0); //TB6612控制引腳拉低
- analogWrite(PWMA, 0); //TB6612控制引腳拉低
- analogWrite(PWMB, 0); //TB6612控制引腳拉低
- pinMode(2, INPUT); //編碼器引腳
- pinMode(4, INPUT); //編碼器引腳
- pinMode(5, INPUT); //編碼器引腳
- pinMode(8, INPUT); //編碼器引腳
- pinMode(3, INPUT); //按鍵引腳
- Wire.begin(); //加入 IIC 總線
- Serial.begin(9600); //開啟串口,設(shè)置波特率為 9600
- delay(1500); //延時(shí)等待初始化完成
- Mpu6050.initialize(); //初始化MPU6050
- delay(20);
- if(digitalRead(KEY)==0) { //讀取EEPROM的參數(shù)
- Balance_Kp = (float)((EEPROM.read(addr+0)*256)+EEPROM.read(addr+1) )/100;
- Balance_Kd = (float)((EEPROM.read(addr+2)*256)+EEPROM.read(addr+3))/100;
- Velocity_Kp = (float)((EEPROM.read(addr+4)*256)+EEPROM.read(addr+5))/100;
- Velocity_Ki = (float)((EEPROM.read(addr+6)*256)+EEPROM.read(addr+7))/100;
- }
- MsTimer2::set(5, control); //使用Timer2設(shè)置5ms定時(shí)中斷
- MsTimer2::start(); //使用中斷使能
- attachInterrupt(0, READ_ENCODER_L, CHANGE); //開啟外部中斷 編碼器接口1
- attachPinChangeInterrupt(4, READ_ENCODER_R, CHANGE); //開啟外部中斷 編碼器接口2
- }
- /**************************************************************************
- 函數(shù)功能:主循環(huán)程序體
- 入口參數(shù):無(wú)
- 返回 值:無(wú)
- **************************************************************************/
- void loop() {
- int Voltage_Temp;
- static unsigned char flag;
- unsigned char Balance_Kp_Temp=0,Balance_Kd_Temp=0,Velocity_Kp_Temp=0,Velocity_Ki_Temp=0;
- Voltage_Temp = (Battery_Voltage - 11.1) * 60; //根據(jù)APP的協(xié)議對(duì)電池電壓變量進(jìn)行處理
- if (Voltage_Temp > 100)Voltage_Temp = 100;
- if (Voltage_Temp < 0)Voltage_Temp = 0;
- if (Flag_Stop == 0)
- {
- Serial.begin(9600); //開啟串口,設(shè)置波特率為 9600
- flag=!flag;
- if(PID_Send==1)//發(fā)送PID參數(shù)
- {
- Serial.print("{C");
- Serial.print((int)(Balance_Kp*100)); //左輪編碼器
- Serial.print(":");
- Serial.print((int)(Balance_Kd*100)); //右輪編碼器
- Serial.print(":");
- Serial.print((int)(Velocity_Kp*100)); //電池電壓
- Serial.print(":");
- Serial.print((int)(Velocity_Ki*100)); //平衡傾角
- Serial.print("}$");
- PID_Send=0;
- }
- else if(flag==0)
- {
- Serial.print("{A");
- Serial.print(abs(Velocity_Left / 2)); //左輪編碼器
- Serial.print(":");
- Serial.print(abs(Velocity_Right / 2)); //右輪編碼器
- Serial.print(":");
- Serial.print(Voltage_Temp); //電池電壓
- Serial.print(":");
- Serial.print(Angle); //平衡傾角
- Serial.print("}$");
- }
- else
- {
- Serial.print("{B");
- Serial.print(Angle);
- Serial.print(":");
- Serial.print(Voltage_Temp);
- Serial.print(":");
- Serial.print(Velocity_Left/2);
- Serial.print(":");
- Serial.print(Velocity_Right/2);
- Serial.print("}$");
- }
- delay(50);
- }
- else Serial.begin(128000), DataScope(); //使用上位機(jī)時(shí),波特率是128000
- if(Flash_Send==1) //寫入PID參數(shù)到EEPROM,由app控制該指令
- {
- EEPROM.write(addr, ((unsigned int)(Balance_Kp*100)&0xff00)>>8);
- EEPROM.write(addr+1, (unsigned int)(Balance_Kp*100)&0xff);
- EEPROM.write(addr+2, ((unsigned int)(Balance_Kd*100)&0xff00)>>8);
- EEPROM.write(addr+3, (unsigned int)(Balance_Kd*100)&0xff);
- EEPROM.write(addr+4, ((unsigned int)(Velocity_Kp*100)&0xff00)>>8);
- EEPROM.write(addr+5, (unsigned int)(Velocity_Kp*100)&0xff);
- EEPROM.write(addr+6, ((unsigned int)(Velocity_Ki*100)&0xff00)>>8);
- EEPROM.write(addr+7, (unsigned int)(Velocity_Ki*100)&0xff);
- Flash_Send=0;
- }
- }
- /**************************************************************************
- 函數(shù)功能:外部中斷讀取編碼器數(shù)據(jù),具有二倍頻功能 注意外部中斷是跳變沿觸發(fā)
- 入口參數(shù):無(wú)
- 返回 值:無(wú)
- **************************************************************************/
- void READ_ENCODER_L() {
- if (digitalRead(ENCODER_L) == LOW) { //如果是下降沿觸發(fā)的中斷
- if (digitalRead(DIRECTION_L) == LOW) Velocity_L--; //根據(jù)另外一相電平判定方向
- else Velocity_L++;
- }
- else { //如果是上升沿觸發(fā)的中斷
- if (digitalRead(DIRECTION_L) == LOW) Velocity_L++; //根據(jù)另外一相電平判定方向
- else Velocity_L--;
- }
- }
- /**************************************************************************
- 函數(shù)功能:外部中斷讀取編碼器數(shù)據(jù),具有二倍頻功能 注意外部中斷是跳變沿觸發(fā)
- 入口參數(shù):無(wú)
- 返回 值:無(wú)
- **************************************************************************/
- void READ_ENCODER_R() {
- if (digitalRead(ENCODER_R) == LOW) { //如果是下降沿觸發(fā)的中斷
- if (digitalRead(DIRECTION_R) == LOW) Velocity_R--;//根據(jù)另外一相電平判定方向
- else Velocity_R++;
- }
- else { //如果是上升沿觸發(fā)的中斷
- if (digitalRead(DIRECTION_R) == LOW) Velocity_R++; //根據(jù)另外一相電平判定方向
- else Velocity_R--;
- }
- }
- /**************************************************************************
- 函數(shù)功能:串口接收中斷
- 入口參數(shù):無(wú)
- 返回 值:無(wú)
- **************************************************************************/
- void serialEvent()
- {
- static unsigned char Flag_PID,Receive[10],Receive_Data,i,j;
- static float Data;
- while (Serial.available()) {
- Receive_Data=Serial.read();
- if(Receive_Data==0x7B) Flag_PID=1; //參數(shù)指令起始位
- if(Receive_Data==0x7D) Flag_PID=2; //參數(shù)指令停止位
- if(Flag_PID==1)
- {
- Receive[i]=Receive_Data; //記錄數(shù)據(jù)
- i++;
- }
- else if(Flag_PID==2) //執(zhí)行指令
- {
- if(Receive[3]==0x50) PID_Send=1; //獲取PID參數(shù)
- else if(Receive[3]==0x57) Flash_Send=1; //掉電保存參數(shù)
- else if(Receive[1]!=0x23) //更新PID參數(shù)
- {
- for(j=i;j>=4;j--)
- {
- Data+=(Receive[j-1]-48)*pow(10,i-j); //通訊協(xié)議
- }
- switch(Receive[1])
- {
- case 0x30: Balance_Kp=Data/100;break;
- case 0x31: Balance_Kd=Data/100;break;
- case 0x32: Velocity_Kp=Data/100;break;
- case 0x33: Velocity_Ki=Data/100;break;
- case 0x34: break; //9個(gè)通道,預(yù)留5個(gè)
- case 0x35: break;
- case 0x36: break;
- case 0x37: break;
- case 0x38: break;
- }
- }
- Flag_PID=0; //相關(guān)標(biāo)志位清零
- i=0;
- j=0;
- Data=0;
- }
- else //藍(lán)牙遙控指令
- {
- switch (Receive_Data) {
- //這是MinibalanceV1.0的APP發(fā)送指令
- case 0x01: Flag_Qian = 1, Flag_Hou = 0, Flag_Left = 0, Flag_Right = 0; break; //前進(jìn)
- case 0x02: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 0, Flag_Right = 1; break; //右轉(zhuǎn)
- case 0x03: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 0, Flag_Right = 1; break; //右轉(zhuǎn)
- case 0x04: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 0, Flag_Right = 1; break; //右轉(zhuǎn)
- case 0x05: Flag_Qian = 0, Flag_Hou = 1, Flag_Left = 0, Flag_Right = 0; break; //后退
- case 0x06: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 1, Flag_Right = 0; break; //左轉(zhuǎn)
- case 0x07: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 1, Flag_Right = 0; break; //左轉(zhuǎn)
- case 0x08: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 1, Flag_Right = 0; break; //左轉(zhuǎn)
- //這是MinibalanceV3.5的APP發(fā)送指令
- case 0x41: Flag_Qian = 1, Flag_Hou = 0, Flag_Left = 0, Flag_Right = 0; break; //前進(jìn)
- case 0x42: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 0, Flag_Right = 1; break; //右轉(zhuǎn)
- case 0x43: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 0, Flag_Right = 1; break; //右轉(zhuǎn)
- case 0x44: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 0, Flag_Right = 1; break; //右轉(zhuǎn)
- case 0x45: Flag_Qian = 0, Flag_Hou = 1, Flag_Left = 0, Flag_Right = 0; break; //后退
- case 0x46: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 1, Flag_Right = 0; break; //左轉(zhuǎn)
- case 0x47: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 1, Flag_Right = 0; break; //左轉(zhuǎn)
- case 0x48: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 1, Flag_Right = 0; break; //左轉(zhuǎn)
- default: Flag_Qian = 0, Flag_Hou = 0, Flag_Left = 0, Flag_Right = 0; break; //停止
- }
- }
- }
- }
復(fù)制代碼
以上資料51hei提供下載:
Minibalance_for_Arduino_Final20181113.rar
(6.24 KB, 下載次數(shù): 70)
2019-12-21 23:19 上傳
點(diǎn)擊文件名下載附件
單片機(jī)平衡小車源碼 下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|