File [scripts/mpd_lcd.py]
| 1 |
#!/usr/bin/python |
| 2 |
import smbus |
| 3 |
import time |
| 4 |
from mpd import MPDClient |
| 5 |
import socket |
| 6 |
# Server for MPD |
| 7 |
SERVER = "lounge-pi" |
| 8 |
client = MPDClient() # create client object |
| 9 |
client.timeout = 10 # network timeout in seconds (floats allowed), default: None |
| 10 |
client.idletimeout = None # timeout for fetching the result of the idle command is handled seperately, default: None |
| 11 |
# Host lookup for determining Internet connectivity |
| 12 |
INET_SERVER = "www.google.com" |
| 13 |
# Define some device parameters |
| 14 |
I2C_ADDR = 0x27 # I2C device address |
| 15 |
LCD_WIDTH = 20 # Maximum characters per line |
| 16 |
# Define some device constants |
| 17 |
LCD_CHR = 1 # Mode - Sending data |
| 18 |
LCD_CMD = 0 # Mode - Sending command |
| 19 |
LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line |
| 20 |
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line |
| 21 |
LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line |
| 22 |
LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line |
| 23 |
LCD_BACKLIGHT = 0x08 # On |
| 24 |
#LCD_BACKLIGHT = 0x00 # Off |
| 25 |
ENABLE = 0b00000100 # Enable bit |
| 26 |
# Timing constants |
| 27 |
E_PULSE = 0.0005 |
| 28 |
E_DELAY = 0.0005 |
| 29 |
ZERO_DISP = 3 |
| 30 |
#Open I2C interface |
| 31 |
#bus = smbus.SMBus(0) # Rev 1 Pi uses 0 |
| 32 |
bus = smbus.SMBus(1) # Rev 2 Pi uses 1 |
| 33 |
def lcd_init(): |
| 34 |
# Initialist display |
| 35 |
lcd_byte(0x33,LCD_CMD) # 110011 Initialise |
| 36 |
lcd_byte(0x32,LCD_CMD) # 110010 Initialise |
| 37 |
lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction |
| 38 |
lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off |
| 39 |
lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size |
| 40 |
lcd_byte(0x01,LCD_CMD) # 000001 Clear display |
| 41 |
time.sleep(E_DELAY) |
| 42 |
def lcd_byte(bits, mode): |
| 43 |
# Send byte to data pins |
| 44 |
# bits = the data |
| 45 |
# mode = 1 for data |
| 46 |
# 0 for command |
| 47 |
bits_high = mode | (bits &; 0xF0) | LCD_BACKLIGHT |
| 48 |
bits_low = mode | ((bits<<4) &; 0xF0) | LCD_BACKLIGHT |
| 49 |
# High bits |
| 50 |
bus.write_byte(I2C_ADDR, bits_high) |
| 51 |
lcd_toggle_enable(bits_high) |
| 52 |
# Low bits |
| 53 |
bus.write_byte(I2C_ADDR, bits_low) |
| 54 |
lcd_toggle_enable(bits_low) |
| 55 |
def lcd_toggle_enable(bits): |
| 56 |
# Toggle enable |
| 57 |
time.sleep(E_DELAY) |
| 58 |
bus.write_byte(I2C_ADDR, (bits | ENABLE)) |
| 59 |
time.sleep(E_PULSE) |
| 60 |
bus.write_byte(I2C_ADDR,(bits &; ~ENABLE)) |
| 61 |
time.sleep(E_DELAY) |
| 62 |
def lcd_string(message,line): |
| 63 |
# Send string to display |
| 64 |
message = message.ljust(LCD_WIDTH," ") |
| 65 |
lcd_byte(line, LCD_CMD) |
| 66 |
for i in range(LCD_WIDTH): |
| 67 |
lcd_byte(ord(message[i]),LCD_CHR) |
| 68 |
def music_details(): |
| 69 |
# Set defaults just in case of errors |
| 70 |
artist = "Cannot connect to" |
| 71 |
album = SERVER |
| 72 |
song = "" |
| 73 |
length = 0 |
| 74 |
position = 0 |
| 75 |
# Connect to MPD on the server |
| 76 |
server_up = 1 |
| 77 |
try: |
| 78 |
client.connect(SERVER, 6600) |
| 79 |
# Catch socket errors |
| 80 |
except IOError: |
| 81 |
server_up = 0 |
| 82 |
print("Car_Server_LCD.py: Could not connect to " + SERVER) |
| 83 |
# Catch Other MPD Errors |
| 84 |
except MPDError: |
| 85 |
server_up = 0 |
| 86 |
print("Car_Server_LCD.py: Could not connect to " + SERVER) |
| 87 |
if server_up == 1: |
| 88 |
status = client.status() |
| 89 |
if status['state'] == "play": |
| 90 |
position = int(float(status['elapsed'])) |
| 91 |
track = client.currentsong() |
| 92 |
if len(track) > 0: |
| 93 |
artist = track['artist'] |
| 94 |
if len(artist) > LCD_WIDTH: |
| 95 |
artist += " " |
| 96 |
album = track['album'] |
| 97 |
if len(album) > LCD_WIDTH: |
| 98 |
album += " " |
| 99 |
song = track['title'] |
| 100 |
if len(song) > LCD_WIDTH: |
| 101 |
song += " " |
| 102 |
length = int(track['time']) |
| 103 |
else: |
| 104 |
artist = "Unknown" |
| 105 |
album = "Unknown" |
| 106 |
song = "Unknown" |
| 107 |
# Close and disconnect from the server |
| 108 |
client.close() |
| 109 |
client.disconnect() |
| 110 |
return (artist, album, song, length, position) |
| 111 |
def format_string(old_string, cur_string, pos): |
| 112 |
if old_string != cur_string: |
| 113 |
# We need to reset the position on a new string |
| 114 |
pos = 0 |
| 115 |
if len(cur_string) > LCD_WIDTH: |
| 116 |
return cur_string[pos:pos + 20] |
| 117 |
else: |
| 118 |
return cur_string |
| 119 |
def string_pos(cur_string, pos, zero_count): |
| 120 |
return_pos = 0 |
| 121 |
if (pos + 20) < len(cur_string): |
| 122 |
if (zero_count < ZERO_DISP) and (pos == 0): |
| 123 |
zero_count = zero_count + 1 |
| 124 |
else: |
| 125 |
zero_count = 0 |
| 126 |
return_pos = pos + 1 |
| 127 |
return (return_pos, zero_count) |
| 128 |
def is_connected(hostname): |
| 129 |
try: |
| 130 |
# see if we can resolve the host name -- tells us if there is |
| 131 |
# a DNS listening |
| 132 |
host = socket.gethostbyname(hostname) |
| 133 |
# connect to the host -- tells us if the host is actually |
| 134 |
# reachable |
| 135 |
s = socket.create_connection((host, 80), 2) |
| 136 |
s.close() |
| 137 |
return True |
| 138 |
except: |
| 139 |
pass |
| 140 |
return False |
| 141 |
def main(): |
| 142 |
# Main program block |
| 143 |
# Initialise display |
| 144 |
lcd_init() |
| 145 |
# Define old variables to speed up display updates |
| 146 |
old_artist = "" |
| 147 |
old_album = "" |
| 148 |
old_song = "" |
| 149 |
# Define old displays to speed up display updates |
| 150 |
disp_artist = "" |
| 151 |
disp_album = "" |
| 152 |
disp_song = "" |
| 153 |
disp_timer = "" |
| 154 |
# Define the start positions of text strings |
| 155 |
start_artist = 0 |
| 156 |
start_album = 0 |
| 157 |
start_song = 0 |
| 158 |
# Define the number of times a scrolling message has been at pos=0 |
| 159 |
zero_artist = 0 |
| 160 |
zero_album = 0 |
| 161 |
zero_song = 0 |
| 162 |
# Define an internet check timer |
| 163 |
inet_timer = 0 |
| 164 |
while True: |
| 165 |
# Query the MPD server |
| 166 |
the_music = music_details() |
| 167 |
artist = the_music[0] |
| 168 |
album = the_music[1] |
| 169 |
song = the_music[2] |
| 170 |
length = the_music[3] |
| 171 |
position = the_music[4] |
| 172 |
# Convert the times into HH:SS |
| 173 |
song_len = time.strftime('%M:%S', time.gmtime(length)) |
| 174 |
song_pos = time.strftime('%M:%S', time.gmtime(position)) |
| 175 |
# Work out if we need to display part of a string |
| 176 |
artist_string = format_string(old_artist, artist, start_artist) |
| 177 |
old_artist = artist |
| 178 |
pos_artist = string_pos(artist, start_artist, zero_artist) |
| 179 |
start_artist = pos_artist[0] |
| 180 |
zero_artist = pos_artist[1] |
| 181 |
album_string = format_string(old_album, album, start_album) |
| 182 |
old_album = album |
| 183 |
pos_album = string_pos(album, start_album, zero_album) |
| 184 |
start_album = pos_album[0] |
| 185 |
zero_album = pos_album[1] |
| 186 |
song_string = format_string(old_song, song, start_song) |
| 187 |
old_song = song |
| 188 |
pos_song = string_pos(song, start_song, zero_song) |
| 189 |
start_song = pos_song[0] |
| 190 |
zero_song = pos_song[1] |
| 191 |
# Now work out if we have Internet connection, but only |
| 192 |
# do it every 10 seconds to save bandwidth |
| 193 |
if time.time() - inet_timer >= 10: |
| 194 |
if is_connected(INET_SERVER): |
| 195 |
inet = "*" |
| 196 |
else: |
| 197 |
inet = "-" |
| 198 |
inet_timer = time.time() |
| 199 |
timer = song_pos + " - " + song_len + " " + inet |
| 200 |
# Send some test |
| 201 |
if artist_string != disp_artist: |
| 202 |
disp_artist = artist_string |
| 203 |
lcd_string(artist_string, LCD_LINE_1) |
| 204 |
if album_string != disp_album: |
| 205 |
disp_album = album_string |
| 206 |
lcd_string(album_string, LCD_LINE_2) |
| 207 |
if song_string != disp_song: |
| 208 |
disp_song = song_string |
| 209 |
lcd_string(song_string, LCD_LINE_3) |
| 210 |
if timer != disp_timer: |
| 211 |
disp_timer = timer |
| 212 |
lcd_string(timer, LCD_LINE_4) |
| 213 |
time.sleep(0.2) |
| 214 |
if __name__ == '__main__': |
| 215 |
try: |
| 216 |
main() |
| 217 |
except KeyboardInterrupt: |
| 218 |
pass |
| 219 |
finally: |
| 220 |
lcd_byte(0x01, LCD_CMD) |
Computing Power
- Acer Aspire R3700
- Acknowledgements
- BOINC
- Desktop PC
- Eee PC 4G (701)
- Eee PC 901
- Gigabit Network
- Inspiron 14 5485 Laptop
- Kids Gaming PCs
- Kids PC 1
- Kids PC 2
- Media PC
- Mini-ITX PC
- My Useful Scripts
- Nano ITX PC
- Nook Simple Touch
- Processing Power
- Raspberry Pi (*)
- Sharp Zaurus SL-C3200
- Storage Capacity
- The Server
Galleries
(* updated in last 14 days)



![Validate my Atom 1.0 feed [Valid Atom 1.0]](./images/valids/valid-atom10-yellow.gif)
![Validate my RSS 2.0 feed [Valid RSS 2.0]](./images/valids/valid-rss20-yellow.gif)