How to Make a Music-Time Display
by SalCortes in Circuits > Microcontrollers
2423 Views, 24 Favorites, 0 Comments
How to Make a Music-Time Display
Introduction:
For our project we will make digital stopwatch that displays the amount of time a song plays. Our device will display time (second, tenths of a seconds, hundredths of a seconds) using the 7 segment display. The user can chose from one of two songs.
A switch will allow the user to start the song and once the song is over, reset the display to zero (and the song will reset to the beginning). The potentiometer will allow the user to select one of two song, Star Wars Theme Song (pot arrow pointing up) or Star Wars Imperial March (pot arrow pointing down).
Similarly an LED will blink in unison to the song.
For this we will use both a Arduino and FPGA board (Basys 3). We choose this gizmo because we really enjoyed the clock signal found in our FPGA and it gave us an opportunity to display our mad VHDL skills. This is similar to a car radio, that displays the timing for a song. The user will have the option of selecting one of three song. Then the Arduino will play the selected song. Once the song starts playing the 7-segment display will begin to count up, displaying seconds, tenths of a second, and hundreds of a second.
Gather Your Parts and Materials
1. Xilinx Vivado 2016.2 https://www.xilinx.com/support/download/index.htm... Arduino
2. Softwarehttps://www.xilinx.com/support/download/index.htm...
3. Arduino Uno https://www.xilinx.com/support/download/index.htm...
4. Basys 3 Board https://www.xilinx.com/support/download/index.htm... FPGA Code: (Vivado)
5. (16) Jumper Wires
6. Potentiometer
7. (6) 10k Ω
8. Piezo electric buzzer ( or a small speaker)
9. Switch
10. (1) LED
11. Bread board
12. USB A to USB B
13. Micro USB cable
Optional
14. Wire Crimpers
Wire the Arduino to the Breadboard and Components
Take the provided schematic diagram and wire the components to the Arduino. The Arduino micro controller has 14 digital input/output pins and 6 analog inputs. For this project we will be using three digital pins (7, 4, 2) and one analog pin (A0). Similarly we will use the 5V output pin and the ground pin on the Arduino board.
- Pin 7 will be connected to the buzzer, that will may the song
- Pin 4 switch, on/off switch that resets song and timer after the song has played and when on plays song
- Pin 2 resistor (2) voltage divider circuit
- Potentiometer, song selector Star Wars Theme Song or Star Wars Imperial March
- LED in parallel with buzzer
Program the Arduino
/* Star Wars Song Selector <p>/* Star Wars Song Selector<br> * Program to choose between two melodies by using a potentiometer and a piezo buzzer. */ // TONES // // Defining the relationship between note, period & frequency. // period is in microsecond so P = 1/f * (1E6)</p><p>#define c3 7634<br>#define d3 6803 #define e3 6061 #define f3 5714 #define g3 5102 #define a3 4545 #define b3 4049</p><p>#define c4 3816 // 261 Hz <br>#define d4 3401 // 294 Hz #define e4 3030 // 329 Hz #define f4 2865 // 349 Hz #define g4 2551 // 392 Hz #define a4 2272 // 440 Hz #define a4s 2146 #define b4 2028 // 493 Hz #define c5 1912 // 523 Hz #define d5 1706</p><p>#define d5s 1608 #define e5 1517 // 659 Hz #define f5 1433 // 698 Hz #define g5 1276 #define a5 1136 #define a5s 1073 #define b5 1012 #define c6 955 #define R 0 // Define a special note, 'R', to represent a rest <p>// SETUP // <br>int speakerOut = 7; // Set up speaker on digital pin 7 int potPin = A0; // Set up potentiometer on analogue pin 0. int reset = 4; // Pin that will output signal to FPGA, Reset Signal int VoltsOut = 2; // Pin that will output singal to FPGA, Pause Signal</p><p>void setup() { <br> pinMode(speakerOut, OUTPUT); pinMode(reset, INPUT); pinMode(VoltsOut , OUTPUT); Serial.begin(9600); // Set serial out if we want debugging }</p><p>// MELODIES and TIMING //<br>// melody[] is an array of notes, accompanied by beats[], // which sets each note's relative length (higher #, longer note)</p><p>// Melody 1: Star Wars Imperial March<br>int melody1[] = { a4, R, a4, R, a4, R, f4, R, c5, R, a4, R, f4, R, c5, R, a4, R, e5, R, e5, R, e5, R, f5, R, c5, R, g5, R, f5, R, c5, R, a4, R, a4, R, a4, R, a4, R, f4, R, c5, R, a4, R, f4, R, c5, R, a4, R, e5, R, e5, R, e5, R, f5, R, c5, R, g5, R, f5, R, c5, R, a4, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R };</p><p>int beats1[] = { 50, 20, 50, 20, 50, 20, 40, 5, 20, 5, 60, 10, 40, 5, 20, 5, 60, 80, 50, 20, 50, 20, 50, 20, 40, 5, 20, 5, 60, 10, 40, 5, 20, 5, 60, 40,<br> 50, 20, 50, 20, 50, 20, 40, 5, 20, 5, 60, 10, 40, 5, 20, 5, 60, 80, 50, 20, 50, 20, 50, 20, 40, 5, 20, 5, 60, 10, 40, 5, 20, 5, 60, 40, 50, 20, 50, 20, 50, 20, 40, 5, 20, 5, 60, 10, 40, 5, 20, 5, 60, 80, 50, 20, 50, 20, 50, 20, 40, 5, 20, 5, 60, 10, 40, 5, 20, 5, 60, 40, 50, 20, 50, 20, 50, 20, 40, 5, 20, 5, 60, 10, 40, 5, 20, 5, 60, 80, 50, 20, 50, 20, 50, 20, 40, 5, 20, 5, 60, 10, 40, 5, 20, 5, 60, 40, };</p><p>// Melody 2: Star Wars Theme</p><p>int melody2[] = { f4, f4, f4, a4s, f5, d5s, d5, c5, a5s, f5, d5s, d5, c5, a5s, f5, d5s, d5, d5s, c5, f4, f4, f4, a4s, f5, d5s, d5, c5, a5s, f5, d5s, d5, c5, a5s, f5, d5s, d5, d5s, c5, f4, f4, f4, a4s, f5, d5s, d5, c5, a5s, f5, d5s, d5, c5, a5s, f5, d5s, d5, d5s, c5, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,</p><p> };</p><p>int beats2[] = { 21, 21, 21, 128, 128, 21, 21, 21, 128, 64, 21, 21, 21, 128, 64, 21, 21, 21, 128,<br> 21, 21, 21, 128, 128, 21, 21, 21, 128, 64, 21, 21, 21, 128, 64, 21, 21, 21, 128, 21, 21, 21, 128, 128, 21, 21, 21, 128, 64, 21, 21, 21, 128, 64, 21, 21, 21, 128, };</p><p>int MAX_COUNT = sizeof(melody1) / 2; // Melody length, for looping. <br>long tempo = 10000; // Set overall tempo int pause = 1000; // Set length of pause between notes int rest_count = 50; // Loop variable to increase Rest length (BLETCHEROUS HACK; See NOTES) // Initialize core variables int toneM = 0; int beat = 0; long duration = 0; int potVal = 0; int resetVal = 0; int outVoltVal = 0; int Voltage = 0; int number = 0;</p><p>// Play Tone Funtion<br>// Pulse the speaker to play a tone for a particular duration void playTone() { long elapsed_time = 0; if (toneM > 0) { // if this isn't a Rest beat, while the tone has while (elapsed_time < duration) { // PlAY digitalWrite(speakerOut,HIGH); delayMicroseconds(toneM / 2); // DOWN digitalWrite(speakerOut, LOW); delayMicroseconds(toneM / 2); // Keep track of how long we pulsed elapsed_time += (toneM); } } else { // Rest beat; loop times delay for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count delayMicroseconds(duration); } } } void loop () { potVal = analogRead(potPin); //Read potentiometer value and store in potVal variable resetVal = digitalRead(reset); outVoltVal = analogRead(outVolt); if (potVal < 511 && resetVal == HIGH) { // If potVal is less than 511, play Melody1... for (int i=0; i<max_count; i++)="" {="" ="" if="" (i=""> 70) { digitalWrite(VoltsOut, HIGH); } toneM = melody1[i]; beat = beats1[i]; duration = beat * tempo; // Set up timing playTone(); // A pause between notes delayMicroseconds(pause); } }</max_count;></p><p> else if (potVal > 511 && resetVal == HIGH) { // If potVal is less than 511, play Melody2... for (int i=0; i<max_count; i++)="" {="" ="" if="" (i=""> 56) { digitalWrite(VoltsOut,HIGH); } toneM = melody2[i]; beat = beats2[i]; duration = beat * tempo; // Set up timing playTone(); // A pause between notes delayMicroseconds(pause); } } else if (resetVal == LOW) { //digitalWrite(VoltsOut, LOW); digitalWrite(speakerOut, LOW); } }</max_count;></p>
Use the provided code and upload it to your configured Arduino Uno board.
Downloads
Wire the Arduino to the Basys Board
For this step connect the ground on the Basys 3 board to the ground from the Arduino.
Next connect the H1 port on the Basys 3 board to the center stepped down voltage coming from the center node on the switch.
Finally connect the J1 port on the Basys 3 to the stepped down voltage coming from digital pin 2 on the Arduino.
Notice that the FPGA will only read LOW or HIGH signals.
Program the Basys 3 Board
-- Authors: Andy McKeown and Salvador Cortes Soancatl -- Digital Design <p>library IEEE;<br>use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL;</p><p>-- Top Level Code</p><p>entity DigitsDisplayModule is Port ( CLK : in STD_LOGIC; RST : in STD_LOGIC; PS : in STD_LOGIC; Cathode : out STD_LOGIC_VECTOR (6 downto 0); Anode : out STD_LOGIC_VECTOR (3 downto 0)); end DigitsDisplayModule;</p><p>architecture Behavioral of DigitsDisplayModule is component ClockSignals Port ( CLK_IN : in STD_LOGIC; Pause : in STD_LOGIC; Reset : in STD_LOGIC; NUM0 : out STD_LOGIC_VECTOR (3 downto 0); NUM1 : out STD_LOGIC_VECTOR (3 downto 0); NUM2 : out STD_LOGIC_VECTOR (3 downto 0); NUM3 : out STD_LOGIC_VECTOR (3 downto 0));</p><p> end component; signal clkRefresh : std_logic:= '0'; SIGNAL NUMA : STD_LOGIC_VECTOR (3 downto 0); SIGNAL NUMB : STD_LOGIC_VECTOR (3 downto 0); SIGNAL NUMC : STD_LOGIC_VECTOR (3 downto 0); SIGNAL NUMD : STD_LOGIC_VECTOR (3 downto 0);</p><p>begin</p><p> SUBPART : ClockSignals port map (CLK_IN => CLK, Reset => RST,Pause => PS, NUM0 => NUMA, NUM1 => NUMB, NUM2 => NUMC, NUM3 => NUMD); -- System Clock Counter</p><p>MyProcClkRefresh : process (CLK) is variable count : unsigned (35 downto 0) := x"000000000"; --36 zeros -- 32 zeros to fit variable begin if (rising_edge(CLK)) then count := (count + 1); --if count = x"00055730" then if count = x"000927C0" then -- 350,000 couts = count := x"000000000"; clkRefresh <= '1'; else clkRefresh <= '0'; end if; end if; end process MyProcClkRefresh;</p><p>-- Seven Segment Display</p><p>display : process (clkRefresh) is variable digit : unsigned (1 downto 0) := "00"; begin if (rising_edge(clkRefresh)) then case digit is when "00" => -- display digit 1 Anode <= "1110"; case (NUMA (3 downto 0)) is WHEN "0000" => CATHODE <= "0000001"; WHEN "0001" => CATHODE <= "1001111"; WHEN "0010" => CATHODE <= "0010010"; --2 WHEN "0011" => CATHODE <= "0000110"; WHEN "0100" => CATHODE <= "1001100"; --4 WHEN "0101" => CATHODE <= "0100100"; --5 WHEN "0110" => CATHODE <= "0100000"; --6 WHEN "0111" => CATHODE <= "0001111"; WHEN "1000" => CATHODE <= "0000000"; --8 WHEN "1001" => CATHODE <= "0001100"; WHEN OTHERS => CATHODE <= "1111111"; end case; when "01" => Anode <= "1101"; case (NUMB (3 downto 0)) is WHEN "0000" => CATHODE <= "0000001"; WHEN "0001" => CATHODE <= "1001111"; WHEN "0010" => CATHODE <= "0010010"; --2 WHEN "0011" => CATHODE <= "0000110"; WHEN "0100" => CATHODE <= "1001100"; --4 WHEN "0101" => CATHODE <= "0100100"; --5 WHEN "0110" => CATHODE <= "0100000"; --6 WHEN "0111" => CATHODE <= "0001111"; WHEN "1000" => CATHODE <= "0000000"; --8 WHEN "1001" => CATHODE <= "0001100"; WHEN OTHERS => CATHODE <= "1111111"; end case; when "10" => -- display digit 1 Anode <= "1011"; case (NUMC (3 downto 0)) is WHEN "0000" => CATHODE <= "0000001"; WHEN "0001" => CATHODE <= "1001111"; WHEN "0010" => CATHODE <= "0010010"; -- WHEN "0011" => CATHODE <= "0000110"; WHEN "0100" => CATHODE <= "1001100"; --4 WHEN "0101" => CATHODE <= "0100100"; --5 WHEN "0110" => CATHODE <= "0100000"; --6 WHEN "0111" => CATHODE <= "0001111"; WHEN "1000" => CATHODE <= "0000000"; --8 WHEN "1001" => CATHODE <= "0001100"; WHEN OTHERS => CATHODE <= "1111111"; end case; when "11" => Anode <= "0111"; case (NUMD (3 downto 0)) is WHEN "0000" => CATHODE <= "0000001"; WHEN "0001" => CATHODE <= "1001111"; WHEN "0010" => CATHODE <= "0010010"; WHEN "0011" => CATHODE <= "0000110"; WHEN "0100" => CATHODE <= "1001100"; --4 WHEN "0101" => CATHODE <= "0100100"; --5 WHEN "0110" => CATHODE <= "0100000"; --6 WHEN "0111" => CATHODE <= "0001111"; WHEN "1000" => CATHODE <= "0000000"; --8 WHEN "1001" => CATHODE <= "0001100"; WHEN OTHERS => CATHODE <= "1111111"; end case; end case; digit := digit +1; -- move to the next digit end if; end process Display;</p><p>end Behavioral;</p> -- Subpart Module Clock Signals <p>library IEEE;<br>use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL;</p><p>entity ClockSignals is Port ( CLK_IN : in STD_LOGIC; Pause : in STD_LOGIC; Reset : in STD_LOGIC; NUM0 : out STD_LOGIC_VECTOR (3 downto 0); NUM1 : out STD_LOGIC_VECTOR (3 downto 0); NUM2 : out STD_LOGIC_VECTOR (3 downto 0); NUM3 : out STD_LOGIC_Vector (3 downto 0)); end ClockSignals;</p><p>architecture Behavioral of ClockSignals is signal w0,w1,w2,w3 : STD_LOGIC_VECTOR(3 downto 0);</p><p>begin </p><p> CountHundredth : process (CLK_IN, Reset, Pause) is variable X : unsigned (31 downto 0) := x"00000000" ; variable SEC0 : unsigned (3 downto 0) := "0000"; begin if Reset = '0' then SEC0:= "0000"; elsif (rising_edge(CLK_IN)) then -- 1/100 second counter if Pause = '0' then X := (X + 1); if X = x"000F4240" then SEC0 := SEC0 + 1; X := x"00000000"; if SEC0 = "1010" then SEC0 := "0000"; end if; end if; end if; end if; w0 <= STD_LOGIC_VECTOR(SEC0); end process CountHundredth; CountTenth : process (CLK_IN, Reset, Pause) is</p><p> variable X : unsigned (31 downto 0) := x"00000000" ; variable SEC1: unsigned (3 downto 0) := "0000"; begin if Reset = '0' then SEC1:= "0000"; elsif (rising_edge(CLK_IN)) then -- 1/10 second counter if Pause = '0' then X := (X + 1); if X = x"00989680" then SEC1 := SEC1 + 1; X := x"00000000"; if SEC1 = "1010" then SEC1 := "0000"; end if; end if; end if; end if; w1 <= STD_LOGIC_VECTOR(SEC1); end process CountTenth; CountOne : process (CLK_IN, Reset, Pause) is -- 1 and 10 second counter</p><p> variable X : unsigned (31 downto 0) := x"00000000" ; variable SEC2: unsigned (3 downto 0) := "0000"; variable SEC3: unsigned (3 downto 0) := "0000"; begin if Reset = '0' then SEC2 := "0000"; SEC3 := "0000";</p><p> elsif (rising_edge(CLK_IN)) then if Pause = '0' then X := (X + 1); if X = x"05F5E100" then SEC2 := SEC2 + 1; X := x"00000000"; if SEC2 = "1010" then SEC2 := "0000"; SEC3 := SEC3 +1; if SEC3 = "1010" then SEC3 := "0000"; end if; end if; end if; end if; end if; w2 <= STD_LOGIC_VECTOR(SEC2); w3 <= STD_LOGIC_VECTOR(SEC3); end process CountOne; Num0 <= w0; Num1 <= w1; Num2 <= w2; Num3 <= w3;</p><p>end behavioral;</p> -- Constraints File for FPGA Basys 3 board <p>set_property PACKAGE_PIN W4 [get_ports {Anode[3]}]<br>set_property IOSTANDARD LVCMOS33 [get_ports {Anode[3]}]</p><p>set_property PACKAGE_PIN V4 [get_ports {Anode[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {Anode[2]}]</p><p>set_property PACKAGE_PIN U4 [get_ports {Anode[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {Anode[1]}]</p><p>set_property PACKAGE_PIN U2 [get_ports {Anode[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {Anode[0]}]</p><p>set_property PACKAGE_PIN W7 [get_ports {Cathode[6]}] set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[6]}]</p><p>set_property PACKAGE_PIN W6 [get_ports {Cathode[5]}] set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[5]}]</p><p>set_property PACKAGE_PIN U8 [get_ports {Cathode[4]}] set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[4]}]</p><p>set_property PACKAGE_PIN V8 [get_ports {Cathode[3]}] set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[3]}]</p><p>set_property PACKAGE_PIN U5 [get_ports {Cathode[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[2]}]</p><p>set_property PACKAGE_PIN V5 [get_ports {Cathode[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[1]}]</p><p>set_property PACKAGE_PIN U7 [get_ports {Cathode[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[0]}]</p><p>set_property PACKAGE_PIN H1 [get_ports {RST}] set_property IOSTANDARD LVCMOS33 [get_ports {RST}]</p><p>set_property PACKAGE_PIN J1 [get_ports {PS}] set_property IOSTANDARD LVCMOS33 [get_ports {PS}]</p><p>set_property PACKAGE_PIN W5 [get_ports {CLK}] set_property IOSTANDARD LVCMOS33 [get_ports {CLK}]</p><p>create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {CLK}]</p>
For this project you will need three files, two .HDL files and one .XDC file
Plug Everything In, Power Up and Test
Enjoy!
Overall Project Design - Black Box Diagram
Black Box Diagram
Authors: Andy McKeown & Salvador Cortes Soancatl