PDA

View Full Version : Help with LCD Scroll



ozarkshermit
- 22nd January 2015, 13:57
Howdy

I'm using a 4 x 20 LCD, and scrolling a text message from right to left. That is no problem. The letters "fall off" line one of the display as they reach the end of the first line, and then continue to scroll on line 3. What I want to do is, as the letters reach the end of line one, then restart over on line one, rather than "wrapping" and continuing on line 3. It would be OK if the entire message scrolls off before restarting.

I realize that this "line wrapping" is the way the display normally works., since there are 40 character positions per line, and line one actually continues starting on line 3. Also line 2 continues on line 4.

I thought the sending the command 68 would disable "line wrapping" , but that does not work.

I have searched every related thread I can find, but do not find this discussed. The HD44780 data sheet might explain how to do it, if possible, but I have not found that either.

Is there a way do do this?

Thanks

Ken

andybarrett1
- 22nd January 2015, 14:15
7683

LCD Datasheet Enclosed.

ozarkshermit
- 22nd January 2015, 18:28
Thanks Andy.
I guess I wasn't clear, I do have the data sheet, but have not found how to do this. If it is in there, it's not very clear (at least to me)

I have tried several different scrolling methods, some of which were in links that I found by searching the PBP forums.
Yes, they all do a nice scroll, but on a 4 x 20 LCD screen the text "wraps" from line one to line 3 , and after line three scrolls off, it "wraps back to line one. I only want to display the scroll on Line one.

Ken

Tabsoft
- 22nd January 2015, 20:26
Ken,

Here is a link to a good thread lead by Melanie, long time PBP contributor, about this very subject.

Topic of the thread: "i just want to know how it is possible to scroll just 1 line of a 4x20 lcd using LCDout. example if i wanted to scroll just line 2"

Perhaps it will help you.

pblist.melabs.com/forum/messages/3064/3672.html

Good Luck

Heckler
- 23rd January 2015, 02:48
Might want to take a look at this thread...
http://www.picbasic.co.uk/forum/showthread.php?t=13084
Although it is "rolling" not scrolling.

dwight

Art
- 2nd February 2015, 02:16
If it’s character by character scrolling you feed each character into a FIFO buffer of 16 char length,
(or however long a line of the display is) rotate the byte buffer (should be a byte array)
so the last character is ditched. You print the FIFO buffer to the display for each frame.

Art
- 2nd February 2015, 19:20
So since that was meaningless if you can’t scroll on LCD already, I’ll try an example.



string var byte [16] ‘ because I assume it’s one line of a 2x16 display but you can change this
character var byte ‘ the current character
counter var byte ‘ a step counter and index
lindex var byte ‘ a lookup table index


Now how you’re getting the string in the first place you didn’t say, it could be being typed in serial,
or already stored in eprom or something. I’ll go with a longer than 16 char message stored in lookup table,
and put it in a subroutine at the end of the program.



lookuptable: ‘ get the next character from the table into the character buffer
LOOKUP lindex,[“CHECK IT OUT A SCROLLING TEXT DEMO!!!”],character ‘ 0-36 length message (37 characters in Human talk)
return


We need something to actually rotate the 16 char line buffer and drop the oldest byte off the end
whenever a new character is shifted in. This goes in a subroutine also at the end of the program.



'
rotatearray: ‘ rotate line array
for counter = 16 to 1 step - 1
string[counter] = string[counter-1]
next counter
string[0] = character ‘ insert new character byte at zero index
return



Then a main cycle is needed to index the lookup table, call the lookup and rotate routines and
print the line to LCD. After the variable declarations and before the subroutines:




lindex = 0
CLEARLCD ‘ it’s been a while since I looked at LCDOUT, but whatever two byte code to clear LCD and home.
'
cycle:
HOMELCD ‘ it’s been a while since I looked at LCDOUT, but whatever two byte code to home LCD cursor.
'
gosub lookuptable
lindex = lindex + 1 ‘ increment lookup index
if lindex > 36 then ‘ limit lookup index to length of message
lindex = 0
endif
gosub rotatearray ‘ rotate line with new character at zero index

for counter = 0 to 15 ‘ print the line to lcd
LCDOUT string[counter]
next counter

pause 1000 ‘ delay to see one movement per second

goto cycle ‘ do cycle forever



Largely untested so if someone has a simulation with LCD pls feel free to run it :)

