4. 알람이 울리는 무드등

by 이서희 | 2017-07-04 17:01
arduino character coding mp3 노래 만들기 무드등 빛센서 쉬운 아두이노 알람 캐릭터

재료

  • 캐릭보드 싱글박스 1개

이번에는 정해진 시간이 되면 조명과 함께 노래가 나오는 알람기능을 추가해보겠습니다.



1. 모듈 연결하기

자신의 캐릭보드에 네오픽셀과 스피커&mp3모듈이 연결되어있는지 확인하세요. 연결되어 있지 않으면 링크를 참고하여 연결해야합니다.

1) RTC 연결하기


연결을 완료한 모습입니다.



2. 라이브러리 설치하기

프로그램을 실행하기에 앞서 time library를 추가해야합니다.

다음 링크에서 라이브러리를 다운로드 받습니다.

-Time Library  https://github.com/PaulStoffregen/Time


1) 다른 라이브러리들과 마찬가지로 오른쪽 상단의 Download Zip 버튼을 클릭한 후 압축을 풀어줍니다.



2) 압축을 풀고나서 자신의 컴퓨터 환경에 맞게 Arduino-Libraries 폴더안에 가져다 놓습니다. 

저는 windows 환경이므로 C:\Program Files (x86)\Arduino\libraries 위치에 이동시켰습니다.

이제 프로그램을 실행할 수 있습니다.


3. 아듀이노 프로그램 실행하기

1) 현재시간 설정하기

먼저 다음과 같은 코드를 실행시킵니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <Time.h>
#include <TimeLib.h>
#include <Wire.h>
#include <DS1307RTC.h>
 
