Arduino 製作交通燈 (結合超聲波)

一、交通燈

硬件

Arduino Uno
WS2812B串行5050全綵驅動LED
TM1637 4位數碼管

環境

arduino IDE

實物

在這裏插入圖片描述

接線

Arduino 數碼管
5V VCC
GND GND
11 CLK
12 DIO
Arduino 5050全綵驅動LED
5V VCC
GND GND
2 S

程序

#include <TM1637.h>
// 數碼管  配置引腳
#define CLK 11 //!參數 clk -數字引腳連接到模塊的時鐘引腳數
#define DIO 12//!參數 dio -數字引腳連接到模塊的DIO引腳數 
TM1637 TM(CLK, DIO);//!初始化一個TM1637對象,設置時鐘和數據引腳。

//RGB 彩燈
#include <Adafruit_NeoPixel.h>
#define PIN 2
#define MAX_LED 9
Adafruit_NeoPixel strip = Adafruit_NeoPixel( MAX_LED, PIN, NEO_RGB + NEO_KHZ800 );//長度,引腳,類型
uint32_t color_green = strip.Color(255,0,0); //綠  紅 藍
uint32_t color_red = strip.Color(0,255,0); 
uint32_t color_yellow = strip.Color(255,255,0); 
uint32_t color_traffic[]={color_red,color_yellow,color_green};
//紅燈10秒 綠燈10秒 黃燈2秒
int red_light=5;
int green_light=5;
int yellow_light=2;
int time_count=15; //總時間 15s
int time_=0;//時間 
void setup() { 
 
  TM.show(true);//設置數碼管顯示  爲真顯示,否則不顯示
//  TM.DNum(00,red_light,true);//顯示雙數字,左邊兩位顯示num1最後兩位;左邊兩位顯示num2最後兩位;piont 是否顯示中間的兩點
  
  strip.begin();           //初始化Adafruit_NeoPixel; 
//  initalize_rgb(color_traffic[0]);//初始化彩燈顏色爲紅色
}

void loop(){ 
  static unsigned long time_light=0;
  if(millis()-time_light>1000){//計算時間 1秒 time_ +1
    time_light=millis();
    time_++;
  }
  if(time_<=red_light){//紅燈
    traffic(red_light-time_); //時間
    initalize_rgb(color_traffic[0]);//顏色
  }
  else if(time_<=yellow_light+red_light){//黃燈
    traffic(yellow_light+red_light-time_);
    initalize_rgb(color_traffic[1]);
  }else if(time_<=yellow_light+red_light+green_light){//綠燈
    traffic(yellow_light+red_light+green_light-time_);
    initalize_rgb(color_traffic[2]);
  }else if(time_<=yellow_light*2+red_light+green_light){//黃燈
    traffic(yellow_light*2+red_light+green_light-time_);
    initalize_rgb(color_traffic[1]);
  }

  if(time_==time_count) time_=0;//時間歸零
 
}
void traffic(int time_traffic){
   TM.DNum(00,time_traffic,true);
   time_traffic--;
}

void initalize_rgb(uint32_t color){
  strip.setPixelColor(0, color);//顏色
  strip.setPixelColor(1, color);
  strip.setBrightness(255);//亮度
  strip.show();//顯示
}

下載鏈接:
https://download.csdn.net/download/m0_37738838/11143906

二、交通燈(結合超聲波)

硬件

數碼管 *2
超聲波 *2
LED交通燈 *2

環境

arduino IDE

實物

在這裏插入圖片描述

程序

const int TrigPin = 6;
const int EchoPin = 7;
const int TrigPin2 = 4;//超聲波引腳2
const int EchoPin2 = 5;

//紅綠仍引腳
int y1=8;
int red1=9;
int g1=10;
int y2=11;
int red2=12;
int g2=13;

float cm;
float p1=0;
float p2=0;
#include <Metro.h> 
#include <TM1637.h>// 配置引腳
#define CLK 2 //!參數 clk -數字引腳連接到模塊的時鐘引腳數
#define DIO 3//!參數 dio -數字引腳連接到模塊的DIO引腳數 

#define CLK2 A0 //!參數 clk -數字引腳連接到模塊的時鐘引腳數
#define DIO2 A1//!參數 dio -數字引腳連接到模塊的DIO引腳數 