Tabsoft
- 2nd February 2015, 23:01
Art,

I ran your suggestions through a simulator and a couple of things.
1. Scrolls from Left to Right, ozarkshermit wanted Right to Left.
2. Characters are in reverse order. Should read for 20 chars on the screen "CHECK IT OUT A SCROL", but comes out "LORCS A TUO TI KCEHC"

So I took your example and modified it to change these items.

I put this together for a 18F4620.
Compiles and runs fine in the simulator.




'*****PIC MCU Configuration Fuses (MPASM)*****
#IF __PROCESSOR__ = "18F4620"
#CONFIG
CONFIG OSC = ECIO6 ; EC oscillator, port function on RA6
CONFIG WDT = OFF ; WDT disabled (control is placed on the SWDTEN bit)
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled
CONFIG IESO = OFF ; Oscillator Switchover mode disabled
CONFIG PWRT = OFF ; PWRT disabled
CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
CONFIG BORV = 3 ; Minimum setting
;CONFIG WDT = ON ; WDT enabled
CONFIG WDTPS = 512 ; 1:512
CONFIG CCP2MX = PORTC ; CCP2 input/output is multiplexed with RC1
CONFIG PBADEN = OFF ; PORTB<4:0> pins are configured as digital I/O on Reset
CONFIG LPT1OSC = OFF ; Timer1 configured for higher power operation
CONFIG MCLRE = ON ; MCLR pin enabled; RE3 input pin disabled
CONFIG STVREN = ON ; Stack full/underflow will cause Reset
CONFIG LVP = OFF ; Single-Supply ICSP disabled
CONFIG XINST = OFF ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
CONFIG DEBUG = OFF ; Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
CONFIG CP0 = OFF ; Block 0 (000800-003FFFh) not code-protected
CONFIG CP1 = OFF ; Block 1 (004000-007FFFh) not code-protected
CONFIG CP2 = OFF ; Block 2 (008000-00BFFFh) not code-protected
CONFIG CP3 = OFF ; Block 3 (00C000-00FFFFh) not code-protected
CONFIG CPB = OFF ; Boot block (000000-0007FFh) not code-protected
CONFIG CPD = OFF ; Data EEPROM not code-protected
CONFIG WRT0 = OFF ; Block 0 (000800-003FFFh) not write-protected
CONFIG WRT1 = OFF ; Block 1 (004000-007FFFh) not write-protected
CONFIG WRT2 = OFF ; Block 2 (008000-00BFFFh) not write-protected
CONFIG WRT3 = OFF ; Block 3 (00C000-00FFFFh) not write-protected
CONFIG WRTC = OFF ; Configuration registers (300000-3000FFh) not write-protected
CONFIG WRTB = OFF ; Boot Block (000000-0007FFh) not write-protected
CONFIG WRTD = OFF ; Data EEPROM not write-protected
CONFIG EBTR0 = OFF ; Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
CONFIG EBTR1 = OFF ; Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
CONFIG EBTR2 = OFF ; Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
CONFIG EBTR3 = OFF ; Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
CONFIG EBTRB = OFF ; Boot Block (000000-0007FFh) not protected from table reads executed in other blocks

#ENDCONFIG
#else
#ERROR "This program requires a PIC 18F4620 MCU"
#endif

OSCCON = $60 ' Set PIC to 4Mhz & ECIO Clock Mode
'*****END PIC Configuration*****

'*****Defines*****
define OSC 4 ' Set clock to 4Mhz in PIC Basic
'*****Define LCD registers and bits*****
define LCD_BITS 4
define LCD_LINES 2
Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
define LCD_RWREG PORTE
define LCD_RWBIT 2
define LCD_COMMANDUS 1500
define LCD_DATAUS 44
'*****END Defines*****

ADCON0.0 = 0 ' A/D Converter module is disabled
ADCON1 = $0F ' %0000 1111 AN2=VSS, AN3=VDD, AN12-0 = Digital
ADCON2 = $00 ' %0000 0000
TRISA = 0
TRISB = 0
TRISC = 0
TRISD = 0
TRISE = 0


string var byte[20] ' because I assume it’s one line of a 2x20 display but you can change this
character var byte ' the current character
counter var byte ' a step counter and index
lindex var byte ' a lookup table index

' Initialize LCD
Low PORTE.2 ' LCD R/W low = write
Pause 100 ' Wait for LCD to startup

