Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Музыкальный проигрыватель с сенсорным экраном Arduino и проект будильника

<основной класс="главный сайт" id="главный">

В этом проекте я покажу вам, как сделать музыкальный MP3-плеер и будильник на Arduino с сенсорным экраном. Вы можете посмотреть следующее видео или прочитать письменное руководство ниже.

Обзор

На главном экране есть большие часы, информация о дате и температуре, а также две кнопки для музыкального проигрывателя и будильника.

Если мы войдем в музыкальный проигрыватель, мы сможем начать воспроизведение музыки, нажав большую кнопку «Воспроизвести» в центре экрана. Рядом с ней есть еще две кнопки для воспроизведения предыдущей или следующей песни.

Над этими кнопками находится индикатор выполнения песни, а внизу экрана у нас есть полоса громкости и две кнопки для уменьшения и увеличения громкости. В правом верхнем углу есть часы, а слева кнопка «Меню», которая возвращает нас на главный экран.

С другой стороны, если мы входим в будильник, мы можем установить будильник, используя две кнопки для установки часов и минут.

Когда будильник будет активирован, песня начнет играть с большей громкостью и будет продолжать играть, пока мы не нажмем кнопку «Отклонить».

Как это работает

Теперь давайте посмотрим, как работает это устройство. Он использует плату Arduino Mega и 3,2-дюймовый сенсорный экран TFT с подходящим экраном для подключения экрана к плате Arduino. Для воспроизведения музыки используется модуль MP3-плеера BY8001, а для будильника — модуль часов реального времени DS3231.

Вы можете получить компоненты, необходимые для этого проекта Arduino, по ссылкам ниже:

Схемы схем

Вот принципиальная схема этого проекта:

Здесь мы можем отметить, что экран TFT блокирует свободные контакты платы Arduino, поэтому нам нужно сделать специальные разъемы для контактов, которые мы сможем вставить между экраном и Arduino.

Также обратите внимание, что для питания Arduino нам необходимо припаять дополнительный контактный разъем к контакту 5 В на шилде, так как шилд уже использует все контакты Arduino VCC.

Как только мы соединим все вместе, мы можем приступить к программированию Arduino. Однако, прежде чем мы продолжим, я хотел бы предложить вам ознакомиться с моими предыдущими подробными руководствами по сенсорному экрану TFT и модулю часов реального времени DS3231. А что касается модуля MP3 Player, я дам краткое объяснение здесь, в этой статье.

Модуль MP3-плеера BY8001-16P

BY8001-16P — это модуль MP3, который работает с картами MicroSD и поддерживает файлы аудиоформатов MP3 и WAV. Модуль имеет встроенный усилитель мощности 3 Вт и может напрямую управлять одним динамиком мощностью 3 Вт.

Модуль MP3-плеера может управляться кнопками с помощью 5 входных контактов или с помощью микроконтроллера через последовательную связь.

Обратите внимание, что контакты последовательного порта модуля работают при напряжении 3,3 В, поэтому контакт RX модуля необходимо подключить через резистор 1K к контакту TX Arduino. Также обратите внимание на 3 порта A, B и C, которые используются для выбора режимов управления. Для управления модулем с помощью микроконтроллера необходимо удалить 3 резистора на этих контактных площадках. Контакты 6 и 7 можно использовать для прямого подключения маломощных динамиков или контакты 4 и 5 при использовании внешнего усилителя.

Что касается части Arduino, проще всего использовать библиотеку BY8001, которую можно загрузить с GitHub. Если мы откроем некоторые из его демонстрационных примеров, мы увидим, как это работает. Так что после инициализации модуля в разделе настройки мы можем использовать любую из пользовательских функций для управления модулем.

Исходный код

Теперь мы готовы взглянуть на код этого музыкального плеера и будильника с сенсорным экраном Arduino. Так как код немного длиннее, для лучшего понимания я буду размещать исходный код программы в разделах с описанием для каждого раздела. И в конце этой статьи я опубликую полный исходный код.

Итак, сначала нам нужно включить библиотеки для сенсорного TFT-экрана, MP3-плеера BY8001-16P и модуля часов реального времени DS3231, а также библиотеку для последовательной связи. Затем мы должны создать соответствующие объекты и определить некоторые переменные, необходимые для программы.

#include <UTFT.h>
#include <URTouch.h>
#include <SoftwareSerial.h>
#include <BY8001.h>
#include <DS3231.h>

//==== Creating Objects
UTFT     myGLCD(SSD1289, 38, 39, 40, 41); //Parameters should be adjusted to your Display/Schield model
URTouch  myTouch( 6, 5, 4, 3, 2);


SoftwareSerial mp3Serial(11, 10);  // RX, TX
BY8001 mp3;  // creating an instance of class BY8001 and call it 'mp3'

DS3231  rtc(SDA, SCL);

//==== Defining Fonts
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];

extern unsigned int MusicPlayerButton[0x1040];
extern unsigned int AlarmButton[0x1040];
extern unsigned int ButtonPlay[0x1AE9];
extern unsigned int ButtonPause[0x1AE9];
extern unsigned int PreviousButton[0x9C4];
extern unsigned int NextButton[0x9C4];
extern unsigned int VolumeDown[0x170];
extern unsigned int VolumeUp[0x3B8];

int x, y; // Variables for the coordinates where the display has been pressed
char currentPage, playStatus;
int iV = 15;
int trackNum = 1;
int b = 16;
int aHours = 0;
int aMinutes = 0;
boolean alarmNotSet = true;
String alarmString = "";
float currentTemperature, temperature;
static word totalTime, elapsedTime, playback, minutes, seconds, lastSeconds, minutesR, secondsR;
String currentClock, currentHours, currentMinutes, currentSeconds, currentDate;
String timeString, hoursString, minutesString, secondsString, hoursS, minutesS, secondsS, dateS;Code language: Arduino (arduino)