TM1637 TM1(CLK, DIO);//!初始化一個TM1637對象,設置時鐘和數據引腳。
TM1637 TM2(CLK2, DIO2);//!初始化一個TM1637對象,設置時鐘和數據引腳。
Metro metro1 = Metro(1000);
Metro metro2 = Metro(600);
int Yellow_LED=2;
int Green_LED=10;
int Red_LED=10;
int ms=0; 
int flag=0;
int flag2=0;
int ms2;
int ms3;
int sum;
int sum2;
bool FLAG=false;
bool flag_one=false;
bool flag_two=false;
bool flag_three=true;
void setup()
{
  Serial.begin(9600);
   pinMode(red1, OUTPUT);
   pinMode(red2, OUTPUT);
   pinMode(g1, OUTPUT);
   pinMode(g2, OUTPUT);
   pinMode(y1, OUTPUT);
   pinMode(y2, OUTPUT);
  pinMode(TrigPin, OUTPUT);
  pinMode(EchoPin, INPUT);
  pinMode(TrigPin2, OUTPUT);
  pinMode(EchoPin2, INPUT);
  TM1.show(true);//設置數碼管顯示  爲真顯示,否則不顯示
  TM2.show(true);//設置數碼管顯示  爲真顯示,否則不顯示

//  TM1.DNum(0,28,true);
}

void loop()
{
  if(metro2.check()){
     float cm1=Chao_shen_bo( TrigPin,  EchoPin);
      float cm2=Chao_shen_bo( TrigPin2,  EchoPin2);
      if(cm1<30){
        p1=p1+1;
      }
      if(cm2<30){
        p2=p2+1;
      }
      Serial.print("p1:");
      Serial.print(p1);
      Serial.print(" p2:");
      Serial.print(p2);
      Serial.println();
      Serial.print("sum:");
      Serial.print(sum);
      Serial.print(" sum2:");
      Serial.print(sum2);
      Serial.println();
      Serial.println();
//     Serial.println(cm1);   
  }

 if(metro1.check()){
    ms++;
    ms2++;
    ms3++;
 }


  if(ms==Red_LED){
    flag=1;
 }else if(ms==(Red_LED+Yellow_LED)){
    flag=2;
 }else if(ms==(Green_LED+Yellow_LED+Red_LED)){
    flag=0;
 }

 if(ms2==Green_LED){
    flag2=1;
 }else if(ms2==(Green_LED+Yellow_LED)){
    flag2=2;
 }else if(ms2==(Green_LED+Yellow_LED+Red_LED)){
    flag2=0;
 }
 if(flag_one||flag_three){
  one();
 }else if(flag_two){
  two();
 }
 


 
  if(ms==22||ms2==22){
    ms=0;
    ms2=0;
    FLAG=true;
   TM1.DNum(0,0,true);
 }
  if(ms3==23){
   ms3=1;
   p1=0;
   p2=0;
 }
 if(p1-p2>=2&&FLAG){
  Yellow_LED=2;
  Green_LED=12;
  Red_LED=8;
  flag_one=true;
  flag_two=false;
  flag_three=false;
  
 }else if(p2-p1>=2&&FLAG){
  Yellow_LED=2;
  Green_LED=8;
  Red_LED=12;
  flag_one=false;
  flag_two=true;
  flag_three=false;
 }else{
  if(FLAG){
  Yellow_LED=2;
  Green_LED=10;
  Red_LED=10;
  flag_one=false;
  flag_two=false;
  flag_three=true;
  }
  
 }
 
 

//  Serial.print("Distance:");
//  Serial.print(cm1);
//  Serial.print("cm");
//  Serial.println();
//  delay(1000);
}

void one(){
  if(flag==0){
   FLAG=false;
  LED1(3);
  sum=Red_LED-ms;
  TM1.DNum(0,sum,true);//顯示雙數字,左邊兩位顯示num1最後兩位;左邊兩位顯示num2最後兩位;piont 是否顯示中間的兩點
 }else if(flag==1){
   FLAG=false;
  LED1(2);
  sum=Red_LED+Yellow_LED-ms;
  TM1.DNum(0,sum,true);
 }else if(flag==2){
   FLAG=false;
  LED1(1);
  sum=Green_LED+Yellow_LED+Red_LED-ms;
  TM1.DNum(0,sum,true);
 }

 if(flag2==0){
   FLAG=false;
  LED2(1);
  sum2=Green_LED-ms2;
  TM2.DNum(0,sum2,true);//顯示雙數字,左邊兩位顯示num1最後兩位;左邊兩位顯示num2最後兩位;piont 是否顯示中間的兩點
 }else if(flag2==1){
   FLAG=false;
  LED2(2);
  sum2=Green_LED+Yellow_LED-ms2;
  TM2.DNum(0,sum2,true);
 }else if(flag2==2){
   FLAG=false;
  LED2(3);
  sum2=Green_LED+Yellow_LED+Red_LED-ms2;
  TM2.DNum(0,sum2,true);
  }
}

