久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 10667|回復: 9
打印 上一主題 下一主題
收起左側

Arduino智能小車程序+資料 pid算法

  [復制鏈接]
跳轉到指定樓層
樓主
ID:559809 發表于 2019-7-11 15:06 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
  1. #include "pid.h"
  2. #ifdef ARDUINO_DEBUG
  3. int debugLeftSpeed;
  4. int debugRightSpeed;
  5. uint8_t debugIrs = 0;
  6. #endif
  7. const float motorSpeed = 140; //
  8. const int IR_PIN[] = {A0, A1, A2, A3, A4}; //
  9. const int IN_A1 = 13;   //
  10. const int IN_A2 = 12;   //
  11. const int IN_B1 = 11;  //
  12. const int IN_B2 = 10;  //
  13. const int _pwmLeftPin = 5;
  14. const int _pwmRightPin = 6;
  15. pid_t pid;
  16. float pidValue = 0;
  17. bool turnFlag = false;
  18. void setup(void)
  19. {
  20.   int i;
  21.   /********************1.初始化電機模塊引腳13,12,11,10為輸出模式******************/
  22.   /*
  23.    *   編寫代碼
  24.   */
  25.     /********************2.設置小車啟動速度為140---set_speed()******************/
  26.   /*
  27.    *   編寫代碼
  28.   */
  29.   
  30.   /********************3.初始化循跡模塊引腳A0, A1, A2, A3, A4為輸入模式******************/
  31.    /*
  32.    *   編寫代碼
  33.   */
  34.   //3.設置PID參數
  35.   pid.sampleTime = SAMPLE_TIME;
  36.   pid.Kp = KP_VALUE;
  37.   pid.Ki = KI_VALUE;
  38.   pid.Kd = KD_VALUE;
  39.   pid.error = 0;
  40.   pid.previous_error = 0;
  41.   Serial.begin(115200);
  42.   delay(5000);
  43.   goForward();
  44.   return;
  45. }

  46. //get ir data and middle filter
  47. uint8_t getIrData(void)  //
  48. {
  49.   int i, j;
  50.   uint8_t level;
  51.   uint8_t temp;
  52.   uint8_t irs[9] = {0};//采集9次傳感器的傳感器的數據
  53.         //減少取平均值,濾波。
  54.   for (j = 0; j < 9; j ++) {
  55.    
  56.       for (i = 0; i < 5; i++) {
  57.         level = digitalRead(IR_PIN[i]);
  58.         if (level) {
  59.           bitSet(irs[j], i); // 設置irs[j]的第jbit 為1
  60.         } else {
  61.           bitClear(irs[j], i); //清除irs[j]的第jbit為0
  62.         }
  63.       }
  64.   }
  65.   //對irs中的數據,進行9次排序,取最中間的值。
  66.   for (i = 0; i < 9 - 1; i ++) {
  67.     for (j = 0; j < 9 - i - 1; j ++) {
  68.       if (irs[j] > irs[j + 1]) {
  69.         temp = irs[j];
  70.         irs[j] = irs[j + 1];
  71.         irs[j + 1] = temp;
  72.       }
  73.     }
  74.   }
  75.   
  76. #ifdef ARDUINO_DEBUG
  77.   debugIrs = irs[4];
  78. #endif
  79.   return irs[4];
  80. }
  81. int calcErrorByIrsValue(uint8_t irs)
  82. {
  83.   //右邊壓線為負,左邊壓線為正。
  84.   //要左轉為負,要右轉為正
  85.   int curError = pid.error; //獲得上一次的pid誤差值
  86.   //壓線輸出低電平0,沒有壓線輸出高電平1
  87.   switch (irs) { //h'h
  88.     case B11110: curError = -8; break; //最右邊壓線
  89.    
  90.     case B10000:
  91.     case B11000: curError = -7; break; //右四個或者右3個沿線
  92.    
  93.     case B11100: curError = -6; break; //右兩個沿線
  94.     case B11101: curError = -4; break; //右倒數第二個沿線
  95.     case B11001: curError = -2; break; //
  96.    
  97.     case B00000:       //全部壓線和中間壓線,對應"十字"彎道,直接郭即可。
  98.     case B11011: curError = 0;  break;
  99.    
  100.     case B10011: curError = 2;  break;
  101.     case B10111: curError = 4;  break;
  102.     case B00111: curError = 6;  break;
  103.    
  104.     case B00011:
  105.     case B00001: curError = 7;  break;
  106.    
  107.     case B01111: curError = 8;  break;
  108. //都沒有沿線,按照上次的PID值來計算
  109.     case B11111: curError = pid.error > 0 ? 9 : - 9; break;
  110.   }
  111.   return curError;
  112. }

  113. void _sortData(int *p, int n)
  114. {
  115.   int temp;
  116.   int i, j;
  117.   
  118.   /**編寫冒泡排序,對采集到的錯誤碼,進行十次從小到大排序 **/
  119.   /*
  120.    *   編寫代碼
  121.   */
  122.   return;
  123. }

  124. //計算當前的誤差值,得到當前的偏移值
  125. void calcCurrentError(void)
  126. {
  127.   int i;
  128.   uint8_t irs;
  129.   float sum = 0;
  130.   int errorData[10];
  131.   //1.采集10次循跡模塊獲得的錯誤碼
  132.   for (i = 0; i < 10; i ++) {
  133.     irs =  getIrData();  //得到這次傳感器采集的數據(5路數據)
  134.     errorData[i] =  calcErrorByIrsValue(irs);
  135.   }
  136.   //2.要求對errorData中的數據進行排序(從小到大排序)
  137.     /*
  138.    *   編寫代碼
  139.   */
  140.   //3.十次中去處一個最高數,去除一個最低數,求中間8次錯誤碼數據的和。
  141.   /*
  142.    *   編寫代碼
  143.   */
  144. //4.求8次錯誤碼數據中的偏差。
  145.   pid.error = sum / 8;
  146.   return;
  147. }
  148. void turnRight(void)
  149. {
  150.     digitalWrite(IN_B1, HIGH); //左正
  151.     digitalWrite(IN_B2, LOW);
  152.     digitalWrite(IN_A1, LOW); //右反
  153.     digitalWrite(IN_A2, HIGH);
  154.    
  155. }
  156. void turnLeft(void)
  157. {
  158.     digitalWrite(IN_B1, LOW);// 左反
  159.     digitalWrite(IN_B2, HIGH);
  160.     digitalWrite(IN_A1, HIGH); //右正
  161.     digitalWrite(IN_A2, LOW);
  162.    
  163. }
  164. void goForward(void)
  165. {
  166.   digitalWrite(IN_B1, HIGH); //左正傳
  167.   digitalWrite(IN_B2, LOW);
  168.   digitalWrite(IN_A1, HIGH); //右正轉
  169.   digitalWrite(IN_A2, LOW);
  170. }
  171. void motorControl(float pidValue, bool turnFlag)
  172. {
  173.   int leftMotorSpeed = 0;
  174.   int rightMotorSpeed = 0;
  175.   
  176.   leftMotorSpeed  = constrain((motorSpeed + pidValue), -255, 255);
  177.   rightMotorSpeed = constrain((motorSpeed - pidValue), -255, 255);
  178.   if (turnFlag) {
  179.     if (abs(leftMotorSpeed) > abs(rightMotorSpeed)) {
  180.       leftMotorSpeed  = abs(leftMotorSpeed);
  181.       rightMotorSpeed = leftMotorSpeed;
  182.     } else {
  183.       rightMotorSpeed =  abs(rightMotorSpeed);
  184.       leftMotorSpeed  = rightMotorSpeed;
  185.     }
  186.   } else {
  187.     leftMotorSpeed  = leftMotorSpeed  > 0 ? leftMotorSpeed  : -leftMotorSpeed;
  188.     rightMotorSpeed = rightMotorSpeed > 0 ? rightMotorSpeed : -rightMotorSpeed;
  189.   }
  190.   analogWrite(_pwmLeftPin,  leftMotorSpeed );
  191.   analogWrite(_pwmRightPin, rightMotorSpeed);
  192. #ifdef ARDUINO_DEBUG
  193.   debugLeftSpeed  = leftMotorSpeed ;
  194.   debugRightSpeed = rightMotorSpeed;
  195. #endif
  196.   return;
  197. }
  198. bool calculatePid(float *pValue)
  199. {
  200.   float P = 0;
  201.   static float I = 0 ;
  202.   float D = 0 ;
  203.   static unsigned long lastTime = 0;
  204.   //獲得機器從啟動到現在所運行的時間
  205.   unsigned long now = millis();
  206.   int timeChange = now - lastTime;//得到這次的時間
  207.   //若是我們的這次變化的時間,小于pid的
  208.   //采樣時間,就需要等待一下。
  209.   if (timeChange < pid.sampleTime) {
  210.     return false;
  211.   }
  212.   P = pid.error; //本次小車傳感器的偏移大小
  213.   I = I + pid.error;//歷史的偏移
  214.   D = pid.error - pid.previous_error; //最近兩次的差值
  215.   *pValue = (pid.Kp * P) + (pid.Ki * I) + (pid.Kd * D) + 1;
  216.   //constrain()函數的功能:若是*pvalue > motorSpeed,取 motorSpeed,
  217.   //                       若是*pvalue < -motorSpeed,取 -motorSpeed,
  218.   //        若是-pValue<=*pvalue <= motorSpeed,取*pvalue
  219.   *pValue = constrain(*pValue, -motorSpeed,motorSpeed);
  220.   pid.previous_error = pid.error; //記錄本次的pid.error,作為下一次的歷史差值。
  221.   lastTime = now; // 記錄本次的運行時間,作為下一次時間的歷史時間參考。
  222.   return true;
  223. }

  224. void calcDirection(void) //判斷小車的轉向
  225. {
  226.   //pid.error > 0 說明小車左邊壓線多,要
  227.   if (pid.error >= 7 && pid.error <= 8) {
  228.     turnRight();
  229.     turnFlag = true;
  230.   } else if (pid.error >= -8 && pid.error <= -7) {
  231.     turnLeft();
  232.     turnFlag = true;
  233.   } else if(pid.error == 9 || pid.error == -9){
  234.     turnRight();
  235.     turnFlag = true;
  236.     }else {
  237.     goForward();
  238.     turnFlag = false;
  239.   }
  240.   return;
  241. }
  242. void loop(void)
  243. {
  244.   bool ok;
  245.   float  pidValue;
  246.   calcCurrentError();
  247.   ok = calculatePid(&pidValue); //計算當前pid的差值。,若是就緒了
  248.   if (ok) {
  249.     calcDirection();
  250.     motorControl(pidValue, turnFlag);
  251.   }
  252.   return;
  253. }
