LCD display and buttons in Python (tutorial and code)

Raspberry Pi related support

Re: LCD display and buttons in Python (tutorial and code)

Postby DennisPi » 29 Jan 2017, 10:37

Thx for your info, is it right dat i can not use de i2c interface on de backside of the LCD (4pins) because it is in use with the HifiBerry DAC+ ?
Because i follow all your steps succesfully. But there is nothing on my LCD screen !
DennisPi
 
Posts: 2
Joined: 28 Jan 2017, 20:42

Re: LCD display and buttons in Python (tutorial and code)

Postby den_hr » 07 Feb 2017, 22:07

TommyBoy wrote:great SK, but how about a STANDARD 1602 with out I2C module,
the cpu on the pi can easyly bit-bang the needed info out on some GPIO
and you see all sorts of cool and cheap displays are super easy to find all over the world,
the most normal is offcourse the 1602, but 2002 2402 or even 4 line variants are also very easy to find.


The reason why almost everyone is using i2c LCDs is that those need ONLY 2 wire connections (i.e. occupy only 2 GPIO I2C-related pins).
Also, you can use i2c devices "chained" - so you can have 2 i2c devices hooked up to the same two i2c pins.... In short, i2c LCDs use less GPIO pins, and make everything a lot simpler: from wiring connections (only 2 wires for signal and 2 wires for power).

In my case, I also have an IR sensor and an i2c DAC connected to RasPi - so already a mess of wires :)
I2C makes life a lot easier in that regard...
den_hr
 
Posts: 52
Joined: 06 Feb 2015, 17:10
Location: Croatia

Re: LCD display and buttons in Python (tutorial and code)

Postby TommyBoy » 08 Feb 2017, 10:54

ya exactly good point,
i did order one of them i2c displays, and is going to have a test if i can make it write stuff from my rune player.
hopefully it dont affect dac and its performance, or its i2c, that would be the end of it..
User avatar
TommyBoy
 
Posts: 111
Joined: 29 Mar 2016, 14:04
Location: Copenhagen Denmark

Re: LCD display and buttons in Python (tutorial and code)

Postby den_hr » 12 Feb 2017, 17:17

