Sida 1 av 3

HD44780-kompatibel display: Kommer inte över till CGRAM...

Postat: 10 augusti 2013, 15:19:06
av JimmyAndersson
Jag har ett gäng rutiner (skrivna i Python) till min display. (Använder 4bit för data-pinnarna.)
Allt fungerar fint. Kan initiera, skriva text, byta rad/kolumn.

Men jag lyckas inte göra egna tecken.
Jag skickar nedanstående i tur och ordning:
(med 1 sekunds mellanrum för att utesluta att displayen inte hinner med.)

RS: 0
DB7-DB4: 0100
Skaka E-pinnen (skicka först 1 sedan 0 till den.)
DB7-DB4: 0000
Skaka E-pinnen (samma här.)
(Totalt sett blir ju detta 0b01000000, som är "Set CGRAM adress to AC (Adress Counter)".)


Det som händer är att markören på displayen går ner till första kolumnen på rad 2.
Varför? Jo: DDRAM-adressen för "första kolumnen på rad 2" är också 0b01000000 !

Men jag förstår inte vad jag gör för fel...
Jag sätter ju RS till 0.
För att sätta DDRAM adressen till AC (som man gör för att ändra markörens position) så ska ju RS vara 1.
Men jag har kollat med oscilloskopet och RS sätts till 0 innan jag skickar 0b01000000.
RS stannar även kvar på 0 efter att 0b01000000 har skickats.
Därefter har jag en Break i koden som avslutar där, så det är inget annat konstigt som påverkar.
Jag har även kollat med oscilloskopet så att 0b01000000 verkligen skickas och att det kommer i rätt tid.


Och som sagt:
Jag kan ju skriva text/siffror och ändra markörens position (med flit)
så allt är ju rätt kopplat och kodat i övrigt.


Jag har kollat igenom allt många gånger. Både i dag och i går.
För att vara säker på att "det jag tror att jag skickar" är samma sak som "det jag skickar" så har jag
en massa print-rader som (på datorns skärm) visar innehållet i den variabel som går direkt till displayens pinnar.




Här är därför utskriften av det jag påstår mig skicka ovan:
Förklaringar:
Bit 7-4 = DB7-DB4 på displayen.
Bit 3 = Används inte. (Funderade ett tag på att använda R/W-pinnen, men ångrade mig.)
Bit 2-1 = E-pinnarna på displayerna. (Det är en 4x40-display, därav 2st. Jag t.ex initierar båda samtidigt framgångsrikt.)
Bit 0 = RS-pinnen.

(Krysset/kryssen inom parentes markerar vilken/vilka bitar som kommentaren gäller.)

Utskriften på skärmen:
Först RS 0:
00000000 = RS off (-------X)
Nu CGRAM:
01000000 = DB (XXXX----) Högsta 4 bitarna.
01000110 = E on (-----XX-) Notera att datan från DB ligger kvar. Displayen "laddar" den till minnet när E är hög.
00000000 = E off (-----XX-) Här är datan från DB borta. Helt som det ska. Displayen har redan fångat det.
00000000 = DB (XXXX----) Lägsta 4 bitarna.
00000110 = E on (-----XX-)
00000000 = E off (-----XX-)
-----------------------







Såhär ser koden ut när jag anropar rutinerna och skickar den aktuella datan:

print("Först RS 0:")
lcd.rs(0)
sleep(1)
print("Nu CGRAM:")
lcd.db(0b01000000)

Om någon fastnade för det här med att jag inte har med DB7-DB4 när jag släcker E-pinnarna:
Jag använder exakt samma rutiner för när jag initierar displayen och skriver text/siffror. Dvs lcd.rs() och lcd.db()
E-pinnarna sköts av rutinen lcd.db()

Jag har även testat att låta datan från DB7-DB4 vara kvar när jag släcker E-pinnarna, utan skillnad.

Jag kan förstås visa koden, men jag tänkte först höra om någon känner igen fenomenet med att man stannar i DDRAM..



Något tips på vad som kan vara galet? (Bortsett från att den verkar stanna kvar i DDRAM.) :)



edit: Två av de datablad som jag studerat:
http://www.farnell.com/datasheets/1485446.pdf <-- Den aktuella displayen.
http://icecap.se/Sublevel/LCD_Dot_Matri ... Manual.pdf <-- Databladet för HD44780 från Sharp.

