Page 1 of 1

[SOLVED]Garbled Text on LCD only when running Pyton script.

Posted: Tue Jan 13, 2015 4:38 am
by pi_noob
Hello, I'm running into a strange issue where when I add an additional function or elseif (elif), upon running the python script, and scrolling through the menu, it garbles the 20X4 lcd (no rgb). However, I have another python script that works perfectly. Scratching my head against this one. I have tried adjusting the epulse and edelay as I read from another post. What I would like it to do is output the artist and title information by running, mpc current | tail -c25 on lcd. Here is the attached python script: Thanks!

Code: Select all

# Define GPIO output pins for Radio Controls
PIN_SW1_PREV = 4
PIN_SW2_NEXT = 18

# The Adafruit_CharLCD class controls the LCD display
# using six GPIO output pins:
#  7 = RS (register select)
#  8 = E (enable/strobe)
#  25 = Data bit 4
#  24 = Data bit 5
#  23 = Data bit 6
#  17 = Data bit 7

#dependancies
from Adafruit_CharLCD import Adafruit_CharLCD
from datetime         import datetime
from subprocess       import *
from time             import sleep, strftime
import RPi.GPIO as GPIO

# globals
LCD = Adafruit_CharLCD()
PLAYLIST_MSG = []
STATION = 1
NUM_STATIONS = 0

E_PULSE = 0.000005
E_DELAY = 0.000005

def main():
   global STATION, NUM_STATIONS, PLAYLIST_MSG

   # Stop music player
   output = run_cmd("mpc stop" )

   # Setup GPIO
   GPIO.setmode(GPIO.BCM)            # Use BCM GPIO numbers
   GPIO.setup(PIN_SW1_PREV, GPIO.IN) # Previous Channel button
   GPIO.setup(PIN_SW2_NEXT, GPIO.IN) # Next Channel button

   # Setup AdaFruit LCD
   LCD.begin(20,4)
   LCD.clear()

# ----------------------------
# LOAD PLAYLIST OF STATIONS
# ----------------------------

   # Startup banner
   LCD.message('Welcome to\nPi Radio!')

   # Run shell script to add all stations
   # to the MPC/MPD music player playlist
   output = run_cmd ("mpc clear")
   output = run_cmd("/home/pi/projects/radio/radio_playlist.sh")

   # Load PLAYLIST_MSG list
   with open ("/home/pi/projects/radio/radio_playlist.sh", "r") as playlist:
      # Skip leading hash-bang line
      for line in playlist:
         if line[0:1] != '#!':  
               break
      # Remaining comment lines are loaded
      for line in playlist:
         if line[0] == "#" :
            PLAYLIST_MSG.append(line.replace(r'\n','\n')[1:-1] + "                ")
   playlist.close()

   sleep(1.5)
   NUM_STATIONS = len(PLAYLIST_MSG)

# ----------------------------
# START THE MUSIC!
# ----------------------------

   # Start music player
   LCD.clear()
   LCD.message(PLAYLIST_MSG[STATION - 1] )
   mpc_play(STATION)
   countdown_to_play = 0
      
   # Main loop
   while True:
      press = read_switches()

      # PREV button pressed
      if(press == 1):
         STATION -= 1
         if(STATION < 1):
            STATION = NUM_STATIONS
         LCD.setCursor(0,0)
         LCD.message(PLAYLIST_MSG[STATION - 1] )
         # start play in 300msec unless another key pressed
         countdown_to_play = 3

      # NEXT button pressed
      if(press == 2):
         STATION += 1
         if(STATION > NUM_STATIONS):
            STATION = 1
         LCD.setCursor(0,0)
         LCD.message(PLAYLIST_MSG[STATION - 1] )
         # start play in 300msec unless another key pressed
         countdown_to_play = 3

      # BOTH buttons pressed together
      if(press == 3):
         menu_pressed()
      # If we haven't had a key press in 300 msec
      # go ahead and issue the MPC command
      if(countdown_to_play > 0):
         countdown_to_play -= 1
         if(countdown_to_play == 0):
            # Play requested station
            mpc_play(STATION)

      delay_milliseconds(100)


def read_switches():

   # Initialize
   got_prev = False
   got_next = False

   # Read switches
   sw1_prev = GPIO.input(PIN_SW1_PREV)
   sw2_next = GPIO.input(PIN_SW2_NEXT)

   # Debounce switches and look for two-button combo
   while(sw1_prev or sw2_next):
      if(sw1_prev):
         got_prev = True
      if(sw2_next):
         got_next = True
      delay_milliseconds(1)
      sw1_prev = GPIO.input(PIN_SW1_PREV)
      sw2_next = GPIO.input(PIN_SW2_NEXT)
   if(got_prev and got_next):
      return 3
   if(got_next):
      return 2
   if(got_prev):
      return 1
   return 0



