zaterdag 16 januari 2016

Raspberry PI(2) MP3 player based on mpdclient, controlled with analog joystick and PCF8544 and a Nokia LCD display the PCD8544

I'm fiddling with electronics for many years, besides that I'm very new in at the Raspberry PI thing, I love it. I'm publishing this because many posts in forums and on blogs didn't gave what I needed.

What I made
A really simple MP3 player on a Raspberry PI that displays the song and artists and also displays play/pause/next/previous. It is all controlled with an analog joystick.

You can see how it works: https://youtu.be/rmaHO2rLwvg

Why?
Why I used these components? It is what I had without going to the store. This display was included in a kit. The analog joystick was because I didn't have enough buttons. I know the Rapsberry PI is totally useless for audio playback.

What is used? 
The Raspberry PI(2)

PCD8544:
This was included in a kit, with the connector can it be placed directly on the RPi but in a project it doesn't really make sense.










Analog joystick:
Mine was with a red PCB.











The AD converter PCF8591
Be sure you remove the jumpers.











The hook it up
Connect the PCF8591 board with the VCC to the 3.3V from the RPi. GND to the GND of the RPi.
Connect the PCF8591 board with SCL to the SCL from the RPi
Connect the PCF8591 board with SDA to the SDA from the RPi
Connect the PCF8591 board AIN2 and AIN3 to GND

Connect the joystick board with the + to the 3.3V from the RPi. GND to the GND of the RPi.
Connect the joystick board B (button) to pin 25 on the RPi
Connect the joystick board X to the AIN0 on the PCF8591 board
Connect the joystick board Y to the AIN1 on the PCF8591 board

Now comes the hard part, connecting the PCD to the Rapsberry.  This picture was very helpful.

The first column is counted from the top left as seen on the picture so:
1-2
3-4
5-6
ans so on.

Pin 1 is 3.3V
Pin 25 is GND

