You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

320 lines
8.2 KiB

  1. // === OVERVIEW ===
  2. // Tape Deck player replacement
  3. //
  4. // VU meter --> OLED display
  5. // Cassette player --> MP3 player
  6. // === MP3 PLAYER ===
  7. /***************************************************
  8. DFPlayer - A Mini MP3 Player For Arduino
  9. <https://www.dfrobot.com/product-1121.html>
  10. ***************************************************
  11. This example shows the basic function of library for DFPlayer.
  12. Created 2016-12-07
  13. By [Angelo qiao](Angelo.qiao@dfrobot.com)
  14. GNU Lesser General Public License.
  15. See <http://www.gnu.org/licenses/> for details.
  16. All above must be included in any redistribution
  17. ****************************************************/
  18. /***********Notice and Trouble shooting***************
  19. 1.Connection and Diagram can be found here
  20. <https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299#Connection_Diagram>
  21. 2.This code is tested on Arduino Uno, Leonardo, Mega boards.
  22. ****************************************************/
  23. #include "Arduino.h"
  24. #include "SoftwareSerial.h"
  25. #include "DFRobotDFPlayerMini.h"
  26. #include "EEPROM.h"
  27. #define PIN_EQ A1
  28. #define PIN_CHROME 6
  29. #define PIN_FORWARD 10
  30. #define EEPROM_SONG_INDEX 1
  31. #define SKIP_LIMIT 250
  32. #define EEPROM_SKIP 2
  33. SoftwareSerial mySoftwareSerial(9, 8); // RX, TX
  34. DFRobotDFPlayerMini myDFPlayer;
  35. void printDetail(uint8_t type, int value);
  36. int song_index = 0;
  37. unsigned long song_started = 0;
  38. int files_max = -1;
  39. bool skipping = false;
  40. void setup_player()
  41. {
  42. pinMode(PIN_EQ, INPUT);
  43. pinMode(PIN_CHROME, INPUT);
  44. pinMode(PIN_FORWARD, INPUT);
  45. analogReference(DEFAULT);
  46. Serial.begin(9600);
  47. while (!Serial && millis() < 2000) { delay(10); }
  48. song_index = EEPROM.read(EEPROM_SONG_INDEX);
  49. unsigned int song_skip = EEPROM.read(EEPROM_SKIP);
  50. if (song_skip > SKIP_LIMIT) {
  51. song_skip = 0;
  52. }
  53. song_index += song_skip;
  54. if (song_index >= 255) {
  55. song_index = 0;
  56. }
  57. Serial.println();
  58. Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
  59. mySoftwareSerial.begin(9600);
  60. if (!myDFPlayer.begin(mySoftwareSerial)) {
  61. Serial.println(F("Unable to begin:"));
  62. Serial.println(F("1.Please recheck the connection!"));
  63. Serial.println(F("2.Please insert the SD card!"));
  64. while(true){
  65. delay(0);
  66. }
  67. }
  68. Serial.println(F("DFPlayer Mini online."));
  69. myDFPlayer.volume(20); //Set volume value. From 0 to 30
  70. myDFPlayer.play(song_index+1); //Play the first mp3
  71. do {
  72. delay(100);
  73. files_max = myDFPlayer.readFileCounts();
  74. } while (files_max <= -1);
  75. if (digitalRead(PIN_FORWARD) == 1) {
  76. // FastForward
  77. skipping = true;
  78. while (true) {
  79. delay(500);
  80. if (digitalRead(PIN_FORWARD) == 1) {
  81. song_skip = min(song_skip + 1, SKIP_LIMIT);
  82. EEPROM.update(EEPROM_SKIP, song_skip);
  83. Serial.print("Skipping +1 ... ");
  84. } else {
  85. Serial.print("Skipping +0 ... ");
  86. }
  87. if (song_index + song_skip >= files_max) {
  88. song_index = 0;
  89. song_skip = 0;
  90. }
  91. myDFPlayer.play(song_index + song_skip + 1);
  92. }
  93. }
  94. myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  95. if (files_max > 0 && song_index >= files_max) {
  96. Serial.println("Song index out of bounds, skipping to next.");
  97. nextSong();
  98. }
  99. song_started = millis();
  100. }
  101. int eq_now = DFPLAYER_EQ_NORMAL;
  102. void loop_player()
  103. {
  104. static unsigned long eq_timer = millis();
  105. if (millis() - eq_timer > 100) {
  106. eq_timer = millis();
  107. int eq_next = eq_now;
  108. int eqChrome = digitalRead(PIN_CHROME);
  109. if (eqChrome == 0) {
  110. //analogReference(DEFAULT);
  111. int eqRaw = analogRead(PIN_EQ);
  112. //Serial.print("EQ: ");
  113. //Serial.println(eqRaw);
  114. if (eqRaw < 512) {
  115. eq_next = DFPLAYER_EQ_BASS;
  116. //Serial.println("EQ: Bass");
  117. } else if (eqRaw < 900) {
  118. eq_next = DFPLAYER_EQ_NORMAL;
  119. //Serial.println("EQ: Normal");
  120. } else {
  121. eq_next = DFPLAYER_EQ_POP;
  122. //Serial.println("EQ: POP");
  123. }
  124. } else {
  125. eq_next = DFPLAYER_EQ_ROCK;
  126. //Serial.println("EQ: Rock");
  127. }
  128. if (eq_now != eq_next) {
  129. eq_now = eq_next;
  130. myDFPlayer.EQ(eq_now);
  131. }
  132. }
  133. if (myDFPlayer.available()) {
  134. printDetail(myDFPlayer.readType(), myDFPlayer.read());
  135. }
  136. }
  137. void nextSong() {
  138. int files_max = myDFPlayer.readFileCounts();
  139. song_index = (song_index + 1) % files_max;
  140. EEPROM.update(EEPROM_SONG_INDEX, song_index);
  141. EEPROM.update(EEPROM_SKIP, 0);
  142. myDFPlayer.play(song_index + 1);
  143. song_started = millis();
  144. Serial.println("Next song...");
  145. }
  146. void printDetail(uint8_t type, int value){
  147. switch (type) {
  148. case TimeOut:
  149. Serial.println(F("Time Out!"));
  150. break;
  151. case WrongStack:
  152. Serial.println(F("Stack Wrong!"));
  153. break;
  154. case DFPlayerCardInserted:
  155. Serial.println(F("Card Inserted!"));
  156. break;
  157. case DFPlayerCardRemoved:
  158. Serial.println(F("Card Removed!"));
  159. myDFPlayer.stop();
  160. break;
  161. case DFPlayerCardOnline:
  162. Serial.println(F("Card Online!"));
  163. myDFPlayer.start();
  164. break;
  165. case DFPlayerUSBInserted:
  166. Serial.println("USB Inserted!");
  167. break;
  168. case DFPlayerUSBRemoved:
  169. Serial.println("USB Removed!");
  170. break;
  171. case DFPlayerPlayFinished:
  172. Serial.print(F("Number:"));
  173. //Serial.print(value);
  174. Serial.println(F(" Play Finished!"));
  175. nextSong();
  176. break;
  177. case DFPlayerError:
  178. Serial.print(F("DFPlayerError:"));
  179. switch (value) {
  180. case Busy:
  181. Serial.println(F("Card not found"));
  182. break;
  183. case Sleeping:
  184. Serial.println(F("Sleeping"));
  185. break;
  186. case SerialWrongStack:
  187. Serial.println(F("Get Wrong Stack"));
  188. break;
  189. case CheckSumNotMatch:
  190. Serial.println(F("Check Sum Not Match"));
  191. break;
  192. case FileIndexOut:
  193. Serial.println(F("File Index Out of Bound"));
  194. delay(1000);
  195. song_index = 0;
  196. myDFPlayer.play(song_index + 1);
  197. break;
  198. case FileMismatch:
  199. Serial.println(F("Cannot Find File"));
  200. break;
  201. case Advertise:
  202. Serial.println(F("In Advertise"));
  203. break;
  204. default:
  205. break;
  206. }
  207. break;
  208. default:
  209. break;
  210. }
  211. }
  212. // === DISPLAY ===
  213. #include <SPI.h>
  214. #include <Wire.h>
  215. #include <Adafruit_GFX.h>
  216. #include <Adafruit_SH110X.h>
  217. #define PIN_VU A0
  218. #define VU_SCALE 1
  219. #define VU_WARN 700
  220. #define VU_CRIT 900
  221. #define VU_SLOWDOWN 10
  222. #define VU_ATTACK 1
  223. /* Uncomment the initialize the I2C address , uncomment only one, If you get a totally blank screen try the other*/
  224. #define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
  225. //#define i2c_Address 0x3d //initialize with the I2C addr 0x3D Typically Adafruit OLED's
  226. #define SCREEN_WIDTH 128 // OLED display width, in pixels
  227. #define SCREEN_HEIGHT 64 // OLED display height, in pixels
  228. #define OLED_RESET -1 // QT-PY / XIAO
  229. Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
  230. void setup_display() {
  231. //Serial.begin(9600);
  232. delay(250); // wait for the OLED to power up
  233. display.begin(i2c_Address, true); // Address 0x3C default
  234. display.setContrast (0); // dim display
  235. // Clear the buffer.
  236. display.clearDisplay();
  237. display.display();
  238. display.setTextSize(2);
  239. display.setTextColor(SH110X_WHITE);
  240. display.setCursor(0, 20);
  241. display.println(" UNIVERSUM");
  242. display.setTextSize(1);
  243. display.display();
  244. delay(500);
  245. display.clearDisplay();
  246. }
  247. void loop_display()
  248. {
  249. display.clearDisplay();
  250. display.setTextSize(2);
  251. display.setTextColor(SH110X_WHITE);
  252. display.setCursor(35, 20);
  253. unsigned long song_time = (millis() - song_started) / 1000;
  254. char song_time_text[16];
  255. sprintf(song_time_text, "%02d", song_time / 60);
  256. display.print(song_time_text);
  257. display.print(":");
  258. sprintf(song_time_text, "%02d", song_time % 60);
  259. display.println(song_time_text);
  260. display.setTextSize(1);
  261. display.setCursor(37, 50);
  262. char song_index_text[16];
  263. sprintf(song_index_text, "%03d", song_index+1);
  264. display.print(song_index_text);
  265. display.print(" / ");
  266. char song_count_text[16];
  267. sprintf(song_count_text, "%03d", files_max);
  268. display.print(song_count_text);
  269. display.display();
  270. }
  271. // === MAIN ===
  272. void setup() {
  273. setup_player();
  274. setup_display();
  275. }
  276. void loop() {
  277. loop_player();
  278. loop_display();
  279. }