Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2023:abirlica:music_player [2023/05/03 09:52]
gabriel.orzata [Hardware Design]
pm:prj2023:abirlica:music_player [2023/05/25 23:12] (current)
gabriel.orzata [Rezultate Obţinute]
Line 11: Line 11:
  
 <note tip> <note tip>
-{{ :​pm:​prj2023:​abirlica:​diagrama.png?​direct&​300 ​|}} +{{ :​pm:​prj2023:​abirlica:​diagrama.png?​350 |}}
 </​note>​ </​note>​
  
Line 18: Line 17:
  
 <note tip> <note tip>
-Lista de piese:\\  +**Lista de piese:** 
- ​Arduino UNO\\  +  ​- ​Arduino UNO 
- Led RGB\\  +  ​- ​Led RGB 
- Modul de card SD\\  +  - Rezistente 1k 
- ​Difuzor\\  +  - Condesator 
- ​Amplificator\\  +  - Fire tata-tata 
- ​Butoane\\  +  - Fire mama-tata 
- Ecran LCD\\  +  - Modul de card SD 
- ​Breadboard+  - Card SD 
 +  - Difuzor 
 +  ​- ​Amplificator 
 +  ​- ​Butoane 
 +  ​- ​Ecran LCD 
 +  ​- ​Breadboard 
 +  - Difuzor SparkFun 
 + 
 </​note>​ </​note>​
 +
 +===== Schema cablaj =====
 +
 +
 +{{ :​pm:​prj2023:​abirlica:​screenshot_from_2023-05-25_18-59-52.png?​450 |}}
 +
 +
  
 ===== Software Design ===== ===== Software Design =====