Länk till displayen hos Farnell:
http://se.farnell.com/midas/mc44005a6w- ... dp/2063179

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 10 augusti 2013, 16:26:53
av spaderkung
För ett par år sedan körde jag en 2 raders med samma controller. Om jag minns rätt var initieringsrutinen i databladet fel för 4-pinsläget (sen första displayen har man ju aldrig rört dessa rutiner efter att ha fått det att fungera). Nu fungerar ju din initiering och jag kan ju ha läst eller minnas fel, men detta som förslag på en ny ingångsvinkel till ditt dilemma.

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 10 augusti 2013, 16:51:11
av JimmyAndersson
Bra idé. Jag kan visa initieringen:

Kod: Markera allt

def LCD_init():
    # Initiera LCD
    # Bit 7 - 4 motsvarar displayens DB7-DB4.
    sleep(0.02)
    lcd.rs_first(0)
    lcd.db_init(0b00110000)
    lcd.db_init(0b00110000)
    lcd.db_init(0b00110000)
    #
    lcd.db_init(0b00100000) # Switch to 4 bitar!
    # From here: 4 bitar
    # 2-line. 5x8 dot format:
    lcd.db_init(0b00100000) # F in datablad
    lcd.db_init(0b10000000)
    #
    # Display turned on. Chursor is On. Blink is On:
    lcd.db_init(0b00000000) # D in datablad
    lcd.db_init(0b11110000)
    #
    # Clear Display:
    lcd.db_init(0b00000000) # A in datablad
    lcd.db_init(0b00010000)
    #
    # Cursor/blink moves to right and DDRAM adress is increased by 1.
    # If DDRAM write operation, shift of entire display is performed
    # according to I/D. I mitt fall: Shift right.
    lcd.db_init(0b00000000) # C in datablad
    lcd.db_init(0b01100000)

Jämfört med databladet:

Kod: Markera allt

4bit init:

Power on
Wait >15ms

00110000
Vänta >4,1ms
00110000
Vänta >100µs
00110000

00100000
------
0010  bit7-4
NFxx  bit3-0   Här har jag 1000  Dvs 2-line. 5x8 dot format
------
0000
1000             Här har jag 1111  Dvs Display turned on. Chursor is On. Blink is On.
------
0000
0001
------
0000
01DS ("D" ska egentligen vara "I/D", men det hade sett rörigt ut.)
       här har jag 0110 Dvs:
       Cursor/blink moves to right and DDRAM adress is increased by 1.
       If DDRAM write operation, shift of entire display is performed
       according to I/D. I mitt fall: Shift is not performed.

Så det ser ju ut som det ska i min kod.
Har även dubbelkollat mellan två olika datablad (det för displayen och det för HD44780-kretsen) utan att hitta något fel.

Jag har tittat om det finns någon inställning i databladet (och initieringen) som påverkar CGRAM men inte hittat något.


:humm:

edit: En annan sida, med tydliga förklaringar av alla funktioner från databladet:
http://mil.ufl.edu/4744/docs/lcdmanual/commands.html

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 10 augusti 2013, 17:56:23
av Icecap

Kod: Markera allt

  const unsigned char LCD_INIT[7] = {0x38,0x38,0x38,0x38,0x0C,0x01,0x06}; /* 16x2, 8-bit mode */
  const unsigned char LCD_Chars[64] = {
    0x00,0x00,0x1C,0x04,0x1C,0x10,0x1C,0x00, /* 00h/08h Subscript '2' */
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 01h/09h */
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 02h/0Ah */
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 03h/0Bh */
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 04h/0Ch */
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 05h/0Dh */
    0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00, /* 06h/0Eh */
    0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0x00};/* 07h/0Fh */
  volatile unsigned char x;
/*  volatile unsigned int  y; /*  */
  .... lite bla bla
  LCD_Delay_40ms();
  for(x = 0;x < 7;x++)
    { /* First initialize the LCD mode */
    LCD_Data    = LCD_INIT[x];
    LCD_Delay_Setup();
    LCD_Shake_Enable();
    LCD_Delay_1530us();
    }
  LCD_Data    = 0x40; /* Load own char's command */
  LCD_Delay_Setup();
  LCD_Shake_Enable();
  LCD_RS     = 1;
  LCD_Delay_60us();
  for(x = 0;x < 64;x++)
    {
    LCD_Data = LCD_Chars[x];
    LCD_Delay_Setup();
    LCD_Shake_Enable();
    LCD_Delay_60us();
    }
  LCD_RS      = 0;
  LCD_Delay_60us();
  }
