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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

超聲波避障小車Arduino源碼

[復制鏈接]
跳轉到指定樓層
樓主
ID:389885 發表于 2018-8-25 12:09 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
硬件電路配置有Arduino、L293D驅動模塊、PCA9685驅動模塊各一個,四個直流電機(由L293D驅動模塊驅動),3個舵機(PCA9685驅動模塊驅動),三個超聲波探測器。代碼有很多的多余注釋,還有想要用定時器2的草稿,大家看著做個參考。
//四輪獨立驅動小車,注意程序已經舵機角度改為不是0-60之間變化,范圍有所縮小。

  1. #include <AFMotor.h>
  2. //#include <MsTimer2.h>


  3.     #define PCA9685_adrr 0x80//  1+A5+A4+A3+A2+A1+A0+w/r
  4.                         //片選地址,將焊接點置1可改變地址,
  5.                         // 當IIC總 呱嫌 多片PCA9685或相同地址時才需焊接
  6.     #define PCA9685_SUBADR1 0x2
  7.     #define PCA9685_SUBADR2 0x3
  8.     #define PCA9685_SUBADR3 0x4

  9.     #define PCA9685_MODE1 0x0//PCA9685模式復位設置
  10.     #define PCA9685_PRESCALE 0xFE//控制周期的寄存器

  11.     #define LED0_ON_L 0x6
  12.     #define LED0_ON_H 0x7
  13.     #define LED0_OFF_L 0x8
  14.     #define LED0_OFF_H 0x9

  15.     #define ALLLED_ON_L 0xFA
  16.     #define ALLLED_ON_H 0xFB
  17.     #define ALLLED_OFF_L 0xFC
  18.     #define ALLLED_OFF_H 0xFD   

  19.     #define SERVOMIN  115 // this is the 'minimum' pulse length count (out of 4096)
  20.     #define SERVOMAX  590 // this is the 'maximum' pulse length count (out of 4096)
  21.     //#define SERVO000  130 //0度對應4096的脈寬計數值
  22.     #define SERVO000  145 //0度對應4096的脈寬計數值
  23.     #define SERVO180  520 //180度對應4096的脈寬計算值,四個值可根據不同舵機修改

  24. AF_DCMotor LF_motor(1);//定義四個車輪電機對應的內存單元
  25. AF_DCMotor RF_motor(3);
  26. AF_DCMotor LB_motor(2);
  27. AF_DCMotor RB_motor(4);
  28. // 設定SR04連接的Arduino引腳
  29.     const int TrigPin = A0;//超聲波測距使能控制信號
  30.     const int EchoPin = A1;//超聲波測距模塊輸出,通過測得高電平持續時間獲得障礙物距離
  31.     //unsigned long distance;
  32.     const int IIC_SDA = A5;//串行數據線信號
  33.     const int IIC_SCL = A4;//串行時鐘線信號
  34.     const int EchoPin_L = A2;//左舵機超聲波探測器接收信號
  35.     const int EchoPin_R = A3;//右舵機超聲波探測器接收信號

  36. boolean stage1_ctrl=false;//前端超聲波云臺控制信號,true表示當前從60度轉到0度;
  37. boolean stage23_ctrl=false;//左右端超聲波云臺控制信號,true表示當前從60度轉到0度;
  38. boolean direction_ctrl_r=true;
  39. boolean direction_ctrl_l=true;


  40. int l=0;
  41. int m=0;
  42. int stage1_dis;
  43. int stage2_dis;
  44. int stage3_dis;


  45. void setup()
  46. {   // 初始化串口通信及連接SR04的引腳
  47. //Serial.begin(9600);
  48. pinMode(TrigPin, OUTPUT);
  49. // 要檢測引腳上輸入的脈沖寬度,需要先設置為輸入狀態
  50. pinMode(EchoPin, INPUT);
  51. //Serial.println("開始");
  52. LF_motor.setSpeed(150);
  53. RF_motor.setSpeed(150);
  54. LB_motor.setSpeed(150);
  55. RB_motor.setSpeed(150);
  56. LF_motor.run(FORWARD);
  57. RF_motor.run(FORWARD);
  58. LB_motor.run(FORWARD);
  59. RB_motor.run(FORWARD);
  60.   pinMode(IIC_SDA,OUTPUT);
  61.   pinMode(IIC_SCL,OUTPUT);
  62. //Serial.println("SDA,SCL引腳初始化");
  63. IIC_init();
  64. // Serial.println("IIC初始化");
  65. reset();
  66.   // Serial.println("初始化結束");
  67.   setPWMFreq(50);
  68.   // Serial.println("初始化結束");
  69. //MsTimer2::set(500, stage1); // 500ms period定時器2初始化;
  70. // Serial.println("初始化結束");
  71. // MsTimer2::start();
  72. //Serial.println("初始化結束");
  73. }

  74. void loop()
  75. {//  Serial.println("主程序");
  76.   if(stage1_ctrl==true)
  77.    {
  78.     stage1_ctrl=false;
  79.     setPWM(0, 0, SERVO000);//第0路舵機從60度轉到0角度   0.12-0.13秒/60度
  80.    }
  81.    else
  82.    {
  83.     stage1_ctrl=true;
  84.     setPWM(0, 0,224);  //第0路舵機從0度轉到60角度   
  85.    }   
  86. for(l=0;l<=100;l++)   
  87. {
  88.     // 產生一個1。、0us的高脈沖去觸發TrigPin,即開啟超聲波測距
  89. digitalWrite(TrigPin, LOW);
  90. delayMicroseconds(2);
  91. digitalWrite(TrigPin, HIGH);
  92. delayMicroseconds(10);
  93. digitalWrite(TrigPin, LOW);

  94.     // 檢測脈沖寬度,并計算出距離
  95. delayMicroseconds(2);
  96. int stage1_dis=pulseIn(EchoPin, HIGH,2000);
  97. //Serial.println(stage1_dis);
  98. //distance = pulseIn(EchoPin, HIGH) / 58.00;
  99. if(stage1_dis>0)//stage1_dis=0表示超過超聲波等待回收信號范圍,即距離超過(1300/58)cm;
  100.   {
  101.     if(stage23_ctrl==true)
  102.      {
  103.     stage23_ctrl=false;
  104.     setPWM(1, 0, SERVO000);//第1路舵機從60度轉到0角度   
  105.     setPWM(2, 0,224);//第2路舵機從0度轉到60角度   
  106.    }
  107.    else
  108.    {
  109.     stage23_ctrl=true;
  110.     setPWM(1, 0,224);  //第1路舵機從0度轉到60角度
  111.     setPWM(2, 0, SERVO000);  //第1路舵機從60度轉到0角度     
  112.    }   
  113.   // Serial.println("外循環");
  114.    for(m=0;m<=40;m++)
  115.    {
  116. //Serial.println("前端超聲波探測循環");
  117.    //delay(1);
  118.    digitalWrite(TrigPin, LOW); // 產生一個10us的高脈沖去觸發TrigPin,即開啟超聲波測距
  119.    delayMicroseconds(2);
  120.    digitalWrite(TrigPin, HIGH);
  121.    delayMicroseconds(10);
  122.    digitalWrite(TrigPin, LOW);
  123.    delayMicroseconds(2);
  124.    stage2_dis=pulseIn(EchoPin_L, HIGH,1500);
  125.    delay(1);//如果不延時處理,stage3_dis測得距離會有問題;
  126.    digitalWrite(TrigPin, LOW);
  127.    delayMicroseconds(2);
  128.    digitalWrite(TrigPin, HIGH);
  129.    delayMicroseconds(10);
  130.    digitalWrite(TrigPin, LOW);
  131.    delayMicroseconds(2);
  132.    stage3_dis=pulseIn(EchoPin_R, HIGH,1500);
  133. //Serial.println(stage1_dis);
  134. //Serial.println(stage2_dis);
  135. // Serial.println(stage3_dis);
  136. //delay(500);
  137.    if(stage2_dis>0)
  138.    {
  139.    direction_ctrl_l=false;
  140.    }
  141.    else
  142.    {
  143.    direction_ctrl_l=true;
  144.    }
  145.    if(stage3_dis>0)
  146.    {
  147.    direction_ctrl_r=false;
  148.    }
  149.    else
  150.    {
  151.    direction_ctrl_r=true;
  152.    }
  153.    }
  154. // Serial.println(direction_ctrl_l);
  155. //Serial.println(direction_ctrl_r);
  156.   if(direction_ctrl_l==true)
  157.   {
  158.   // Serial.println("左轉");
  159.    LF_motor.run(BACKWARD);
  160.    LB_motor.run(BACKWARD);
  161.   // RF_motor.run(FORWARD);
  162.   // RB_motor.run(FORWARD);
  163.    delay(1000);
  164. //  LF_motor.run(FORWARD);
  165.   // LB_motor.run(FORWARD);

  166.   }
  167.   else if(direction_ctrl_r==true)
  168.   {
  169.    // Serial.println("右轉");  
  170.    RF_motor.run(BACKWARD); //如果之前左轉,發現左端忽然有障礙物出現,則機器人實際變成后退動作;
  171.    RB_motor.run(BACKWARD);
  172.    //LF_motor.run(FORWARD);
  173.    //LB_motor.run(FORWARD);
  174.    delay(1000);
  175.   // RF_motor.run(FORWARD);
  176.   // RB_motor.run(FORWARD);

  177.   }
  178.   else
  179.   {
  180.    // Serial.println("后退");
  181.    RF_motor.run(BACKWARD);
  182.    RB_motor.run(BACKWARD);
  183.    LF_motor.run(BACKWARD);
  184.    LB_motor.run(BACKWARD);
  185.    delay(1000);
  186.   // RF_motor.run(FORWARD);
  187. //  RB_motor.run(FORWARD);
  188.   // LF_motor.run(FORWARD);
  189.   // LB_motor.run(FORWARD);


  190.   }

  191.   break;//注意內層的break只能跳出內層的for循環,兩個,三個break,也都只能跳出本層循環,及第二個Break根本不會執行;

  192.    //digitalWrite(LF, HIGH);
  193.    //digitalWrite(LB, HIGH);

  194. }
  195. else
  196. {
  197.    RF_motor.run(FORWARD);
  198.    RB_motor.run(FORWARD);
  199.    LF_motor.run(FORWARD);
  200.    LB_motor.run(FORWARD);
  201. }

  202. }  
  203. //Serial.print(distance);
  204. //Serial.print("cm");
  205. //Serial.println();
  206. //delay(500);
  207. }
  208.   //IIC初始化
  209.     void IIC_init()
  210.     {
  211.     digitalWrite(IIC_SDA,HIGH); //IIC_SDA IIC_SCL使用前被拉高
  212.     delayMicroseconds(4);
  213.     digitalWrite(IIC_SCL,HIGH);
  214.     delayMicroseconds(4);
  215.     }


  216.   void start()//基于IIC總線的物理結構,總線上的START和IIC_stop信號必定是唯一的。
  217.                 //另外,IIC總線標準規定IIC_SDA線的數據轉換必須在IIC_SCL線的低電平期,
  218.                 //在IIC_SCL線的高電平期,IIC_SDA線的上數據是穩定的。所以,start(),IIC_stop()的
  219.                 //特殊情況可以作為指示的起止信號。
  220.     {
  221.    //   Serial.println("start開始");
  222.     digitalWrite(IIC_SDA,HIGH);
  223.     delayMicroseconds(4);
  224.     digitalWrite(IIC_SCL,HIGH); //IIC_SCL高 IIC_SDA拉低表示可以IIC啟動
  225.     delayMicroseconds(4);
  226.     digitalWrite(IIC_SDA,LOW);
  227.     delayMicroseconds(4);
  228.     digitalWrite(IIC_SCL,LOW);
  229.     delayMicroseconds(4);
  230.   //  Serial.println("start結束");
  231.     }

  232.     //IIC停止
  233.     void IIC_stop()
  234.     {
  235.     digitalWrite(IIC_SDA,LOW);
  236.     delayMicroseconds(4);
  237.     digitalWrite(IIC_SCL,HIGH);
  238.     delayMicroseconds(4);
  239.     digitalWrite(IIC_SDA,HIGH);
  240.     delayMicroseconds(4);
  241.     }

  242.     //IIC應答
  243.     void ACK()//IIC_SDA應答信號為0表示正常收發數據,為1表示停止,
  244.     {
  245.     unsigned char i;
  246.     digitalWrite(IIC_SCL,HIGH);
  247.     delayMicroseconds(2);
  248.     pinMode(IIC_SDA,INPUT);
  249.     while((digitalRead(IIC_SDA))&&(i<=255))   
  250.     {
  251.     i++;
  252.     }
  253.     pinMode(IIC_SDA,OUTPUT);
  254.     digitalWrite(IIC_SCL,LOW);
  255.     delayMicroseconds(4);
  256.     }

  257.     //寫字節
  258.     void write_byte(unsigned char byte)
  259.     {
  260.     //Serial.println("地址寫入SDL開始");調試用
  261.     unsigned char i,temp;
  262.     temp=byte;
  263.     for(i=7;i<=7;i--)
  264.     {//unsigned char x;//調試用
  265.     //x=0;//調試用
  266.     //const int test = 2;//調試用
  267.     //pinMode(test,INPUT);//調試用
  268.     digitalWrite(IIC_SCL,LOW);
  269.     delayMicroseconds(4);
  270.     //Serial.println(temp);//調試用
  271.     //Serial.println(bitRead(temp,i));//調試用
  272.     digitalWrite(IIC_SDA,bitRead(temp,i));
  273.    //Serial.println(digitalRead(test));
  274.    // x=(digitalRead(test))|(x<<1);//調試用
  275.    //Serial.println(x);//調試用
  276.    //Serial.println(i);//調試用
  277.     delayMicroseconds(4);
  278.     digitalWrite(IIC_SCL,HIGH);
  279.     delayMicroseconds(4);
  280.     }
  281.     digitalWrite(IIC_SCL,LOW);
  282.     delayMicroseconds(4);
  283.     digitalWrite(IIC_SDA,HIGH);
  284.     delayMicroseconds(4);
  285.     }
  286.     unsigned char read_byte()
  287.     {
  288.     unsigned char i,j,k;
  289.     digitalWrite(IIC_SCL,LOW);
  290.     delayMicroseconds(4);
  291.     digitalWrite(IIC_SDA,HIGH);
  292.     delayMicroseconds(4);
  293.     for(i=0;i<8;i++)
  294.     {
  295.     delayMicroseconds(4);
  296.     digitalWrite(IIC_SCL,HIGH);
  297.     delayMicroseconds(4);
  298.     pinMode(IIC_SDA,INPUT);
  299.     if(digitalRead(IIC_SDA))
  300.     {
  301.       j=1;
  302.     }
  303.     else
  304.     {
  305.       j=0;
  306.     }
  307.     pinMode(IIC_SDA,OUTPUT);
  308.     k=(k<<1)|j;
  309.     digitalWrite(IIC_SCL,LOW);
  310.     }
  311.     delayMicroseconds(4);
  312.     return k;
  313.     }

  314.     void PCA9685_write(unsigned char address,unsigned char date)
  315.     {
  316.    //Serial.println("PCA9685_write開始");
  317.     start();
  318.     write_byte(PCA9685_adrr); //PCA9685
  319.     ACK();
  320.     write_byte(address); //PCA9685對應內部哪個地址
  321.     ACK();
  322.     write_byte(date); //所寫入的數據
  323.     //Serial.println("所寫入的數據:");
  324.     //Serial.println(date);
  325.     ACK();
  326.     IIC_stop();
  327.     //Serial.println("PCA9685_write結束");
  328.     }

  329.     //從PCA9685讀數據有返回值
  330.     unsigned char PCA9685_read(unsigned char address)
  331.     {
  332.     unsigned char date;
  333.     start();
  334.     write_byte(PCA9685_adrr); //PCA9685
  335.     ACK();
  336.     write_byte(address);//PCA9685對應內部哪個地址
  337.     ACK();
  338.     start();
  339.     write_byte(PCA9685_adrr|0x01); //表示此時狀態為從PCA9685讀取數據
  340.     ACK();
  341.     date=read_byte();
  342.    // Serial.println("date");
  343.     //Serial.println(date);
  344.     return date;
  345.     }

  346. //PCA9685復位
  347.     void reset(void)
  348.     {//Serial.println("RESET開始");
  349.     PCA9685_write(PCA9685_MODE1,0x0);
  350.      //Serial.println("RESET結束");
  351.     }

  352. //PCA9685修改頻率
  353. /*---------------------------------------------------------------
  354.                                 PCA9685修改角度函數
  355. num:舵機PWM輸出引腳0~15,on:PWM上升計數值0~4096,off:PWM下降計數值0~4096
  356. 一個PWM周期分成4096份,由0開始+1計數,計到on時跳變為高電平,繼續計數到off時
  357. 跳變為低電平,直到計滿4096重新開始。所以當on不等于0時可作延時,當on等于0時,
  358. off/4096的值就是PWM的占空比。
  359. ----------------------------------------------------------------*/



  360.     void setPWMFreq(float freq)
  361.      { //Serial.print("設置PWM周期:");
  362.                 unsigned int prescale,oldmode,newmode;
  363.                 float prescaleval;
  364.                 freq *= 0.915;
  365.                 prescaleval = 25000000;
  366.                 prescaleval /= 4096;
  367.                 prescaleval /= freq;
  368.                 prescaleval -= 1;
  369.                 prescale = floor(prescaleval + 0.5);

  370.                 oldmode = PCA9685_read(PCA9685_MODE1);
  371.                 newmode = (oldmode&0x7F) | 0x10; // sleep
  372.                 //Serial.println("新模式:");
  373.                 PCA9685_write(PCA9685_MODE1,newmode); // go to sleep
  374.                // Serial.println("新模式:");
  375.                 // Serial.println(newmode);
  376.                 PCA9685_write(PCA9685_PRESCALE,prescale); // set the prescaler
  377.                 // Serial.println("周期頻率設置值:");
  378.                 // Serial.println(prescale);
  379.                 PCA9685_write(PCA9685_MODE1,oldmode);
  380.                // Serial.println("舊模式:");
  381.                 // Serial.println(oldmode);
  382.                 delay(2);
  383.                 PCA9685_write(PCA9685_MODE1,oldmode | 0xa1);
  384.      }
  385.           void setPWM(unsigned int num, unsigned int on, unsigned int off)
  386.         {
  387.                //Serial.print("當前通道:");
  388.                //Serial.print(num);
  389.                 PCA9685_write(LED0_ON_L+4*num,on);
  390.                 PCA9685_write(LED0_ON_H+4*num,on>>8);
  391.                 PCA9685_write(LED0_OFF_L+4*num,off);
  392.                 PCA9685_write(LED0_OFF_H+4*num,off>>8);
  393.         }

  394. /*void stage1()
  395. {
  396.   Serial.print("timer");

  397. if(stage1_ctrl==true)
  398.    {
  399.     stage1_ctrl=false;
  400.     setPWM(0, 0, SERVO000);//第0路舵機從60度轉到0角度   
  401.    }
  402.    else
  403.    {
  404.     stage1_ctrl=true;
  405.     setPWM(0, 0,224);  //第0路舵機從0度轉到60角度   
  406.    }            
  407.                    //setPWM(0, 0, SERVO180);//第0路舵機轉到0角度     
  408.                    //setPWM(1, 0, SERVO000);//第1路舵機轉到0角度
  409. }
  410. */
