실습 과제 

 

 

#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523

#define PIN_PIEZO 10
#define PIN_SWITCH 8 // 버튼 8번 핀에 연결하기 
#define T 200 // 16분 음표 길이
#define DB_WAIT 20 // 디바운싱을 위해 대기 시간 

void setup() {
  pinMode(PIN_PIEZO, OUTPUT);
  pinMode(PIN_SWITCH, INPUT_PULLUP);
  Serial.begin(9600);
  printMsg("\rWelcome to John's JukeBox"); // 환영 메세지 출력
}

int Notes[] = { NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5 };
String NoteStr[] = { "Do", "Re", "Mi", "Fa", "Sol", "La", "Si", "Do5" };

void play_note(int n, int d) {
  Serial.print(NoteStr[n] + " ");
  int duration = T * d; // 지속시간 
  tone(PIN_PIEZO, Notes[n], duration - T * 0.1);
  delay(duration);
}

int airplane_note[] = {2,1,0,1,2,2,2,1,1,1,2,2,2,2,1,0,1,2,2,2,1,1,2,1,0}; 
int airplane_duration[] = {3,1,2,2,2,2,4,2,2,4,2,2,4,3,1,2,2,2,2,4,2,2,2,2,4}; 
int airplane_N = 25;

// 비행기 노래 출력 함수 
void play_airplane() {
  
  for (int i = 0; i < airplane_N; i++) {
    play_note(airplane_note[i], airplane_duration[i]);
  }
}

// 메세지 출력 함수 
void printMsg(char *str){
  Serial.print("\r     ");
  Serial.print(str);
}
// blink 함수 
void blink(){
for(int i=0;i<3;i++){
         digitalWrite(13,HIGH);
         delay(1000);
         digitalWrite(13,LOW);
         delay(1000); 
      }
}
int state=0; //상태 변수 
void loop() {
  switch(state){
    case 0: // 기능 1 안내
      printMsg("\rPlay music?");
      state=1; break;

    case 1: // 기능 1 실행 
      while(digitalRead(8)==HIGH); // 버튼이 눌리지 않은 경우 아무것도 실행하지 않는다 
      printMsg("\rPlay Music....");
      play_airplane(); // 노래 출력 
      state=2; break; 

    case 2: // 기능 2 안내
     printMsg("\rBlink the Light?");
     state=3; break; 

    case 3:
      while(digitalRead(8)==HIGH) ; 
      printMsg("\rBlink LED....");
      blink(); 
      state=0; break; 

    default: break; 
  }
  
}

 

'임베디드 시스템' 카테고리의 다른 글

5장 인터럽트와 millis  (0) 2024.06.16
3. 아두이노 기본 클래스  (0) 2024.06.04
2. 아두이노 소개  (2) 2024.06.04

실습과제 

 

 

 

 

 

#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523

#define PIN_PIEZO 10
#define PIN_SWITCH 2 // Button connected to pin 2, 인터럽트 핀 번호 0번 (Int0)
#define PIN_LED 13 // LED connected to pin 13

#define T 200 // 16th note length
#define DB_WAIT 20 // Debouncing wait time

volatile int sw_pressed = 0; // Interrupt flag

void setup() {
  pinMode(PIN_PIEZO, OUTPUT);
  pinMode(PIN_SWITCH, INPUT_PULLUP);
  pinMode(PIN_LED, OUTPUT);
  
  attachInterrupt(0, sw_isr, FALLING); // 버튼이 눌린 순간 인터럽트 함수 실행 
  Serial.begin(9600);
  printMsg("Welcome to John's JukeBox");
}

// Interrupt service routine
void sw_isr() {
  sw_pressed = 1;
}

int Notes[] = { NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5 };
String NoteStr[] = { "Do", "Re", "Mi", "Fa", "Sol", "La", "Si", "Do5" };

void play_note(int n, int d) {
  if (sw_pressed) return; // 버튼이 눌리면 노래 종료  
  Serial.print(NoteStr[n] + " ");
  int duration = T * d; // 노트 지속 시간
  tone(PIN_PIEZO, Notes[n], duration - T * 0.1);
  delay(duration);
}

int airplane_note[] = {2, 1, 0, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 0, 1, 2, 2, 2, 1, 1, 2, 1, 0}; 
int airplane_duration[] = {3, 1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 3, 1, 2, 2, 2, 2, 4, 2, 2, 2, 2, 4}; 
int airplane_N = 25;