Detta är min kod för initieringen, inkl. egna tecken. Den är för 8-bit setup så den bit får du pilla med själv.

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 10 augusti 2013, 20:34:24
av Marta
För att adressera CGRAM skickar Du 01xx xxxx och för att adressera DDRAM skickar Du 1xxx xxxx . Om det blir som Du säger så beror det på att bit7 är satt när Du utgår från att den inte är det.

Du kanske har en "duktig" rutin som sätter bit7 åt Dig så att Du endast skall behöva skicka de aktuella adressbitarna för att addressera DDRAM? I så fall är denna rutin *inte* användbar för att skriva till CGRAM.

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 11 augusti 2013, 04:32:58
av JimmyAndersson
Jag tittade nu på bit 7 med oscilloscopet och den är 0 hela tiden efter initieringen.

Närmare bestämt:
Efter initieringen så skriver jag ut lite text på displayen. Då rör ju bit 7 på sig.
Därefter är det en paus på 3 sekunder. Sedan skickar jag det jag visat i inläggen.
Från och med pausen så ligger bit 7 på 0 volt. RS är som sagt också 0.
Det är kollat med oscilloskop.

Men du har helt klart en intressant poäng.


Min lcd.db-rutin är visserligen duktig:
Den kan ta emot en sträng (ett tecken eller flera ord) eller "ren data" t.ex 0x61 för tecknet a.
Den delar upp en byte till två nibble.
Den tar även hand om E-pinnarna och ser till så att RS finns med om man ställt in den på raden innan.
Men den lägger inte till bit 7. Det gör bara rutinen lcd.position när man ber den flytta markören.
(I debug-syfte har jag med en massa print-rader som skriver allt som händer på min vanliga skärm.)



Icecap:
Tack för koden!

Fiffigt att använda initieringen fyra första byte för att ställa in det man vill.
I databladet så har de inte ägnat så mycket tid till att beskriva att man kan ändra dem,
så jag har faktiskt aldrig tidigare sett något annat än 0x30 på de fyra första byte'n där.
Men nu ser jag att de bara är "Function set" (8/4bit osv). :)

För övrigt så är din och min initiering väldigt lika. Det var bara 8/4bit och markör on/off som skilde.
Sedan har jag också en paus (1 sek i debugsyfte),
sätter också databitarna till 0x40 (0b01000000),
väntar också en stund (1 sek i debugsyfte) och skakar också E.

Men i samma stund som jag sätter databitarna till 0b01000000 så hoppar markören ner till rad 2 kolumn 1.





--

Jag kom på ett enkelt test:
Jag ska testa att skicka allt utan några rutiner eller klasser inblandade.
Då får jag reda på:
1) Är det något special med just den här displayen.
2) Har jag missat något i databladet.
3) Om det är något knas med någon rutin eller klass.

Resultatet?
Jo, jag ändrade inte något i initieringen. Den gjordes med mina rutiner, precis som jag alltid gjort.
Sedan skickade jag all data "rå", dvs utan rutiner och klasser.
Och det fungerade! :)

Då stryker vi punkt 1 och 2 ovan.

Därefter började jag ersätta mina "råa" kommandon med en rutin i taget tills det blev fel.
Det visade sig att felet ligger i min lcd.db-rutin. Någonstans.
...
Så nu har jag gått igenom allt i den rutinen igen.
Lagt till debug-rader som skriver ut precis allt till min vanliga skärm.
Men jag hittade ändå inte felet.

Så jag lutade mig tillbaka i stolen men drogs direkt mot skärmen igen. :idea:
Visst var det väl så att jag bara skickade *en* rad när jag skickade data för DB-pinnarna utan att blanda in rutinerna??

Jo! Jag tryckte ju:

bus.write_byte_data(DEVICE, OLATA, (0b01000000)) # CGRAM
Och sedan E-pinnarna höga/låga.

Så där delade jag ju inte upp det till två nibble - och det fungerade ju!

Så... jag testade med min initierings-rutin för att skicka 0b01000000. (När man initierar så ska man
inte skicka först bit 7-4 och sedan 3-0. Utan bara 7-4.)
Dra mig baklänges i Nilen och kalla mig Rudolf: Det fungerade!! :)

