Pomoc w skrypcie dla LCD 40x2 / kontrast

Pomoc w skrypcie dla LCD 40x2 / kontrast
Kris Kinski
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6
0

Czy może ktoś rzucić okiem na skrypt w pythonie v2 kontrolujący LCD oled 40x2. Skrypt działa poprawnie ale mam problem z kontrastem Wyświetlacza tzn ma on opcję możliwości kontrastu ( tak doczytałem w specyfikacje tego LCD Winstar ) na full czyli 0x17 i mniejszą o połowę : 0x13 w programie lcdproc nie mogłem tego zastosować chyba raczej nie działa. Ale w pythonie przez przypadek udało się zmniejszyć natężenie do 50% (0x13) ale w dziwnym miejscu tego skryptu i niestety przez to teraz nie widać poprawnie wszystkich danych na LCD :-)... super że to jednak działa czyli softwerowe zmienienie kontrastu LCD / bez drastycznego kombinowania z rezystorami potencjometrami itd. Dla obeznanych w pythonie pewnie będzie to pestka ale dla mnie laika to raczej himalaje :-) kod : 0x13 podmieniłem w miejscu / linii:
LCD_LINE_1 = 0x80
zamiast wpisu 0x80 sam skrypt jest nieduży . A może jest jakaś lepsza metoda lub prostszy skrypt python lub linux który by mógł li tylko zmienić kontrast tego LCD bez ingerencji w ten skrypt ?

Kopiuj
#!/usr/bin/env 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 = 40   # Maximum characters per line
LCD_HEIGHT = 2



# 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_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():

  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:40]
    ekran2L2 = ekran2[40:80]

    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:40]
    ekran3L2 = ekran3[40:80]

    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:40]
    ekran4L2 = ekran4[40:80]

    process = subprocess.Popen('sudo mpc status "jakość dźwięku : %kbitrate% bitrate                audio format: %audioformat%"', shell=True, stdout=subprocess.PIPE)
    ekran5 = process.communicate()[0]
    ekran5 = replace_pl(ekran5)
    statusLines = ekran5.split('\n')
    ekran5 = statusLines[0]
    ekran5L1 = ekran5[0:40]
    ekran5L2 = ekran5[40:80]

    if counter == 1:
      if ekran1 == "":
        counter = 7
      else:
        lcd_string(ekran1L1,LCD_LINE_1)
        lcd_string(ekran1L2,LCD_LINE_2)
    if counter == 7:
      if ekran2 == "":
        counter = 14
      else:
        lcd_string(ekran2L1,LCD_LINE_1)
        lcd_string(ekran2L2,LCD_LINE_2)
    if counter == 14:
      if ekran3 == "":
        counter = 30
      else:
        lcd_string(ekran3L1,LCD_LINE_1)
        lcd_string(ekran3L2,LCD_LINE_2)
    if counter == 30:
      if ekran4 == "":
        counter = 46
      else:
        lcd_string(ekran4L1,LCD_LINE_1)
        lcd_string(ekran4L2,LCD_LINE_2)
    if counter == 46:
      if ekran5 == "":
        counter = 52
      else:
        lcd_string(ekran5L1,LCD_LINE_1)
        lcd_string(ekran5L2,LCD_LINE_2)

    sleep(0.1)
    counter = counter + 1
    if counter == 60:
      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)
    GPIO.cleanup()
    gpio.cleanup()
    lcd.clear()
overcq
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 402
0

Czy ten tzw. „kontrast” to nie jest po prostu włączone/wyłączone podświetlenie (‘backlight’)?
Tutaj masz esencję tego skryptu, tylko do wysyłania komend:

Kopiuj
#!/usr/bin/env python

import smbus
from time       import sleep, strftime
from datetime   import datetime

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

# 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

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_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)

if __name__ == '__main__':
  #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
  try:
    cmd = 0x17
    lcd_byte(cmd, LCD_CMD)
  except KeyboardInterrupt:
    pass
  finally:
    lcd_byte(0x00, LCD_CMD)
    lcd_byte(0x01, LCD_CMD)
    lcd_byte(0x08, LCD_CMD)
    GPIO.cleanup()
    gpio.cleanup()
    lcd.clear()