Line 33: Line 46:
  
 <note tip> <note tip>
 +Bibliotecile folosite sunt:
 +    - SD.h
 +    - LiquidCrystal_I2C.h
 +    - SPI.h
 +
 +
 +**Cod**
 +
 +  #include <​LiquidCrystal_I2C.h>​
 +  #include "​SD.h"​
 +  #include "​SPI.h"​
 +  #define Rpin1 10
 +  #define Gpin1 9
 +  #define Bpin1 8
 +  #define Rpin2 14
 +  #define Gpin2 15
 +  #define Bpin2 16
 +  #define Rpin3 17
 +  #define Gpin3 18
 +  #define Bpin3 19
 +
 +  uint8_t signal_values[] = {250, 240, 230, 220, 210, 200, 190, 180, 170, 160, 150, 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40, 30, 20, 10};                      ​
 +  // Set the LCD address to 0x27 for a 16 chars and 2 line display
 +  LiquidCrystal_I2C lcd(0x27, 16, 2);
 +  File myFile;
 +  // change this to make the song slower or faster
 +  uint16_t tempo = 110;
 +  uint8_t buzzer = 7;
 +  short int melody[120];​
 +  uint8_t len = 0;
 +  uint8_t notes;
 +  volatile uint8_t song = 0, prev_song = 0;
 +  unsigned long lastDebounceTime1 = 0, lastDebounceTime2 = 0, debounceDelay = 500;
 +
 +
 +void RGBColor(uint8_t red, uint8_t green, uint8_t blue)
 +
 +  analogWrite(Rpin1,​ red);
 +  analogWrite(Gpin1,​ green);
 +  analogWrite(Bpin1,​ blue);
 +
 +  analogWrite(Rpin2,​ red);
 +  analogWrite(Gpin2,​ green);
 +  analogWrite(Bpin2,​ blue);
 +
 +  analogWrite(Rpin3,​ red);
 +  analogWrite(Gpin3,​ green);
 +  analogWrite(Bpin3,​ blue);
 +
 +
 +void lights(uint8_t signal) ​
 +
 +  if (signal >= signal_values[0]) {
 +    // blue
 +    RGBColor(0, 0, 255);
 +  } else if (signal >= signal_values[1]) {
 +    // Azure
 +    RGBColor(0, 255, 255);
 +  } else if (signal >= signal_values[2]) {
 +    // Cyan
 +    RGBColor(0, 127, 255);
 +  } else if (signal >= signal_values[3]) {
 +    // Aqua marine
 +    RGBColor(0, 255, 127);
 +  } else if (signal >= signal_values[4]) {
 +    // Green
 +    RGBColor(0, 255, 0);
 +  } else if (signal >= signal_values[5]) {
 +    // Yellow
 +    RGBColor(255,​ 255, 0);
 +  } else if (signal >= signal_values[6]) {
 +    // Magenta
 +    RGBColor(255,​ 0, 255);
 +  } else if (signal >= signal_values[7]) {
 +    // Rose
 +    RGBColor(255,​ 0, 127);
 +  } else if (signal >= signal_values[8]) {
 +    // Orange
 +    RGBColor(255,​ 127, 0);
 +  } else if (signal >= signal_values[9]) {
 +    // Red
 +    RGBColor(255,​ 0, 0);
 +  } else if (signal >= signal_values[9]) {
 +    // Purple
 +    RGBColor(128,​ 0, 128);
 +  } else if (signal >= signal_values[10]) {
 +    // Gold
 +    RGBColor(255,​ 215, 0);
 +  } else if (signal >= signal_values[11]) {
 +    // Spring green
 +    RGBColor(0, 250, 154);
 +  } else if (signal >= signal_values[12]) {
 +    // Turquoise
 +    RGBColor(64,​ 224, 208);
 +  } else if (signal >= signal_values[13]) {
 +    // Indigo
 +    RGBColor(75,​ 0, 130);
 +  } else if (signal >= signal_values[14]) {
 +    // Pink
 +    RGBColor(255,​ 192, 203);
 +  } else if (signal >= signal_values[15]) {
 +    // Lavender
 +    RGBColor(230,​ 230, 250);
 +  } else if (signal >= signal_values[16]) {
 +    // Chocolate
 +    RGBColor(210,​ 105, 30);
 +  } else if (signal >= signal_values[17]) {
 +    // Sea green
 +    RGBColor(46,​ 139, 87);
 +  } else if (signal >= signal_values[18]) {
 +    // Olive
 +    RGBColor(128,​ 128, 0);
 +  } else if (signal >= signal_values[19]) {
 +    // Maroon
 +    RGBColor(128,​ 0, 0);  ​
 +  } else if (signal >= signal_values[20]) {
 +    // Midnight blue
 +    RGBColor(25,​ 25, 112);
 +  } else if (signal >= signal_values[21]) {
 +    // Medium violet red
 +    RGBColor(199,​ 21, 133);
 +  } else if (signal >= signal_values[22]) {
 +    // Orchid
 +    RGBColor(218,​ 112, 214);
 +  } else if (signal >= signal_values[23]) {
 +    // Steel blue
 +    RGBColor(70,​ 130, 180);
 +  } else if (signal >= signal_values[24]) {
 +    // Coral
 +    RGBColor(255,​ 127, 80);
 +  } else {
 +    // White
 +    RGBColor(255,​255,​255);​
 +  }  ​
 +
 +
 +void button1Pressed()
 +
 +    unsigned long current = millis();
 +    if(millis() - lastDebounceTime1 > debounceDelay){
 +      lastDebounceTime1 = current;
 +      Serial.println(song);​
 +      song++;
 +      song = song % 2;
 +    }
 +
 +
 +void button2Pressed()
 +
 +    unsigned long current = millis();
 +    if(current - lastDebounceTime2 > debounceDelay){
 +      lastDebounceTime2 = current;
 +      if(song != 5){
 +        prev_song = song;
 +        song = 5;
 +      } else if (song == 5){
 +        song = prev_song;
 +      }
 +    }
 +
 +void readFile(char *file_name)
 +  Serial.print("​Init SD card..."​);​
 +  if (!SD.begin(4)) {
 +    Serial.println("​init failed!"​);​
 +    while (1);
 +  }
 +  Serial.println("​init done."​);​
 +  // open the file for reading:
 +  myFile = SD.open(file_name);​
 +  if (myFile) {
 +    Serial.println(file_name);​
 +    uint8_t i = 0;
 +    // read from the file until there'​s nothing else in it:
 +    while (myFile.available()) {
 +      short int note = myFile.parseInt();​
 +      melody[i] = note;
 +      if (i > 120)
 +        break; ​     ​
 +      i++;
 +    }
 +    len = i;
 +    notes = len / 2;
 +    // close the file:
 +    myFile.close();​
 +  } else {
 +    // if the file didn't open, print an error:
 +    Serial.println("​error opening file"​);​
 +  }
 +
 +
 +void sing(uint8_t song_id)
 +  // this calculates the duration of a whole note in ms
 +  int wholenote = (60000 * 4) / tempo;
 +  int divider = 0, noteDuration = 0;
 +  // iterate over the notes of the melody.
 +  // the array is twice the number of notes (notes + durations)
 +  for (uint8_t thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) {
 +    if (song_id != song) {
 +      return;
 +    }    ​
 +    lights(abs(melody[thisNote]) % 255);
 +    // calculates the duration of each note
 +    divider = melody[thisNote + 1];
 +    if (divider > 0) {
 +      // regular note, just proceed
 +      noteDuration = (wholenote) / divider;
 +    } else if (divider < 0) {
 +      // dotted notes are represented with negative durations!!
 +      noteDuration = (wholenote) / abs(divider);​
 +      noteDuration *= 1.5; // increases the duration in half for dotted notes
 +    }
 +    // we only play the note for 90% of the duration, leaving 10% as a pause
 +    tone(buzzer,​ melody[thisNote],​ noteDuration * 0.9);
 +
 +    // Wait for the specief duration before playing the next note
 +    delay(noteDuration);​
 +    // stop the waveform generation before the next note
 +    noTone(buzzer);​
 +  }
 +
 +void play(char *song_name, uint8_t song_id)
 +  readFile(song_name);​
 +  sing(song_id);​
 +
 +void setup()
 +
 +  // Start with the LEDs off.
 +  pinMode(10, OUTPUT);
 +  pinMode(9, OUTPUT);
 +  pinMode(8, OUTPUT);
 +  pinMode(14, OUTPUT);
 +  pinMode(15, OUTPUT);
 +  pinMode(16, OUTPUT);
 +  pinMode(17, OUTPUT);
 +  pinMode(18, OUTPUT);
 +  pinMode(19, OUTPUT);
 +  ​
 +  pinMode(2, INPUT_PULLUP);​
 +  attachInterrupt(digitalPinToInterrupt(2),​ button1Pressed,​ FALLING);
 +
 +  pinMode(3, INPUT_PULLUP);​
 +  attachInterrupt(digitalPinToInterrupt(3),​ button2Pressed,​ FALLING);
 +  // Open serial communications and wait for port to open
 +  Serial.begin(9600);​
 +  while (!Serial) {
 +      // wait for serial port to connect
 +  }
 +  // initialize the LCD
 +  lcd.begin();​
 +  // Turn on the blacklight and print a message.
 +  lcd.backlight();​
 +
 +
 +void loop()
 +
 +  lcd.clear();​
 +  switch(song) {
 +    case 0:
 +      lcd.clear();​
 +      lcd.print("​Game of thrones"​);​
 +      play((char*)"​got.txt",​ 0);
 +      break;
 +    case 1:
 +      lcd.clear();​
 +      lcd.print("​Fur Elise-"​);​
 +      lcd.setCursor(3,​1);​
 +      lcd.print("​Beethoven"​);​
 +      play((char*)"​furelise.txt",​ 1);
 +      break;
 +    default: ​     ​
 +      break;  ​
 +  }
 +
  
 </​note>​ </​note>​