Tydligen blir det geggamoja om man skickar en nibble i taget när man ska adressera CGRAM.
Så i det här fallet ska man bara skicka:
0100 (bit 7-4). Thats it.

Eller, ja E-pinnarna ska ju vara med också, så hela lottoraden blir alltså:

00000000 = RS (bit 0) off.
01000000 = DB (bit 7-4). (Ljudtomte som man är så skriver jag alltid "dB" och får ändra. Skadad...)
01000110 = E (bit 1 och 2) on. Det är ju här som DB laddas in i displayen.
00000000 = E (bit 1 och 2) off. Och så var allt klart. Släcker E-pinnarna.

That's it. :)


edit:
Men det blir inte helt rätt när jag gör själva tecknen.
Samtidigt som jag gör tecknet så dyker det upp t.ex "@ 0pbp0" osv.
Dessa tecken skiljer sig något mellan "displayerna" (det är ju två i en 4x40-display)
trots att jag skakar e-pinnarna på båda samtidigt.

Men: När det är klart så kan jag ändå få upp mitt tecken på displayen.

Så något är lite skevt med min lcd_db-rutin ändå...
Hittar jag inte felet så lägger jag nog upp rutinen här.

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 11 augusti 2013, 15:48:35
av Marta
Du kan inte ändra datapinnar och E i samma instruktion, det Du skrivit tyder på att Du gör så när E nollas samtidigt med databitarna.

Utöver setuptime som Du har beaktat finns det finns även en holdtime på data och styrsignaler. Inte lång, men nollar Du alla bitarna på en gång så är det absolut inte garanterat att detta krav möts. Just att det blir olika på de två chipen tyder också lite på att det kan vara ett timingproblem.

RS och R/W har både setup- och holdtime relativt början och slut på E.
Data har setup- och holdtime relativt den negativa flanken på E.

De angivna tiderna skiljer lite mellan olika datablad, men ändra inget annat samtidigt med E så möter den kraven med en normal MCU.

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 11 augusti 2013, 16:49:08
av JimmyAndersson
Aha. Jo för jag blev lite överraskad att hitta att flankerna såg ut så i databladet.

I princip all källkod för mikrokontrollers där man skickar något till en LCD
så skickar man först något till datapinnarna
och därefter E = 1, följt av E = 0.
Det tyckte inte jag stämde med databladet, men med din förklaring så är jag med på varför det ändå fungerar.

Som sagt så nollar ju jag allt samtidigt som jag släcker E-pinnarna.
Jag lät först datan till DB-pinnarna vara kvar när jag släckte E-pinnarna,
men då blev det mycket oväntade tecken (blandat ur hela teckentabellen) över hela displayen.
Så då provade jag att nolla datan när jag nollade E-pinnarna och då fungerade det
att skriva bokstäver och siffror på displayen. Därför lät jag det vara så.

Men jag håller med om att det kan vara en felkälla. Skrivning till CGRAM verkar vara känsligare för fel jämfört med DDRAM.
Allt som har med DDRAM att göra fungerar nämligen perfekt med exakt samma rutiner,
alltså där jag släcker datapinnarna samtidigt som jag nollar E-pinnarna.



Så nu provade jag att verkligen gå tillbaka till grunden med CGRAM och egna tecken.
Gjorde *allt* direkt till displayens pinnar, utan att blanda in någon som helst rutin.
Den här gången lät jag datan vara kvar när jag släckte E-pinnarna.

Bitarna i koden symboliserar:
Bit 7-4: Displayens DB7-DB4
Bit 3: Oanvänd
Bit 2-1: E-pinnarna.
Bit 0: RS-pinnen.

DEVICE : I2C-kanalen som styr en "portexpander"-krets (MCP23017-E/SP) från Microchip.
OLATA : Port A på den kretsen. Alla dessa pinnar är anslutna enligt tabellen ovan.

Jag kan redan nu säga att resultatet av koden blir nästan identiskt med när jag testade använda rutinen i natt.
dvs "@ 0pdp0 ".



I kodrutan nedan så har har bara utelämnat initieringen av I2C och displayen,
men den sistnämnda finns i ett tidigare inlägg.
Eftersom jag kör med 4bit så skickar jag först DB-bitar 7-4 och sedan 3-0.
(Just raderna med bitar 3-0 har ett "L" med i kommentaren.)