Zastanawiam się, czy to kod 0x13/0x17 spowodował zmianę „kontrastu” czy raczej flaga LCD_BACKLIGHT, która jest ustawiona ostatecznie na ‘off’.
Oprócz podmieniania komendy w linii 60 możesz też spróbować zakomentować linię 22, by pozostało tylko LCD_BACKLIGHT ‘on’.

Kris Kinski
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6
0

Niestety ale nie działa. Wyświetlacz zmienia kontrast z 50% na 100% jedynie jak wyświetli się jakieś info na wyświetlaczu ? ...w terminalu klepłem taki wpis żeby coś więcej zerknąć w info może coś podpowie ...

Kopiuj
/root/venv/python2/bin/python /root/start.py

info w terminalu :

Kopiuj
Traceback (most recent call last):
  File "/root/start.py", line 65, in <module>
    lcd_byte(0x00, LCD_CMD)
  File "/root/start.py", line 49, in lcd_byte
    lcd_toggle_enable(bits_high)
  File "/root/start.py", line 32, in lcd_toggle_enable
    time.sleep(E_DELAY)
NameError: global name 'time' is not defined

Cały skrypt jest w wersji v2 i dlatego uruchamiam go z opcji pythona2 virtual ...nie mogłem i nie umialem skonwertować poprawnie pod v3 ...upsss ale działa :-) u mnie teraz najmniejsza wersja która działa i zmienia kontrast na LCD na stałe jest taki:

Kopiuj
#!/usr/bin/env 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 = 40   # Maximum characters per line
LCD_HEIGHT = 2

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

LCD_LINE_1 = 0x17 # LCD RAM address for the 1st 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_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 main():

  counter = 0

  while True:

  # Get current status and playtime
    process = subprocess.Popen('sudo mpc -v', shell=True, stdout=subprocess.PIPE)
    ekran1 = process.communicate()[0]
    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()

    
    if counter == 1:
      if ekran1 == "":
        counter = 7
      else:
        lcd_string(ekran1L1,LCD_LINE_1)
        lcd_string(ekran1L2,LCD_LINE_2)
    

    sleep(0.1)
    counter = counter + 1
    if counter == 10:
      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)
    GPIO.cleanup()
    gpio.cleanup()
    lcd.clear()

tutaj temat z tym problemem w programie lcdproc / LCDd ... szkoda że tu nie działa bo było by prościej
https://github.com/lcdproc/lcdproc/issues/185

Na bezrybiu i rak ryba ..w ostateczności i ten mało profesjonalny ale działający skrypt jakoś można wykorzystać ...uruchomić potem skryptem zabić prog. pythona i uruchomić zegar na lcdproc / LCDd

overcq
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 402
0

Faktycznie zgubiłem import time i skrypt nie działał. Niestety nie mogę przetestować na Pythonie 2 (oraz nie mam modułu “smbus”).
Nie napisałeś, czy ‘backlight’ coś zmienia. Z tego, co się domyślam po przeczytaniu podlinkowanego ‘issue’, to kontrast jest osobną komendą. Można zapisać dowolny znak na ekran po wysłaniu komendy, a nie całą linię jak w skrypcie. Poza tym możesz zintegrować ustawianie kontrastu w docelowym programie (zależnie od zastosowania) zamiast liczyć na funkcję, która osobno ustawia kontrast. Ten skrypt w Pythonie może być punktem wyjścia do zmiany tego drugiego programu, ale wymaga sprawdzenia.

Kris Kinski
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6
0

Zakomentowałem #LCD_BACKLIGHT = 0x0C # Off ...ale nic nie wnosi do sprawy. ciekawa zagwozdka niby jest podana komenda ale nie wiadomo jak jej użyć i jakim programem :-) ... gdzieś znalazłem też takie wpisy ale czym to wykonać :
$FE, $17 full contrast
$FE, $13 half contrast
Na linux-ie Debian jest np. program i2cset a LCD jest podpięty i funkcjonuje na interfejsie I2C ...nawet chciałem wykonać komendę np.
0x17 / 0x13 na adres I2C tego LCD jednak przed wykonaniem jest ostrzeżenie o niebezpieczeństwie i że można uszkodzić sprzęt itp ...nie wiedząc czy to poprawne działanie zrezygnowałem :-)
Jeszcze popytam w necie może koś coś podpowie.