The code:
 #!/usr/bin/env python  
   
   
 #basic needs  
 from smbus import SMBus  
 from time import sleep  
 from socket import error as SocketError  
   
 #Needed for the PMD8544/NokiaLCD   
 import Adafruit_Nokia_LCD as LCD  
 from PIL import Image  
 from PIL import ImageFont  
 from PIL import ImageDraw  
   
 #This is needed for the PCF85  
 from smbus import SMBus  
   
 #Needed for reading the button  
 import RPi.GPIO as GPIO  
   
 #Needed for the MPDClient  
 from mpd import (MPDClient, CommandError)  
   
 ## SETTINGS  
 ##  
 HOST = 'localhost'  
 PORT = '6600'  
 PASSWORD = False  
 ###  
   
   
 #Set some basic values  
 bus = SMBus(1) #This is for the PCF8591   
 last_reading_1 = -1  
 last_reading_2 = -1  
 volume = 70   
 status = "stop"  
   
 # This is for the button of the analog joystick.  
 GPIO.setmode(GPIO.BCM)  
 GPIO.setup(25, GPIO.IN)  
   
 # Raspberry Pi software SPI config:  
 SCLK = 17  
 DIN = 18  
 DC = 27  
 RST = 23  
 CS = 22  
 client = MPDClient()  
   
   
 #This function displays the icons  
 def display(action):  
     #clean display first  
      draw.rectangle((0,0,LCD.LCDWIDTH,LCD.LCDHEIGHT), outline=255, fill=255)  
     disp.image(image)  
     disp.display()  
      #Set the right icon to show:   
      if (action == "volumeplus"):   
          draw.rectangle((25,24,61,28), outline=0, fill=0)  
         draw.rectangle((40,12,46,40), outline=0, fill=0)  
     elif (action == "volumeminus"):  
           draw.rectangle((25,24,61,28), outline=0, fill=0)  
      elif (action == "play_pause"):  
           if (status == "play"):  
             draw.rectangle((33,12,40,34), outline=0, fill=0)  
             draw.rectangle((43,12,50,34), outline=0, fill=0)  
         else:  
             draw.polygon([(31,10), (51,22), (31,34)], outline=0, fill=0)  
      elif (action == "next"):   
           draw.polygon([(21,10), (41,22), (21,34)], outline=0, fill=0)  
         draw.polygon([(41,10), (61,22), (41,34)], outline=0, fill=0)  
      elif (action == "previous"):   
           draw.polygon([(21,22), (41,10), (41,34)], outline=0, fill=0)  
         draw.polygon([(41,22), (61,10), (61,34)], outline=0, fill=0)            
      disp.image(image)  
     disp.display()  
      sleep(0.5) # the time the icon is showed   
      #below the icon is cleared from the screen again.  
      draw.rectangle((0,0,LCD.LCDWIDTH,LCD.LCDHEIGHT), outline=255, fill=255)  
      disp.image(image)  
     disp.display()  
   
   
 #This function is to compensate for the non-linear volume controll of the   
 #Raspberry PI   
 def logvolume(action, volume):  
      if (volume <=50):  
           if (action == "volumeplus"):  
                volume = volume + 20  
           else:   
                volume = volume - 20  
      elif (volume >= 50 and volume <= 70):  
           if (action == "volumeplus"):  
             volume = volume + 10  
         else:   
             volume = volume - 10   
      elif (volume >=70 and volume <= 79):  
           if (action == "volumeplus"):  
             volume = volume + 5  
         else:   
             volume = volume - 5   
     elif (volume >=80 and volume <= 89):  
         if (action == "volumeplus"):  
             volume = volume + 2  
         else:  
             volume = volume - 2  
      elif (volume >=90):   
           if (action == "volumeplus"):  
             volume = volume + 1  
         else:   
             volume = volume - 1  
      elif (volume == 100):   
           volume = 100  
      return(volume)  
   
   
   
   
 #In this function the core functionality is called.   
 #     - It calls the logaritmic volume controll   
 #      - It calls the screen action   
   
 def action(action, volume):   
      if (action == "volumeplus"):  
           volume = logvolume(action, volume)   
           client.setvol(volume)  
      if (action == "volumeminus"):  
           volume = logvolume(action, volume)  
         client.setvol(volume)  
      if (action == "play_pause"):  
           if (status == "play"):  
             client.pause()  
         else:  
             client.play()  
      if (action == "next"):   
         client.next()  
      if (action == "previous"):   
         client.previous()  
      display(action)   
      return(volume)  
   
   
 #This connects the MCP client to the deamon  
 try:  
     client.connect(host=HOST, port=PORT)  
     print "connect"  
 except SocketError:  
     print "socketerror"  
     exit(1)  
   
   
   
 # Software SPI usage (defaults to bit-bang SPI interface):  
 disp = LCD.PCD8544(DC, RST, SCLK, DIN, CS)  
   
 # Initialize library.  
 disp.begin(contrast=60)  
   
 # Clear display.  
 disp.clear()  
 disp.display()  
   
 # Create image buffer.  
 # Make sure to create image with mode '1' for 1-bit color.  
 image = Image.new('1', (LCD.LCDWIDTH, LCD.LCDHEIGHT))  
   
 # Get drawing object to draw on image.  
 draw = ImageDraw.Draw(image)  
   
 # Draw a white filled box to clear the image.  
 draw.rectangle((0,0,LCD.LCDWIDTH,LCD.LCDHEIGHT), outline=255, fill=255)  
   
 # Load default font.  
 #font = ImageFont.load_default()  
   
 # Alternatively load a TTF font.  
 # Some nice fonts to try: http://www.dafont.com/bitmap.php  
 font = ImageFont.truetype('visitor1.ttf', 9)  
 font1 = ImageFont.truetype('visitor1.ttf', 12)  
   
 #Set basic volume to 60%  
 client.setvol(volume)  
   
 while True:  
      bus.write_byte(0x48, 0x40) #This writes to the channel that needs to be read      
      reading = bus.read_byte(0x48) #This reads the value from the channel   
      #Make sure that it is only read if it is different than before   
     if(abs(last_reading_1 - reading) > 2):   
           if (reading >= 230):          #This about 90% of the joystick change of value        
                #Calls the action function and returns the volume   
             volume = action("volumeminus", volume)   
           elif (reading <= 30): #This is also 80% the other way around   
                volume = action("volumeplus", volume)  
           last_reading_1 = reading  
     #Now the other axis needs to be read so it writes to the other channel   
     bus.write_byte(0x48, 0x41)   
     reading = bus.read_byte(0x48)  
     if(abs(last_reading_2 - reading) > 2):  
         if (reading >= 230):                
                action("next", volume)  
         elif (reading <= 30):  
                action("previous", volume)   
         last_reading_2 = reading  
      if (GPIO.input(25)== True):  
           action("play_pause", volume)   
      sleep(0.3)  
      running  = client.status() #Checks the state of the player   
     status = running['state'] #Puts the running state in status   
        
      #This shows the current song on the display   
      if (status == "play"):  
         curSongInfo = client.currentsong()  
         draw.text((1,1), curSongInfo['albumartist'], font=font)  
         draw.text((1,8), curSongInfo['title'], font=font)  
      disp.image(image)  
     disp.display()  
   
 client.disconnect()  