Däremot skickar jag *bara* de höga bitarna när jag sätter CGRAM-adressen.
Om jag även skickar de låga bitarna så blir istället resultatet
att AC (Adress Counter) skickar markören till rad 2 och stegar fram en kolumn
för varje gång jag skickar en byte med data till det egna tecknet.

Koden:

Kod: Markera allt

# Testar att göra ett eget tecken helt manuellt

sleep(0.1) #Inbyggd rutin i Pythons sys-klass. Enheten är sekunder.
bus.write_byte_data(DEVICE, OLATA, 0b00000000) # RS 0
sleep(0.1)

bus.write_byte_data(DEVICE, OLATA, 0b01000000) # CGRAM
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b01000110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b01000000) # E off. Notera att jag låter datapinnarna vara kvar.
sleep(0.1)


bus.write_byte_data(DEVICE, OLATA, 0b01000001)  #RS. Låter även datapinnarna vara kvar som jag tidigare ställde dem.
sleep(0.1)


bus.write_byte_data(DEVICE, OLATA, 0b00000001) #1
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000001)  #E off
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00010001) #1L
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00010111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00010001)  #E off
sleep(0.01)

bus.write_byte_data(DEVICE, OLATA, 0b00000001) #2
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000001)  #E off
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00110001) #2L
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00110111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00110001)  #E off
sleep(0.01)

bus.write_byte_data(DEVICE, OLATA, 0b00000001) #3
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000001)  #E off
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b01110001) #3L
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b01110111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b01110001)  #E off
sleep(0.01)

bus.write_byte_data(DEVICE, OLATA, 0b00000001) #4
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000001)  #E off
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b11110001) #4L
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b11110111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b11110001)  #E off
sleep(0.01)

bus.write_byte_data(DEVICE, OLATA, 0b00000001) #5
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000001)  #E off
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b01110001) #5L
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b01110111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b01110001)  #E off
sleep(0.01)

bus.write_byte_data(DEVICE, OLATA, 0b00000001) #6
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000001)  #E off
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00110001) #6L
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00110111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00110001)  #E off
sleep(0.01)

bus.write_byte_data(DEVICE, OLATA, 0b00000001) #7
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000001)  #E off
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00010001) #7L
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00010111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00010001)  #E off
sleep(0.01)

bus.write_byte_data(DEVICE, OLATA, 0b00000001) #8
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000001)  #E off
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000001) #8L
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000111)  #E
sleep(0.01)
bus.write_byte_data(DEVICE, OLATA, 0b00000001)  #E off
sleep(0.01)

exit()

Allt efter första byten av det egna tecknet (dvs efter rad 31) har ju identisk struktur
som den första byten (märkt med kommentaren "#1").
Så det ser ut att vara mer kod att titta igenom än vad det verkligen är. :)

Hoppas ni kan hitta något som jag har missat.
Jag letar förstås också. Tro inget annat. :D

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 11 augusti 2013, 17:01:10
av Icecap
Om du måste nolla databit för att utläsningen skal bli stabil gör du fel från början! Se till att timingen blir korrekt, sedan ska du se att det blir mycket enklare att få det hela att fungera korrekt.

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 11 augusti 2013, 17:34:20
av Marta
Här är någonting som inte alls stämmer.... Någonting tycks hända på vägen mellan att data skickas och att denna anländer till displaykretsarna. Du *måste* skicka hela CGRAM-instruktionen, fungerar inte detta är något mycket trasigt och skall absolut åtgärdas.

Hur latchar portexpandern data till pinnarna? Kan det vara så illa att denna är utförd så utgångarna fladdrar när data skiftas in eller på något sätt släpper ifrån sig glitchar? I så fall kan det uppstå vilka magiska fenomen som helst. Kan Du koppla E direkt till processorn så Du med absolut såkerhet *vet* vad som skickas till denna pinne? Det kan möjligtvis även vara av betydelse att RS och R/W inte fladdrar mellan två nibbles, men där är jag osäker.

Hur ser hårdvaran ut, är det möjligtvis en utmmanande härva som inviterar allehanda problem?

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 12 augusti 2013, 16:23:37
av JimmyAndersson
Tack för svaren. :tumupp:

Displayen har en lödd kontakt med 8cm långa sladdar med stiftpinnar i andra änden.
(Såna där sladdar som säljs i en bunt med olika färger och svarta pinnar, just för labplattor.)
Dessa sitter anslutna så nära portexpander-IC'n som det bara är möjligt.
Mindre härva än så här kan man inte få med en display ansluten till en labplatta.