Line 39: Line 325:
  
 <note tip> <note tip>
 +Link catre demo: https://​www.youtube.com/​shorts/​H1VGBhJymu8
 +{{ :​pm:​prj2023:​abirlica:​poza.jpg?​650 |}}
 </​note>​ </​note>​
  
 ===== Concluzii ===== ===== Concluzii =====
 +<note tip>
 +Am dorit inițial să implementez un media player care să redea fișiere audio .wav de pe un card SD și să adauge un efect luminos pentru a sincroniza culorile cu notele muzicale, insa din motive necunoscute,​ am întâmpinat dificultăți în redarea fișierelor .wav de pe cardul SD utilizând biblioteca TMRpcm.
  
 +Ca soluție alternativă,​ am decis să stochez mai multe fișiere .txt pe card, fiecare conținând notele corespunzătoare unei melodii. Am citit notele din fișierul selectat într-un vector și le-am redat folosind funcția "​note"​ din Arduino IDE.
 +
 +Am implementat un buton pentru schimbarea melodiilor și un alt buton pentru a pune pauza redarii unei melodii. În timpul redarii, cele 3 LED-uri își schimbă culorile în funcție de nota redată în prezent de difuzor.
 +
 +Am încercat să îmbunătățesc procesul de eliminare a rezonanțelor provocate de contactele imperfecte ale butonului prin adăugarea unui condensator în serie cu fiecare buton. Cu toate acestea, butoanele tot nu functionau corespunzator,​ asadar, am adaugat o metoda de debouncing pentru a detecta o singura apasare de buton.
 +
 +Am fost nevoit să folosesc o lista restransa de melodii, deoarece adaugarea ecranului LCD, si implicit a bibliotecii "​LiquidCrystal_I2C",​ supraincarca memoria placii Arduino si componentele nu mai funcționau corect.\\
 +Dupa ce erau citite doua melodii de pe cardul SD, memoria se incarca si programul se bloca la citirea urmatoarei melodii.
 +
 +Din punct de vedere hardware, versiunea finală a proiectului a suferit câteva modificări. Am economisit pini prin adăugarea a încă 2 LED-uri RGB și am optat pentru un LCD cu interfață I2C în locul celui standard. De asemenea, am adăugat un amplificator LM386 pentru a amplifica sunetul unui difuzor SparkFun de 0.5W.
 +
 +Dezvolatarea acestui proiect nu a fost una usoara. Pe parcusului acesteia am intampinat probleme in ceea ce priveste constructia hardware-ului cat si dezvoltarea corecta a software-ului,​ insa rezultatul final, desi este unul mai simplu decat mi-am propus initial, este unul complet functional.
 +</​note>​
 ===== Download ===== ===== Download =====
  
 +<​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​PDF Proiect</​a></​html>​
  
 ===== Jurnal ===== ===== Jurnal =====
  
 <note tip> <note tip>
-3 mai - documentatie initiala+3 mai - documentatie initiala\\ 
 +14 mai - hardware\\ 
 +25 mai - software
 </​note>​ </​note>​
  
Line 55: Line 361:
  
 <​note>​ <​note>​
-Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**.+Diagrama bloc https://app.diagrams.net \\ 
 +Schema cablaj - https://​fritzing.org \\ 
 +LCD I2C - https://​github.com/​fdebrabander/​Arduino-LiquidCrystal-I2C-library \\ 
 +SD library - https://​github.com/​arduino-libraries/​SD \\
 </​note>​ </​note>​
- 
-<​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​PDF Proiect</​a></​html>​ 
  
pm/prj2023/abirlica/music_player.1683096737.txt.gz · Last modified: 2023/05/03 09:52 by gabriel.orzata
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0