void two(){
  if(flag==0){
   FLAG=false;
  LED1(3);
  sum=Red_LED-ms;
  TM1.DNum(0,sum,true);//顯示雙數字,左邊兩位顯示num1最後兩位;左邊兩位顯示num2最後兩位;piont 是否顯示中間的兩點
 }else if(flag==1){
   FLAG=false;
  LED1(2);
  sum=Red_LED+Yellow_LED-ms;
  TM1.DNum(0,sum,true);
 }else if(flag==2){
   FLAG=false;
  LED1(1);
  sum=Green_LED+Yellow_LED+Red_LED-ms;
  TM1.DNum(0,sum,true);
 }

 if(flag==0){
   FLAG=false;
  LED2(1);
  sum2=Red_LED-ms2;
  TM2.DNum(0,sum2,true);//顯示雙數字,左邊兩位顯示num1最後兩位;左邊兩位顯示num2最後兩位;piont 是否顯示中間的兩點
 }else if(flag==1){
   FLAG=false;
  LED2(2);
  sum2=Red_LED+Yellow_LED-ms2;
  TM2.DNum(0,sum2,true);
 }else if(flag==2){
   FLAG=false;
  LED2(3);
  sum2=Green_LED+Yellow_LED+Red_LED-ms2;
  TM2.DNum(0,sum2,true);
  }
}


float Chao_shen_bo(int TrigPin,int EchoPin){//超聲波測距
   digitalWrite(TrigPin, LOW); //低高低電平發一個短時間脈衝去TrigPin
  delayMicroseconds(2);
  digitalWrite(TrigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(TrigPin, LOW);
  cm = pulseIn(EchoPin, HIGH) / 58.0; //檢測脈衝寬度  將回波時間換算成cm
  cm = (int(cm * 100.0)) / 100.0; //保留兩位小數
  return cm;
}
void LED1(int color ){
  switch(color){
    case 1:digitalWrite(g1,HIGH);digitalWrite(y1,LOW);digitalWrite(red1,LOW);break;
    case 2:digitalWrite(g1,LOW);digitalWrite(y1,HIGH);digitalWrite(red1,LOW);break;
    case 3:digitalWrite(g1,LOW);digitalWrite(y1,LOW);digitalWrite(red1,HIGH);break;
  } 
}

void LED2(int color ){
  switch(color){
    case 1:digitalWrite(g2,HIGH);digitalWrite(y2,LOW);digitalWrite(red2,LOW);break;
    case 2:digitalWrite(g2,LOW);digitalWrite(y2,HIGH);digitalWrite(red2,LOW);break;
    case 3:digitalWrite(g2,LOW);digitalWrite(y2,LOW);digitalWrite(red2,HIGH);break;
  } 
}

拓展

超聲波發射器向某一方向發射超聲波,在發射的同時開始計時,超聲波在空氣中傳播,途中碰到障礙物就立即返回來,超聲波接收器收到反射波就立即停止計時。聲波在空氣中的傳播速度爲340m/s,根據計時器記錄的時間t,就可以計算出發射點距障礙物的距離s,即:s=340m/s×t
/ 2 。這就是所謂的時間差測距法。

pulseIn函數知識要點:
pulseIn():用於檢測引腳輸出的高低電平的脈衝寬度。
pulseIn(pin, value)
pulseIn(pin, value, timeout)
Pin—需要讀取脈衝的引腳
Value—需要讀取的脈衝類型,HIGH或LOW
Timeout—超時時間,單位微秒,數據類型爲無符號長整型

pulseIn函數其實就是一個簡單的測量脈衝寬度的函數,默認單位是us。也就是說pulseIn測出來的是超聲波從發射到接收所經過的時間。對於除數58也很好理解,聲音在乾燥、攝氏 20度的空氣中的傳播速度大約爲343米/秒,合34,300釐米/秒。或者,我們作一下單位換算,34,300除以1,000,000釐米/微秒。即爲:0.0343釐米/微秒,再換一個角度,1/(0.0343 釐米/微秒)即:29.15 微秒/釐米。這就意味着,每291.5微秒錶示10CM的距離。1釐米就是29.15微秒。但是發送後到接收到回波,聲音走過的是2倍的距離呀。
所以實際距離就是1釐米,對應58.3微秒。實際上整個測距過程是測的發出聲波到收到回波的時間,你的程序裏的第一個distance實際上是時間us。所以換成距離cm,要除以58。當然除以58.3可能更精確。所以我們可以用 pulseIn(EchoPin, HIGH) / 58.00獲取測得的距離。

使用方法及時序圖:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

1、使用Arduino採用數字引腳給SR04的Trig引腳至少10μs的高電平信號,觸發SR04模塊測距功能;
2、觸發後,模塊會自動發送8個40KHz的超聲波脈衝,並自動檢測是否有信號返回。這步會由模塊內部自動完成。
3、如有信號返回,Echo引腳會輸出高電平,高電平持續的時間就是超聲波從發射到返回的時間。此時,我們能使用pulseIn()函數獲取到測距的結果,並計算出距被測物的實際距離。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章