Från portexpander-IC'n så går en 10cm lång flatkabel med IDC-kontakt till Raspberry Pi'ens I2C-anslutningar.
Matningspänning för display och portexpander kommer från ett bra köpt labaggregat.
(Labaggregatet och Raspberryn har sina GND ihopkopplade till en punkt på labplattan.)

Det är allt.




Jag håller med om att det verkar som timingproblem eller att något hamnar "snett",
t.ex att sista nibblen uteblir på något ställe.

Men jag kan inte låta bli att fundera på en sak:

Hur skulle det kunna vara ett fel med hårdvaran eller mjukvaran (glitchar, timingproblem, fel i rutiner, osv)
när jag kan göra allt utom att göra egna tecken? Dvs:
Att initieringsrutinen körs korrekt bevisas av att jag kan skriva text/siffror på displayen.
Att jag kan skriva text/siffror, flytta markören (med flit) visar ju att rutinerna fungerar
och att det inte är glitchar eller timingproblem.

Eller ligger CGRAM möjligen på en separat minneskrets som skiljer sig mellan DDRAM,
eller är det något annat i displayens hårdvara som skiljer dem åt rent elektroniskt
och därmed gör att just enbart CGRAM drabbas av vad som nu orsakar problemen?



Om jag går igenom portexpanderns utgångar:

Eftersom jag kör med 4bit så används bit 7-4 till allt som ska ut på skärmen.
De används alltså flitigt. Och det har aldrig blivit något som helst tecken till problem.
Bit 3 använder jag inte.
Bit 1 och 2 styr E. Utan dem hade jag inte kunnat få ut något livstecken alls på displayen.
Bit 0 styr RS. RS ska vara 0 när man initierar. Jag kan initiera.
RS ska vara 1 för att kunna skriva text på displayen. Jag kan skriva text på displayen.

Jag förstår inte hur ovanstående skulle kunna ha varit möjligt om det var något med
hårdvara, glitchar, egenheter i portexpandern, fel i mina rutiner, och liknande.


För visst måste ni hålla med om att det vore ytterst märkligt om portexpandern
skulle uppföra sig annorlunda när jag t.ex vill skriva till CGRAM jämfört med om jag vill skriva till DDRAM. :)
Den har ju inte en aning om vad det är.
Om det var någon enstaka eller ett par bitar i kommunikationen som uppförde sig konstigt
så skulle det ju märkas även när jag använder samma bitar till andra saker.

Upplys mig gärna ifall det är något i mitt resonemang som jag missar. :)





"Hur latchar portexpandern data till pinnarna? Kan det vara så illa att denna är utförd så utgångarna fladdrar när data skiftas in eller på något sätt släpper ifrån sig glitchar? I så fall kan det uppstå vilka magiska fenomen som helst."

Jag bifigade några bilder på loggning av den data som displayen får samt datablad till portexpandern.
Se slutet av inlägget.


När jag loggade signalerna så samplade jag bara med 10MHz eftersom minnet inte räcker annars,
men så långt ser jag inga fel iallafall.
Men jag kan ju göra allt som står i databladet felfritt, varje gång - förutom att skriva till CGRAM.
Det borde väl inte vara möjligt om felet beror på det du beskriver?
Den här portexpandern (MCP23017-E/SP) är förresten en mycket vanlig komponent
bland de som kopplar en display till sin Raspberry Pi.

Jag skriver till OLAT. I databladet för portexpandern står det:
"The OLAT register provides access to the output
latches. A read from this register results in a read of the
OLAT and not the port itself. A write to this register
modifies the output latches that modifies the pins
configured as outputs."





Marta:
"Du *måste* skicka hela CGRAM-instruktionen, fungerar inte detta är något mycket trasigt och skall absolut åtgärdas."

Jag har korrigerat så att jag nu skickar hela CGRAM-instruktionen.

Jag är medveten om att jag inte har visat programmet,
men har du något förslag på vad som skulle kunna vara trasigt
utan att något annat (t.ex allt som har med DDRAM att göra) skulle påverkas av det trasiga?

Det enda jag kan komma på är om jag adresserar CGRAM på fel sätt.
Jag har inte hittat någon information om vilka displaykretsar som sitter på displayen
och det finns ju de "HD44780-kompatibla" kretsar som inte är 100% kompatibla.
Tyvärr har jag ingen erfarenhet av på vilket sätt de brukar skilja sig från riktiga HD44780-kretsar
och jag har inte hittat något på nätet om detta.

