Displej s I2C rozhraním

DavidO
Příspěvky: 549
Registrován: 01 kvě 2013, 21:27

Re: Displej s I2C rozhraním

Příspěvek od DavidO » 18 pro 2015, 00:00

viki píše:Když zkusím dát adresu 0x74 tak to skončí chybou input/output error, s adresou 0x3a to tuhle chybu nevyhodí.
To by souhlasilo, protože když se něco posílá, tak hned ten první byte s adresou správný příjemce potvrdí, že poslouchá. Takže když tam zařízení s tou adresou není, tak první byte nikdo nepotvrdí a odesilatel správně usoudí, že nemá cenu pokračovat.

viki
Příspěvky: 42
Registrován: 14 pro 2013, 22:23

Re: Displej s I2C rozhraním

Příspěvek od viki » 19 pro 2015, 14:19

Díky za odpovědi už jsem se bál že ho nerozchodím.
Díky Petrovi za kód. Jen kdyby to nekdo do budoucna potřeboval tak v Pythonu to vypadá takhle:

Kód: Vybrat vše

import smbus

bus = smbus.SMBus(1)
address = 0x3a

bus.write_byte_data(address, 0x00, 0x26)
bus.write_byte_data(address, 0x00, 0x0e)
bus.write_byte_data(address, 0x00, 0x06)

bus.write_byte_data(address, 0x40, 0x21)
bus.write_byte_data(address, 0x40, 0x22)
Tohle vypíše dva znaky (myslím že obrázek stavu baterie ) vedle sebe.
Měl bych ještě dotaz na Petra po smazání displeje - bus.write_byte_data(0x3a, 0x00, 0x01) ho musím znavu nastavit a zobrazit kurzor, nebo ho lze ještě mazat nějak jinak? Jakým příkazem dostanu kurzor na jiný řádek, nebo na místo na které chci, abych mohl přepsat znak který je zobrazený?

Ješte jednou díky za pomoc.

DavidO
Příspěvky: 549
Registrován: 01 kvě 2013, 21:27

Re: Displej s I2C rozhraním

Příspěvek od DavidO » 19 pro 2015, 16:25

Nejsem Petr, ale to snad nevadí.
Příkaz Clear display vyplní paměť samýma mezerama, nastaví pozici pro psaní na začátek a zobrazování od začátku (pokud byl posunutý). Nová inicializace ani nastavování kurzoru tedy není potřeba. Když se tam pak bude něco zapisovat, na displeji se to ukáže v 1. řádku hned odleva.

Nastavení kurzoru na zvolenou pozici se udělá příkazem Set DDRAM Address, viz tabulka 3 v datasheetu PCF2116 - nahozený nejvyšší bit a zbytek je adresa, přičemž první řádek má adresy 0x00-0x27, druhý 0x40-0x67 (viz obrázek 5 tamtéž). Vidět je samozřejmě jen prvních 16, pokud zobrazování na displeji neposuneš.
Takže třeba nastavit pozici na druhý znak druhého řádku se udělá
bus.write_byte_data(adresa, 0, 0xC1)

DavidO
Příspěvky: 549
Registrován: 01 kvě 2013, 21:27

Re: Displej s I2C rozhraním

Příspěvek od DavidO » 19 pro 2015, 17:31

viki píše:Díky za odpovědi už jsem se bál že ho nerozchodím.
Díky Petrovi za kód. Jen kdyby to nekdo do budoucna potřeboval tak v Pythonu to vypadá takhle:

Kód: Vybrat vše

import smbus
bus = smbus.SMBus(1)
address = 0x3a
bus.write_byte_data(address, 0x00, 0x26)
bus.write_byte_data(address, 0x00, 0x0e)
bus.write_byte_data(address, 0x00, 0x06)

bus.write_byte_data(address, 0x40, 0x21)
bus.write_byte_data(address, 0x40, 0x22)
Hele, tohle by mělo jít poslat po blokách najednou, mohl bys to prosímtě zkusit?

Kód: Vybrat vše

bus.write_i2c_block_data(address, 0x80, [0x26, 0x0e, 0x06])
bus.write_i2c_block_data(address, 0xC0, [0x21, 0x22])
(v prvním bytu je potřeba nahodit nejvyšší bit, místo 0x00 dát 0x80 a místo 0x40 dát 0xC0)

Nějaký text by se pak asi poslal takhle:

Kód: Vybrat vše

bus.write_i2c_block_data(address, 0xC0, ['H'+128, 'e'+128, 'l'+128, 'l'+128, 'o'+128, atd.])
Tady to s tím +128 je trochu ošklivý, ale jestli ten displej má fakt znakovou sadu C, tak to asi jinak nejde. Vlastně možná jo - na obvyklých ASCII pozicích jsou písmena vzhůru nohama, tak kdyby se ten displej dal vzhůru nohama a nastavil na psaní zprava doleva? Anebo, v Pythonu by mohlo jít projet string a všem písmenům ten nejvyšší bit nahodit?