復制代碼

pid_student.zip

3.1 KB, 下載次數: 148, 下載積分: 黑幣 -5

Arduino 智能小車 - 尋跡.pdf

322.06 KB, 下載次數: 149, 下載積分: 黑幣 -5

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏18 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:560595 發表于 2019-7-16 13:46 | 只看該作者
這個要頂
回復

使用道具 舉報

板凳
ID:505027 發表于 2019-7-16 21:26 | 只看該作者
這個好,記錄一下
回復

使用道具 舉報

地板
ID:594846 發表于 2019-8-4 22:31 | 只看該作者
真好,贊一個!
回復

使用道具 舉報

5#
ID:609660 發表于 2019-9-9 19:22 來自手機 | 只看該作者
這個資源確實好
回復

使用道具 舉報

6#
ID:149774 發表于 2019-9-21 21:44 | 只看該作者
做個記號,回頭學習一下
回復

使用道具 舉報

7#
ID:614623 發表于 2019-9-22 00:16 | 只看該作者
這個可以參考
回復

使用道具 舉報

8#
ID:652804 發表于 2019-12-15 15:42 | 只看該作者
謝謝,學習學習。
回復

使用道具 舉報

9#
ID:28942 發表于 2020-9-15 19:24 | 只看該作者
編輯不過是什么原因?
回復