edit:
Jag testade nu med en 4x20 LCD med en synlig HD44780-krets och den uppför sig exakt likadant.
Då kan jag stryka min tanke med att jag adresserar CGRAM på fel sätt.



"Kan Du koppla E direkt till processorn så Du med absolut såkerhet *vet* vad som skickas till denna pinne?"

Jag får bygga om en del då och skaffa en annan kontakt, men det är förstås möjligt att ordna. :)




Nu kanske det verkar som att jag resonerar "näää, men *det* är det iallafall inte fel på, och så kollar jag inte det".
Men det stämmer naturligtvis inte. Jag utesluter ingenting.
Att "ifrågasätta" är ju bara en naturlig del av lärandeprocessen och felsökningen.
Jag ville bara berätta vilka tankar som väcktes när jag läste era senaste inlägg. :)






Jag plockade som sagt fram min logik-analysator.
(Jag har tidigare använt den för att hitta små fel i bl.a MIDI-data, I2C-kommunikation mm.)

I bilderna nedan så har jag inga filter eller något på signalerna. Allt är vad displayen får.


Såhär ser första delen av initieringen ut:

Bild
(Klicka för att se full storlek.)


Följande bild: Hela initieringen och texten "Hej! 26,5C" :
(Detta utförs enbart av mina rutiner.)

Bild
(Klicka för att se full storlek.)



Bilden nedan visar signalerna som följande kod genererar,
och som resulterar i att markören bara går ner till rad 2 kolumn 1.
Notera att bus.write_byte_data() skriver direkt till portexpandern via I2C och Python's standard-library för I2C.
*Ingen* av mina rutiner är inblandade här.

Kod: Markera allt

bus.write_byte_data(DEVICE, OLATA, 0b00000000) # RS 0
sleep(0.1)

bus.write_byte_data(DEVICE, OLATA, 0b01000000) # CGRAM
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b01000110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b01000000) # E off
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00000000) # CGRAM L
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00000110) # E on
sleep(0.1)
bus.write_byte_data(DEVICE, OLATA, 0b00000000) # E off
sleep(0.1)

exit()
Bild
(Klicka för att se full storlek.)





Mer om portexpandern MCP23017-E/SP:
Databladet: http://ww1.microchip.com/downloads/en/D ... 21952b.pdf

Min initiering av portexpandern:

Kod: Markera allt

# - - - - - -
# Definiera adresser

DEVICE = 0x22 # Adressen till min krets

# A
IODIRA = 0x00 # Register for pin direction. In or Out
OLATA = 0x0A  # Register for outputs (When IOCON.BANK=1)
GPIOA = 0x09  # Register for inputs (When IOCON.BANK=1)

# B
IODIRB = 0x10
OLATB = 0x1A
GPIOB = 0x19

#
IOCON = 0x04
GPPUA = 0x06
GPPUB = 0x16

# - - - - - -




bus = smbus.SMBus(1) # I2C-bussen och vilken kanal.


#Bank 1. No mirror in INT. Sequential operation enabled.
bus.write_byte_data(DEVICE, IOCON, 0b10000000)

# Pull-up disabled for inputs
bus.write_byte_data(DEVICE, GPPUA, 0b00000000)
bus.write_byte_data(DEVICE, GPPUB, 0b00000000)

# Set all GPA and GPB pins as outputs by setting
# all bits of IODIRA and IODIRB register to 0
bus.write_byte_data(DEVICE,IODIRA, 0x00)
bus.write_byte_data(DEVICE,IODIRB, 0x00)

# Set output all 7 output bits to 0 on GPA and GPB
bus.write_byte_data(DEVICE,OLATA, 0)
bus.write_byte_data(DEVICE,OLATA, 0)


Nu är inlägget väldigt långt, så jag stoppar här för tillfället och inväntar era tankar.
Under tiden ska jag fortsätta som jag gjort med att läsa, fundera, mäta och prova.

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 12 augusti 2013, 17:19:02
av Marta
Har Du provat att skriva till displayen och därefter ladda tecken till CGRAM? På det sättet får Du bekräftat att initieringen är avslutad samt att den inte står i ett mellanläge mellan två nibbles när Du påbörjar komandot.