overcq
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 402
0

A wysyłasz jakiś znak do wyświetlenia na ekran? Bo z opisów, które czytałem wynika, że sekwencja jest następująca:

  1. wysłanie komendy do wyświetlacza
  2. wysłanie znaku na wyświetlacz

Wtedy dopiero wykonuje komendę.
W powyższym skrypcie dane przychodzą z zewnętrznego programu, ale może go nie być. Najlepiej, jakbyś samodzielnie wysłał jakiś znak do wyświetlenia i wtedy sprawdził obie komendy (0x13/0x17).

Kris Kinski
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6
0

Ja to rozumiem że jeśli użyję komendy np. 0x13 ...jak w pierwszym poście z niezbyt profesjonalną podmianką tak na rympał w miejsce : LCD_LINE_1 = 0x80
to potem LCD automatycznie powinien już być na 50% kontrastu ...i tak jest bo zabijając ten skrypt pythona i uruchamiając zupełnie inny program lcdproc z dużym zegarem na wyświetlaczu jest on już w kontraście 50% :-)
A w tym skrypcie który miał niby tylko wysłać komendę bez użycia dodatkowych opcji wyświetlania informacji na LCD ...nic się nie dzieje brak reakcji ? kontrast pozostaje bez zmian ...
Ps. znalazłem w necie dwa przykłady w pythonie odnoście kontrastu....ale chyba dla innego rodzaju LCD bo ma dodatkowy wpis :
odnośnie poziomu kontrastu (contrast_level) a w moim LCD jest tylko funkcja 100% / 50% czyli to nie poziom a metoda przełączania z jednego na drugie.

pierwszy

Kopiuj
import smbus

# I2C bus number (usually 1 for Raspberry Pi)
bus = smbus.SMBus(0)

# OLED I2C address (e.g., 0x3C)
oled_address = 0x3f

# Contrast value (0-15)
contrast_level = 13

# Set contrast command
command = 0x13

# Prepare data to send
data = [command, contrast_level]

# Write the data to the OLED
bus.write_i2c_block_data(oled_address, 0x00, data)

drugi

Kopiuj
import smbus

# I2C bus number (usually 1 for the main I2C bus)
bus = 0

# OLED I2C address (e.g., 0x3c for many SSD1306)
i2c_address = 0x3f

# Function to set contrast
def set_contrast(contrast_level):
    try:
        bus = smbus.SMBus(bus)
        # Command to set contrast (0x13 in the command_code)
        command_code = 0x13 
        # Contrast level as a byte (0-255 or higher resolution)
        data = [contrast_level]
        bus.i2c_write_block_data(i2c_address, command_code, data)
        bus.close()
    except Exception as e:
        print(f"Error setting contrast: {e}")

# Example: Set contrast to level 128
set_contrast(128)

nie mam pojęcia czy można by coś z tego skorzystać

overcq
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 402
0

Skrypt wysyłający komendę 0x13 lub 0x17 i linię tekstu:

Kopiuj
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import smbus
import time

from time       import sleep, strftime
from datetime   import datetime

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

# 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_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_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 main():
  cmd = 0x13
  lcd_byte(cmd, LCD_CMD)
  lcd_string("A",LCD_LINE_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)
    GPIO.cleanup()
    gpio.cleanup()
    lcd.clear()

Działa po podmianie cmd w linii 64?

Kris Kinski
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6
0

Tak teraz działa ...ale w sumie robi to samo co moje kombinacje na tzw rympał :-) .... czyli pewnie jest konieczność wysłania znaku na wyświetlacz !
Dziękuję za pomoc teraz już sobie poradzę w konfiguracji przełączania kontrastu ...pewnie użyję dwóch skryptów pythona z 0x13 / 0x17
A to taka zabawa w radio internetowe + LCD które skleciłem a brakowało mi opcji mniejszego kontrastu ...nocą :-)
więcej: https://ubuntu.pl/forum/viewtopic.php?t=186893
Swoją drogą brakowało mi możliwości programowania w pythonie bo wszystko wyglądało by profesjonalnie a tak korzystałem z bash-a i dużej bazy wiedzy w internecie i też dało radę :-)