復制代碼



評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

沙發
ID:1 發表于 2018-8-25 17:02 | 只看該作者
原理圖能分享下嗎?
回復

使用道具 舉報

板凳
ID:389885 發表于 2018-8-26 11:55 | 只看該作者
admin 發表于 2018-8-25 17:02
原理圖能分享下嗎?

額,沒有畫原理圖,直接接線的。我等下簡單手畫一下吧
回復

使用道具 舉報

地板
ID:389885 發表于 2018-8-26 12:48 | 只看該作者
不懂得怎么發圖片啊。。。那樣成功了沒
回復

使用道具 舉報

5#
ID:390585 發表于 2018-11-8 19:18 | 只看該作者
Riton 發表于 2018-8-26 12:48
不懂得怎么發圖片啊。。。那樣成功了沒

沒有看到圖片
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 91久久久久久久久 | 国产亚洲精品精品国产亚洲综合 | 久久人人网 | 亚洲第一天堂无码专区 | 久久久久久久国产精品影院 | 91久色 | k8久久久一区二区三区 | 欧美日韩国产高清 | 四虎伊人| jizz亚洲人 | 亚洲成人在线免费 | 在线免费看黄 | 国产精品久久久久久久白浊 | 日韩一区二区三区在线视频 | 国产黄色小视频在线观看 | 成人精品一区二区 | 日韩视频在线一区 | 高清一区二区三区 | 国产一区二 | 华人黄网站大全 | 欧美一区二区三区在线 | 久久国产精99精产国高潮 | 男女羞羞视频在线 | 999热精品视频 | 中文字幕在线一区二区三区 | 国产伦精品一区二区三区视频金莲 | 亚洲欧美日韩精品久久亚洲区 | 天天av网 | 欧美一区二区视频 | 日韩三级在线观看 | 日韩精品在线观看免费 | 久久久夜夜夜 | 亚洲精品日韩在线观看 | 一级二级三级在线观看 | 中文字幕高清av | 欧美福利久久 | 欧美色综合| 亚洲精品久久久久久久久久久久久 | www.操.com | 国产一区二区三区四 | 一区二区在线观看免费视频 |