Touchscreen Musicbox With Lightshow 2.0

by SamTeerlinck in Circuits > Raspberry Pi

1484 Views, 12 Favorites, 0 Comments

Touchscreen Musicbox With Lightshow 2.0

20170815_203531.jpg
20170619_223351.jpg

Hi!

Here we are again with another musicbox! This is my second attempt at my original Touchscreen musicbox from a few months ago.
Although it was a fun project that looked cool, it was not perfect and some parts were unfinished. Now I'm doing this project again and I tried my best to improve it in every way possible.

Be sure to give my first instructable a quick look so if you want some more info on why I chose this project and how I came to the idea of a musicbox.

Without further ado, let's start with the project!

Materials

20170618_161407.jpg
20170815_203321.jpg
20170619_162335.jpg
20170619_162845.jpg

First of all, let's have a look at what materials we need for the Music Player:

  1. Raspberry Pi (almost any version will do)
  2. SD card (8GB is probably the best)
  3. Touchscreen for the Raspberry Pi
    (I used the Adafruit PiTFT, but I had a LOT of trouble with it, so I would recommend a different one)
  4. A speaker for the Raspberry Pi
  5. USB swivels (to make the USB ports of your Pi more flexible)

Then for the Lightshow you'll need:

  1. Arduino UNO (or any higher version should work as well)
  2. Breadboards (1 or two depending on how many LEDs you're using)
  3. Potentiometer (to manipulate the lightshow speed)
  4. LEDs (as many as you want!)
  5. 220/330 Ohm resistors (one for each LED and 1 for the Potentiometer)
  6. lots of cables (depends on your amount of LEDs)

Finally, you'll need some Plexiglas for the box. You could get some decorative stickers if you want.

In the file below, you'll find a list with all these items and where to buy them (from the Belgium area).

Lightshow With Arduino

Musicbox Fritzing.png
20170813_124546.jpg
20170813_124602.jpg

Let's start with the most fun (and the easiest) part: the Lightshow!

There's multiple ways you can do this, but by far the easiest is to code the Lightshow, upload it to your Arduino and voila!
You could also try doing it straight from the Raspberry Pi with the pyserial library in Python. If you're experienced at Python, Raspbian and Arduino, you should be able to do this, but you'll be making it very hard for yourself when there's a very simple way to do it that is just as much fun.

Install the Arduino software

This should be fairly easy, just go to the Arduino website and download it there.

Plug in your Arduino

Plugging in the Arduino will make it install all its drivers automatically, so no worries there.

Open the IDE

In this enviroment, we'll start to code our lightshow, just open a new blank file and let's begin!

Coding

GitHub link

The code is quite simple, you read the value from the potentiometer to determine the length of the delay between putting lights on or off.
You can tweak the code a bit if you want a different kind of lightshow (for example, make the lights go on from left to right)

After you're done checking out the code, just verify it and upload it to the Arduino.

//Variables
int potpin = 1; //Potentiometer pin (analog)
int val = 0; //to store the Potentiometer value
int randNumber1 = 0; //to store the random number
int randNumber2 = 0; //to store the random number

void setup()
{
  //set LED pins to output
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

void loop()
{
  randNumber1 = random(2, 12); //random number between 2 and 11
  randNumber2 = random(2, 12);
  val = analogRead(potpin); //read the Potentiometer value and store it
  
  if (val <= 900) //if the potentiometer is not turned all the way down, start lightshow
  {
    analogWrite(randNumber1, 255); //turn one of the LEDs on
    analogWrite(randNumber2, 255); //turn one of the LEDs on
    delay(val); //wait
    analogWrite(randNumber1, 0); //turn that same LED off
    analogWrite(randNumber2, 0); //turn that same LED off
    delay(val); //wait
  }
  else //if the potentiometer is all the way down, turn off all LEDs
  {
    for (int i=2; i < 12; i++){
      analogWrite(i, 0);
   } 
  }
} 

Assemble the circuit

Now all we need to do is put the lights in the lightshow. Check out the pictures for some more info.

All done!

Now you should be able to control a lightshow with the potentiometer!

Raspberry Pi and MusicPlayer

20170616_152300.jpg
20170616_152400.jpg
20170815_203620.jpg
20170815_203647.jpg

With the Lightshow done, now comes the hard part: the music player with touchscreen.

Again before we start, I have to say that I find the Adafruit PiTFT very annoying to use. It's not very responsive, very small and it makes your Raspbian OS very difficult to use. I recommend using a different one than this.

Touchscreen setup

The installation of the touchscreen I used can be found here: adafruit.
I suggest using the image and burning it into an empty SD card.

If you have trouble with the touchscreen (I for example couldn't get the touch aspect to work). Consider buying a new copy (this solved my problem as the first one I bought was apparently broken)

Since the screen is so small, it might be smart to hide your taskbar when it's not used, so you have more space.

Coding

GitHub link

Now to start coding our music player.

Be sure to check if you installed all the libraries that are imported at the start of the code. Or else you'll run into trouble. (Googling the library names will get you to their installation guides)

The code isn't that hard and I expain a lot in the comments as well, so have a look:

#Here we import all the required libraries

import os

import pygame

from Tkinter import *
import tkFileDialog

import random

import MySQLdb

#Connect to the database with played songs
db = MySQLdb.connect("localhost", "root", "root", "musicplayer")
curs=db.cursor()

#Create Tkinter screen
root = Tk()
root.minsize(320,240)

listofsongs = []
realnames = []
 
v = StringVar()
songlabel = Label(root,textvariable=v,width=35)

shufflevar = IntVar()
shufflevar.set(0)
 
index = 0
numberrandom = 0

#Choose the directory with the songs 
def directorychooser():
	directory = tkFileDialog.askdirectory()
	os.chdir(directory)
	
	for files in os.listdir(directory):
		if files.endswith(".mp3"):
			listofsongs.append(files)
			
	#Start playing the first song
	pygame.mixer.init()
	pygame.mixer.music.load(listofsongs[0])
	pygame.mixer.music.play()
	
	#Send to database
	curs.execute("INSERT INTO playedsongs (song, playeddate, playedtime) values(%s, CURRENT_DATE(), NOW())", (listofsongs[index].replace(".mp3","")))
	db.commit()
	v.set(listofsongs[index].replace(".mp3",""))
	
	
#Start directorychooser	
directorychooser()

#Update the label with the song name
def updatelabel():
	global index
	global songname
	v.set(listofsongs[index].replace(".mp3",""))
	#Return songname

#Pause when it's playing, play when it's paused
def playpause(event):
	global index
	if pausebutton["text"] == 'Pause':
		pygame.mixer.music.pause()
		pausebutton["text"] = 'Play'
	elif pausebutton["text"] == 'Play':
		pygame.mixer.music.unpause()
		pausebutton["text"] = 'Pause'
	
#Next song in the list (+1)
def nextsong(event):
	global index
	#Check if shuffled
	if shufflevar.get() == 1:
		numberrandom = random.randint(0,len(listofsongs)-1)
		
		while index == numberrandom:
			numberrandom = random.randint(0,len(listofsongs)-1)

		index = numberrandom
		pygame.mixer.music.load(listofsongs[index])
		pygame.mixer.music.play()
		curs.execute("INSERT INTO playedsongs (song, playeddate, playedtime) values(%s, CURRENT_DATE(), NOW())", (listofsongs[index].replace(".mp3","")))
		db.commit()
		updatelabel()
	else:
		if index < len(listofsongs)-1:
			index += 1
			pygame.mixer.music.load(listofsongs[index])
			pygame.mixer.music.play()
			curs.execute("INSERT INTO playedsongs (song, playeddate, playedtime) values(%s, CURRENT_DATE(), NOW())", (listofsongs[index].replace(".mp3","")))
			db.commit()
			updatelabel()

#Previous song in the list (-1)
def prevsong(event):
	global index
	#Check if shuffled
	if shufflevar.get() == 1:
		numberrandom = random.randint(0,len(listofsongs)-1)
		
		while index == numberrandom:
			numberrandom = random.randint(0,len(listofsongs)-1)

		index = numberrandom
		pygame.mixer.music.load(listofsongs[index])
		pygame.mixer.music.play()
		curs.execute("INSERT INTO playedsongs (song, playeddate, playedtime) values(%s, CURRENT_DATE(), NOW())", (listofsongs[index].replace(".mp3","")))
		db.commit()
		updatelabel()
	else:
		if index > 0:
			index -= 1
			pygame.mixer.music.load(listofsongs[index])
			pygame.mixer.music.play()
			curs.execute("INSERT INTO playedsongs (song, playeddate, playedtime) values(%s, CURRENT_DATE(), NOW())", (listofsongs[index].replace(".mp3","")))
			db.commit()
			updatelabel()

#Stop playing song and clear label
def stopsong(event):
	pygame.mixer.music.stop()
	v.set("")


#Tkinter objects
label = Label(root,text='Selected songs:')
label.place(x=5,y=5)

listbox = Listbox(root)
listbox.place(x=5,y=30)

listofsongs.reverse()

indexforloop = 1
for items in listofsongs:
	listbox.insert(0,str(indexforloop) + ". " + items.replace(".mp3",""))
	indexforloop += 1

listofsongs.reverse()

pausebutton = Button(root,text = 'Pause')
pausebutton.place(x=180,y=40)

nextbutton = Button(root,text = 'Next Song')
nextbutton.place(x=180,y=70)

previousbutton = Button(root,text = 'Previous Song')
previousbutton.place(x=180,y=100)

stopbutton = Button(root,text='Stop Music')
stopbutton.place(x=180,y=130)

shufflechkbox = Checkbutton(root,text = 'Shuffle', variable=shufflevar, onvalue = 1, offvalue = 0)
shufflechkbox.place(x=180,y=160)

pausebutton.bind("<Button-1>",playpause)
nextbutton.bind("<Button-1>",nextsong)
previousbutton.bind("<Button-1>",prevsong)
stopbutton.bind("<Button-1>",stopsong)

songlabel.place(x=40,y=185)


root.mainloop()

File management

The code should be store in a *.py file. What we now could do is make a desktop shortcut to make it more nice to interact with. For this you'll need to make 2 files (these are made assuming that you named the file MusicPlayer.py and placed it in the Music folder of the Raspberry Pi):

[Desktop Entry]
Name=MusicPlayer
Comment=Starts the Music Player python app
Icon=/usr/share/pixmaps/pimixer.xpm
Exec=lxterminal -t "Starting Music Player" --working-directory=/home/pi/Music/musicplayer -e ./StartMusicPlayer.sh 
Type=Application
Encoding=UTF-8
Terminal=false
Categories=None;

This was the Shortcut file that you see on the picture.

#! /bin/bash
cd /home/pi/Music/musicplayer &>/dev/null
sudo python MusicPlayer.py &>/dev/null

This little script starts the python MusicPlayer in silent mode (not showing terminal commands.

Add Songs

Now to add some songs!

The easiest way is to just use the USB drive to transfer songs, but you can also download them from the Pi if it has internet connection. Since there is a directorychooser present this time, you can play music from whichever folder you prefer (even USB sticks).

Done!

Now go and test your music player.

Top 5 and Database

ERD.jpg
20170815_203708.jpg

Apart from the Musicplayer being very much improved, this database and Top 5 is also a big improvement compared to my first attempt.

This is the guide that I followed to get a webserver installed on my Raspberry Pi: webserver guide.

And here you will find the Top 5 python code (again also available on Github).

#Import required libraries

import MySQLdb
from Tkinter import *

#Create Tkinter screen
root = Tk()
root.minsize(320,240)


#Connect to Database
db = MySQLdb.connect("localhost", "root", "root", "musicplayer")
curs=db.cursor()

#Show Top 5 most played songs
curs.execute ("SELECT song, COUNT(*) Amount FROM playedsongs GROUP BY song ORDER BY amount DESC LIMIT 5")

index = 1
top5list = ""

#Display Top 5
for reading in curs.fetchall():
	top5list += "Nr. " + str(index) + "  = #" + str(reading[1]) + "  " + str(reading[0]) + "\n"
	index += 1


#Tkinter label with Top 5	
label = Label(root,text= 'Top 5 played songs \n \n' + top5list, anchor = W, justify = LEFT)
label.place(x=5,y=5)

root.mainloop()

I also added a desktop link and a bash file (similar to the Musicplayer), just copy the .desktop and .sh files from the MusicPlayer and change the destination to Top5.

What's in the Box?

Sketch box.jpg
20170619_185339.jpg
20170619_194721.jpg
20170619_215559.jpg
20170619_203649.jpg
20170815_203742.jpg

Now to create the box.

The sketch I made is the easiest way I could think of to get all of these parts together. yet when I tried to get them all together, well... let's just say it didn't go as planned (at first).

This can be the tricky part. The way I see it, there are 3 ways to make the box:

  • Glue
  • Tape
  • Drilling

I first tried with glue, but I probably used a wrong kind of glue because my Plexi just didn't stick. I then tried with tape, but it just looked more messy and not very appealing.

Eventually we used a drill to get the Plexiglass in a box-shape. I'm pretty sure you can get some decent glue or tape for this, but I didn't have any around at that time so drilling was my only option.

The inside of the box is quite loose so it's easy to move around with all the Arduino cables. This way you can also place LEDs wherever you want to get some more light out of them.

Be sure to watch out that no cables get disconnected while you're assembling the box, that's why I recommend leaving the top loose so you can easily get inside and tweak/repair a few things.

Party!

Touchscreen Musicbox with Lightshow
Now that you assembled the box, everything should be good to go! I hope you enjoyed my new and improved version of my first Instructable! Feedback and (constructive) criticism would be greatly appreciated ;) Party on!