문제 2-1
- LED, Buzzer 사용
- 2초 간격으로 교대로 점멸
- 스위치가 눌릴 경우 Buzzer 동작
- delay() 를 사용해서 코드 작성
문제 이해
- 문제 그대로 코드를 작성
코드
int switch_state;
int int_sw = 2;
int LED1 = 22;
int LED2 = 24;
int BUZZER = 8;
int LED1_state = HIGH;
int LED2_state = LOW;
void setup() {
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(BUZZER, OUTPUT);
}
void loop() {
flush();
switch_state = digitalRead(2);
if (switch_state == HIGH) {
digitalWrite(BUZZER, HIGH);
} else {
digitalWrite(BUZZER, LOW);
}
}
void flush() {
if (LED1_state == HIGH) {
digitalWrite(LED1, LED1_state);
delay(2000);
} else if (LED1_state == LOW) {
digitalWrite(LED1, LED1_state);
delay(2000);
}
if (LED2_state == HIGH) {
digitalWrite(LED2, LED2_state);
delay(2000);
} else if (LED2_state == LOW) {
digitalWrite(LED2, LED2_state);
delay(2000);
}
LED1_state = !LED1_state;
LED2_state = !LED2_state;
}
문제 2-2, 2-3
- 2-2
- MsTimer2 인터럽트 이용
- 2-3
- TimerOne 인터럽트 이용
문제 이해
- 각 타이머 인터럽트를 이용하자
코드
#include <TimerOne.h>
#include <MsTimer2.h>
int switch_state;
int int_sw = 2;
int LED1 = 22;
int LED2 = 24;
int BUZZER = 8;
int LED1_state = HIGH;
int LED2_state = LOW;
void setup() {
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(BUZZER, OUTPUT);
MsTimer2::set(2000, flush);
MsTimer2::start();
}
void loop() {
switch_state = digitalRead(2);
if (switch_state == HIGH) {
digitalWrite(BUZZER, HIGH);
} else {
digitalWrite(BUZZER, LOW);
}
}
void flush() {
if (LED1_state == HIGH) {
digitalWrite(LED1, LED1_state);
} else if (LED1_state == LOW) {
digitalWrite(LED1, LED1_state);
}
if (LED2_state == HIGH) {
digitalWrite(LED2, LED2_state);
} else if (LED2_state == LOW) {
digitalWrite(LED2, LED2_state);
}
LED1_state = !LED1_state;
LED2_state = !LED2_state;
}
#include <TimerOne.h>
#include <MsTimer2.h>
#include <LiquidCrystal.h>
// LiquidCrystal lcd(42, 43, 44, 45, 46, 47);
int switch_state;
int int_sw = 2;
int LED1 = 22;
int LED2 = 24;
int BUZZER = 8;
int LED1_state = HIGH;
int LED2_state = LOW;
void setup() {
// put your setup code here, to run once:
// lcd.begin(16, 2);
// lcd.print("hello!");
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(BUZZER, OUTPUT);
Timer1.initialize(2000000); // 2초
Timer1.attachInterrupt(flush);
}
void loop() {
// put your main code here, to run repeatedly:
// lcd.setCursor(0, 1);
// lcd.print(millis() / 1000);
switch_state = digitalRead(2);
if (switch_state == HIGH) {
digitalWrite(BUZZER, HIGH);
} else {
digitalWrite(BUZZER, LOW);
}
}
void flush() {
if (LED1_state == HIGH) {
digitalWrite(LED1, LED1_state);
} else if (LED1_state == LOW) {
digitalWrite(LED1, LED1_state);
}
if (LED2_state == HIGH) {
digitalWrite(LED2, LED2_state);
} else if (LED2_state == LOW) {
digitalWrite(LED2, LED2_state);
}
LED1_state = !LED1_state;
LED2_state = !LED2_state;
}
문제 3
- 디바운스 회로 설계
- Falling 1번 :
- 초음파 센서 LCD에 거리 디스플레이
- 타이머 인터럽트 사용 2행에 디스플레이, 1초마다 LED 점멸
- Falling 3번 :
- 실시간 LCD에 거리 디스플레이
- 20센티미터 미만 LED 계속 HIGH
- 20센티미터 초과 타이머 인터럽트 사용 1초마다 점멸
- Rising 5번 :
- 초음파 센서 LCD에 거리 디스플레이
- 20센티미터 미만 타이머 인터럽트 사용 1초마다 LED 점멸
- 그 이외 LED HIGH, LCD 2행에 경고 문자 출력
문제 이해
- 하나의 핀으로 폴링과 라이징 엣지를 동시에 검출할 수 없다
- 폴링이 끝나면 인터럽트를 초기화 하는 수 밖에.
- 타이머 인터럽트는 마지막에 세팅된 함수만 실행한다.
- stop()을 호출할 것.
코드
#include <TimerOne.h>
#include <MsTimer2.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(42, 43, 44, 45, 46, 47);
int switch_state;
int LED = 22;
int TRIGGER = 12;
int ECHO = 13;
int LED_state = HIGH;
int LCD_state = HIGH;
const byte interruptPin = 2;
volatile int fallingCount = 0;
volatile int risingCount = 0;
volatile long cm; // 거리를 전역적으로 사용하기
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(LED, OUTPUT);
pinMode(ECHO, INPUT);
pinMode(TRIGGER, OUTPUT);
noInterrupts();
interrupts();
attachInterrupt(digitalPinToInterrupt(interruptPin), fallingAct, FALLING); // Falling 부터 진행
lcd.begin(16, 2);
}
void loop() { // 항상 초음파 거리는 lcd에 디스플레이
// put your main code here, to run repeatedly:
cm = getDistanceOfCm();
lcd.setCursor(0, 0);
lcd.print(cm);
}
// 첫번째 Falling edge 시 동작 함수
void countOneAct() {
lcd.setCursor(0, 1);
lcd.print(millis() / 1000);
flushLed();
}
// lcd 점멸
void countFiveAct() {
if (LCD_state == HIGH) {
lcd.setCursor(0, 1);
lcd.print("Warning!!");
} else if (LCD_state == LOW) {
lcd.clear();
}
LCD_state = !LCD_state;
}
// led 점멸
void flushLed() {
digitalWrite(LED, LED_state);
LED_state = !LED_state;
}
// 초음파센서 작동 및 cm 변환 함수
long getDistanceOfCm() {
digitalWrite(TRIGGER, LOW); // 출력 깨끗히!
delayMicroseconds(2);
digitalWrite(TRIGGER, HIGH); // 출력 시작
delayMicroseconds(10);
digitalWrite(TRIGGER, LOW); // 출력 종료
long duration = pulseIn(ECHO, HIGH); // 에코가 트리거가 HIGH 였을 시간을 저장
return (duration / 2) / 29.1; // cm로 변환하여 반환
}
//Falling edge Interrupt Service Routine
void fallingAct() {
fallingCount++; // Falling count 1 증가
if (fallingCount == 1) {
MsTimer2::set(1000, countOneAct);
MsTimer2::start();
}
if (fallingCount == 3) {
lcd.clear();
if (cm < 20) {
MsTimer2::stop();
digitalWrite(LED, HIGH);
} else {
MsTimer2::set(1000, flushLed);
MsTimer2::start();
}
}
if (fallingCount > 3) {
MsTimer2::stop();
noInterrupts(); // Rising Edge를 검출해야 하므로 인터럽트 종료
interrupts();
attachInterrupt(digitalPinToInterrupt(interruptPin), risingAct, RISING);
}
}
void risingAct() {
risingCount++;
if (risingCount == 5) {
lcd.clear();
if (cm < 20) {
MsTimer2::stop();
MsTimer2::set(1000, flushLed);
MsTimer2::start();
} else {
MsTimer2::stop();
digitalWrite(LED, HIGH);
MsTimer2::set(2000, countFiveAct);
MsTimer2::start();
}
}
}
반응형
'💻 Microprocessor > 캡스톤 챌린지' 카테고리의 다른 글
[6주차] (Led Matrix) Capston Challenge (0) | 2022.10.13 |
---|---|
[2주차] (External Interrupt) Caston Challenge 4 (2) | 2022.10.05 |
[2주차] Capston challenge 1 (0) | 2022.09.12 |