viki
Příspěvky: 42
Registrován: 14 pro 2013, 22:23

Re: Displej s I2C rozhraním

Příspěvek od viki » 21 pro 2015, 01:55

Díky za objasnění DavidO , pozicování už chápu a funguje mi.
DavidO píše: Hele, tohle by mělo jít poslat po blokách najednou, mohl bys to prosímtě zkusit?

Kód: Vybrat vše

bus.write_i2c_block_data(address, 0x80, [0x26, 0x0e, 0x06])
bus.write_i2c_block_data(address, 0xC0, [0x21, 0x22])
Poslat data k zobrazení v blocích jde, ale inicializovat displej v blocích nejde.

Tohle taky nefunguje:

Kód: Vybrat vše

bus.write_i2c_block_data(address, 0xC0, ['H'+128, 'e'+128, 'l'+128, 'l'+128, 'o'+128, atd.])
Python chce hodnoty typu int což ['H'+128] není.

Ale šlape mi tohle:

Kód: Vybrat vše

import smbus
import time


bus = smbus.SMBus(1)
address = 0x3a

slovo = input("Zadejte slovo: ")

bus.write_byte_data(address, 0x00, 0x26)
bus.write_byte_data(address, 0x00, 0x0e)
bus.write_byte_data(address, 0x00, 0x06)
time.sleep(1)
bus.write_byte_data(address, 0, int(hex(int(128+0)), 16))
      
for pismeno in slovo:
    cislo=ord(pismeno)+128
    bus.write_byte_data(address, 0x40, int(hex(int(cislo)), 16))

DavidO
Příspěvky: 549
Registrován: 01 kvě 2013, 21:27

Re: Displej s I2C rozhraním

Příspěvek od DavidO » 11 led 2016, 15:10

viki píše:Poslat data k zobrazení v blocích jde, ale inicializovat displej v blocích nejde.
Tak jsem na to o Vánocích ještě jednou mrknul, a konstatuju, že jsem to napsal špatně. Já totiž blbě přečetl v datasheetu jednu tabulku, správně to mělo být v podstatě tak, jak to bylo v původním "modrém" textu:

Kód: Vybrat vše

bus.write_i2c_block_data(address, 0x00, [0x26, 0x0e, 0x06])
bus.write_i2c_block_data(address, 0x40, [0x21, 0x22])
(myslel jsem, že ten Co flag v prvním byte je obráceně -- číst datasheet rychločtením není dobré)
viki píše:Tohle taky nefunguje:

Kód: Vybrat vše

bus.write_i2c_block_data(address, 0xC0, ['H'+128, 'e'+128, 'l'+128, 'l'+128, 'o'+128, atd.])
Python chce hodnoty typu int což ['H'+128] není.
No jo, Python, zapomněl jsem :D
V C/C++ by to tak fungovalo ...
viki píše:Ale šlape mi tohle:

Kód: Vybrat vše

import smbus
import time

bus = smbus.SMBus(1)
address = 0x3a

slovo = input("Zadejte slovo: ")

bus.write_byte_data(address, 0x00, 0x26)
bus.write_byte_data(address, 0x00, 0x0e)
bus.write_byte_data(address, 0x00, 0x06)
time.sleep(1)
bus.write_byte_data(address, 0, int(hex(int(128+0)), 16))
      
for pismeno in slovo:
    cislo=ord(pismeno)+128
    bus.write_byte_data(address, 0x40, int(hex(int(cislo)), 16))