På den mellersta bilden från logikanalysatorn har en negativ flank hamnat så den går rakt igenom där pixlarna tar ett språng i sidled. Samma språng syns på databitarna. Det kan ge intrycket att dessa händelser är samtidiga, men jag antar att det inte är så?

Verkligen egendomligt att allt annat fungerar, hade det funnits störnigar skulle de rimligtvis ha gjort sig gällande även när tecken skrivs till displayen. Det är ju samma sak som sker, bara att kommandot är ett annat.

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 12 augusti 2013, 17:27:21
av Icecap
Just det: kommer på ett problem en kund hade med sådana displayer. Montera en avkopplingskondensator på displayen om du kan, detta då för matningsspänningen. 100nF duger fint.

Det är osannolikt att det är orsaken till problem - men då kan du utesluta det också och det är aldrig fel!

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 12 augusti 2013, 18:24:43
av JimmyAndersson
edit: Jag kom att tänka på det, så i slutet av inlägget gör jag om testet med bl.a en sådan.
---

Marta:
Ja det har jag provat. Alltså:
Initiera med min rutin.
RS = 0
Skicka första nibble av 0b0100 0000 (CGRAM), dvs 0b01000000
E on/off
Skicka andra nibble av 0b0100 0000 (CGRAM), dvs 0b00000000
E on/off


Mellan varje rad så har jag skickat en paus på 0.1 sek.
När 0b0100000 är skickat så ställer sig markören på första kolumnen i rad 2.


Jag har även provat att initiera och därefter skicka ett "A", dvs:
Initiera med min rutin.
RS = 1
Skicka första nibble av 0b0100 0001 (ASCII-koden för bokstaven A), dvs 0b01000000
E on/off
Skicka andra nibble av 0b0100 0001 (ASCII-koden för bokstaven A), dvs 0b00010000
E on/off


Då visas ett A på rad 1 kolumn 1.


I båda fallen skriver jag direkt till I2C-porten utan någon rutin eller annat.
Detta visar att försöket med CGRAM inte bekräftar att initieringen är korrekt,
men att försöket med DDRAM bekräftar att initieringen är korrekt.
Notera att det *endast* är RS (0 istället för 1) och 1st bit i datan till db-pinnarna (DB7-DB4) som skiljer.


--

Men jag är starkt medveten om en detalj:
När man som jag förutsätter att "det fungerar ju, jag ser ju texten"
så ökar risken för att man missar detaljer som har att göra med just detta. :)

Vi har ju sett det förr:
Personen med problem-projektet ägnar mindre uppmärksamhet åt "det" som "fungerar"
och de med erfarenhet återkommer till just "det".
De trådarna brukar ju sluta med att det är exakt *det* som var felet. :)

--

Så jag har nu rivit sladdarna och kopplat in displayen igen.
Bytt avkopplingskondingar (både för displayen och portexpandern).

Härefter gjorde jag om de båda testerna högst upp i inlägget
och jag upptäckte en sak:

När jag brutit/anslutit spänningen och kört initieringen första gången
så misslyckas nu initieringen. Om jag då behåller matningspänningen på
och kör initieringen igen så lyckas den.
Så var det inte innan jag gjorde om sladdarna och bytte avkopplingskondingar.
Det är jag 100% säker på.

Jag ska undersöka det närmare och även göra en helt ny initiering.
Helst hade jag kört helt utan någon rutin eller klass för detta, men det blir så enormt många rader kod.
Bara att skicka 2st nibbles med E on/off och delayer tar 12st rader.
Det skulle bli 144 rader för att bara initiera displayen.

Jovisst, jag tycker ju som bekant om att skriva långt, men att
knappa in så många rader ökar risken för att man gör och missar fel.
Jag fick tanken att göra ett litet program som levererar dessa rader,
men ni vet ju vad man säger om "ju fler kockar".



Jag återkommer efter jag gjort en ny initiering, så får vi se.


edit:
Marta:
"På den mellersta bilden från logikanalysatorn har en negativ flank hamnat så den går rakt igenom där pixlarna tar ett språng i sidled. Samma språng syns på databitarna. Det kan ge intrycket att dessa händelser är samtidiga, men jag antar att det inte är så?"

Jag ska kolla upp det närmare. Återkommer med det också.

Re: HD44780-kompatibel display: Kommer inte över till CGRAM.

Postat: 12 augusti 2013, 18:34:32
av Icecap
I databladet är det tydligt angivit att man ska vänta ung. 4,1ms från power-on/Reset till man börjar prata med displayen.