PS. a czy konwersja tego skryptu pythona w wer. v2 jest trudna do wersji 3 ? ... ja próbowałem jakimiś programami i trochę samodzielnie ale zawsze lipa ...jak nie błędy w kodzie to smbus nie działał dlatego pozostałem na wirtualnym python 2

overcq
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 402
0

Dla Pythona 3 można by użyć modułu “smbus3”.

Kopiuj
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from smbus3 import SMBus
from time import sleep

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

# 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_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(0)  # Rev 1 Pi uses 0 (and Orange PI PC, for pins 3 and 5)
#bus = SMBus(1) # Rev 2 Pi uses 1

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
  sleep(E_DELAY)
  bus.write_byte(I2C_ADDR, (bits | ENABLE))
  sleep(E_PULSE)
  bus.write_byte(I2C_ADDR,(bits & ~ENABLE))
  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 main():
  cmd = 0x13
  lcd_byte(cmd, LCD_CMD)
  lcd_string(" ",LCD_LINE_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)
    GPIO.cleanup()
    gpio.cleanup()
    lcd.clear()
Kris Kinski
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6
1

Bardziej chodziło mi o cały podstawowy skrypt ten z pierwszego postu...ale sprawdziłem i wywala błąd smbus3 co zresztą doświadczałem próbując konwertować nieudolnie tylko że tam był błąd smbus / smbus2 i ogólnie dużo nieprawidłowości i niekompatybilności w kodzie do pythona3

Kopiuj
from smbus3 import SMBus
ModuleNotFoundError: No module named 'smbus3'

bo przydało by się mieć sprawny skrypt do nowych systemów Debian w których stare wersje pythona 2 to już przeszłość i kolejna zagwozdka przy instalacji i konfiguracji LCD... a tu jeszcze smbus3 :-) ..ciągle zmieniają pewnie niedługo będzie python4 / smbus4 :-)
To może być też wina systemu Debian bookworm który jest niby aktualny ale repozytoria pochodzą z platformy ARM dla mojego OrangePi3LTS.

PS. OK już chyba działa kod w python3 :-) .... kolega chatgpt skonwertował.
Efekt działania prze-konwertowanego skryptu początkowo mierny sporo stresu bo LCD zamilkł i nawet po restarcie systemu ciemno :-) ...ale poprawiłem jedną pozycję ręcznie i o dziwo działa prawidłowo z python3 :-) ...no jeszcze troszkę się rozjeżdżają informacje z mpd ale to już pikuś ...
Tak więc wypijmy za chatgpt ! :-)
dla potomnych wklejam pod python3

Kopiuj
#!/usr/bin/env python3
# -*- 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
LCD_WIDTH = 40
LCD_HEIGHT = 2

# Define some device constants
LCD_CHR = 1
LCD_CMD = 0

LCD_LINE_1 = 0x80
LCD_LINE_2 = 0xC0
LCD_LINE_3 = 0x94
LCD_LINE_4 = 0xD4

LCD_BACKLIGHT  = 0x08  # On
#LCD_BACKLIGHT = 0x0C  # Assuming "On" was intended

ENABLE = 0b00000100

# Timing constants
E_PULSE = 0.005
E_DELAY = 0.005

# Open I2C interface
bus = smbus.SMBus(0)

def lcd_byte(bits, mode):
    bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
    bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT

    bus.write_byte(I2C_ADDR, bits_high)
    lcd_toggle_enable(bits_high)

    bus.write_byte(I2C_ADDR, bits_low)
    lcd_toggle_enable(bits_low)

def lcd_toggle_enable(bits):
    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):
    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 run_cmd(cmd):
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE)
    return result.stdout.decode('utf-8')