Tady bys to výrazně zrychlil (odhadem 4x), kdyby sis ty data nejdřív připravil, a poslal je až všechny najednou.
Taky mi není jasná ta šaráda int(hex(int(..., tam by imho mělo bohatě stačit jen to cislo.
Asi takhle:

Kód: Vybrat vše

zapsat=[0]
for pismeno in slovo:
   zapsat.append(ord(pismeno)+128)
bus.write_byte_data(address, 0x40, zapsat)
(a ten sleep tam asi ani není potřeba, protože všechny akce co provádíš by měly trvat 3 takty hodin LCD čili snad 20 mikrosekund. Jediná delší akce je Clear display, ale i na ni by sleep myslím neměl být potřeba, protože komunikace po i2c je tak pomalá, že než by tam došel další příkaz, už by to bylo provedené.)

viki
Příspěvky: 42
Registrován: 14 pro 2013, 22:23

Re: Displej s I2C rozhraním

Příspěvek od viki » 12 led 2016, 00:18

Díky za rady.
DavidO píše::

Kód: Vybrat vše

bus.write_i2c_block_data(address, 0x00, [0x26, 0x0e, 0x06])
bus.write_i2c_block_data(address, 0x40, [0x21, 0x22])
Tohle funguje skvěle.

Tu pauzu tam mám proto že to někdy nestíhalo a některé znaky se mi nezobrazily. Hlavně po tom mazání, už přesně nevím.
DavidO píše:

Kód: Vybrat vše

zapsat=[0]
for pismeno in slovo:
   zapsat.append(ord(pismeno)+128)
bus.write_byte_data(address, 0x40, zapsat)


Tohle nešlape, háže to tuhle chybu:
bus.write_byte_data(address, 0x40, zapsat)
TypeError: an integer is required


Když jsem to zkusil doplnit o tu mojí šarádu tak to háže tohle:
bus.write_byte_data(address, 0x40, int(hex(int(zapsat)), 16))
TypeError: int() argument must be a string or a number, not 'list'


Jinak tu šarádu tam mám proto že jsem to na typ int uměl převést pouze z hex a ten potřeboval taky mít typ int.
Programátorům se z toho asi krouti pejzy ala já nic lepšího nevymyslel a tohle fugovalo :-)

AlesH
Příspěvky: 322
Registrován: 25 úno 2013, 09:18

Re: Displej s I2C rozhraním

Příspěvek od AlesH » 12 led 2016, 12:13

Jen poznamenám, že ten závěrečný kód od DavidO by měl fungovat, jen samozřejmě na posledním (neodsazeném) řádku nemůže být "bus.write_byte_data(...)", ale "bus.write_i2c_block_data(address, 0x40, zapsat)".

DavidO
Příspěvky: 549
Registrován: 01 kvě 2013, 21:27

Re: Displej s I2C rozhraním

Příspěvek od DavidO » 12 led 2016, 17:29

AlesH píše:Jen poznamenám, že ten závěrečný kód od DavidO by měl fungovat, jen samozřejmě na posledním (neodsazeném) řádku nemůže být "bus.write_byte_data(...)", ale "bus.write_i2c_block_data(address, 0x40, zapsat)".
No jo, samozřejmě, trapná chybka :oops: Má to být tím blokovým přenosem stejně jak když se tam posílá to pole při inicializaci.
Ále co, však jsem tam psal "Asi takhle" :lol:

DavidO
Příspěvky: 549
Registrován: 01 kvě 2013, 21:27

Re: Displej s I2C rozhraním

Příspěvek od DavidO » 12 led 2016, 18:31

viki píše:Tu pauzu tam mám proto že to někdy nestíhalo a některé znaky se mi nezobrazily. Hlavně po tom mazání, už přesně nevím.
Ano, instrukce Display Clear je oproti ostatním dlouhá, ale ty ji ani nepoužíváš (Display Clear je kód 0x01, ty máš to čekání za 0x06 což je Entry mode set a ta trvá krátce, viz datasheet, str. 23, tabulka 3). Jestli to někdy nezobrazuje nějaké znaky, tak problém bude jinde.
viki píše: Jinak tu šarádu tam mám proto že jsem to na typ int uměl převést pouze z hex a ten potřeboval taky mít typ int.
Programátorům se z toho asi krouti pejzy ala já nic lepšího nevymyslel a tohle fugovalo :-)
Spíš je to mate, programátor začne koumat, co za spešl trik to autor použil :o
Ty sis totiž vzal jedno písmeno z řetězce (pomocí konstrukce for pismeno in slovo) a pak sis z toho pismene udělal číslo přiřazením cislo=ord(pismeno) (+128 ale to je nezajímavé). Výrazem int(hex(int(cislo))) jsi převedl cislo na celé číslo (ten int vpravo), to se ale nic nezměnilo, protože celé číslo už to bylo. Pak jsi to tím hex převedl na řetězec ve tvaru '0xněco' (viz popis funkce hex) a pak jsi to zase převedl na celé číslo (ten int vlevo, viz popis funkce int). Čili nakonec jsi dostal zase celé číslo, jako jsi měl na začátku, akorát to mezitím chvilku byl řetězec obsahující hexadecimální záznam toho čísla. Takže to fungovalo, ale úplně stejně by to mělo fungovat, i kdybys tam místo int(hex(int(cislo))) napsal jen cislo. Leda pokud by cislo nebylo celé číslo, tak by stačilo napsat int(cislo) a to by z obsahu té proměnné cislo už celé číslo vyrobilo (tedy pokud by to šlo, samozřejmě, nicméně ani to v tomhle případě není potřeba, protože tím přiřazením na začátku jsi ze znaku udělal číslo).

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 1 host