一、交通燈
硬件
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()函數獲取到測距的結果,並計算出距被測物的實際距離。