// 비행기 노래 출력 
void play_airplane() {
  for (int i = 0; i < airplane_N; i++) {
    if (sw_pressed) { // 노래 실행 도중 버튼이 눌리면
      sw_pressed = 0; // 리셋
      break; // 노래 종료 
    }
    play_note(airplane_note[i], airplane_duration[i]);
  }
  noTone(PIN_PIEZO); // 재생 중지
}

// 메세지 출력 
void printMsg(const char *str) {
  Serial.print("\r     ");
  Serial.print(str);
}

// led 함수 
void blink() {
  for (int i = 0; i < 10; i++) {
    if (sw_pressed) {
      sw_pressed = 0; // 리셋
      break;
    }
    digitalWrite(PIN_LED, HIGH);
    delay(1000);
    digitalWrite(PIN_LED, LOW);
    delay(1000);
  }
}

int state = 0; // State variable
void loop() {
  switch (state) {
    case 0: // Guide for function 1
      printMsg("Play music?");
      state = 1; 
      break;

    case 1: // Execute function 1
      if(sw_pressed){ // 첫번째 버튼 눌렀을때 
      printMsg("Playing Music....");
      sw_pressed = 0; // 첫번째 버튼에 대한 인터럽트 변수 리셋!! 
      play_airplane(); // 노래 재생
      Serial.print(String("sw_pressed= ")+sw_pressed);
      state = 2; 
      }
     
      break; 

    case 2: // Guide for function 2
      printMsg("Blink the Light?");
      state = 3; 
      break; 

    case 3: // Execute function 2
     if(sw_pressed){
      printMsg("Blinking LED....");
      sw_pressed = 0; // 리셋
      Serial.print(String("sw_pressed= ")+sw_pressed);
      blink();
      state = 0; 
     }
     break; 

    default: 
      break; 
  }
}

 

 

Q 이미 각각의  paly_airplane 과 blink 안에 sw_pressed를 처리하는 부분이 있음에도 불구하고 case문 안에서 sw_pressed를 다시 리셋해주는 이유가 무엇인가 ?

 

Q case문 안에 있는 sw_pressed가 있을때와 없을때의 차이를 생각해보시오 

'임베디드 시스템' 카테고리의 다른 글

4장 디지털 입 출력  (2) 2024.06.16
3. 아두이노 기본 클래스  (0) 2024.06.04
2. 아두이노 소개  (2) 2024.06.04

1. 수업 내용 

▶  Serial과 String 클래스 

 

아두이노는  흔히 사용되는 시리얼 통신과 문자열을 다루기 위해 Serial과 String 클래스를 기본 클래스로 포함하고 있다. 

기본 클래스는 클래스를 사용하기 위한 별도의 헤더파일을 선언 할 필요가 없다. 

 

통신을 하기 위해 직접 연결될 기기와 핀을 꽂아 하드웨어적으로 통신하는 방법도 있지만, 미리 생성된 객체를 통해 통신하는 것이 더욱 좋다. ( 간결성, 편리성, 등등.. ) 

 

 

우노의 경우 하드웨어에 기반한 통신을 위한 포트를 하나만 제공한다. (우노에 보면 핀 번호 0번은 RX, 1번은 TX를 위한 핀이다.)

즉, 우노의 경우 시리얼 통신을 위해 생성 될 수 있는 객체는 하나뿐인 것이다. 

메가의 경우에는 시리얼 통신을 위한 포트가 4개 존재한다. 즉, 우노와 달리 시리얼 통신을 위해 생성 할 수 있는 객체가 4개인 것이다. 

 

Serial 클래스에서 생성한 객체는 Serial_ 로 이름이 붙여지게 된다.  우노의 경우에는 Serial 통신을 위한 객체가 하나뿐이므로 Serial은 클래스이면서 객체로 사용된다. 하지만 메가의 경우 Serial , Serial 1~3 의 객체가 정의되어 있다. 

 

 

 

 

▶ UART 시리얼 통신 

RX와 TX는 서로 교차되어 연결 되야 한다. 

아두이노 보드와 컴퓨터간의 통신은 usb로 이루어지는데 , 컴퓨터에서 보낸 데이터를 직접 받아들일 수 없기 때문에 UART데이터로 변환해서 받아야한다. 

USB-UART 변환을 위해 우노와 메가2560에서는 ATmega16u2를 이용한다. 

 

 

 

컴퓨터와 아두이노의 통신을 위해 스케치에서 통신을 위한 포트를 설정해줘야한다. 

송신측에서  데이터를 보내는 속도와 수신측에서 데이터를 받는 속도를 맞추기 위해  baud rate 가 사용된다. 

 

void setup() { 
  Serial.begin(9600); // 괄호 안에 baud rate값 설정
}

 

 