BTW, currently I'm playing with another extension to this (LCD) system. I'm not too happy with the "bastard code" I currently have (mix of Randy's and my own Python stuff), and, besides, I've always been annoyed by the RasPi's lack of "proper" power supply handling (turning on/off).

So, my next idea (we'll see how it goes) is to use an Arduino to act as a "proper" ATX "power control" for Rune on RasPi - meaning you'll be able to shutdown the Rune RasPi server properly using either Web UI, power button, or an IR remote. Arduino will have some kind of relay to turn the power for RasPi on and off, and it will also take over the handling of the character LCD and IR remote signals. This also means that you'll be able not only to turn off RasPi using IR remote, but also to turn it ON via IR remote - just like a TV :)
(BTW, that means that Arduino part will always be powered on - but it will be in power saving mode, waiting for IR signal to turn ON, which doesn't use much power - certainly not more than a TV in standby...)

The hardware side on the Arduino is more or less done -as a concept - and now I have to do the "hard part" - serial communication between RasPi and Arduino (sending of formatted strings from Rune to Arduino to show on LCD, powerup and shutdown mesages and communication)...

Will take some more time, but so far, on the conceptual level, it looks promising. We'll see how it goes :)
den_hr
 
Posts: 52
Joined: 06 Feb 2015, 17:10
Location: Croatia

Re: LCD display and buttons in Python (tutorial and code)

Postby Legufix » 15 Feb 2017, 21:51

Hi all,

first of all I have to mention that I am new to rune audio (also to python and Linux) and this forum helped me a lot - thanks!

I am trying to build a music player with display and buttons, too. But instead of an LCD display, I want to use one of this nice little OLED displays. Therefore I was not able to use the code from RandyCubic (I am using a library for the SSD1306 chip I found in the web). I also was not satisfied with the power down solution, hence I designed Arduino based shut down circuit.

Somehow I managed to compile a working code (based on snippets I found: RandyCubic, hondagx35,...). But now I am stuck with a problem that I can not find a solution for: my code works fine if I start the programm manualy but when I start it via a service and a bash script it takes 2 or more iterations (Restart=on-failure) until the programm works properly.

Here is my simplified (I removed some parts of the programm that had no influence on the above mentioned problem to keep the code short for the forum - if someone is interested in the full code, just ask me) approach:

Python programm for buttons, display control remove for simplification:
Code: Select all
#!/usr/bin/env python
#-*- coding: UTF-8 -*-

# IMPORTS
import sys, time, threading, os

import socket
import fcntl
import struct

from mpd import (MPDClient, CommandError)
from socket import error as SocketError

import RPi.GPIO as GPIO
import Queue

import psutil
from datetime import datetime

## Some functions
def mpdConnect(client, con_id):
    # Simple wrapper to connect MPD.
    try:
        client.connect(**con_id)
    except SocketError:
        return False
    return True

def mpdAuth(client, secret):
    """
    Authenticate
    """
    try:
        client.password(secret)
    except CommandError:
        return False
    return True


def find_title(s):
    end = s.rfind('.')
    start = s.rfind('/')
    return s[start+1:end]

def convert_string(s):
    s = s.replace('ü', 'ue')
    s = s.replace('ö', 'oe')
    s = s.replace('ä', 'ae')
    s = s.replace('Ü', 'Ue')
    s = s.replace('Ö', 'Oe')
    s = s.replace('Ä', 'Ae')
    s = s.replace('´', '\'')
    s = s.replace('ß', 'ss')
    return s


def my_callback(channel):
    current = time.strftime("%d.%m.%Y %H:%M:%S")
    #print ("{} falling edge detected on {}".format(current, channel))
    time.sleep(0.01)
    if not GPIO.input(channel):
        queue.put(channel)


# This function allows us to grab any of our IP addresses
def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])

##


NextButton = 23
PrevButton = 22
PlayButton = 20
StopButton = 26
MenuButton = 24

SignOut = 12   #Client active signal for power control

HOST = 'localhost'
PORT = '6600'
PASSWORD = False
##
CON_ID = {'host':HOST, 'port':PORT}
##

GPIO.setmode(GPIO.BCM)

GPIO.setwarnings(False)

GPIO.setup(SignOut, GPIO.OUT)
GPIO.setup(NextButton, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(PrevButton, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(PlayButton, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(StopButton, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(MenuButton, GPIO.IN, pull_up_down=GPIO.PUD_UP)

client = MPDClient()

queue = Queue.Queue()


def main_frontpanel():

    global text_line1, text_line2, text_line3

    GPIO.output(SignOut,GPIO.HIGH) #Send Boot complete signal to Arduino

    print ("Start_Main")

    GPIO.add_event_detect(NextButton, GPIO.FALLING, callback=my_callback, bouncetime=500)
    GPIO.add_event_detect(PrevButton, GPIO.FALLING, callback=my_callback, bouncetime=500)
    GPIO.add_event_detect(PlayButton, GPIO.FALLING, callback=my_callback, bouncetime=500)
    GPIO.add_event_detect(StopButton, GPIO.FALLING, callback=my_callback, bouncetime=500)
    GPIO.add_event_detect(MenuButton, GPIO.FALLING, callback=my_callback, bouncetime=500)

    try:
        IP_address = get_ip_address('wlan0') # WiFi address of WiFi adapter. NOT ETHERNET
    except IOError:
        try:
            IP_address = get_ip_address('eth0') # WiFi address of Ethernet cable. NOT ADAPTER
        except IOError:
            IP_address = ('NO INTERNET!')


    ## MPD object instance
    # client = MPDClient()

    connectionCounter = 0
    connectionCounterMax = 10
    waitReconnect = 5
    notConnected = True

    while (connectionCounter < 10) and (notConnected):
        connectionCounter += 1
        #draw.rectangle((0,0,width,height), outline=0, fill=0)
        if mpdConnect(client, CON_ID):
            print('Got connected!')
            print("Attempt {}" .format(connectionCounter))
            notConnected = False
        else:
            print('failed to connect MPD server.')
            print("Attempt {}" .format(connectionCounter))
            time.sleep(waitReconnect)

    if (connectionCounter == connectionCounterMax):
        sys.exit(1)

    # Auth if password is set non False
    if PASSWORD:
        if mpdAuth(client, PASSWORD):
            print('Pass auth!')
        else:
            print('Error trying to pass auth.')
            client.disconnect()
            sys.exit(2)


    last_file = ""
    last_state = ""
    last_title = ""


    while(1):

        try:
            currentsong = client.currentsong()
            state = client.status()
            #currenttitle = client.currentsong()['title']
        except:
            currentsong = ""     #check if this makes sense
            state = ""         #check if this makes sense
            print ("unexpected error [0]")

        try:
            title = currentsong['title']
        except KeyError:
            try:
                title = find_title(currentsong['file'])
            except:
                print("unexpected error:")
        try:
            c_file = currentsong['file']
        except KeyError:
            c_file = ''


        if not queue.empty():
            job = queue.get()
            if job == NextButton:
               if (int(state['song']) < (int(state['playlistlength']))-1):
                    if state['state'] == "stop":
                        print ("cmd: next(stopped)")
                        client.play()
                        client.next()
                        client.stop()
                    else:
                        print ("cmd: next")
                        client.next()
                else:
                   print("End of Playlist")
            elif job == PrevButton:
               if (int(state['song']) > 0):
                    if state['state'] == "stop":
                        print ("cmd: prev(stopped)")
                        client.play()
                        client.previous()
                        client.stop()
                    else:
                        print ("cmd: prev")
                        client.previous()
                else:
                   print("End of Playlist")
            elif job == PlayButton:
                if state['state'] == 'play':
                    print ("cmd: pause")
                    client.pause()
                else:
                    print ("cmd: play")
                    client.play()
            elif job == StopButton:
                print ("cmd: stop")
                client.stop()



        if ((last_state != state['state']) or (c_file != last_file) or (title != last_title)):
            try:
                currentsong = client.currentsong()
            except:
               print ("unexpected error [1]")

            try:
                station = currentsong['name']
            except KeyError:
                station = ''

            try:
                title = currentsong['title']
            except KeyError:
                try:
                    title = find_title(currentsong['file'])
                except KeyError:
                    title = ''

            try:
                artist = currentsong['artist']
            except KeyError:
                artist = '[no artist]'

            try:
                album = currentsong['album']
            except KeyError:
                album = '[no album]'

            try:
                c_file = currentsong['file']
            except KeyError:
                c_file = ''

            if(station != ''):    # webradio
                print('Station = ' + station)
                print('Title = ' + title)
                print('Album = ' + album)
                #print(state['song'] + ' / ' + state['playlistlength'])
                #print(client.currentsong())


            else:                 # file
                print('Title = ' + title)
                print('Artist = ' + artist)
                print('Album = ' + album)
                #print(state['song'] + ' / ' + state['playlistlength'])


            last_state = state['state']
            last_file = c_file
            last_title = title



        #print(menu_state)
        time.sleep(.1)

    ## disconnect
    client.disconnect()
    sys.exit(0)

# Script starts here
if __name__ == "__main__":
    try:
        main_frontpanel()
    except (KeyboardInterrupt, SystemExit):
        print("\nQuit\n")
        GPIO.cleanup()


For automatic start I use a startfrontpanel.service:

Code: Select all
[Unit]
Description=Starts script to interact with front panel
Requires=
After=network.target
#After=mpd.service

[Service]
ExecStartPre=/usr/bin/sh -c "sleep 20"
ExecStart=/usr/bin/myStartBash.sh
TimeoutSec=0
Restart=on-failure

[Install]
WantedBy=multi-user.target


and a bash script:

Code: Select all
#!/bin/bash
cd /root/ssd1306/examples
echo "Boot $(date +"%Y/%m/%d %H:%M:%S")" >> /root/shutdown.log
python2 hochri_player_v0_1_2_reduced.py >> /root/text.log 2>&1


In the log file I can see that the python script is started twice (or more often).

For shutdown I also use a service and a bash script:

Code: Select all
[Unit]
Description=Save Off Switch  Service
After=systemd-modules-load.service
[Service]
Type=simple
ExecStart=/etc/save_off_switch.sh
[Install]
WantedBy=multi-user.target


Code: Select all
#!/bin/bash
# this is the GPIO pin receiving the shut-down signal
GPIOpin1=25
echo "$GPIOpin1" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio$GPIOpin1/direction
while true; do
  sleep 1
  power=$(cat /sys/class/gpio/gpio$GPIOpin1/value)
  if [ $power != 0 ]; then
    sleep 0.1
    power=$(cat /sys/class/gpio/gpio$GPIOpin1/value)
    if [ $power != 0 ]; then
      sleep 0.2
      power=$(cat /sys/class/gpio/gpio$GPIOpin1/value)
      if [ $power != 0 ]; then
        mpc stop
        /srv/http/command/rune_shutdown
        # echo "out" > /sys/class/gpio/gpio$GPIOpin1/direction
        # echo "1" > /sys/class/gpio/gpio$GPIOpin1/value
   echo  "Shutdown $(date +"%Y/%m/%d %H:%M:%S")" >> /root/shutdown.log
        sleep 3
        poweroff
      fi
    fi
  fi
done


I realy would appreciate if you could give me any advice.

Thank you in advance!

Best regards,
Legufix
Legufix
 
Posts: 1
Joined: 16 Apr 2016, 00:31
Location: Austria

Re: LCD display and buttons in Python (tutorial and code)

Postby nmbb » 19 Feb 2017, 13:36

Hello. New here, after many tries and errors finally got my lcd i2c working. Except when I change music it didn't change on display neither the info and only shows the music player when rebooted. Using RuneAudioLCD, the other version (RuneAudioLCDMod) didn't worked here...

used:

RuneOs: 0.3-beta
RuneUI: 1.3-beta
Hw-env: RaspberryPi 2

cheap 20x4 lcd plus i2c bus

just in case...

http://imgur.com/a/eDZh3




UPDATE:

In web radio it displays the streaming function and time and the sampling rate... but when the music changed didn't update. Probably something missing, but what? Not a 100% newbie to this, but this time nothing occurs :)



Thanks
nmbb
 
Posts: 4
Joined: 16 Feb 2017, 01:51

Re: LCD display and buttons in Python (tutorial and code)

Postby nmbb » 19 Feb 2017, 18:40

3 nespresso later... and problem solved. For those who have the same trouble... found this on RuneAudioLCD/start.py

######### MPD PARAMETERS ##############
# Only if you know what you're doing!
HOST = 'runeaudio.local' ---> replace localhost with player name.local or IP
PORT = '6600'
PASSWORD = False
CON_ID = {'host':HOST, 'port':PORT}
#########################################

And that's it!
nmbb
 
Posts: 4
Joined: 16 Feb 2017, 01:51

Re: LCD display and buttons in Python (tutorial and code)

Postby Caudio12 » 26 May 2017, 21:48

Newbie - RuneAudio and Linux
First great thanks for all contributing to this forum, great work.
Now my "problem".
I have made a upgrade from Rasp Pi 2 and a HifiBerry Digi to the more advance Hifiberry Digi+ PRO and a Rasp 3 platform. This works fine after updated the Kernel to the latest, else the Digi+ PRO board will not work.
Running RuneAudio latest version 0.4. rasp Pi 3.
LCD 2 x 16 , with a i2c backpack - Adafruit.
My plan was to built in the new unit in a nice case with a LCD display and some buttons - looks nice. And this is why I writing to you all.
I am new in Linux, Python, vi etc, so the learning curve is quite steep.
I am not sure which tutorial to follow and what is actually is needed to get it working.
For the moment only two buttons works, NEXT and PREV.
The following is done:
First I followed the post on page 12, by s.k.
All worked fine. I can see that the i2c adress is 0x20
But nothing worked, LDC etc.
I then went to page 1,
And started from the top;
installed python2, python2-pip (eventhough I dont know if is needed, or if the page 12 list all is needed?)
installed gcc
installed RPi.GPO, version 0.6.3
tried to installed Adafruit_Python_CharLCD result in a mutiple list of errors. Is this module needed?

If a run the start.py I get this: Not any more, before I got an error IOError on a about 8 different sub modules related to the LCD display. Now just blank screen.
based on this I assume I have not been able to get all needed modules installed for the LCD, but the bottons are half working, two of four (!).

It would be great if someone could make a list what need to installed if you are running RuneAudio 0.4 on Rasp Pi 3 and have nothing else pre-installed. Now I am just guessing. I dont know what is included in the new RuneAudio 0.4 etc,
/CJ
Caudio12
 
Posts: 1
Joined: 26 May 2017, 20:44

Re: LCD display and buttons in Python (tutorial and code)

Postby hana » 19 Jun 2017, 13:01

Hi everybody
I have it finally working LCD 2004A i2c version, but only Xplod files are going as well, MOD code had a lot of issues with spaces and tabs, after all it throw up some other error code. so finally Xplod version is up and runnning except one thing: turn off backlight. does anybody same problem?
when I check basic working (it the display support it) with some test code, it works, but in Xplod script not.
thank you for help.
hana
 
Posts: 2
Joined: 21 Jun 2016, 07:42

Re: LCD display and buttons in Python (tutorial and code)

Postby jeroenrood » 25 Jun 2017, 17:31

Hello,
I've posted this problem also in the RuneAudio 0.4b thread, but ik think this might be a better place to ask for help.

I've switched to a RPi 3b (I had a RPi 1b fully functioning), and reinstalled te display. I've used the instructions of s.k. http://www.runeaudio.com/forum/lcd-display-and-buttons-in-python-tutorial-and-code-t1191-110.html#p19483, and the display shows me all the info.
Only problem is that the sound disappears if I start the python program. I only get the sound back if I reboot.
If the sound is gone, the web interface and the display are still showing the tracks that should come out.
The display is connected by I2C.
Any suggestions?

Regards, Jeroen.
jeroenrood
 
Posts: 12
Joined: 06 Nov 2015, 14:45

support RuneAudio Donate with PayPal

PreviousNext

Return to Raspberry Pi

Who is online

Users browsing this forum: No registered users and 4 guests