LCD 16x2 / mpd / mpc - przewijanie tekstu ?

  • 2 replies
  • 87 views
*

Online kris777

  • ***
  • 158
  • 33
LCD 16x2 / mpd / mpc - przewijanie tekstu ?
« dnia: Czerwiec 29, 2018, 23:14:50 pm »
Czy jest ktoś kto zna dość dobrze programowanie w pythonie ?
Mam problem z tzw. opcją przewijania tekstu a dokładniej nazw granych i  wyświetlanych na moim LCD 16x2 nazw utworów piosenek.
Oczywiście jest to powiązane z programami mpd / mpc .
Radio internetowe mam postawione na systemie Armbian / OrangePi Lite (ARM) ale wszystko może być tak samo na każdym linux-ie.Tu mój skrypt:
#!/usr/bin/python
# -*- coding: utf-8 -*-

import smbus
import time
import subprocess

from time       import sleep, strftime
from datetime   import datetime
from subprocess import *

# Define some device parameters
I2C_ADDR  = 0x3f # I2C device address
LCD_WIDTH = 16   # Maximum characters per line

# Timing constants for low level write operations
# NOTE: Enable cycle time must be at least 1 microsecond
# NOTE2: Actually, these can be zero and the LCD will typically still work OK
EDEL_TAS =  0.00001      # Address setup time (TAS)
EDEL_PWEH = 0.00001      # Pulse width of enable (PWEH)
EDEL_TAH =  0.00001      # Address hold time (TAH)

# Timing constraints for initialisation steps - IMPORTANT!
# Note that post clear display must be at least 6.2ms for OLEDs, as opposed
# to only 1.4ms for HD44780 LCDs. This has caused confusion in the past.
DEL_INITMID = 0.01       # middle of initial write (min 4.1ms)
DEL_INITNEXT = 0.0002     # post ssecond initial write (min 100ns)
DEL_POSTCLEAR = 0.01       # post clear display step (busy, min 6.2ms)


# Define some device constants
LCD_CHR = 1 # Mode - Sending data
LCD_CMD = 0 # Mode - Sending command

LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line

LCD_BACKLIGHT  = 0x08  # On
#LCD_BACKLIGHT = 0x0C  # Off


ENABLE = 0b00000100 # Enable bit

# Timing constants
E_PULSE = 0.005
E_DELAY = 0.005

#Open I2C interface
bus = smbus.SMBus(0)  # Rev 1 Pi uses 0 (and Orange PI PC, for pins 3 and 5)
#bus = smbus.SMBus(1) # Rev 2 Pi uses 1

def lcd_init():
  # Initialise display
  lcd_byte(0x33,LCD_CMD) # 110011 Initialise
  lcd_byte(0x32,LCD_CMD) # 110010 Initialise
  lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction
  lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
  lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
  lcd_byte(0x01,LCD_CMD) # 000001 Clear display
  time.sleep(E_DELAY)


  lcd_byte(0x06,LCD_CMD)    # entry mode set

# extra steps required for OLED initialisation (no effect on LCD)
  lcd_byte(0x17,LCD_CMD)    # character mode, power on

  # now turn on the display, ready for use - IMPORTANT!
  lcd_byte(0x0C,LCD_CMD)    # display on, cursor/blink off

def lcd_byte(bits, mode):
  # Send byte to data pins
  # bits = the data
  # mode = 1 for data
  #        0 for command

  bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
  bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT

  # High bits
  bus.write_byte(I2C_ADDR, bits_high)
  lcd_toggle_enable(bits_high)

  # Low bits
  bus.write_byte(I2C_ADDR, bits_low)
  lcd_toggle_enable(bits_low)

def lcd_toggle_enable(bits):
  # Toggle enable
  time.sleep(E_DELAY)
  bus.write_byte(I2C_ADDR, (bits | ENABLE))
  time.sleep(E_PULSE)
  bus.write_byte(I2C_ADDR,(bits & ~ENABLE))
  time.sleep(E_DELAY)

def lcd_string(message,line):
  # Send string to display

  message = message.ljust(LCD_WIDTH," ")

  lcd_byte(line, LCD_CMD)

  for i in range(LCD_WIDTH):
    lcd_byte(ord(message[i]),LCD_CHR)

def replace_pl(chars):
  pl = {  'ą': 'a',
          'ć': 'c',
          'ę': 'e',
          'ł': 'l',
          'ń': 'n',
          'ó': 'o',
          'ś': 's',
          'ź': 'z',
          'ż': 'z',
          'Ą': 'A',
          'Ć': 'C',
          'Ę': 'E',
          'Ł': 'L',
          'Ń': 'N',
          'Ó': 'O',
          'Ś': 'S',
          'Ź': 'Z',
          'Ż': 'Z',
  }
  for f, t in pl.items():
    chars = chars.replace(f,t)
  return chars