def delay_milliseconds(milliseconds):
   seconds = milliseconds / float(1000)	# divide milliseconds by 1000 for seconds
   sleep(seconds)



# ----------------------------
# RADIO SETUP MENU
# ----------------------------

MENU_LIST = [
   '1. Display Time \n   & IP Address ',
   '2. Output Audio \n   to HDMI      ',
   '3. Output Audio \n   to Headphones',
   '4. Auto Select  \n   Audio Output ',
   '5. Song        \n     Track       ',
   '6. Reboot       \n   Reboot       ',
   '7. System       \n   Shutdown!    ',
   '8. Exit         \n                ']

def menu_pressed():
   global MENU_LIST

   item = 0
   LCD.clear()
   LCD.message(MENU_LIST[item] )

   keep_looping = True
   while (keep_looping):

      # Wait for a key press
      press = read_switches()

      # PREV button
      if(press == 1):
         item -= 1
         if(item < 0):
            item = len(MENU_LIST) - 1
         LCD.clear()
         LCD.message(MENU_LIST[item] )

      # NEXT button
      elif(press == 2):
         item += 1
         if(item >= len(MENU_LIST)):
            item = 0
         LCD.clear()
         LCD.message(MENU_LIST[item] )

      # BOTH buttons together, This is "Select"
      elif(press == 3):
         keep_looping = False

         # Take action
         if(  item == 0):
            # display time and IP address
            display_ipaddr()
         elif(item == 1):
            # output to HDMI
            output = run_cmd("amixer -q cset numid=3 2")
         elif(item == 2):
            # output to headphone jack
            output = run_cmd("amixer -q cset numid=3 1")
         elif(item == 3):
            # output auto-select
              output = run_cmd("amixer -q cset numid=3 0")
         elif(item == 4):
            # Check artist/title info
              output = run_cmd("mpc current | tail -c25")          
         elif(item == 5):
            #reboot the system
            output = run_cmd("mpc clear")
            output = run_cmd("sudo reboot")
         elif(item == 6):
            #shutdown the system
            output = run_cmd("mpc clear")
            output = run_cmd("sudo halt -p")
      else:
         delay_milliseconds(100)

   # Restore display
   LCD.clear()
   LCD.message(PLAYLIST_MSG[STATION - 1] )

      

#def get_track():
#    show_track=run_cmd ("mpc current | tail -c25")   
#    if get_track == "":
#    get_track = run_cmd(show_track)
#    i = 0
#    keep_looping = True

     
def display_ipaddr():
   show_wlan0 = "ip addr show wlan0 | cut -d/ -f1 | awk '/inet/ {printf \"w%15.15s\", $2}'"
   show_eth0  = "ip addr show eth0  | cut -d/ -f1 | awk '/inet/ {printf \"e%15.15s\", $2}'"
   ipaddr = run_cmd(show_eth0)
   if ipaddr == "":
      ipaddr = run_cmd(show_wlan0)

   i = 0
   keep_looping = True
   while (keep_looping):

      # Every second, update the time display
      i += 1
      if(i % 10 == 0):
         LCD.setCursor(0,0)
         LCD.message(datetime.now().strftime('%b %d  %H:%M:%S\n'))
         LCD.message(ipaddr)
         #LCD.message('e%15.15s' % ( ipaddr ) )

      # Every 3 seconds, update ethernet or wi-fi IP address
      if(i == 60):
         ipaddr = run_cmd(show_eth0)
         i = 0
      elif(i == 30):
         ipaddr = run_cmd(show_wlan0)

      # Every 100 milliseconds, read the switches
      press = read_switches()
      if(press == 3):
         keep_looping = False
      delay_milliseconds(100)



def run_cmd(cmd):
   p = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT)
   output = p.communicate()[0]
   return output



def run_cmd_nowait(cmd):
   pid = Popen(cmd, shell=True, stdout=NONE, stderr=STDOUT).pid



def mpc_play(STATION):
   pid = Popen(["/usr/bin/mpc", "play", '%d' % ( STATION )]).pid