使用道具 舉報

10#
ID:1011808 發表于 2022-4-5 13:47 | 只看該作者
arduino如何設置小車啟動速度
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲丝袜天堂 | 秋霞精品| 成人毛片视频免费 | 国产成人精品a视频一区www | 国产一级大片 | 中文字幕一级毛片视频 | 天天插天天操 | 四虎影| 国产精品一二区 | 久久精品99久久 | avav在线看| 91伊人网 | 亚洲精品在线观 | 国产精品久久视频 | 美女天堂在线 | 伊人久久综合 | 国产精品成人一区二区三区夜夜夜 | 欧美一区二区三区在线 | 欧美日本一区 | 在线视频国产一区 | 国产精品一区在线 | 中文字幕在线观看av | 日韩综合在线播放 | 国产精品99久| 亚洲最大的黄色网址 | 亚洲成人免费观看 | 成人国产精品一级毛片视频毛片 | 婷婷久久综合 | 国产福利资源在线 | 国产精品欧美一区二区三区不卡 | 欧美日韩专区 | 99久久99久久精品国产片果冰 | 午夜影院网站 | 亚洲综合色丁香婷婷六月图片 | 日韩av资源站 | 亚洲欧美在线视频 | 青青久久| 69热视频在线观看 | 国产免费一区二区 | 国产成人精品一区二 | 亚洲精品日日夜夜 |