def main():

  # Initialise display
  lcd_init()

  counter = 0

  while True:

  # Get current status and playtime
    process = subprocess.Popen('sudo mpc -v', shell=True, stdout=subprocess.PIPE)
    ekran1 = process.communicate()[0]
    ekran1 = replace_pl(ekran1)
    statusLines = ekran1.split('\n')
    ekran1 = statusLines[1]
    if ekran1 <> '':
      ekran1L1 = ekran1.split(' ',1)[0].strip()
      ekran1L2temp = ekran1.split(' ',1)[1].strip()
      ekran1L2 = ekran1L2temp.split(' ',1)[0].strip()

    process = subprocess.Popen('sudo mpc -f %name%', shell=True, stdout=subprocess.PIPE)
    ekran2 = process.communicate()[0]
    ekran2 = replace_pl(ekran2)
    statusLines = ekran2.split('\n')
    ekran2 = statusLines[0]
    ekran2L1 = ekran2[0:16]
    ekran2L2 = ekran2[16:31]

    process = subprocess.Popen('sudo mpc -f %artist%', shell=True, stdout=subprocess.PIPE)
    ekran3 = process.communicate()[0]
    ekran3 = replace_pl(ekran3)
    statusLines = ekran3.split('\n')
    ekran3 = statusLines[0]
    ekran3L1 = ekran3[0:16]
    ekran3L2 = ekran3[16:31]

    process = subprocess.Popen('sudo mpc -f %title%', shell=True, stdout=subprocess.PIPE)
    ekran4 = process.communicate()[0]
    ekran4 = replace_pl(ekran4)
    statusLines = ekran4.split('\n')
    ekran4 = statusLines[0]
    ekran4L1 = ekran4[0:16]
    ekran4L2 = ekran4[16:31]

    if counter == 1:
      if ekran1 == "":
        counter = 15
      else:
        lcd_string(ekran1L1,LCD_LINE_1)
        lcd_string(ekran1L2,LCD_LINE_2)
    if counter == 15:
      if ekran2 == "":
        counter = 30
      else:
        lcd_string(ekran2L1,LCD_LINE_1)
        lcd_string(ekran2L2,LCD_LINE_2)
    if counter == 30:
      if ekran3 == "":
        counter = 45
      else:
        lcd_string(ekran3L1,LCD_LINE_1)
        lcd_string(ekran3L2,LCD_LINE_2)
    if counter == 45:
      if ekran4 == "":
        counter = 60
      else:
        lcd_string(ekran4L1,LCD_LINE_1)
        lcd_string(ekran4L2,LCD_LINE_2)

    sleep(0.1)
    counter = counter + 1
    if counter == 61:
      counter = 1


if __name__ == '__main__':

  try:
    main()
  except KeyboardInterrupt:
    pass
  finally:
    lcd_byte(0x00, LCD_CMD)
    lcd_byte(0x01, LCD_CMD)
    lcd_byte(0x08, LCD_CMD)
Udało mi się (z pomocą ) dodać część kodu usuwający polskie ogonki w znakach diakrytycznych ( nie każdy wyświetlacz je akceptuje a nawet większość )
Jeśli ktoś jest zainteresowany to może zerknąć tu:
[Guide] Internet radio + LCD 2x16 + TactSwitch
« Ostatnia zmiana: Czerwiec 30, 2018, 22:32:46 pm wysłana przez kris777 »

*

Offline dedito

  • ***
  • 173
  • 79
Odp: LCD 16x2 / mpd / mpc - przewijanie tekstu ?
« Odpowiedź #1 dnia: Czerwiec 30, 2018, 09:43:42 am »
Co prawda nie znam zbyt dobrze pythona, ale patrząc w ten kod nie widzę w nim funkcji przewijania tekstu.
W podanym linku masz przykład funkcji https://gist.github.com/hulehule20/bdf464d734f83dfc0abc
Pobieżnie przeglądając ten przykładowy kod rzuca mi się w oczy funkcja sleep, raczej niezbyt dobre rozwiązanie w przypadku Twojej aplikacji, ale nie ma problemu użyć tutaj przykładowo millis.
« Ostatnia zmiana: Czerwiec 30, 2018, 11:17:50 am wysłana przez dedito »

*

Online kris777

  • ***
  • 158
  • 33
Odp: LCD 16x2 / mpd / mpc - przewijanie tekstu ?
« Odpowiedź #2 dnia: Czerwiec 30, 2018, 14:55:10 pm »
Dzięki za info ...ale będąc  nogą w programowaniu raczej trudno coś zdziałać :-)
Co nie znaczy iż nie próbowałem ...jednak z marnym skutkiem.Wiadomo czasem wystarczy jeden przecinek i z całości kodu lipa. Można w ten sposób spędzić z pół roku na szukaniu rozwiązania :-)
Ale może jeszcze w wolnej chwili powalczę ....
Dodatkowo podany przykład dotyczy raczej RPI a nie OrangePi / Armbian system więc nie wiem czy wogóle jest możliwe zaimportowanie np.
import Adafruit_CharLCDpozdro!
« Ostatnia zmiana: Czerwiec 30, 2018, 22:11:45 pm wysłana przez kris777 »