Мы можем отметить здесь определение растровых изображений. Некоторые кнопки программы на самом деле являются изображениями, которые преобразуются в растровые изображения с помощью инструмента ImageConverter565, который поставляется с библиотекой TFT.

Итак, эти файлы «.c» нужно включить в каталог файла кода, чтобы они загружались при запуске скетча. Здесь вы можете загрузить эти изображения и файлы ".c".

В разделе настройки после инициализации объектов мы вызываем пользовательскую функцию drawHomeScreen(), которая отрисовывает всю графику домашнего экрана. Также здесь мы устанавливаем начальные значения некоторых переменных, таких как playStatus, currentTemp и Date, начальное значение громкости и так далее.

void setup() {
  // Initiate display
  myGLCD.InitLCD();
  myGLCD.clrScr();
  myTouch.InitTouch();
  myTouch.setPrecision(PREC_MEDIUM);

  // Initialize the rtc object
  rtc.begin();

  // Music
  Serial.begin(9600);  // set serial monitor baud rate to Arduino IDE
  mp3Serial.begin(9600);  // BY8001 set to 9600 baud (required)
  mp3.setup(mp3Serial); // tell BY8001 library which serial port to use.
  delay(800);  // allow time for BY8001 cold boot; may adjust depending on flash storage size
  
  drawHomeScreen();  // Draws the Home Screen
  currentPage = '0'; // Indicates that we are at Home Screen
  playStatus = '0';

  mp3.setVolume(15);
  delay(100);
  currentTemperature = rtc.getTemp();
  currentDate = rtc.getDateStr();
  currentClock = rtc.getTimeStr();
  timeString = rtc.getTimeStr();
  currentHours = timeString.substring(0, 2);
  currentMinutes = timeString.substring(3, 5);
  currentSeconds = timeString.substring(6, 8);
}Code language: Arduino (arduino)

Далее идет участок петли. Первый оператор if верен, поскольку мы установили для переменной currentPage значение 0, что указывает на то, что мы находимся на главном экране. Здесь с помощью следующего оператора if мы проверяем, есть ли у нас изменения в часах, и это происходит каждую секунду. Теперь, когда мы используем семисегментный шрифт библиотек TFT, который не поддерживает никаких символов, кроме чисел, нам нужно извлечь только числа из строки, которая приходит с функцией getTimeStr() для чтения часов с DS3231. Модуль RTC.

Таким образом, используя функцию substring(), мы получаем часы, минуты и секунды в отдельные переменные и печатаем их каждый раз, когда происходит изменение в секундах, минутах или часах.
Что касается даты и температуры, аналогично , мы проверяем, есть ли изменение по сравнению с предыдущим состоянием.