const char *monthName[12= {
  "Jan""Feb""Mar""Apr""May""Jun",
  "Jul""Aug""Sep""Oct""Nov""Dec"
};
 
tmElements_t tm;
 
void setup() {
  bool parse=false;
  bool config=false;
 
  // get the date and time the compiler was run
  if (getDate(__DATE__) && getTime(__TIME__)) {
    parse = true;
    // and configure the RTC with this info
    if (RTC.write(tm)) {
      config = true;
    }
  }
 
  Serial.begin(9600);
  while (!Serial) ; // wait for Arduino Serial Monitor
  delay(200);
  if (parse && config) {
    Serial.print("DS1307 configured Time=");
    Serial.print(__TIME__);
    Serial.print(", Date=");
    Serial.println(__DATE__);
  } else if (parse) {
    Serial.println("DS1307 Communication Error :-{");
    Serial.println("Please check your circuitry");
  } else {
    Serial.print("Could not parse info from the compiler, Time=\"");
    Serial.print(__TIME__);
    Serial.print("\", Date=\"");
    Serial.print(__DATE__);
    Serial.println("\"");
  }
}
 
void loop() {
}
 
bool getTime(const char *str)
{
  int Hour, Min, Sec;
 
  if (sscanf(str, "%d:%d:%d"&Hour, &Min, &Sec) != 3return false;
  tm.Hour = Hour;
  tm.Minute = Min;
  tm.Second = Sec;
  return true;
}
 
bool getDate(const char *str)
{
  char Month[12];
  int Day, Year;
  uint8_t monthIndex;
 
  if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3return false;
  for (monthIndex = 0; monthIndex < 12; monthIndex++) {
    if (strcmp(Month, monthName[monthIndex]) == 0break;
  }
  if (monthIndex >= 12return false;
  tm.Day = Day;
  tm.Month = monthIndex + 1;
  tm.Year = CalendarYrToTm(Year);
  return true;
}
 
cs


2) 캐릭터 알람코드 실행하기

이제 알람을 설정해봅시다. 아래 코드를 실행시켜봅시다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <Time.h>
#include <TimeLib.h>
#include <Wire.h>
#include <DS1307RTC.h>
#include <DFPlayer_Mini_Mp3.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
 
SoftwareSerial mp3Serial(1213);
 
#define neopixelPIN    6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(5, neopixelPIN, NEO_GRB + NEO_KHZ800);
 
int red;
int green;
int blue;
 
String inputString = "";
boolean stringComplete = false;
boolean stringYear = false;
String input_year = "";
String input_month = "";
String input_day = "";
String input_hour = "";
String input_min = "";
 
int year_int = 0;
int month_int = 0;
int day_int = 0;
int hour_int = 0;
int min_int = 0;
 
tmElements_t tm;
 
void setup() {
  Serial.begin(9600);
  strip.begin();
  mp3Serial.begin(9600);
  mp3_set_serial (mp3Serial);
  delay(1);
  mp3_set_volume (15);
}
 
void loop() {
 
  if (Serial.available() > 0) {
    inputString = Serial.readString();
    if (inputString.charAt(0== 'a') {
      Serial.println("Time Setting");
      timeConverter();
    }
  }
 
  if (RTC.read(tm)) {
    //시간 출력하기 (시리얼창)
    Serial.print("computer : ");
    Serial.print(tmYearToCalendar(tm.Year));
    Serial.print("/");
    Serial.print(tm.Month);
    Serial.print("/");
    Serial.print(tm.Day);
    Serial.print("  ");
    Serial.print(tm.Hour);
    Serial.print(":");
    Serial.print(tm.Minute);
    Serial.println();
    delay(500);
    //알람시간체크하기
    if (tmYearToCalendar(tm.Year) == year_int && tm.Month == month_int && tm.Day == day_int && tm.Hour == hour_int && tm.Minute == min_int) {
      Serial.println("Wake up!!!!!!");
      for (int i = 0; i < 5; i++) { //불 켜기
        red = 255;
        green = 255;
        blue = 255;
        strip.setPixelColor(i, strip.Color(red, green, blue));
        strip.show();
      }
      mp3Serial.listen();
      if (mp3Serial.isListening()) { //소리켜기
        Serial.println("Play");
        mp3_play(1);
        delay (4000);
        mp3_stop();
      }
    } else { //설정한 시간이 아닐 때, 불 끄기
      for (int i = 0; i < 5; i++) { //불 끄기
        strip.setPixelColor(i, strip.Color(000));
        strip.show();
      }
    }
  }
}
 
//Data Check---------------------------------------------------------------
void timeConverter() { //읽어온 데이터를 알람시간으로 바꾸기
  //serial input to char
  Serial.print("Set Alarm Time : ");
  input_year = inputString.substring(15);
  Serial.print(input_year);
  Serial.print("/");
  input_month = inputString.substring(57);
  Serial.print(input_month);
  Serial.print("/");
  input_day = inputString.substring(79);
  Serial.print(input_day);
  Serial.print("   ");
  input_hour = inputString.substring(911);
  Serial.print(input_hour);
  Serial.print(":");
  input_min = inputString.substring(1113);
  Serial.println(input_min);
  //to int
  year_int = input_year.toInt();
  month_int = input_month.toInt();
  day_int = input_day.toInt();
  hour_int = input_hour.toInt();
  min_int = input_min.toInt();
}
 
cs


혹시 업로드시 시리얼 포트  'COM7' 를 여는데 에러 발생 (Port busy) 라는 오류가 발생하면 포트를 뽑고 다시 연결해보시기 바랍니다.


이제 시리얼창을 열어봅시다.

시리얼창은 아듀이노 창의 오른쪽 상단의 돋보기 표시를 클릭하면 나타납니다.

다음과 같이 포트제목으로 된 창에서 상단의 한 칸이 입력 창, 하단의 커다란 칸이 출력 창입니다.



그런데 시리얼창에 아무런 출력이 보이지 않는군요. 코드 상 현재 시각이 계속해서 찍혀야 합니다.

원인 분석을 위해 모듈검사를 실시해보겠습니다.


그리고 코드는 다른 분의 프로젝트 의 코드로 새롭게 실행해보았습니다. 알람이 울리기 3분전에 캐릭터가 무지개 빛이 켜지며 알람시간이 되면 음악과 함께 하얀 불빛으로 빛나는 코드입니다.

코드는 다음과 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <Time.h>
#include <TimeLib.h>
#include <Wire.h>
#include <DS1307RTC.h>
#include <DFPlayer_Mini_Mp3.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
 
SoftwareSerial mp3Serial(1213);
 
#define neopixelPIN    6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(5, neopixelPIN, NEO_GRB + NEO_KHZ800);
 
int red;
int green;
int blue;
 
String inputString = "";
boolean stringComplete = false;
boolean stringYear = false;
String input_year = "";
String input_month = "";
String input_day = "";
String input_hour = "";
String input_min = "";
 
int year_int = 0;
int month_int = 0;
int day_int = 0;
int hour_int = 0;
int min_int = 0;
 
tmElements_t tm;
 
void setup() {
  Serial.begin(9600);
  strip.begin();
  mp3Serial.begin(9600);
  mp3_set_serial (mp3Serial);
  delay(1);
  mp3_set_volume (15);
}
void rainbow() {
  uint16_t i, j, k;
  for(k=0; k<5; k++){
    for(j=0; j<256; j++){ 
      for(i=0; i< 5; i++){
        strip.setPixelColor(i, rainbowcolor(((i * 256 / 5+ j*k) & 255));
      }
      strip.show();
      delay(10);
    }
  }
}
 
uint32_t rainbowcolor(byte Pos) {
  if(Pos < 85) {
   return strip.Color(Pos * 3255 - Pos * 30);
  } else if(Pos < 170) {
   Pos -= 85;
   return strip.Color(255 - Pos * 30, Pos * 3);
  } else {
   Pos -= 170;
   return strip.Color(0, Pos * 3255 - Pos * 3);
  }
}
 
void lightChase(uint32_t c) 
{
  for (int j=0; j<50; j++) {
    for (int q=0; q < 3; q++) {
      for (int i=0; i < 5; i=i+3) {
        strip.setPixelColor(i+q, c);   
      }
      
      strip.show();
      delay(10);
 
      for (int i=0; i < 5; i=i+3) {
        strip.setPixelColor(i+q, 0);   
      }
    }
  }
}
  void randcolor()
{
  red = random(256);
  green = random(256);
  blue = random(256);
void loop() {
 
  if (Serial.available() > 0) {
    inputString = Serial.readString();
    if (inputString.charAt(0== 'a') {
      Serial.println("Time Setting");
      timeConverter();
    }
  }
 
  if (RTC.read(tm)) {
    //시간 출력하기 (시리얼창)
    Serial.print("computer : ");
    Serial.print(tmYearToCalendar(tm.Year));
    Serial.print("/");
    Serial.print(tm.Month);
    Serial.print("/");
    Serial.print(tm.Day);
    Serial.print("  ");
    Serial.print(tm.Hour);
    Serial.print(":");
    Serial.print(tm.Minute);
    Serial.println();
    delay(500);
    //알람시간체크하기
    if (tmYearToCalendar(tm.Year) == year_int && tm.Month == month_int 
&& tm.Day == day_int && tm.Hour == hour_int && tm.Minute == min_int) {
      Serial.println("일어나세요!!");
      randcolor();
      lightChase(strip.Color(red, green, blue));
      for (int i = 0; i < 5; i++) { //불 켜기
        strip.setPixelColor(i, strip.Color(red, green, blue));
        strip.show();
      }
      mp3Serial.listen();
      if (mp3Serial.isListening()) { //소리켜기
        Serial.println("Play");
        mp3_play(1);
        delay (3000000);
        mp3_stop();
        mp3_play(2);
        delay (3000000);
        mp3_stop();
      }
    } 
    else if (tmYearToCalendar(tm.Year) == year_int && tm.Month == month_int 
&& tm.Day == day_int && tm.Hour == hour_int && tm.Minute == min_int-3 
|| tm.Minute == min_int-2 || tm.Minute == min_int-1) {
      Serial.println("알람이 곧 울립니다");
      rainbow();
      }
    
    else { //설정한 시간이 아닐 때, 불 끄기
      for (int i = 0; i < 5; i++) { //불 끄기
        strip.setPixelColor(i, strip.Color(000));
        strip.show();
      }
    }
  }
}
 
//Data Check---------------------------------------------------------------
void timeConverter() { //읽어온 데이터를 알람시간으로 바꾸기
  //serial input to char
  Serial.print("Set Alarm Time : ");
  input_year = inputString.substring(15);
  Serial.print(input_year);
  Serial.print("/");
  input_month = inputString.substring(57);
  Serial.print(input_month);
  Serial.print("/");
  input_day = inputString.substring(79);
  Serial.print(input_day);
  Serial.print("   ");
  input_hour = inputString.substring(911);
  Serial.print(input_hour);
  Serial.print(":");
  input_min = inputString.substring(1113);
  Serial.println(input_min);
  //to int
  year_int = input_year.toInt();
  month_int = input_month.toInt();
  day_int = input_day.toInt();
  hour_int = input_hour.toInt();
  min_int = input_min.toInt();
}
cs




모듈검사

모듈 검사를 위해 오류가 있을 가능성이 큰 모듈들을 각기 테스트해보겠습니다.

먼저 나노보드를 바꿔 끼워보았습니다. 하지만 역시나 시리얼창에 아무것도 찍히지 않는 상태입니다.



다음은 RTC 모듈을 바꿔 끼워보았습니다. 이번에는 시리얼 창에 시간 로그라 찍히기 시작했습니다.


RTC 모듈에 이상이 있거나, 배터리가 떨어졌던 것 같습니다.

이제 알람을 설정해볼까요?


3) 시리얼창에 알람시간 입력하기

시리얼 창에  'ayyyymmddhhmm' 형식으로 알람이 울리는 시간을 설정할 수 있습니다.

예를 들면 'a201707040430'이라고 입력하면 2017년 7월 4일 오후 2시 30분에 알람이 울리게 됩니다.


현재 시각의 1분 뒤로 설정해보았습니다.

그러자 시리얼 창에 'Time Setting'의 메세지가 뜨면서 설정된 알람시각을 보여줍니다.

정해진 시각이 되자 '일어나세요!!' 메세지와 'Play' 메세지가 뜨면서 LED가 하얀 빛으로 켜지고 음악이 울립니다.




<알람이 울리기 직전 모습>






알람시각이 되면 어떻게 될까요? 동영상으로 확인해봅시다.





다행히 알람이 제대로 울리는 것을 확인할 수 있습니다.

자신만의 색깔과 노래로 알람이 울리는 캐릭터를 만들어보세요!



댓글 0

MADE BY