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 00:39]
gabriel.orzata created
pm:prj2023:abirlica:music_player [2023/05/25 23:12] (current)
gabriel.orzata [Rezultate Obţinute]
Line 11: Line 11:
  
 <note tip> <note tip>
-O schemă bloc cu toate modulele proiectului vostru, atât software cât şi hardware însoţită de o descriere a acestora precum şi a modului în care interacţionează. +{{ :pm:prj2023:​abirlica:​diagrama.png?350 |}}
- +
-Exemplu de schemă blochttp://​www.robs-projects.com/​mp3proj/​newplayer.html+
 </​note>​ </​note>​
  
Line 19: Line 17:
  
 <note tip> <note tip>
-Aici puneţi tot ce ţine de hardware design+**Lista ​de piese:** 
-  ​* listă de piese +  ​- Arduino UNO 
-  ​* scheme electrice (se pot lua şi de pe Internet şi din datasheet-uri, e.g. http://​www.captain.at/​electronic-atmega16-mmc-schematic.png) +  - Led RGB 
-  ​* diagrame ​de semnal ​ +  ​Rezistente 1k 
-  ​* rezultatele simulării+  ​Condesator 
 +  - Fire tata-tata 
 +  ​- Fire mama-tata 
 +  - Modul de card SD 
 +  ​- 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 30: Line 46:
  
 <note tip> <note tip>
-Descrierea codului aplicaţiei ​(firmware): +Bibliotecile folosite sunt: 
-  * mediu de dezvoltare ​(if any) (e.gAVR Studio, CodeVisionAVR+    - SD.h 
-  ​* librării şsurse 3rd-party ​(e.gProcyon AVRlib+    - LiquidCrystal_I2C.h 
-  * algoritmi şstructuri pe care plănuiţsă le implementaţ+    - SPI.h 
-  * (etapa 3) surse şi funcţii implementate+ 
 + 
 +**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 ​= 0; 
 +    // read from the file until there'​s nothing else in it: 
 +    while (myFile.available()) { 
 +      short int note = myFile.parseInt(); 
 +      ​melody[i] = note; 
 +      if (> 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 40: Line 325:
  
 <note tip> <note tip>
-Care au fost rezultatele obţinute în urma realizării proiectului vostru.+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.
  
-===== Download =====+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.
  
-<note warning>​ +Am implementat un buton pentru schimbarea melodiilor și un alt buton pentru a pune pauza redarii unei melodiiÎn timpul redariicele 3 LED-uri îșschimbă culorile în funcție de nota redată în prezent de difuzor.
-O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului:​ surse, scheme, etcUn fişier READMEun ChangeLog, un script de compilare şcopiere automată pe uC crează întotdeauna o impresie bună ;-).+
  
-Fişierele se încarcă pe wiki folosind facilitatea **Add Images or other files**Namespace-ul în care se încarcă fişierele este de tipul **:​pm:​prj20??:​c?​** sau **:​pm:​prj20??:​c?:​nume_student** (dacă este cazul)**Exemplu:​** Dumitru Alin331CC -> **:​pm:​prj2009:​cc:​dumitru_alin**.+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-uluiinsa rezultatul final, desi este unul mai simplu decat mi-am propus initial, este unul complet functional.
 </​note>​ </​note>​
 +===== Download =====
 +
 +<​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​PDF Proiect</​a></​html>​
  
 ===== Jurnal ===== ===== Jurnal =====
  
 <note tip> <note tip>
-Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului.+3 mai - documentatie initiala\\ 
 +14 mai - hardware\\ 
 +25 mai - software
 </​note>​ </​note>​
  
Line 62: 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">​Export to PDF</​a></​html>​ 
  
pm/prj2023/abirlica/music_player.1683063553.txt.gz · Last modified: 2023/05/03 00:39 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