You might bump into some issues so need to do some stuff:
sudo pip install smbus
sudo apt-get install alsa-utils mpd python-mpd python-imaging

alter the music directory in /etc/mpd.conf
And restart it: sudo service mpd restart

install the adafruit GPIO library: https://github.com/adafruit/Adafruit_Python_GPIO

Enable the audio jack output on the RPi:
amixer cset numid=3 1

Load the drivers for the I2C bus:
modprobe i2c_bcm2708
modprobe i2c_dev
And maybe add them to load them at boot: /etc/modules




maandag 16 februari 2015

Use the build in TFTP server in OSX

Use the build in TFTP server in OSX

To start the TFTP server: 
sudo launchctl load -F /System/Library/LaunchDaemons/tftp.plist

To stop the TFTP Server: 
sudo launchctl unload -F /System/Library/LaunchDaemons/tftp.plist

You can put your files in the folder: 
/private/tftpboot

You can change this folder in: 
/System/Library/LaunchDaemons/tftp.plist

To test the TFTP setup

Create a file named test.txt in:
/private/tftpboot

Change into your home folder: 
cd ~

Enter the following command: 
tftp 127.0.0.1 

You will get a prompt: 
tftp>

To get the test file: 
get test.txt 

You will get a response like: 
Received 8 bytes in 0.0 seconds

Use SCREEN to connect to a serial device on OSX with a USB-Serial adapter

Use SCREEN to connect to a serial device on OSX 

How to use the SCREEN command how to connect to a serial device with a USB-serial adapter. Plug in your USB-serial adapter and install the driver.
To start you open a terminal, Applications->Utilities->Terminal.app

First we need to find out where the USB-serial is located.
ls /dev/tty.*

This gives an output like:
/dev/tty.Bluetooth-Modem /dev/tty.PL2303-0000201A   /dev/tty.Bluetooth-PDA-Sync

You can ignore the bluetooth devices. Mostly you see something like  PL2303-xxxxxxxx of USBxxxxxxxx those are most common. PL2303 stands for a Profilic chipset. To connect to this device use this command.

screen /dev/tty.PL2303-0000201A 9600

In this case we use a baudrate of 9600 bps (Cisco) in other cases you can fill in another baudrate, the most common are:
9600
38400
115200

The standard values are: 9600/8-N-1
9600
8 bits
Parity None
1 stopbit

