아두이노 센서 및 모든 부품을 인터넷 검색해서 아들에게 보여주고, 어떤 것을 만들 수 있을 지 아이디어를 물어 본 적이 있었습니다.  그 중에서 가장 쓸만한 아이디어를 직접 만들어 봤습니다.  (발명대회에 출품하기 위해서)

  • 빨간 버턴을 누르면 밸브가 닫깁니다.  노란 버턴을 누르면 밸브가 열립니다.  전동 밸브를 사용하는 대신 LED로 표현했습니다.  (전기를 이용한 밸브 차단기는 http://www.banggood.com/Brass-220V-AC-12inch-Electric-Water-Air-Fuels-Gas-Solenoid-Valve-p-908334.html)
  • 왼쪽 밑에 초음파 센서에 사람이 감지되지 않으면, 즉 가스를 켜두고 자리를 비우면 숫자 LED가 0에서부터 9까지 1초마다 증가합니다.
  • 초음파 센서에 사람이 감지되면 초음파 센서 위에 빨간 LED에 불이 들어오고, 숫자 LED는 0으로 다시 세팅 됩니다.
  • 밸브가 열려있고, 9초 이상 자리를 비우면 알람 소리가 나면서 밸브가 자동으로 닫히게 됩니다.
    • 시연을 위해서 시간을 짧게 하였습니다.

숫자 LED 모듈을 뱅굿에 주문을 했지만, 제 때 도착하지 않고 있어서 직접 만들었습니다.  주문한 제품은 4자리 숫자이기 때문에 시간 설정을 좀 더 자유롭게 할 수 있습니다.


소스 코드가 너무 길어서 아이에게 다시 설명하는 동안 많이 어려워 합니다.  특히 시프트 레지스터를 이용한 숫자 표시 부분에서 많이 어려워합니다.  (아두이노 핀이 모자라서, 숫자 LED마다 아두이노 핀을 사용 할 수는 없었습니다)


아래는 프로토타입을 만들고 동작 설명을 하는 영상입니다.




전체 소스 코드는 아래와 같습니다.


// LED Digit Display
int pinData = 2; 
int pinClock = 3;
int pinLatch = 4;

// Two Button Module
int pinButtonOn = 5;
int pinButtonOff = 6;

// LED for valve On/Off
int pinValveOn = 7;
int pinValveOff = 8;

int pinBuzzer = 9; 

// Ultra Sonic Sensor
int pinEcho = 10;
int pinTrigger = 11;

// LED for Ultra Sonic Sensor
int pinObjectDetected = 12;

int timer_count_limit = 9 * 1000;

int isObjectDetected = false;
int isValveOpen = false;
int timer_count = 0;

unsigned long oldMillis = 0;

void setup() {
  Serial.begin(9600);

  pinMode(pinData, OUTPUT);
  pinMode(pinClock, OUTPUT);  
  pinMode(pinLatch, OUTPUT);

  pinMode(pinButtonOn, INPUT);
  pinMode(pinButtonOff, INPUT);
  
  pinMode(pinValveOn, OUTPUT);
  pinMode(pinValveOff, OUTPUT);
  
  pinMode(pinBuzzer, OUTPUT);  
  
  pinMode(pinEcho, INPUT);
  pinMode(pinTrigger, OUTPUT);
  pinMode(pinObjectDetected, OUTPUT);
  
  oldMillis = millis();
}

void loop() {
  check_ObjectDetected();
  check_ValveButton();
  check_timer();
  check_value();
}

void check_ObjectDetected()
{
  digitalWrite(pinTrigger, HIGH); 
  delayMicroseconds(10); 
  digitalWrite(pinTrigger, LOW);
  
  long duration = pulseIn(pinEcho, HIGH); 
  
  Serial.print(microsecondsToCentimeters(duration));
  Serial.println();
  
  isObjectDetected = microsecondsToCentimeters(duration) <= 30;
  
  if (isObjectDetected) digitalWrite(pinObjectDetected, HIGH);
  else digitalWrite(pinObjectDetected, LOW);
}

void check_ValveButton()
{
  if (digitalRead(pinButtonOn)  == LOW) isValveOpen = true;
  if (digitalRead(pinButtonOff) == LOW) isValveOpen = false;

  if (isValveOpen) {
    digitalWrite(pinValveOn, HIGH);
    digitalWrite(pinValveOff, LOW);
  } else {
    digitalWrite(pinValveOn, LOW);
    digitalWrite(pinValveOff, HIGH);
  }  
}

void check_timer()
{
  unsigned long currentMillis = millis();
  
  if (isObjectDetected || (!isValveOpen)) {
    timer_count = 0;
  } else {  
    timer_count = timer_count + (currentMillis - oldMillis);
  }
  
  displayNumber(timer_count / 1000);
  
  oldMillis = currentMillis;
}

void check_value()
{
  if ((isValveOpen) && (timer_count >= timer_count_limit)) {
    isValveOpen = false;

    digitalWrite(pinValveOn, LOW);
    digitalWrite(pinValveOff, HIGH);

    alarm(pinBuzzer);
  }
}

long microsecondsToInches(long microseconds)
{
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29 / 2;
}

void beep(int speakerPin, float noteFrequency, long noteDuration) {
	int x;
	// Convert the frequency to microseconds
	float microsecondsPerWave = 1000000 / noteFrequency;
	// Calculate how many milliseconds there are per HIGH/LOW cycles.
	float millisecondsPerCycle = 1000 / (microsecondsPerWave * 2);
	// Multiply noteDuration * number or cycles per millisecond
	float loopTime = noteDuration * millisecondsPerCycle;
	// Play the note for the calculated loopTime.
	for (x = 0; x < loopTime; x++) {
		digitalWrite(speakerPin, HIGH);
		delayMicroseconds(microsecondsPerWave);
		digitalWrite(speakerPin, LOW);
		delayMicroseconds(microsecondsPerWave);
	}
}

void alarm(int pinNo) {
  int i, j;

	for (j = 1; j < 10; j++) {
		for (i = 300; i < 1800; i = i + 40) {
			beep(pinNo, i, 11);
		}
	}
}

void displayNumber(int number)
{
  if (number > 9) number = 9;
  
  byte digits[10] = {
    0b11000000,  // 0
    0b11111001,  // 1
    0b10100100,  // 2
    0b10110000,  // 3
    0b10011001,  // 4
    0b10010010,  // 5
    0b10000010,  // 6
    0b11011000,  // 7
    0b10000000,  // 8
    0b10011000   // 9
  };

  byte data = digits[number];
  
  shiftOut(pinData, pinClock, MSBFIRST, data);
  digitalWrite(pinLatch, HIGH);
  digitalWrite(pinLatch, LOW);
}


아래는 제작을 하기 전에 두서 없이 쏟아내는 아이의 아이디어를 마인드 맵으로 정리해 준 자료입니다.





기타


'프로그래밍 > Arduino & IoT' 카테고리의 다른 글

아두이노 - 뮤직박스  (0) 2015.04.19
SW-420 센서  (0) 2015.04.12
아두이노 가스 안전 밸브  (0) 2015.04.05
Arduino based wireless power  (0) 2015.03.21
중국산 저가형 아두이노 사용 후기  (0) 2015.03.20
RC Car #1  (1) 2015.03.07

Posted by 류종택