def main():
    counter = 0
    while True:
        ekran1 = replace_pl(run_cmd('sudo mpc -v'))
        statusLines = ekran1.splitlines()
        ekran1 = statusLines[1] if len(statusLines) > 1 else ""

        if ekran1 != "":
            ekran1L1 = ekran1.split(' ', 1)[0].strip()
            ekran1L2temp = ekran1.split(' ', 1)[1].strip() if ' ' in ekran1 else ""
            ekran1L2 = ekran1L2temp.split(' ', 1)[0].strip()

        ekran2 = replace_pl(run_cmd('sudo mpc -f %name%')).splitlines()[0]
        ekran2L1 = ekran2[0:40]
        ekran2L2 = ekran2[40:80]

        ekran3 = replace_pl(run_cmd('sudo mpc -f %artist%')).splitlines()[0]
        ekran3L1 = ekran3[0:40]
        ekran3L2 = ekran3[40:80]

        ekran4 = replace_pl(run_cmd('sudo mpc -f %title%')).splitlines()[0]
        ekran4L1 = ekran4[0:40]
        ekran4L2 = ekran4[40:80]

        ekran5 = replace_pl(run_cmd('sudo mpc status "jakość dźwięku : %kbitrate% bitrate audio format: %audioformat%"')).splitlines()[0]
        ekran5L1 = ekran5[0:40]
        ekran5L2 = ekran5[40:80]

        if counter == 1:
            if ekran1 == "":
                counter = 7
            else:
                lcd_string(ekran1L1, LCD_LINE_1)
                lcd_string(ekran1L2, LCD_LINE_2)
        if counter == 7:
            if ekran2 == "":
                counter = 14
            else:
                lcd_string(ekran2L1, LCD_LINE_1)
                lcd_string(ekran2L2, LCD_LINE_2)
        if counter == 14:
            if ekran3 == "":
                counter = 30
            else:
                lcd_string(ekran3L1, LCD_LINE_1)
                lcd_string(ekran3L2, LCD_LINE_2)
        if counter == 30:
            if ekran4 == "":
                counter = 46
            else:
                lcd_string(ekran4L1, LCD_LINE_1)
                lcd_string(ekran4L2, LCD_LINE_2)
        if counter == 46:
            if ekran5 == "":
                counter = 52
            else:
                lcd_string(ekran5L1, LCD_LINE_1)
                lcd_string(ekran5L2, LCD_LINE_2)

        sleep(0.1)
        counter += 1
        if counter == 60:
            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)

powiem więcej w dzisiejszych czasach to nieodzowna pomoc dla laika i jeśli się wszystko super wyjaśni to efekt jest perfekcyjny podam kod dla samego kontrastu tak podpowiedzial chatgpt i.....miał 100% rację :-)

Kopiuj
import smbus
import time

# Adres I2C i ustawienia
I2C_ADDR = 0x3f
I2C_BUS = 0  # Orange Pi I2C bus 0
CMD = 0x13   # Komenda zmiany kontrastu na 50%

# Mapowanie pinów PCF8574 — najczęstsze:
# RS = P0, RW = P1 (zawsze 0), EN = P2, D4 = P4, D5 = P5, D6 = P6, D7 = P7

# Maski pomocnicze
EN = 0b00000100
RS = 0b00000000  # RS=0 dla komendy
BACKLIGHT = 0b00001000  # Jeśli masz sterowanie podświetleniem

# Złożenie danych do przesłania w trybie 4-bitowym
def write4bits(bus, data):
    bus.write_byte(I2C_ADDR, data | EN | BACKLIGHT)
    time.sleep(0.001)
    bus.write_byte(I2C_ADDR, (data & ~EN) | BACKLIGHT)
    time.sleep(0.001)

def send_command(bus, cmd):
    upper = cmd & 0xF0
    lower = (cmd << 4) & 0xF0
    write4bits(bus, upper | RS)
    write4bits(bus, lower | RS)

# Główna część
bus = smbus.SMBus(I2C_BUS)

# Wysłanie komendy 0x13 (kontrast 50%)
send_command(bus, CMD)

print("Wysłano komendę 0x13 (kontrast 50%)")

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.