프로그래밍/Arduino & IoT
아두이노 가스 안전 밸브
ryujt
2015. 4. 5. 14:30
아두이노 센서 및 모든 부품을 인터넷 검색해서 아들에게 보여주고, 어떤 것을 만들 수 있을 지 아이디어를 물어 본 적이 있었습니다. 그 중에서 가장 쓸만한 아이디어를 직접 만들어 봤습니다. (발명대회에 출품하기 위해서)
- 빨간 버턴을 누르면 밸브가 닫깁니다. 노란 버턴을 누르면 밸브가 열립니다. 전동 밸브를 사용하는 대신 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); }
아래는 제작을 하기 전에 두서 없이 쏟아내는 아이의 아이디어를 마인드 맵으로 정리해 준 자료입니다.
기타
- 주문했지만 아직 오지 않은 숫자 LED 모듈: http://www.banggood.com/4-Bits-Digital-Tube-LED-Display-Module-Board-For-Arduino-p-931236.html