본문 바로가기

코딩과 교육/아두이노

CEA-014 아두이노 2개로 신호등 2개 연결하기

CEA-014 아두이노 2개로 신호등 2개 연결하기

인터넷에서 "아두이노 신호등" 으로 검색해 보면 상당한 많은 자료들을 얻을 수 있습니다. 대부분 아두이노 우노에 LED 3개를 연결해서 신호등 하나를 만드는 내용입니다. 혹은 5개를 연결해서 차량용 신호등 하나와 보행자용 신호등하나를 만드는 것도 있습니다.

이 정도의 신호등은 지난시간까지 공부한 내용으로 여러분이 혼자서도 충분히 만들수 있습니다.

오늘 여러분에게 소개할 신호등은 아두이노 우노 2개를 사용해서 만들게 됩니다. 하나의 아두이노에서 LED 3개를 순차적으로 점멸시키는 것은 대부분의 신호등 프로그램과 비슷합니다. 그런데 거기에 두가지를 추가했습니다.




1. 시작시간을 초기화 하는 신호등 리셋 스위치

이 리셋스위치를 누르면 신호등의 신호는 처음으로 초기화됩니다. 초기화되서 맨 처음부터 정해진 순서대로 다시 순서대로 불이 들어옵니다.

2. 설정된 시간이 되면 작동하는 타이머

가변저항, 포텐셔미터의 값을 읽어서 1 에서 100 사이의 값으로 만듭니다. 그 값을 시간으로 계산합니다. 리셋스위치를 누른 후 정해진 시간이 지나면 다른 아두이노의 리셋스위치를 작동시킵니다.




신호등 1개는 너무 쉬워서 2개를 만들어서 연결해 보겠습니다.



그냥 막 연결하지 말고, "제대로" 연결해 봅시다. 보행자도 차를 탄 사람도 불편하지 않게 신호등 체계를 만들어 봅시다.



신호등간 신호를 주는 방식을 간단하게 고안해봤습니다. 하나의 신호등을 초기화하면 옆에 붙은 신호등이 일정한 시간간격을 두고 같이 초기화됩니다. 이 시간간격을 차량이동 예상 시간으로 만들어두면 됩니다.



3개의 아두이노를 꾸며봤습니다. 저항을 잘 보면 색띠가 있습니다. 색띠를 읽으면 저항값을 알 수 있습니다. 참고로 위에서부터 330, 330, 330, 10k, 1k 값을 가집니다. 맨 마지막 저항은 왜 들어갔을까요? 영상에서는 설명해주지 않습니다만 들어가지 않으면 안되는 저항입니다. 나중에 조금 더 아두이노를 공부한 다음에 이 저항에 대해서 설명할 기회가 되면 그때 설명하겠습니다.



Notepad++ 를 사용해서 편집합니다. 제가 주로 사용하는 텍스트에디터는 노트패드++ 입니다. 무료라서 쓰고 있지만 성능도 결코 왠만한 다른 에디터에 떨어지지 않습니다. 플러그인이 많고 다양해서 만족하면서 쓰고 있습니다. 



맨 위의 영상을 꼭 확인해보세요. 여기 전체 소스코드를 올립니다.



#define SIGNAL_RED  5

#define SIGNAL_YELLOW  6

#define SIGNAL_GREEN  7

#define TIMEPIN   A0

#define STARTSWITCH  10 // 스위치 입력

#define NEXTSIGNAL  11 // 다음 신호등 스위치 출력

#define BUTTON_ON   0

#define BUTTON_OFF  1


#define LED_RED_TIME  3000

#define LED_YELLOW_TIME  2000

#define LED_GREEN_TIME  3000



bool buttonState = 1;

bool lastButtonState = 1;

bool resetFlag = 0;

unsigned long timeValue = 0;

byte i=0;

unsigned long nowTime, oldTime;

  

void setup(){

  Serial.begin(9600);

  pinMode(SIGNAL_RED, OUTPUT);

  pinMode(SIGNAL_YELLOW, OUTPUT);

  pinMode(SIGNAL_GREEN, OUTPUT);

  pinMode(STARTSWITCH, INPUT);

  pinMode(NEXTSIGNAL, OUTPUT);

}


void loop(){

  buttonState = digitalRead(STARTSWITCH);


  if(buttonState != lastButtonState ) {

    lastButtonState = buttonState;

    delay(100);

i++;

if(i%2==1) {

signalTowerReset();

Serial.print("timeValue = ");

Serial.println(timeValue);

}

  }

  if(resetFlag) sendTimeSignal();

  ledSignalTower();

}




void signalTowerReset()

{

ledBlink3(); // 전체 신호등이 3번 깜박


resetFlag = 1;

    timeValue = map(analogRead(TIMEPIN), 0, 1023, 1, 100); // 신호등간 시간간격 [0~1023] => [0~99]

nowTime = millis();

oldTime = nowTime;

}



void sendTimeSignal(){

if((nowTime-oldTime)<timeValue*1000){

digitalWrite(NEXTSIGNAL, HIGH);

}

if(((nowTime-oldTime)>=timeValue*1000) && ((nowTime-oldTime)<(timeValue+1)*1000)) {

digitalWrite(NEXTSIGNAL, LOW);

}

if((nowTime-oldTime)>=(timeValue+1)*1000) {

digitalWrite(NEXTSIGNAL, HIGH);

resetFlag = 0;

}

}


void ledSignalTower(){

  nowTime = millis();

  if((nowTime-oldTime>=0)&&(nowTime-oldTime<LED_RED_TIME)) {

 digitalWrite(SIGNAL_RED, HIGH);

 digitalWrite(SIGNAL_YELLOW, HIGH);

 digitalWrite(SIGNAL_GREEN, LOW);

 }


  if((nowTime-oldTime>=LED_RED_TIME)&&(nowTime-oldTime<LED_RED_TIME+LED_YELLOW_TIME+LED_GREEN_TIME)) {

 digitalWrite(SIGNAL_RED, HIGH);

 digitalWrite(SIGNAL_GREEN, HIGH);

 for(byte i=0;i<6;i++ ){

   if((nowTime-oldTime>=LED_RED_TIME+LED_YELLOW_TIME*i/6)&&(nowTime-oldTime<LED_RED_TIME+LED_YELLOW_TIME*(i+1)/6))

 {  digitalWrite(SIGNAL_YELLOW, i%2); }  

 }

  }  

 

 

  if((nowTime-oldTime>LED_RED_TIME+LED_YELLOW_TIME)&&(nowTime-oldTime<LED_RED_TIME+LED_YELLOW_TIME+LED_GREEN_TIME)) {

 digitalWrite(SIGNAL_RED, LOW);

 digitalWrite(SIGNAL_YELLOW, HIGH);

 digitalWrite(SIGNAL_GREEN, HIGH);  

 }

  if(nowTime-oldTime>LED_RED_TIME+LED_YELLOW_TIME+LED_GREEN_TIME) oldTime = nowTime;

}


 

void ledBlink3(){

  for(int tempi=0;tempi<3;tempi++){

digitalWrite(SIGNAL_RED, 1);

digitalWrite(SIGNAL_YELLOW, 1);

digitalWrite(SIGNAL_GREEN, 1);

delay(200);

digitalWrite(SIGNAL_RED, 0);

digitalWrite(SIGNAL_YELLOW, 0);

digitalWrite(SIGNAL_GREEN, 0);

delay(200);

  }

}