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()函数获取到测距的结果,并计算出距被测物的实际距离。

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