LCDOUT $fe,1,"Startup"
pause 1000



start:
lindex = 0
lcdout $fe,1 'CLEARLCD it’s been a while since I looked at LCDOUT, but whatever two byte code to clear LCD and home.

cycle:
lcdout $fe, $02 'HOMELCD it’s been a while since I looked at LCDOUT, but whatever two byte code to home LCD cursor.
gosub lookuptable
lindex = lindex + 1 ' increment lookup index
if lindex > 37 then ' limit lookup index to length of message
lindex = 0
endif
gosub rotatearray ' rotate line with new character at zero index

for counter = 0 to 19 ' print the line to lcd
LCDOUT string[counter]
next counter
pause 1000 ' delay to see one movement per second

goto cycle ' do cycle forever


lookuptable: ' get the next character from the table into the character buffer
LOOKUP lindex,["CHECK IT OUT A SCROLLING TEXT DEMO!!! "],character ' 0-37 length message (38 characters in Human talk)
return

rotatearray: ' rotate line array
for counter = 0 to 18 step 1
string[counter] = string[counter+1]
next counter
string[19] = character
return

Art
- 3rd February 2015, 03:05
Lol, thanks, there will always be something off when you don’t actually run it :D

Thing is I was reading about string support in the wish list section and thought to myself
a string is just a character array with a zero value at the end of it.
All of the C functions: string length, string compare, sprint, etc. can all be written into BASIC easily.

ozarkshermit
- 3rd February 2015, 14:01
Thanks to all the responses.

Eventually I came up with the lookup table approach, sending one character at a time, and of course it works. The display was just too "jerkey" for my tastes.

In all the various scrolling approaches linked to, none of them use a "conventional" scroll on a 4 line LCD, and prohibit the scroll from "wrapping" to line 3.

Disabling the "line wrap" simply is not possible, IMHO.

Ken

Art
- 4th February 2015, 01:17
I’m not sure what you mean there by “disabling line wrap not possible”.
Did you get what you want done?

ozarkshermit
- 4th February 2015, 13:18
Thanks Art

See my first post in this thread. I have not been able to accomplish that

Ken

Art
- 4th February 2015, 14:59
The way I read it, that should be what the version Tabsoft posted does.
I might be seeing something else in my mind, or does it just scroll the wrong direction?

Basically, this could be written simpler if it never had to be a real program.
You could ditch the line buffer and rotate routine, step the index where you read the lookup table,
check it’s bounds, and write 20 char to LCD at a time directly to LCD.

Usually you want to look at, or change the display data, so I’d normally prepare
all lines of text in buffers, and write all four lines from the line's start positions for every frame.
even if the text doesn’t change or move.
If you never write past the end of a line the text can’t wrap.

Tabsoft
- 11th February 2015, 17:03
Carrying on with what Art mentioned previously.
I looked pretty closely at the LCD controller and can not find away to disable the line wrapping when you use a shift command.
Looks like that is the way the controller works.

That being said I put together this program that will shift the message from Right to Left.
See if this helps.



'************************************************* ***************
'* Name : LCDScroll_v1.pbp *
'* Author : TABSoft *
'* Notice : Copyright (c) 2015 TABSoft *
'* : All Rights Reserved *
'* Date : 2/6/2015 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************

