Arduino 制作交通灯 (结合超声波)

一、交通灯

硬件

Arduino Uno
WS2812B串行5050全彩驱动LED
TM1637 4位数码管

环境

arduino IDE

实物

Arduino 制作交通灯 (结合超声波)_第1张图片

接线

Arduino 数码管
5V VCC
GND GND
11 CLK
12 DIO
Arduino 5050全彩驱动LED
5V VCC
GND GND
2 S

程序

#include 
// 数码管  配置引脚
#define CLK 11 //!参数 clk -数字引脚连接到模块的时钟引脚数
#define DIO 12//!参数 dio -数字引脚连接到模块的DIO引脚数 
TM1637 TM(CLK, DIO);//!初始化一个TM1637对象,设置时钟和数据引脚。

//RGB 彩灯
#include 
#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  
#include // 配置引脚
#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()函数获取到测距的结果,并计算出距被测物的实际距离。

你可能感兴趣的:(Arduino,Maker)