These values are very usefull in most cases but you can change them with the following
cs7 / cs8 = 7 databits / 8 databits
parodd / -parodd = Parity odd / Parity even
cstopb / -cstopb = 2 stopbits / 1 stopbit

For example if you would want to use 38400 7E2 we fill in:
screen /dev/tty.PL2303-0000201A 38400,cs7,-parrodd,cstopb
To disconnect use ctrl-a followed by ctrl-k

maandag 6 januari 2014

Nano syntax highlighting on OSX

This post explains you how to install syntax highlighting on Nano in OSX

If you haven't got it already install homebrew first. For info on homebrew 


After this you need to do a:

brew doctor

and fix the problems. (don't worry about the man pages) 
Now make sure the right repository is added: 
brew tap homebrew/dupes

And now install nano with brew:
brew install nano

Now edit the ~/.nanorc to:

set nowrap
set smooth
set autoindent
set backup
set historylog
set morespace
set tabsize 4
set tabstospaces
set mouse
set const
set backupdir "~/werk/backup/nano-backups"
include "/usr/local/share/nano/asm.nanorc"
include "/usr/local/share/nano/awk.nanorc"
include "/usr/local/share/nano/c.nanorc"
include "/usr/local/share/nano/cmake.nanorc"
include "/usr/local/share/nano/css.nanorc"
include "/usr/local/share/nano/debian.nanorc"b
include "/usr/local/share/nano/fortran.nanorc"
include "/usr/local/share/nano/gentoo.nanorc"
include "/usr/local/share/nano/groff.nanorc"
include "/usr/local/share/nano/html.nanorc"
include "/usr/local/share/nano/java.nanorc"
include "/usr/local/share/nano/makefile.nanorc"
include "/usr/local/share/nano/man.nanorc"
include "/usr/local/share/nano/mgp.nanorc"
include "/usr/local/share/nano/mutt.nanorc"
include "/usr/local/share/nano/nanorc.nanorc"
include "/usr/local/share/nano/objc.nanorc"
include "/usr/local/share/nano/ocaml.nanorc"
include "/usr/local/share/nano/patch.nanorc"
include "/usr/local/share/nano/perl.nanorc"
include "/usr/local/share/nano/php.nanorc"
include "/usr/local/share/nano/pov.nanorc"
include "/usr/local/share/nano/python.nanorc"
include "/usr/local/share/nano/ruby.nanorc"
include "/usr/local/share/nano/sh.nanorc"
include "/usr/local/share/nano/tcl.nanorc"
include "/usr/local/share/nano/tex.nanorc"
include "/usr/local/share/nano/xml.nanorc"

This should do the trick. 
It is possible that you bump into some errors like this:

Error in /usr/local/Cellar/nano/2.2.6/share/nano/mgp.nanorc on line 4: Command "header" not understood

Press Enter to continue starting nano.


Error in /usr/local/Cellar/nano/2.2.6/share/nano/perl.nanorc on line 4: Command "header" not understood

Press Enter to continue starting nano.


Error in /usr/local/Cellar/nano/2.2.6/share/nano/python.nanorc on line 4: Command "header" not understood

Press Enter to continue starting nano.


Error in /usr/local/Cellar/nano/2.2.6/share/nano/ruby.nanorc on line 4: Command "header" not understood

Press Enter to continue starting nano.


Error in /usr/local/Cellar/nano/2.2.6/share/nano/sh.nanorc on line 4: Command "header" not understood

Press Enter to continue starting nano.

This can mean two problems, the $PATH is not pointing to the new version of nano.
Start nano, see at the top if the version 2.2.6 is running. If not then type $PATH at the commandline you should see: /usr/local/bin at the beginning of the line. If not then edit /ets/paths so the /usr/local/bin is on top. This should solve it. 

Just go to:  https://github.com/Munter/dotfiles/tree/master/.nano and get this missing files and add them. 

zondag 5 januari 2014

Organize or clean your downloads folder

My downloads folder is always a mess and I got fed up with it, I have wrote in a script that will clean up my downloads folder.

First I created a few folders in the downloads folder:

  • DL-Compressed 
  • DL-Firmware 
  • DL-Programs 
  • DL-Android
  • DL-Documents
  • DL-media
After this I created a bash script:


# Move Wetransfer files to tje picure folder 
mv ~/Downloads/wetransfer*  ~/Pictures/Wetransfer

# Move all Airdroid Files to the DL-Airdroid folder
mv ~/Downloads/Files_downloaded_by_AirDroid*  ~/Downloads/DL-Airdroid/

# Move all porn to DL-Media
mv ~/Downloads/*.jpg ~/Downloads/DL-media/
mv ~/Downloads/*.JPG ~/Downloads/DL-media/
mv ~/Downloads/*.png ~/Downloads/DL-media/
mv ~/Downloads/*.PNG ~/Downloads/DL-media/
mv ~/Downloads/*.mov ~/Downloads/DL-media/    
mv ~/Downloads/*.MOV ~/Downloads/DL-media/
mv ~/Downloads/*.bmp ~/Downloads/DL-media/
mv ~/Downloads/*.BMP ~/Downloads/DL-media/
mv ~/Downloads/*.jpeg ~/Downloads/DL-media/
mv ~/Downloads/*.JPEG ~/Downloads/DL-media/
mv ~/Downloads/*.gif ~/Downloads/DL-media/
mv ~/Downloads/*.GIF ~/Downloads/DL-media/
mv ~/Downloads/*.tif ~/Downloads/DL-media/
mv ~/Downloads/*.TIF ~/Downloads/DL-media/

# move al compressed files to DL-Compressed folder
mv ~/Downloads/*.zip ~/Downloads/DL-Compressed/
mv ~/Downloads/*.ZIP ~/Downloads/DL-Compressed/
mv ~/Downloads/*.rar ~/Downloads/DL-Compressed/
mv ~/Downloads/*.RAR ~/Downloads/DL-Compressed/
mv ~/Downloads/*.jar ~/Downloads/DL-Compressed/
mv ~/Downloads/*.JAR ~/Downloads/DL-Compressed/
mv ~/Downloads/*.7z ~/Downloads/DL-Compressed/
mv ~/Downloads/*.7Z ~/Downloads/DL-Compressed/
mv ~/Downloads/*.tgz ~/Downloads/DL-Compressed/
mv ~/Downloads/*.TGZ ~/Downloads/DL-Compressed/

# Move all installers to DL-Programs 
mv ~/Downloads/*.dmg ~/Downloads/DL-Programs/
mv ~/Downloads/*.DMG ~/Downloads/DL-Programs/
mv ~/Downloads/*.pkg ~/Downloads/DL-Programs/
mv ~/Downloads/*.pkg ~/Downloads/DL-Programs/
mv ~/Downloads/*.prefPane ~/Downloads/DL-Programs/

# Split up all the documents
mv ~/Downloads/*.pdf  ~/Downloads/DL-Documenten/DL-PDF/
mv ~/Downloads/*.PDF  ~/Downloads/DL-Documenten/DL-PDF/
mv ~/Downloads/*.txt  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.TXT  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.csv  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.CSV  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.htm  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.html  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.HTM  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.HTML  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.cfg  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.CFG  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.tpl  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.TPL  ~/Downloads/DL-Documenten/DL-TXT/
mv ~/Downloads/*.doc  ~/Downloads/DL-Documenten/DL-Docs/
mv ~/Downloads/*.docx  ~/Downloads/DL-Documenten/DL-Docs/
mv ~/Downloads/*.DOC  ~/Downloads/DL-Documenten/DL-Docs/
mv ~/Downloads/*.DOCX  ~/Downloads/DL-Documenten/Docs/

# Remove windows stuff
rm ~/Downloads/*.exe 
rm ~/Downloads/*.EXE

# Verwijderen van overbodige folders (alle niet DL- folders) 
find ~/Downloads/. -type d -not -name 'DL-*' -print0 | xargs -0  rm -R

# Remove files from Compressed after 30 days. 
find ~/Downloads/DL-Compressed/* -mtime +30 -exec rm {} \;

Now i added the file to the crontab
Create a file called crontab.txt 
fill it up with: 
15  * * * * ~/scripts/download.sh  &> /dev/null

Now put it in the crontab:
crontab crontab.txt 

Check your crontabs with:
crontab -l 

Clear your crontabs with:
crontab -r 

Slow and too much memory Google Chrome on OSX Mavericks

After upgrading to Mavericks I have the problem that Google Chrome is eating a lot of memory. My macbook is getting slower. More memory will solve the problem. If you don't want to upgrade your memory there is a great solution: The Great suspender 

What will it do for you? It wil suspend the tabs you are not using so the tabs will only ask memory from your computer when it is used. 

Make things easier for me

I have a somewhat demanding job, a lott of things running in the same time. I can manage to do 50 todo's in comfortable way, but with just a little more todo's it becomes a mess. 

What are my main problems? 

  • keep track of all my todo's without forgetting the (for me) unimportant stuff 
  • getting new todo's in the system
  • organizing my todo's
  • organizing my notes that belong to the todo's 
Keeping track in of all the todo's is just a simple solution, just do it: 

  1. Every morning read your mail, add the todo's to your list 
  2. Close your mailbox
  3. Review your todo list 
  4. Make a short-list for that morning
  5. Start to work
After lunch, the same thing. 

How do I deal with this mail every day. 

1. I use Apple's mail.app and I've set-up this system: 

  • INBOX - all unread mail
  • Answer - These mails need an answer 
  • Follow Up - Answered them of just information I need to follow up on.  
  • Today - Need answering today
  • ToDo - Make a todo from this

Create the following smart mailboxes: 
  • INBOX - all unread mail
  • Answer - showing all blue marked messages. 
  • Follow Up - showing all orange marked messages 
  • Today - showing all yellow messages
  • ToDo - showing all green messages
  • Recently seen - for the mistakes or review 
  • Recently send - for review 
Create the following shortcuts: (http://support.apple.com/kb/PH13916)
  • alt-cmd-b =  Blue (in dutch b for beantwoorden (answer)
  • alt-cmd-o =  Orange (in dutch o for opvolgen (follow up)
  • alt-cmd-v =  Yellow (in dutch v for vandaag (today)
  • alt-cmd-t =  Green (t for todo) 
When a mail comes in you need to decide right away what to do. If it takes less than 2 minutes to deal with it I will, not I'll make a todo or put it in answer. 

2. Close your mailbox, it will distract you from your work, if they need you they'll call. 

3. Review your todo list. 

I was a long time user of Wunderlist, great app on all platforms. But I discovered that I love text files, you can open it everywhere, small.  And also organizing notes in outliners, but then I had problems with the files, large and I couldn't open them everywhere. Just recently I discoverd Taskpaper and I love it. TaskPaper — Simple to-do list software for Mac & iPhone It brings it all together for me I just love it. 

I sync a file on dropbox wich I can open everywhere with a texteditor. 

You can automate some more stuff with Tasklist: http://www.hogbaysoftware.com/wiki/TaskPaper

I use this option:


Service Menu Items
Service menu items provide similar functionally to the quick entry window. They allow 
you to add new tasks to your list without switching to TaskPaper. To use the service 
menu:
1. Select text in any application that you want to make into a task.
2. Choose Application Name > Services > TaskPaper > New Entry and a new task 
will be created from your selected text and inserted into your lists Inbox project.
4. It helps me to create a list for me what is important for that morning. It gives me more focus and less cherry picking. 

5. Start to work, there are a million things to explore, but it doesn't getting your todo's done, just add them to your list. You will get to it.