if __name__ == '__main__':
  main()

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 11:28 am
by FTrevorGowen
Since I'm not a Python programmer I can't comment on the Python code but I can point out a hardware issue that can lead to garbled text (as shown here: http://www.cpmspectrepi.webspace.virgin ... ml#Testing_... ). If your interface is "4-bit parallel" and your "garbling" is similar to that shown in the last photo. your E-strobe pulse may be too short. A little more info. is here:
http://www.cpmspectrepi.webspace.virgin ... gData.html
and, FWIW, there's a forum thread here:
http://www.raspberrypi.org/forums/viewt ... 00#p641100
Trev.

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 2:22 pm
by PangolinPaws
I've noticed a similar thing happening to my LCD a couple of times. Turns out I had a second script running in the background that was also trying to use the LCD.

Perhaps this is unlikely for your setup, but I thought I'd mention it, just in case. ^_^

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 3:07 pm
by pi_noob
Thanks, FTrevorGowen for the hardware information! I believe I have an 8-bit parrallel lcd. PangolinPaws - I know it is strange. I do have another python script which calls the Adafruit LCD dependency for my lcd. However, if I remove this code from the else, else if statements:
elif(item == 4):
# Check artist/title info
output = run_cmd("mpc current | tail -c25")
The LCD display works perfectly and I am able to toggle between the menus. I am trying to achieve checking the artist/song title as an option and tried using output = run_cmd("mpc current"). I also did try to call a function from the else elseif statements.

Any help would be appreciated!

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 3:23 pm
by mike_p
If you're using Adafruit_CharLCD then you are communicating with LCD with 4 bits, not 8.
The pulse widths and delay times that you need are built into the Adafruit_CharLCD.py script.
I'd have a play with those to get things working.
That script has "self.delayMicroseconds(1)" twice in the pulseEnable function. I'd replace the '1' with a constant and try a few different (longer) variations.

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 3:27 pm
by PangolinPaws
pi_noob wrote:I do have another python script which calls the Adafruit LCD dependency for my lcd. However, if I remove this code from the else, else if statements:

Code: Select all

elif(item == 4):
# Check artist/title info 
output = run_cmd("mpc current | tail -c25") 
The LCD display works perfectly and I am able to toggle between the menus.
You've got a bit deeper into this than I have, but is it possible to completely clear the LCD briefly before the problematic code and see if that makes any difference?

P.S. Could you stick your code in [ code ] tags so we can see the indentation etc.?

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 6:26 pm
by pi_noob
Do you mean enter this code like below (without brackets) to clear lcd?

[lcd.clear()
elif(item == 4):
#Check artist/title info
output = run_cmd("mpc current | tail -c25") ]

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 6:46 pm
by DougieLawson
pi_noob wrote:Do you mean enter this code like below (without brackets) to clear lcd?

[lcd.clear()
elif(item == 4):
#Check artist/title info
output = run_cmd("mpc current | tail -c25") ]
No he means enter the code like:
[code]lcd.clear()
elif(item == 4):
#Check artist/title info
output = run_cmd("mpc current | tail -c25") [/code]

To get it formatted as:

Code: Select all

lcd.clear()
   elif(item == 4):
   #Check artist/title info
   output = run_cmd("mpc current | tail -c25") 

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 8:47 pm
by PangolinPaws
pi_noob wrote:Do you mean enter this code like below (without brackets) to clear lcd?

Code: Select all

lcd.clear()
   elif(itemr == 4):
   #Check artist/title info
   output = run_cmd("mpc current | tail -c25") 
Something like that. If not clearing the LCD is the problem then its position within your If statements is probably the key.

If you could add those code tags to your original post we could figure out where to try the lcd.clear()

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 8:58 pm
by ame
What is the actual output of this command?

Code: Select all

mpc current | tail -c25

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 10:13 pm
by pi_noob
Thanks, Pangolin and Dougie for the tip. The original code has bee placed into the proper tags. Obvious newb on forum. Ame, the output of the tail command would ouput the last 25 bytes of the current artist/song on the radio station. However, sometimes it doesn't display the artist and song title as this depends on the radio station streaming site. It's not the best way, just was playing with this type of command.

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 10:17 pm
by ame
pi_noob wrote:Thanks, Dougie for the tip. The original code has bee placed into the proper tags. Obvious newb on forum. Ame, the output of the tail command would ouput the last 25 bytes of the current artist/song on the radio station. However, sometimes it doesn't display the artist and song title as this depends on the radio station streaming site. It's not the best way, just was playing with this type of command.
I know what the command does, but my purpose for asking was to know *exactly* what the output of the command is. You said it corrupts the display, so it's quite possible that there are junk characters in those 25 bytes that do odd things to the display.

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 10:20 pm
by pi_noob
I have even tried using the mpc current command.

Re: Garbled Text on LCD only when running certain Python scr

Posted: Tue Jan 13, 2015 11:46 pm
by pi_noob
I've tried adjusting the self.delayMicroseconds(1)" on both for the pulseEnable function..no dice. Any other suggestions?

I've added functions in the script. Here is the added code if anyone wants to try it out and get back to me, please.

Code: Select all

# ----------------------------
# RADIO SETUP MENU
# ----------------------------

MENU_LIST = [
   '1. Display Time \n   & IP Address ',
   '2. Output Audio \n   to HDMI      ',
   '3. Output Audio \n   to Headphones',
   '4. Auto Select  \n   Audio Output ',
   '5. Song        \n     Track       ',
   '6. Reboot       \n   Reboot       ',
   '7. System       \n   Shutdown!    ',
   '8. Exit         \n                ']

def menu_pressed():
   global MENU_LIST

   item = 0
   LCD.clear()
   LCD.message(MENU_LIST[item] )

   keep_looping = True
   while (keep_looping):

      # Wait for a key press
      press = read_switches()

      # PREV button
      if(press == 1):
         item -= 1
         if(item < 0):
            item = len(MENU_LIST) - 1
         LCD.clear()
         LCD.message(MENU_LIST[item] )

      # NEXT button
      elif(press == 2):
         item += 1
         if(item >= len(MENU_LIST)):
            item = 0
         LCD.clear()
         LCD.message(MENU_LIST[item] )

      # BOTH buttons together, This is "Select"
      elif(press == 3):
         keep_looping = False

         # Take action
         if(  item == 0):
            # display time and IP address
            display_ipaddr()
            
         elif(item == 1):
            # output to HDMI
            output = run_cmd("amixer -q cset numid=3 2")
         
         elif(item == 2):
            # output to headphone jack
            output = run_cmd("amixer -q cset numid=3 1")
         
         elif(item == 3):
            # output auto-select
              output = run_cmd("amixer -q cset numid=3 0")

         elif(item == 4):
            # Check artist/title info
              #output = run_cmd("mpc current")  
              load_playlist()
              getTrack()
         elif(item == 5):
            #reboot the system
            output = run_cmd("mpc clear")
            output = run_cmd("sudo reboot")

         elif(item == 6):
            #shutdown the system
            output = run_cmd("mpc clear")
            output = run_cmd("sudo halt -p")
      else:
         delay_milliseconds(100)

   # Restore display
   LCD.clear()
   LCD.message(PLAYLIST_MSG[STATION - 1] )

def load_playlist():
   global STATION, NUM_STATIONS, PLAYLIST_MSG

   # Run shell script to add all stations
   # to the MPC/MPD music player playlist
   output = run_cmd("mpc clear")
   output = run_cmd("/home/pi/projects/radio/radio_playlist.sh")

   # Load PLAYLIST_MSG list
   PLAYLIST_MSG = []
   with open ("/home/pi/projects/radio/radio_playlist.sh", "r") as playlist:
      # Skip leading hash-bang line
      for line in playlist:
         if line[0:1] != '#!':  
               break
      # Remaining comment lines are loaded
      for line in playlist:
         if line[0] == "#" :
            PLAYLIST_MSG.append(line.replace(r'\n','\n')[1:-1] + "                ")
   playlist.close()
   NUM_STATIONS = len(PLAYLIST_MSG)



def getTrack():
   L= [S.strip('\n') for S in os.popen('mpc').readlines()]        # Get the Track info from the stdout of the mpc command
   output = run_cmd("mpc current | tail -c25")
   station = output [0:20]                                           # Pick out the Station and Track info
   track =  output [-21:-1]
   LCD.message(station + " "*(20 - len(station)), 0, 0)
   LCD.message(track + " "*(20 - len(track)), 0, 1) 

Re: Garbled Text on LCD only when running certain Python scr

Posted: Sat Jan 17, 2015 2:20 am
by pi_noob
After endless programming, I resolved this by modifying certain functions. You may close out this post.

Re: Garbled Text on LCD only when running certain Python scr

Posted: Sat Jan 17, 2015 6:08 am
by rpdom
How about posting your solution so that others may benefit from your experience? :)

(You can't "close" the post, but you can edit the thread title on your first post and add [SOLVED] to show it as fixed)

Re: [SOLVED]Garbled Text on LCD only when running Pyton scri

Posted: Fri Jan 23, 2015 1:03 am
by pi_noob
Sorry for the delay. The reason for my garbled text, as strange as this sounds, was some faulty coding. I used the os.system commands, for example:

Code: Select all

 if ( GPIO.input(PIN_SW3_PAUSE) == True):
          os.system("mpc pause")