void loop() {
  // Homes Screen
  if (currentPage == '0') {
    // Checks for change of the clock
    if ( currentClock != rtc.getTimeStr()) {
      timeString = rtc.getTimeStr();
      hoursS = timeString.substring(0, 2);
      minutesS = timeString.substring(3, 5);
      secondsS = timeString.substring(6, 8);

      myGLCD.setFont(SevenSegNumFont);
      myGLCD.setColor(0, 255, 0);

      myGLCD.print(secondsS, 224, 50);
      
      if ( currentMinutes != minutesS ) {
        myGLCD.print(minutesS, 128, 50);
        currentMinutes = minutesS;
      }
      if ( currentHours != hoursS ) {
        myGLCD.print(hoursS, 32, 50);
        currentHours = hoursS;
      }
      // Checks for change of the date
      dateS = rtc.getDateStr();
      delay(10);
      if ( currentDate != dateS){
          myGLCD.setColor(255, 255, 255); // Sets color to white
          myGLCD.setFont(BigFont); // Sets font to big
          myGLCD.print(rtc.getDateStr(), 153, 7);
        }
      // Checks for change of the temperature
      temperature = rtc.getTemp();
      delay(10);
      if ( currentTemperature != temperature ){
        myGLCD.setColor(255, 255, 255); // Sets color to white
        myGLCD.setFont(BigFont); // Sets font to big
        myGLCD.printNumI(temperature, 39, 7);
        currentTemperature = temperature;
      }
      delay(10);
      currentClock = rtc.getTimeStr();
    }Code language: Arduino (arduino)

Затем, используя функцию myTouch.dataAvailable(), мы проверяем, коснулись ли мы экрана, а также проверяем, является ли это музыкальным проигрывателем или кнопкой будильника. Итак, если это кнопка музыкального проигрывателя, сначала мы вызываем пользовательскую функцию drawFrame(), которая рисует красный кружок вокруг кнопки, указывая, что кнопка была нажата. Также эта пользовательская функция имеет цикл while, который удерживает программу в стеке, пока мы не отпустим кнопку. Сразу после этого мы устанавливаем переменную currentPage в 1, очищаем экран и вызываем пользовательскую функцию drawMusicPlayerScreen(), которая рисует всю графику экрана музыкального проигрывателя. Аналогично, если мы нажмем кнопку будильника, мы установим для переменной currentPage значение 2 и очистим экран.

// Checks whether the screen has been touched
    if (myTouch.dataAvailable()) {
      myTouch.read();
      x = myTouch.getX(); // X coordinate where the screen has been pressed
      y = myTouch.getY(); // Y coordinates where the screen has been pressed
      // If we press the Music Player Button
      if ((x >= 55) && (x <= 120) && (y >= 125) && (y <= 190)) {
          drawFrame(87, 157, 33);
          currentPage = '1';
          myGLCD.clrScr();
          delay(100);
          drawMusicPlayerScreen();
          delay(100);
        }
      // If we press the Alarm Button
      if ((x >= 195) && (x <= 260) && (y >= 125) && (y <= 190)) {
          drawFrame(227, 160, 29);
          currentPage = '2';
          myGLCD.clrScr();
        }
    }Code language: Arduino (arduino)

Далее давайте посмотрим, что происходит на экране музыкального проигрывателя. Здесь мы постоянно проверяем, не коснулись ли мы экрана. Если мы коснемся кнопки Play и текущая переменная playStatus равна 0, мы вызовем функцию mp3.playTrackFromFolder(), которая начнет воспроизведение первой песни с карты MicroSD. В то же время мы вызываем пользовательскую функцию drawPauseButton(), которая рисует кнопку «Пауза», и присваиваем переменной playStatus значение 2. Используя следующие два оператора if, в зависимости от переменной playStatues, мы переключаемся между воспроизведением и приостановкой песни.

// Music Player Screen
  if (currentPage == '1') {
    if (myTouch.dataAvailable()) {
      myTouch.read();
      x = myTouch.getX(); // X coordinate where the screen has been pressed
      y = myTouch.getY(); // Y coordinates where the screen has been pressed
      // If we press the Play Button
      if ((x >= 116) && (x <= 204) && (y >= 77) && (y <= 165)) {
        if (playStatus == '0') {
          drawFrame(159, 121, 42);
          drawPauseButton();
          mp3.playTrackFromFolder(00, 001);
          delay(100);
          playStatus = '2';
          return;
        }
        if (playStatus == '1') {
          drawFrame(159, 121, 42);
          drawPauseButton();
          mp3.play();
          delay(100);
          playStatus = '2';
          return;
        }
        if (playStatus == '2') {
          drawFrame(159, 121, 42);
          drawPlayButton();
          mp3.pause();
          delay(100);
          playStatus = '1';
          return;
        }
      }Code language: Arduino (arduino)

Аналогичным образом для каждой нажатой кнопки мы вызываем соответствующие функции воспроизведения предыдущего или следующего трека, уменьшения или увеличения громкости, а также кнопку «Меню», которая возвращает нас на главный экран.

// If we press the Previous Button
      if ((x >= 45) && (x <= 95) && (y >= 97) && (y <= 147)) {
        drawFrame(70, 121, 26);
        mp3.previousTrack();
        delay(100);
        drawTrackBar();
      }
      // If we press the Next Button
      if ((x >= 227) && (x <= 277) && (y >= 97) && (y <= 147)) {
        drawFrame(252, 122, 26);
        mp3.nextTrack();
        delay(100);
        drawTrackBar();
      }
      // If we press the VolumeDown Button
      if ((x >= 35) && (x <= 75) && (y >= 165) && (y <= 209)) {
        drawUnderline(45, 205, 65, 205);
        if (iV >= 0 & iV <= 30) {
          iV--;
          drawVolume(iV);
        }
        mp3.decreaseVolume();
        delay(100);
      }
      // If we press the VolumeUp Button
      if ((x >= 230) && (x <= 280) && (y >= 165) && (y <= 209)) {
        drawUnderline(235, 205, 275, 205);
        if (iV >= 0 & iV <= 30) {
          iV++;
          drawVolume(iV);
        }
        mp3.increaseVolume();
        delay(100);
      }
      // If we press the MENU Button
      if ((x >= 0) && (x <= 75) && (y >= 0) && (y <= 30)) {
        myGLCD.clrScr();
        drawHomeScreen();  // Draws the Home Screen
        currentPage = '0';
        return;
      }Code language: Arduino (arduino)

Следующий оператор if используется для обновления индикатора выполнения отслеживания.

// Updates the track bar
    if (playStatus == '1' || playStatus == '2') {
      trackPlayTime();
    }

Итак, если музыка играет, мы вызываем пользовательскую функцию trackPlayTime(), которая с помощью некоторых функций библиотеки музыкального проигрывателя, таких как mp3.getElapsedTrackPlaybackTime(), вычисляет и печатает прошедшее и оставшееся время, а также графику индикатора выполнения трека. Используя пользовательскую функцию printClock(), мы печатаем часы в правом верхнем углу.

// Updates the track bar
void trackPlayTime() {
  totalTime = mp3.getTotalTrackPlaybackTime();
  delay(10);
  elapsedTime = mp3.getElapsedTrackPlaybackTime();
  delay(10);
  minutes = (int)elapsedTime / 60;
  seconds = (((float)elapsedTime / 60) - minutes) * 60;
  playback = totalTime - elapsedTime;
  minutesR = (int)playback / 60;
  secondsR = (((float)playback / 60) - minutesR) * 60;

  myGLCD.setFont(SmallFont);
  myGLCD.setColor(255, 255, 255);
  myGLCD.printNumI(minutes, 8, 48);

  myGLCD.print(":", 16, 48);
  myGLCD.printNumI((int)seconds, 24, 48, 2, '0');

  myGLCD.print("-", 276, 48);
  myGLCD.printNumI(minutesR, 284, 48);
  myGLCD.print(":", 292, 48);
  myGLCD.printNumI((int)secondsR, 300, 48, 2, '0');

  int trackBarX = map(elapsedTime, 0, totalTime, 0, 224);
  myGLCD.setColor(255, 0, 0);
  myGLCD.fillRect (48, 50, 48 + trackBarX, 50 + 8);

  if (totalTime == elapsedTime) {
    mp3.nextTrack();
    delay(30);
    myGLCD.setColor(255, 255, 255);
    myGLCD.fillRect (48, 50, 48 + 224, 50 + 8);
  }
}Code language: Arduino (arduino)

Далее идет экран будильника. Здесь сначала мы рисуем всю графику, часы, текст и кнопки, а также устанавливаем для переменной alarmNotSet значение true, чтобы мы могли войти в следующий цикл while. Здесь с помощью двух кнопок H и M мы устанавливаем будильник, и как только мы нажимаем кнопку «Установить», значение будильника сохраняется в переменной alarmString.

// Alarm Clock Screen
  if (currentPage == '2') {
    myGLCD.setFont(BigFont);
    myGLCD.setColor(255, 255, 255);
    myGLCD.print("MENU", 5, 5);
    myGLCD.print("Set Alarm", CENTER, 20);
    
    // Draws a colon between the hours and the minutes
    myGLCD.setColor(0, 255, 0);
    myGLCD.fillCircle (112, 65, 4);
    myGLCD.setColor(0, 255, 0);
    myGLCD.fillCircle (112, 85, 4);

    myGLCD.setFont(SevenSegNumFont);
    myGLCD.setColor(0, 255, 0);
    myGLCD.printNumI(aHours, 32, 50, 2, '0');
    myGLCD.printNumI(aMinutes, 128, 50, 2, '0');
    myGLCD.setColor(255, 255, 255);
    myGLCD.drawRoundRect (42, 115, 82, 145);
    myGLCD.drawRoundRect (138, 115, 178, 145);
    myGLCD.setFont(BigFont);    
    myGLCD.print("H", 54, 122);
    myGLCD.print("M", 150, 122);
    
    myGLCD.drawRoundRect (215, 60, 303, 90);
    myGLCD.print("SET", 236, 67);
    myGLCD.drawRoundRect (215, 115, 303, 145);
    myGLCD.print("CLEAR", 220, 122);
    
    alarmNotSet = true;
        
    while (alarmNotSet){
      if (myTouch.dataAvailable()) {
        myTouch.read();
        x = myTouch.getX(); // X coordinate where the screen has been pressed
        y = myTouch.getY(); // Y coordinates where the screen has been pressed
        //Set hours button
        if ((x >= 42) && (x <= 82) && (y >= 115) && (y <= 145)) {
          drawRectFrame(42, 115, 82, 145);
          aHours++;
          if(aHours >=24){
            aHours = 0;
          }
          myGLCD.setFont(SevenSegNumFont);
          myGLCD.setColor(0, 255, 0);
          myGLCD.printNumI(aHours, 32, 50, 2, '0');
        }
        // Set minutes buttons
        if ((x >= 138) && (x <= 178) && (y >= 115) && (y <= 145)) {
          drawRectFrame(138, 115, 178, 145);
          aMinutes++;
          if(aMinutes >=60){
            aMinutes = 0;
          }
          myGLCD.setFont(SevenSegNumFont);
          myGLCD.setColor(0, 255, 0);
          myGLCD.printNumI(aMinutes, 128, 50, 2, '0');
      }
      // Set alarm button
      if ((x >= 215) && (x <= 303) && (y >= 60) && (y <= 80)) {
        drawRectFrame(215, 60, 303, 90);
        if (aHours < 10 && aMinutes < 10){
          alarmString = "0"+(String)aHours + ":" + "0"+ (String)aMinutes + ":" + "00";
        }
        else if (aHours < 10 && aMinutes > 9){
          alarmString = "0"+(String)aHours + ":" + (String)aMinutes + ":" + "00";
        }
        else if (aHours > 9 && aMinutes < 10){
          alarmString = (String)aHours + ":" + "0"+ (String)aMinutes + ":" + "00";
        }
        else {
          alarmString = (String)aHours + ":" + (String)aMinutes + ":" + "00";
        }
        myGLCD.setFont(BigFont);
        myGLCD.print("Alarm set for:", CENTER, 165);
        myGLCD.print(alarmString, CENTER, 191);
      
      }
      // Clear alarm button
      if ((x >= 215) && (x <= 303) && (y >= 115) && (y <= 145)) {
        drawRectFrame(215, 115, 303, 145);
        alarmString="";
        myGLCD.setColor(0, 0, 0);
        myGLCD.fillRect(45, 165, 275, 210); 
      }
      // If we press the MENU Button
      if ((x >= 0) && (x <= 75) && (y >= 0) && (y <= 30)) {
        alarmNotSet = false;
        currentPage = '0';
        myGLCD.clrScr();
        drawHomeScreen();  // Draws the Home Screen
      }    
      }
  }
}Code language: Arduino (arduino)

Обратите внимание, что нам нужно настроить эту строку так, чтобы она имела ту же форму, что и строка, которую мы получаем из функции getTimeString(). Таким образом, мы сможем сравнить их и активировать будильник, когда часы достигнут того же значения или времени.

Если мы нажмем кнопку очистки, мы очистим сигнальную строку, а если мы нажмем кнопку меню, это выведет нас из цикла while и вернет на главный экран.

Для активации будильника мы проверяем, установлен ли будильник, и если будильник совпадает с часами, первая песня на карте MicroSD начнет играть с большей громкостью. Также мы нарисуем всю графику вместе с кнопкой «Dismiss» и установим для переменной alarmOn значение true. Это приведет нас к следующему циклу while, который позволит песне продолжать играть, пока мы не нажмем кнопку «Отклонить».

// Alarm activation     
    if (alarmNotSet == false) {
      if (alarmString == rtc.getTimeStr()){
        myGLCD.clrScr();
        mp3.setVolume(25);
        mp3.playTrackByIndexNumber(1);
        delay(100);
        myGLCD.setFont(BigFont);
        myGLCD.setColor(255, 255, 255);
        myGLCD.print("ALARM", CENTER, 90);
        myGLCD.drawBitmap (127, 10, 65, 64, AlarmButton);
        myGLCD.print(alarmString, CENTER, 114);
        myGLCD.drawRoundRect (94, 146, 226, 170);
        myGLCD.print("DISMISS", CENTER, 150);
        boolean alarmOn = true;
        while (alarmOn){
          if (myTouch.dataAvailable()) {
          myTouch.read();
          x = myTouch.getX(); // X coordinate where the screen has been pressed
          y = myTouch.getY(); // Y coordinates where the screen has been pressed
          
          // Stop alarm button
          if ((x >= 94) && (x <= 226) && (y >= 146) && (y <= 170)) {
          drawRectFrame(94, 146, 226, 170);
          alarmOn = false;
          alarmString="";
          myGLCD.clrScr();
          mp3.stopPlayback();
          delay(100);
          currentPage = '0';
          playStatus = '0';
          mp3.setVolume(15);  
          drawHomeScreen();
          }
      
      }
     }
  }
}Code language: Arduino (arduino)

Вот как работает код, и вы можете найти полный исходный код внизу статьи.

Сборка устройства


Используя Solidworks, я сделал дизайн и вот как он выглядит.

Вы можете скачать эту модель, чтобы снять мерки здесь:

Для этого проекта я решил использовать алюминиевый лист, который я обрезал по размеру с помощью многофункционального инструмента. Затем на краю моего стола и с помощью зажимов и планок я согнул листовой металл.

Что касается динамиков, я распечатал круговую выкройку, прикрепил ее и с помощью дрели сделал все отверстия.

После этого я обрезал боковые стороны до нужной формы и прикрепил их к предварительно согнутому металлическому листу с помощью клеевого пистолета.

В конце я покрасил коробку из листового металла, и она была готова для установки электронных компонентов. Опять же, используя клеевой пистолет, я закрепил все компоненты, соединил все вместе и закрепил заднюю крышку устройства двумя болтами.

Вот и все, не стесняйтесь задавать любые вопросы в разделе комментариев ниже.

Вот полный исходный код устройства:

/*
* Arduino Touch Screen MP3 Music Player and Alarm Clock
*
* Crated by Dejan Nedelkovski,
* www.HowToMechatronics.com
*
* UFTF, URTouch and DS3231 libraries made by Henning Karlsen which can be found and downloaded from his website, www.rinkydinkelectronics.com.
* BY8001 MP3 Player Library made by borland of Arduino forum, Released in public domain. Dowload link: https://github.com/r0ndL/BY8001 
*/

#include <UTFT.h>
#include <URTouch.h>
#include <SoftwareSerial.h>
#include <BY8001.h>
#include <DS3231.h>

//==== Creating Objects
UTFT     myGLCD(SSD1289, 38, 39, 40, 41); //Parameters should be adjusted to your Display/Schield model
URTouch  myTouch( 6, 5, 4, 3, 2);


SoftwareSerial mp3Serial(11, 10);  // RX, TX
BY8001 mp3;  // creating an instance of class BY8001 and call it 'mp3'

DS3231  rtc(SDA, SCL);

//==== Defining Fonts
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];

extern unsigned int MusicPlayerButton[0x1040];
extern unsigned int AlarmButton[0x1040];
extern unsigned int ButtonPlay[0x1AE9];
extern unsigned int ButtonPause[0x1AE9];
extern unsigned int PreviousButton[0x9C4];
extern unsigned int NextButton[0x9C4];
extern unsigned int VolumeDown[0x170];
extern unsigned int VolumeUp[0x3B8];

int x, y; // Variables for the coordinates where the display has been pressed
char currentPage, playStatus;
int iV = 15;
int trackNum = 1;
int b = 16;
int aHours = 0;
int aMinutes = 0;
boolean alarmNotSet = true;
String alarmString = "";
float currentTemperature, temperature;
static word totalTime, elapsedTime, playback, minutes, seconds, lastSeconds, minutesR, secondsR;
String currentClock, currentHours, currentMinutes, currentSeconds, currentDate;
String timeString, hoursString, minutesString, secondsString, hoursS, minutesS, secondsS, dateS;

void setup() {
  // Initiate display
  myGLCD.InitLCD();
  myGLCD.clrScr();
  myTouch.InitTouch();
  myTouch.setPrecision(PREC_MEDIUM);

  // Initialize the rtc object
  rtc.begin();

  // Music
  Serial.begin(9600);  // set serial monitor baud rate to Arduino IDE
  mp3Serial.begin(9600);  // BY8001 set to 9600 baud (required)
  mp3.setup(mp3Serial); // tell BY8001 library which serial port to use.
  delay(800);  // allow time for BY8001 cold boot; may adjust depending on flash storage size
  
  drawHomeScreen();  // Draws the Home Screen
  currentPage = '0'; // Indicates that we are at Home Screen
  playStatus = '0';

  mp3.setVolume(15);
  delay(100);
  currentTemperature = rtc.getTemp();
  currentDate = rtc.getDateStr();
  currentClock = rtc.getTimeStr();
  timeString = rtc.getTimeStr();
  currentHours = timeString.substring(0, 2);
  currentMinutes = timeString.substring(3, 5);
  currentSeconds = timeString.substring(6, 8);
}


void loop() {
  // Homes Screen
  if (currentPage == '0') {
    // Checks for change of the clock
    if ( currentClock != rtc.getTimeStr()) {
      timeString = rtc.getTimeStr();
      hoursS = timeString.substring(0, 2);
      minutesS = timeString.substring(3, 5);
      secondsS = timeString.substring(6, 8);

      myGLCD.setFont(SevenSegNumFont);
      myGLCD.setColor(0, 255, 0);

      myGLCD.print(secondsS, 224, 50);
      
      if ( currentMinutes != minutesS ) {
        myGLCD.print(minutesS, 128, 50);
        currentMinutes = minutesS;
      }
      if ( currentHours != hoursS ) {
        myGLCD.print(hoursS, 32, 50);
        currentHours = hoursS;
      }
      // Checks for change of the date
      dateS = rtc.getDateStr();
      delay(10);
      if ( currentDate != dateS){
          myGLCD.setColor(255, 255, 255); // Sets color to white
          myGLCD.setFont(BigFont); // Sets font to big
          myGLCD.print(rtc.getDateStr(), 153, 7);
        }
      // Checks for change of the temperature
      temperature = rtc.getTemp();
      delay(10);
      if ( currentTemperature != temperature ){
        myGLCD.setColor(255, 255, 255); // Sets color to white
        myGLCD.setFont(BigFont); // Sets font to big
        myGLCD.printNumI(temperature, 39, 7);
        currentTemperature = temperature;
      }
      delay(10);
      currentClock = rtc.getTimeStr();
    }
    // Checks whether the screen has been touched
    if (myTouch.dataAvailable()) {
      myTouch.read();
      x = myTouch.getX(); // X coordinate where the screen has been pressed
      y = myTouch.getY(); // Y coordinates where the screen has been pressed
      // If we press the Music Player Button
      if ((x >= 55) && (x <= 120) && (y >= 125) && (y <= 190)) {
          drawFrame(87, 157, 33);
          currentPage = '1';
          myGLCD.clrScr();
          delay(100);
          drawMusicPlayerScreen();
          delay(100);
        }
      // If we press the Alarm Button
      if ((x >= 195) && (x <= 260) && (y >= 125) && (y <= 190)) {
          drawFrame(227, 160, 29);
          currentPage = '2';
          myGLCD.clrScr();
        }
    }
  }
  
  // Music Player Screen
  if (currentPage == '1') {
    if (myTouch.dataAvailable()) {
      myTouch.read();
      x = myTouch.getX(); // X coordinate where the screen has been pressed
      y = myTouch.getY(); // Y coordinates where the screen has been pressed
      // If we press the Play Button
      if ((x >= 116) && (x <= 204) && (y >= 77) && (y <= 165)) {
        if (playStatus == '0') {
          drawFrame(159, 121, 42);
          drawPauseButton();
          mp3.playTrackFromFolder(00, 001);
          delay(100);
          playStatus = '2';
          return;
        }
        if (playStatus == '1') {
          drawFrame(159, 121, 42);
          drawPauseButton();
          mp3.play();
          delay(100);
          playStatus = '2';
          return;
        }
        if (playStatus == '2') {
          drawFrame(159, 121, 42);
          drawPlayButton();
          mp3.pause();
          delay(100);
          playStatus = '1';
          return;
        }
      }
      // If we press the Previous Button
      if ((x >= 45) && (x <= 95) && (y >= 97) && (y <= 147)) {
        drawFrame(70, 121, 26);
        mp3.previousTrack();
        delay(100);
        drawTrackBar();
      }
      // If we press the Next Button
      if ((x >= 227) && (x <= 277) && (y >= 97) && (y <= 147)) {
        drawFrame(252, 122, 26);
        mp3.nextTrack();
        delay(100);
        drawTrackBar();
      }
      // If we press the VolumeDown Button
      if ((x >= 35) && (x <= 75) && (y >= 165) && (y <= 209)) {
        drawUnderline(45, 205, 65, 205);
        if (iV >= 0 & iV <= 30) {
          iV--;
          drawVolume(iV);
        }
        mp3.decreaseVolume();
        delay(100);
      }
      // If we press the VolumeUp Button
      if ((x >= 230) && (x <= 280) && (y >= 165) && (y <= 209)) {
        drawUnderline(235, 205, 275, 205);
        if (iV >= 0 & iV <= 30) {
          iV++;
          drawVolume(iV);
        }
        mp3.increaseVolume();
        delay(100);
      }
      // If we press the MENU Button
      if ((x >= 0) && (x <= 75) && (y >= 0) && (y <= 30)) {
        myGLCD.clrScr();
        drawHomeScreen();  // Draws the Home Screen
        currentPage = '0';
        return;
      }
    }
    // Updates the track bar
    if (playStatus == '1' || playStatus == '2') {
      trackPlayTime();
    }
    // Printing the clock in the upper right corner
    myGLCD.setFont(BigFont);
    myGLCD.setColor(255, 255, 255);
    printClock(187, 5);
  }
  // Alarm Clock Screen
  if (currentPage == '2') {
    myGLCD.setFont(BigFont);
    myGLCD.setColor(255, 255, 255);
    myGLCD.print("MENU", 5, 5);
    myGLCD.print("Set Alarm", CENTER, 20);
    
    // Draws a colon between the hours and the minutes
    myGLCD.setColor(0, 255, 0);
    myGLCD.fillCircle (112, 65, 4);
    myGLCD.setColor(0, 255, 0);
    myGLCD.fillCircle (112, 85, 4);

    myGLCD.setFont(SevenSegNumFont);
    myGLCD.setColor(0, 255, 0);
    myGLCD.printNumI(aHours, 32, 50, 2, '0');
    myGLCD.printNumI(aMinutes, 128, 50, 2, '0');
    myGLCD.setColor(255, 255, 255);
    myGLCD.drawRoundRect (42, 115, 82, 145);
    myGLCD.drawRoundRect (138, 115, 178, 145);
    myGLCD.setFont(BigFont);    
    myGLCD.print("H", 54, 122);
    myGLCD.print("M", 150, 122);
    
    myGLCD.drawRoundRect (215, 60, 303, 90);
    myGLCD.print("SET", 236, 67);
    myGLCD.drawRoundRect (215, 115, 303, 145);
    myGLCD.print("CLEAR", 220, 122);
    
    alarmNotSet = true;
        
    while (alarmNotSet){
      if (myTouch.dataAvailable()) {
        myTouch.read();
        x = myTouch.getX(); // X coordinate where the screen has been pressed
        y = myTouch.getY(); // Y coordinates where the screen has been pressed
        //Set hours button
        if ((x >= 42) && (x <= 82) && (y >= 115) && (y <= 145)) {
          drawRectFrame(42, 115, 82, 145);
          aHours++;
          if(aHours >=24){
            aHours = 0;
          }
          myGLCD.setFont(SevenSegNumFont);
          myGLCD.setColor(0, 255, 0);
          myGLCD.printNumI(aHours, 32, 50, 2, '0');
        }
        // Set minutes buttons
        if ((x >= 138) && (x <= 178) && (y >= 115) && (y <= 145)) {
          drawRectFrame(138, 115, 178, 145);
          aMinutes++;
          if(aMinutes >=60){
            aMinutes = 0;
          }
          myGLCD.setFont(SevenSegNumFont);
          myGLCD.setColor(0, 255, 0);
          myGLCD.printNumI(aMinutes, 128, 50, 2, '0');
      }
      // Set alarm button
      if ((x >= 215) && (x <= 303) && (y >= 60) && (y <= 80)) {
        drawRectFrame(215, 60, 303, 90);
        if (aHours < 10 && aMinutes < 10){
          alarmString = "0"+(String)aHours + ":" + "0"+ (String)aMinutes + ":" + "00";
        }
        else if (aHours < 10 && aMinutes > 9){
          alarmString = "0"+(String)aHours + ":" + (String)aMinutes + ":" + "00";
        }
        else if (aHours > 9 && aMinutes < 10){
          alarmString = (String)aHours + ":" + "0"+ (String)aMinutes + ":" + "00";
        }
        else {
          alarmString = (String)aHours + ":" + (String)aMinutes + ":" + "00";
        }
        myGLCD.setFont(BigFont);
        myGLCD.print("Alarm set for:", CENTER, 165);
        myGLCD.print(alarmString, CENTER, 191);
      
      }
      // Clear alarm button
      if ((x >= 215) && (x <= 303) && (y >= 115) && (y <= 145)) {
        drawRectFrame(215, 115, 303, 145);
        alarmString="";
        myGLCD.setColor(0, 0, 0);
        myGLCD.fillRect(45, 165, 275, 210); 
      }
      // If we press the MENU Button
      if ((x >= 0) && (x <= 75) && (y >= 0) && (y <= 30)) {
        alarmNotSet = false;
        currentPage = '0';
        myGLCD.clrScr();
        drawHomeScreen();  // Draws the Home Screen
      }    
      }
    }
        
    }
    // Alarm activation     
    if (alarmNotSet == false) {
      if (alarmString == rtc.getTimeStr()){
        myGLCD.clrScr();
        mp3.setVolume(25);
        mp3.playTrackByIndexNumber(1);
        delay(100);
        myGLCD.setFont(BigFont);
        myGLCD.setColor(255, 255, 255);
        myGLCD.print("ALARM", CENTER, 90);
        myGLCD.drawBitmap (127, 10, 65, 64, AlarmButton);
        myGLCD.print(alarmString, CENTER, 114);
        myGLCD.drawRoundRect (94, 146, 226, 170);
        myGLCD.print("DISMISS", CENTER, 150);
        boolean alarmOn = true;
        while (alarmOn){
          if (myTouch.dataAvailable()) {
          myTouch.read();
          x = myTouch.getX(); // X coordinate where the screen has been pressed
          y = myTouch.getY(); // Y coordinates where the screen has been pressed
          
          // Stop alarm button
          if ((x >= 94) && (x <= 226) && (y >= 146) && (y <= 170)) {
          drawRectFrame(94, 146, 226, 170);
          alarmOn = false;
          alarmString="";
          myGLCD.clrScr();
          mp3.stopPlayback();
          delay(100);
          currentPage = '0';
          playStatus = '0';
          mp3.setVolume(15);  
          drawHomeScreen();
          }
      
      }
        }
      }
    }
}

void drawHomeScreen() {
  myGLCD.setBackColor(0, 0, 0); // Sets the background color of the area where the text will be printed to black
  myGLCD.setColor(255, 255, 255); // Sets color to white
  myGLCD.setFont(BigFont); // Sets font to big
  myGLCD.print(rtc.getDateStr(), 153, 7);
  myGLCD.print("T:", 7, 7);
  myGLCD.printNumI(rtc.getTemp(), 39, 7);
  myGLCD.print("C", 82, 7);
  myGLCD.setFont(SmallFont);
  myGLCD.print("o", 74, 5);
  if (alarmString == "" ) {
    myGLCD.setColor(255, 255, 255);
    myGLCD.print("by www.HowToMechatronics.com", CENTER, 215);
  }
  else {
    myGLCD.setColor(255, 255, 255);
    myGLCD.print("Alarm set for: ", 68, 215);
    myGLCD.print(alarmString, 188, 215);
  }
  drawMusicPlayerButton();
  drawAlarmButton();
  drawHomeClock();
}

void drawMusicPlayerScreen() {
  // Title
  myGLCD.setBackColor(0, 0, 0); // Sets the background color of the area where the text will be printed to black
  myGLCD.setColor(255, 255, 255); // Sets color to white
  myGLCD.setFont(BigFont); // Sets font to big
  myGLCD.print("MENU", 5, 5); // Prints the string on the screen
  myGLCD.setColor(255, 0, 0); // Sets color to red
  myGLCD.drawLine(0, 26, 319, 26); // Draws the red line

  myGLCD.setColor(255, 255, 255); // Sets color to white
  myGLCD.setFont(SmallFont); // Sets font to big
  myGLCD.print("by www.HowToMechatronics.com", CENTER, 215); // Prints the string on the screen

  // Volume Bar
  myGLCD.setColor(255, 255, 255);
  myGLCD.fillRect (78, 184, 78 + 150, 184 + 8);
  myGLCD.setColor(240, 196, 30);
  myGLCD.fillRect (78, 184, 78 + 75, 184 + 8);

  // Track Bar
  myGLCD.setColor(255, 255, 255);
  myGLCD.fillRect (48, 50, 48 + 224, 50 + 8);
  myGLCD.setFont(SmallFont);
  myGLCD.setColor(255, 255, 255);
  myGLCD.print("0:00", 8, 48);
  myGLCD.print("-0:00", 276, 48);

  drawPlayButton();
  if (playStatus == '2') {
    drawPauseButton();
  }
  drawPreviousButton();
  drawNextButton();
  drawVolumeDown();
  drawVolumeUp();
}

void drawMusicPlayerButton() {
  myGLCD.drawBitmap (55, 125, 65, 64, MusicPlayerButton);
}
void drawAlarmButton() {
  myGLCD.drawBitmap (195, 125, 65, 64, AlarmButton);
}
void drawPlayButton() {
  myGLCD.drawBitmap (118, 79, 83, 83, ButtonPlay);
}
void drawPauseButton() {
  myGLCD.drawBitmap (118, 79, 83, 83, ButtonPause);
}
void drawNextButton() {
  myGLCD.drawBitmap (227, 97, 50, 50, NextButton);
}
void drawPreviousButton() {
  myGLCD.drawBitmap (45, 97, 50, 50, PreviousButton);
}
void drawVolumeDown() {
  myGLCD.drawBitmap (50, 177, 16, 23, VolumeDown);
}
void drawVolumeUp() {
  myGLCD.drawBitmap (241, 175, 34, 28, VolumeUp);
}
// check for if Mp3 Player is stopped
bool checkFor_mp3IsStopped() {
  if (mp3Serial.available() > 0) {
    if (mp3.getPlaybackStatus() == 0) {
      return true;
    }
  }
  else return false;
}

// Highlights the button when pressed
void drawFrame(int x, int y, int r) {
  myGLCD.setColor(255, 0, 0);
  myGLCD.drawCircle (x, y, r);
  while (myTouch.dataAvailable())
    myTouch.read();
  myGLCD.setColor(0, 0, 0);
  myGLCD.drawCircle (x, y, r);
}
void drawRectFrame(int x1, int y1, int x2, int y2) {
  myGLCD.setColor(255, 0, 0);
  myGLCD.drawRoundRect (x1, y1, x2, y2);
  while (myTouch.dataAvailable())
    myTouch.read();
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRoundRect (x1, y1, x2, y2);
}
void drawUnderline(int x1, int y1, int x2, int y2) {
  myGLCD.setColor(255, 0, 0);
  myGLCD.drawLine (x1, y1, x2, y2);
  while (myTouch.dataAvailable())
    myTouch.read();
  myGLCD.setColor(0, 0, 0);
  myGLCD.drawLine (x1, y1, x2, y2);
}

// Sound bar
void drawVolume(int x) {
  myGLCD.setColor(255, 255, 255);
  myGLCD.fillRect (78 + 5 * x, 184, 78 + 150, 184 + 8);
  myGLCD.setColor(240, 196, 30);
  myGLCD.fillRect (78, 184, 78 + 5 * x, 184 + 8);
}

// Clears the track bar
void drawTrackBar() {
  myGLCD.setColor(255, 255, 255);
  myGLCD.fillRect (48, 50, 48 + 224, 50 + 8);
}
// Updates the track bar
void trackPlayTime() {
  totalTime = mp3.getTotalTrackPlaybackTime();
  delay(10);
  elapsedTime = mp3.getElapsedTrackPlaybackTime();
  delay(10);
  minutes = (int)elapsedTime / 60;
  seconds = (((float)elapsedTime / 60) - minutes) * 60;
  playback = totalTime - elapsedTime;
  minutesR = (int)playback / 60;
  secondsR = (((float)playback / 60) - minutesR) * 60;

  myGLCD.setFont(SmallFont);
  myGLCD.setColor(255, 255, 255);
  myGLCD.printNumI(minutes, 8, 48);

  myGLCD.print(":", 16, 48);
  myGLCD.printNumI((int)seconds, 24, 48, 2, '0');

  myGLCD.print("-", 276, 48);
  myGLCD.printNumI(minutesR, 284, 48);
  myGLCD.print(":", 292, 48);
  myGLCD.printNumI((int)secondsR, 300, 48, 2, '0');

  int trackBarX = map(elapsedTime, 0, totalTime, 0, 224);
  myGLCD.setColor(255, 0, 0);
  myGLCD.fillRect (48, 50, 48 + trackBarX, 50 + 8);

  if (totalTime == elapsedTime) {
    mp3.nextTrack();
    delay(30);
    myGLCD.setColor(255, 255, 255);
    myGLCD.fillRect (48, 50, 48 + 224, 50 + 8);
  }
}

void printClock(int x, int y) {
  if ( currentClock != rtc.getTimeStr()) {
    myGLCD.print(rtc.getTimeStr(), x, y);
    currentClock = rtc.getTimeStr();
  }
}

void drawColon() {
  myGLCD.setColor(0, 255, 0);
  myGLCD.fillCircle (112, 65, 4);
  myGLCD.setColor(0, 255, 0);
  myGLCD.fillCircle (112, 85, 4);

  myGLCD.setColor(0, 255, 0);
  myGLCD.fillCircle (208, 65, 4);
  myGLCD.setColor(0, 255, 0);
  myGLCD.fillCircle (208, 85, 4);
}
void drawHomeClock() {
  timeString = rtc.getTimeStr();
  currentHours = timeString.substring(0, 2);
  currentMinutes = timeString.substring(3, 5);
  currentSeconds = timeString.substring(6, 8);
  myGLCD.setFont(SevenSegNumFont);
  myGLCD.setColor(0, 255, 0);
  myGLCD.print(currentSeconds, 224, 50);
  myGLCD.print(currentMinutes, 128, 50);
  myGLCD.print(currentHours, 32, 50);
  drawColon();
}Code language: Arduino (arduino)

Feel free to ask any question in the comments section below and don’t forget to check out my collection of Arduino Projects.


Производственный процесс

  1. Часы видения Arduino pov
  2. Основные часы
  3. Arduino Temp. Монитор и часы реального времени с дисплеем 3.2
  4. Воспроизведение звука в Arduino
  5. Цифровые часы TM1637 с функцией настройки времени и будильника
  6. Arduino - MP3-плеер с веб-интерфейсом
  7. Tech-TicTacToe
  8. DIY вольтметр с Arduino и дисплеем Nokia 5110
  9. Таймер обратного отсчета Arduino
  10. Простой будильник с DS1302 RTC