▶ Serial 클래스에서 제공하는 함수 

  • print() , println()
  • write() : 문자나 문자열 출력에 사용됨
  • int available( ) : 시리얼 통신 수신 버퍼에 저장된 데이터의 바이트 수 
  • int peek ( ) : 시리얼 통신수신 버퍼의 첫번째 바이트 데이터 또는 -1, 읽어온 데이터를 수신 버퍼에서 제거하지 않음 
  • int read ( ) : 시리얼 통신의 첫번째 문자 데이터 또는 -1 , 읽어온 데이터를 수신 버퍼에서 제거함 

 

 

 

 

2.  실습 과제 

 

▶  수동 부저 

 

 

수동 부저란 능동 부저와 달리 신호 단자(S)에 특정 주파수의 펄스가 인가 되면 해당 음높이의 소리를 출력한다. 

능동 부저와 달리 0,1에 따라 소리가 나고 안나고하는 것이 아니라 원하는 음 높이를 설정하여 소리를 출력할 수 있다는 것이다. 

 

그런데 아날로그 신호는 음의 높낮이를 결정할 수 있지만, 전기적인 값을 어떻게 음낮이를 결정할 수 있을까? 

 

이때 이용되는것이 PWM 신호이다. 이는 마치 디지털 신호를 아날로그 신호처럼 변환해주는 것이다.  

아두이노의 tone함수가 그러한 예 중의 하나이다. tone 함수는 PWM 신호를 이용하여 원하는 음 높이의 소리를 출력할 수 있도록 해준다. 

 

  •  tone ( 핀번호, 출력할 주파수, 출력 지속 시간(ms) ) 

출력 지속 시간을 지정하지 않으면 noTone이 호출 될 때까지 지속된다. 

 

  • noTone(핀번호) 

 


 

✅ 실습 과제 

   

1~8의 번호를 입력 받아 도~한 옥타브 도의 음을 출력해주는 코드 작성하기

 

 

#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(10,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
   if(Serial.available()>0){ // 데이터의 입력이 있을때만 동작
    
    byte data= Serial.read(); // 수신 버퍼에서 한 바이트씩 읽어오기 

    switch(data){

      case '1': tone(10, NOTE_C4);  delay(1000); break; 
      case '2': tone(10, NOTE_D4);  delay(1000); break;
      case '3': tone(10, NOTE_E4);  delay(1000); break;
      case '4': tone(10, NOTE_F4);  delay(1000); break;
      case '5': tone(10, NOTE_G4);  delay(1000); break;
      case '6': tone(10, NOTE_A4);  delay(1000); break;
      case '7': tone(10, NOTE_B4);  delay(1000); break;
      case '8': tone(10, NOTE_C5);  delay(1000); break;

    }

    noTone(10);
    
  }
  
}

 

 

'임베디드 시스템' 카테고리의 다른 글

4장 디지털 입 출력  (2) 2024.06.16
5장 인터럽트와 millis  (0) 2024.06.16
2. 아두이노 소개  (2) 2024.06.04

1. 수업 내용 

 

  • pinMode : 디지털 입출력 핀을 입력핀으로 할지 출력핀으로 할지 설정하기 위한 함수
  • digitalWrite : 데이터 출력을 위한 함수, HIGH/LOW 값을 지정 

 


 

▶  1초 간격으로  LED 점멸하기 

 


 

 ▶ 능동 부저 연결하기 



 
능동 부저는 s(신호) 단자에 값이 들어가기만 하면 소리가 출력됨 (원하는 소리를 출력X )  


 

 

 2. 실습 과제

 - blink의 초기주기는 2초이고 반복할때 마다 10%씩 주기가 감소한다.
 - blink의 주기가 20ms가 되면 다시 주기를 2초로 되돌린다. 

 

▶ 풀이과정 

 

#define led 13 // 13번 핀을 led로 사용하기 

int time=1000; //  초기 주기 값 설정 

void setup() {
  pinMode(led,OUTPUT); // led 핀 출력 모드로 설정하기 
  Serial.begin(9600); 
}

void loop() {

digitalWrite(led,HIGH);
delay(time); 
digitalWrite(led,LOW);
delay(time); 

time=time*0.9; // 주기 10% 감소시키기 
if(time<=10){time=1000;} // 주기가 20ms가 되면 다시 2초로 설정하기 
}





 

'임베디드 시스템' 카테고리의 다른 글

4장 디지털 입 출력  (2) 2024.06.16
5장 인터럽트와 millis  (0) 2024.06.16
3. 아두이노 기본 클래스  (0) 2024.06.04

+ Recent posts