Arduino平衡車完整代碼+詳解

代碼中使用了兩套PID參數進行控制,Kp,Ki,Kd是控制平衡速度的。也就是小車往前傾,加速;后傾,減速這個過程。
但是僅靠一個PID控制會出現一個問題:因為小車的平衡角度Setpoint是手動設定的,所以會有一個微小的誤差。當小車以Setpoint為基準進行調整時,可能有一個細微的傾斜,從而導致小車一直向一邊跑。于是引入另一套速度的PID參數:Sp,Si,Sd。 Inputs 為一個變量speedcount,每次中斷檢查車輪的轉向,正向+1,反向-1。這樣,當小車持續向一個方向移動時,speedcount會越來越大,從而產生的Outputs也更大。于是對車輪加一個反向的電壓,使小車盡量停在原地。實現的時候,把Outputs的作用加到第一套PID的目標平衡角度Setpoint上,就可以實現效果。

void setup()
{
  delay(50);  
  pinMode(AN1, OUTPUT);
  pinMode(AN2, OUTPUT);
  pinMode(BN1, OUTPUT);
  pinMode(BN2, OUTPUT);
  pinMode(PWMA, OUTPUT);
  pinMode(PWMB, OUTPUT);
  pinMode(STBY, OUTPUT);//放在setup()函數中來確定引腳的功能
  pinMode(13, OUTPUT);
  digitalWrite(STBY, HIGH);
  analogWrite(PWMA, 0); //產生一個PWM為占空比為0的方波
  analogWrite(PWMB, 0);
  GetParamers();//輸入參數
  speedcount = sc;//每次中斷檢查車輪的轉向,正向+1,反向-1。這樣,當小車持續向一個方向移動時,speedcount會越來越大,從而產生的Outputs也更大。于是對車輪加一個反向的電壓,使小車盡量停在原地
  Offset_Setpoint = osp;//把Outputs的作用加到目標平衡角度Setpoint上,就可以實現效果。
  Serial.begin(115200);//設置波特率為115200
  Wire.begin(); //初始化wire,
  delay(100);
  mpu.initialize();//初始化mpu
  delay(2); 
  devStatus = mpu.dmpInitialize();//初始化mpu6050的數據處理器DMP
  //確保DMP工作正常(如果是,返回0)
  if (devStatus == 0)
  {     
    mpu.setDMPEnabled(true);  
   // // 啟用Arduino中斷檢測 
    attachInterrupt(0, dmpDataReady, RISING);//開啟INT0中斷, mpu6050INT引腳需要接到arduino的PIN 2
    mpuIntStatus = mpu.getIntStatus(); 
    dmpReady = true; // 設置DMP就緒標志,以便main loop()函數知道可以使用它
    packetSize = mpu.dmpGetFIFOPacketSize();  // 獲得期望的DMP包大小以便稍后比較
  }
  Setpoint = Offset_Setpoint;
  myPID.SetTunings(kp, ki, kd);//設置pid的控制參數
  myPID.SetOutputLimits(-255 + dl, 255 - dl);//控制限制量的輸出范圍,PWM限幅
  myPID.SetSampleTime(5);//更新新的采樣時間,同時按照比例更新ID參數
  myPID.SetMode(AUTOMATIC);//自動初始化
  sPID.SetTunings(sp, si, sd);
  sPID.SetOutputLimits(-10, 70);
  sPID.SetSampleTime(200);
  sPID.SetMode(AUTOMATIC);
  attachInterrupt(1, speed, RISING);//設置中斷
  //MsTimer2::set(500, flash);       
 // MsTimer2::start();    
}

void loop()
{
   // 如果編程失敗了,就停在這里
  if (!dmpReady)
    return; 
    // 等待MPU中斷或額外數據包可用
  if (!mpuInterrupt && fifoCount < packetSize)
    return;
     // 重置中斷標志并獲得INT_STATUS字節
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus(); 
  fifoCount = mpu.getFIFOCount(); 
  if ((mpuIntStatus & 0x10) || fifoCount == 1024)
   // 獲取當前FIFO計數
    mpu.resetFIFO();  
   // 檢查是否溢出(除非代碼效率太低,否則不會發生)
  if ((mpuIntStatus & 0x10) || fifoCount == 1024)
  {
    //重置
    mpu.resetFIFO();
    Serial.println(F("FIFO overflow!"));

    // 否則,檢查DMP數據就緒中斷(經常發生)
  }
  else if (mpuIntStatus & 0x02)
  {    
      // 等待正確的可用數據長度
    while (fifoCount < packetSize)
      fifoCount = mpu.getFIFOCount();   
        // 從FIFO讀取數據包
    mpu.getFIFOBytes(fifoBuffer, packetSize); 
  // 跟蹤FIFO計數在這里,以防有多余1個包可用
    // (可以幫助我們立即閱讀更多內容而無需等待中斷)   
    fifoCount -= packetSize;
    mpu.dmpGetQuaternion(&q, fifoBuffer);
    mpu.dmpGetGravity(&gravity, &q);
    mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);//從DMP中取出Yaw、Pitch、Roll三個軸的角度,放入數組ypr。單位:弧度
    angle = -ypr[2] * 180 / M_PI;//提取Roll,轉化為角度制
  }
  // 
  Inputs = speedcount;//車輪的轉向
  sPID.Compute1();//速度pid的控制計算
  Setpoint = Offset_Setpoint + Outputs;//The value we want to Input to maintain (double)
  Input = angle; //車輪的角度
   Serial.println(Input);//上傳波形到電腦
  myPID.Compute2();//角度pid的控制計算
  if (angle > 60 || angle < -60)
    Output = 0;
  motor(Output); //flag=1,轉彎
  SerialControl(); //串行發送接收處理
  sPID.SetTunings(sp, si, sd);//速度
  myPID.SetTunings(kp, ki, kd);//角度
  SendData();//串口發送數據
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,224評論 6 529
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 97,916評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,014評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,466評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,245評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,795評論 1 320
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,869評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,010評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,524評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,487評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,634評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,173評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,884評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,282評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,541評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,236評論 3 388
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,623評論 2 370

推薦閱讀更多精彩內容

  • 今天是什么日子 起床:4:48 就寢:22:35 天氣:晴 心情:小興奮 紀念日: 任務清單 昨日完成的任務,最重...
    修遠聊成長閱讀 379評論 1 13
  • 周五的時候有一個講課的,我因為選課提的時候比較懶,就直接問我小伙伴要講啥我和她弄一樣的,之后她弄她的,我弄我的,互...
    a27ebe1ee286閱讀 223評論 0 2
  • 5月以來,哪怕對市場風向再不敏感的人,也感覺到陣陣涼意。二級市場連續下挫,一級市場融資環境惡化,不論企業融資數量還...
    錢皓頻道閱讀 6,084評論 1 6
  • 推薦指數: 6.0 書籍主旨關鍵詞:特權、焦點、注意力、語言聯想、情景聯想 觀點: 1.統計學現在叫數據分析,社會...
    Jenaral閱讀 5,734評論 0 5
  • 昨天,在回家的路上,坐在車里悠哉悠哉地看著三毛的《撒哈拉沙漠的故事》,我被里面的內容深深吸引住了,盡管上學時...
    夜闌曉語閱讀 3,798評論 2 9