'*****PIC MCU Configuration Fuses (MPASM)*****
#IF __PROCESSOR__ = "18F4620"
#CONFIG
CONFIG OSC = ECIO6 ; EC oscillator, port function on RA6
;CONFIG OSC = INTIO67 ; Internal oscillator block, port function on RA6 and RA7
;CONFIG WDT = OFF ; WDT disabled (control is placed on the SWDTEN bit)
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled
CONFIG IESO = OFF ; Oscillator Switchover mode disabled
CONFIG PWRT = OFF ; PWRT disabled
CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
CONFIG BORV = 3 ; Minimum setting
CONFIG WDT = ON ; WDT enabled
CONFIG WDTPS = 512 ; 1:512
CONFIG CCP2MX = PORTC ; CCP2 input/output is multiplexed with RC1
CONFIG PBADEN = OFF ; PORTB<4:0> pins are configured as digital I/O on Reset
CONFIG LPT1OSC = OFF ; Timer1 configured for higher power operation
CONFIG MCLRE = ON ; MCLR pin enabled; RE3 input pin disabled
CONFIG STVREN = ON ; Stack full/underflow will cause Reset
CONFIG LVP = OFF ; Single-Supply ICSP disabled
CONFIG XINST = OFF ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
CONFIG DEBUG = OFF ; Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
CONFIG CP0 = OFF ; Block 0 (000800-003FFFh) not code-protected
CONFIG CP1 = OFF ; Block 1 (004000-007FFFh) not code-protected
CONFIG CP2 = OFF ; Block 2 (008000-00BFFFh) not code-protected
CONFIG CP3 = OFF ; Block 3 (00C000-00FFFFh) not code-protected
CONFIG CPB = OFF ; Boot block (000000-0007FFh) not code-protected
CONFIG CPD = OFF ; Data EEPROM not code-protected
CONFIG WRT0 = OFF ; Block 0 (000800-003FFFh) not write-protected
CONFIG WRT1 = OFF ; Block 1 (004000-007FFFh) not write-protected
CONFIG WRT2 = OFF ; Block 2 (008000-00BFFFh) not write-protected
CONFIG WRT3 = OFF ; Block 3 (00C000-00FFFFh) not write-protected
CONFIG WRTC = OFF ; Configuration registers (300000-3000FFh) not write-protected
CONFIG WRTB = OFF ; Boot Block (000000-0007FFh) not write-protected
CONFIG WRTD = OFF ; Data EEPROM not write-protected
CONFIG EBTR0 = OFF ; Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
CONFIG EBTR1 = OFF ; Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
CONFIG EBTR2 = OFF ; Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
CONFIG EBTR3 = OFF ; Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
CONFIG EBTRB = OFF ; Boot Block (000000-0007FFh) not protected from table reads executed in other blocks

#ENDCONFIG
#else
#ERROR "This program requires a PIC 18F4620 MCU"
#endif

OSCCON = $60 ' Set PIC to 4Mhz & ECIO Clock Mode

DEFINE OSC 4
ADCON0.0 = 0 ' A/D Converter module is disabled
ADCON1 = $0F ' %0000 1111 AN2=VSS, AN3=VDD, AN12-0 = Digital
ADCON2 = $00 ' %0000 0000
TRISB = %11111111 ' Set PORTB as input
INTCON2.7 = 0 ' Enable PORTB pullups
TRISC = TRISC & %11011111 ' Set PORTC pin directions (pin5 output to RTC VCC2)


'*****Define LCD registers and bits*****
define LCD_BITS 4 '8 '4
define LCD_LINES 2 ' Set to number of lines for the LCD
Define LCD_DREG PORTD
Define LCD_DBIT 4 '0 '4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
define LCD_RWREG PORTE
define LCD_RWBIT 2
define LCD_COMMANDUS 1500
define LCD_DATAUS 44

'
' Software Constants
'
LastLCDCol con 19
' number of Columns in your LCD

'
' Software variables
'
LCD_Line1 var byte [50] 'Array to hold the Line 1 LCD Message (0 to 49)
L1_ArrayLen var byte 'Length of LCD Line 1 Message Array
StartPos var byte 'Pointer to start of message in Array
idx var byte 'Current index into Message Array
MaxCount var byte 'Loop counter max number
LoopCount var byte 'Loop Counter
i var byte


'*****Intialize Variables*****
L1_ArrayLen=50

'*****Initialize LCD Line 1 Message Array*****
arraywrite LCD_Line1, ["This is a test of the scrolling text screen...... "]


'*****Initialize LCD*****
Low LATE.2 ' LCD R/W line low (W)
Pause 500 ' Wait .5 second for LCD to Initialize


'
' Program
'


mainloop:
MaxCount = 81
LoopCount = 0
StartPos = 0

do
lcdout $FE, $80
LoopCount = LoopCount + 1
for i = 0 to LastLCDCol
idx = StartPos + i
if idx > (L1_ArrayLen - 1) then
idx = (idx // L1_ArrayLen)
endif
lcdout LCD_Line1(idx)
next i
StartPos = StartPos + 1
if StartPos > (L1_ArrayLen - 1) then
StartPos = 0
endif
pause 500 'Adjust for best scrolling appearance
loop while LoopCount < MaxCount
pause 250
goto mainloop 'Do it forever

end 'Got here by mistake

ozarkshermit
- 24th February 2015, 12:56
Thanks TABSoft

Sorry for the late response

Ken