PDA

View Full Version : Maximun Cable Length for PIC to LCD



wildbilly
- 27th November 2007, 16:15
Hello all, I have just finished a project which includes displaying on three LCD displays. Thanks to a great method by Darrel Taylor. http://www.pbpgroup.com/files/2_LCDs.gif
His idea works fantastic. What is the maximum cable length of cable that can be used between Pic and LCD? I have all the three LCD working close to the PIC but 20 feet away I get gibberish. Am I just stuck with a shorter length of cable or is there a work a around.

Thanks.

KVLV
- 27th November 2007, 18:12
i guess max around 2feet for TTL level. if you require longer length i suggest using serial lcd.

Darrel Taylor
- 28th November 2007, 18:27
wildbilly,

Great, glad that's working for you.

I can't answer the main question, as I've never tried to go more than a couple inches to an LCD.
But, I'll agree that serial might be a better way.

However, I think there's two possible sources for the garbled text. And I might be able to do something about one of them if you still want the parallel interface.


PBP sends everything out to the LCD at the MINIMUM pulse widths defined in the HD44780 datasheet. Which means approximately 1 Mhz squarewave signals since the enable pulse only lasts 1 uS. That's going to be tuff to get through 20 feet of ribbon cable.
<br>
The other source could be inductive pick-up, like an antenna.
Can't help much if that's the case.


If the problem is #1? It may be possible to slow down the LCD data to a point that will propagate thru the long ribbon.

Using the technique described in the LCD_Anypin thread (http://www.picbasic.co.uk/forum/showthread.php?t=7038), we could create whatever timing is required to slow it down to a reasonable speed.

If you want to try, let me know.
You'll have to do the testing though.
<br>

wildbilly
- 28th November 2007, 20:07
Thank you KVLV. I think you are correct about using serial instead. It would be nice though to be able to use the parallel interface. I do enjoy a challenge and it keeps PicBasic interesting.
Thanks Darrel, I have read the LCD_Anypin thread and that is very interesting. I am up for the leg work. I am willing to try and I will do all the testing required.

Thank you.

Ioannis
- 28th November 2007, 20:16
....
2. PBP sends everything out to the LCD at the MINIMUM pulse widths defined in the HD44780 datasheet. Which means approximately 1 Mhz squarewave signals since the enable pulse only lasts 1 uS. That's going to be tuff to get through 20 feet of ribbon cable.

....


Well in this case, I would suggest to use double the number of flat cable wires and the middle ones connected to the ground point. It won't eliminate the problem but will help for sure.

Ioannis

mister_e
- 28th November 2007, 20:36
at very least, if you really want to waste that amount of cable, place some cap close of the LCD VDD/GND (47uF (or greater) + 10 uF tantalum and finally 0.1 uF ceramic)

I don't think there's a real problem with the length of cable so far, my feeling is that you just need to filter the Vdd rail properly at the end and probably play with COMMANDUS & DATAUS DEFINEs.

Darrel Taylor
- 28th November 2007, 23:25
I am up for the leg work. I am willing to try and I will do all the testing required.

Shouldn't take much, but you'll need to install the HighJack routines first.
And you'll also be using the LCD_Anypin files, so download them too.

Start with that, and you should be able to get the LCD working on a Short cable first.

After that, we'll adjust the delays and see what happens on a long one.
If you have any problems getting LCD_Anypin to work, let me know.
<br>

w7ami
- 29th November 2007, 17:04
wildbilly,

It should be possible to send data over 20 feet to your display and have it work, but not using ribbon cable. All the conductors are parallel to each other and divided by insulation. In other words you have a bunch of capacitve coupling between the lines. Also the ribbon cable is likely not shielded so any manner of garbage will be picked up from the nearby environment. I have an absolute encoder (10 lines of TTL data) working over a distance of 50 feet in a high RF environment.

First as stated earlier make sure you have cleaned up the power to the LCD with good bypass capacitors with short lead length. You will need to put the displays in some sort of metal box. Then use a shielded cable with twisted pairs (signal and ground on each pair) between the two units. Then if you are still having problems mess with the pulse widths.

Terry

wildbilly
- 1st December 2007, 20:09
Hello all. As W7AMI suggested, I have tried filtering the supply and I have changed the cable to shielded pairs but no luck. Darrel I have installed the Highjack routines and also included the LCD_Anypin.pbp and VirtualPort.bas in the PBP folder. I then added the Include file in my main program just below the define Parameters.

INCLUDE "LCD_AnyPin.pbp"
I am using MicroCode Studio and when compile is run I get the error
Line 87:Bad expression. (LCD-AnyPin.pbp)
The LCD_AnyPin file is opened and the line LOW LCD_RS : HIGH LCD_E is highlighted causing the error. I have included two images. The green Display is connected on the short cable and the Blue Display is connected to the long cable. As you can see blue is not displaying what the green is and the character on the blue display is constantly changing.

Charles Linquis
- 1st December 2007, 20:25
I think the problem is that it is just plain too cold where you live!

wildbilly
- 1st December 2007, 20:37
That's a good laugh. I thought someone would have that reply.

Darrel Taylor
- 1st December 2007, 21:39
Darrel I have installed the Highjack routines and also included the LCD_Anypin.pbp and VirtualPort.bas in the PBP folder. I then added the Include file in my main program just below the define Parameters.

Excellent!

Does your main program have this section (modified for your hardware of course).
The old lcd DEFINES can be commented out.

;----[ Change these to match your LCD ]---------------------------------------
</i></b></font><b>LCD_DB4 </b><font color="#008000"><b>VAR </b></font><b>PORTA</b>.<font color="#800000"><b>0
</b></font><b>LCD_DB5 </b><font color="#008000"><b>VAR </b></font><b>PORTB</b>.<font color="#800000"><b>3
</b></font><b>LCD_DB6 </b><font color="#008000"><b>VAR </b></font><b>PORTB</b>.<font color="#800000"><b>7
</b></font><b>LCD_DB7 </b><font color="#008000"><b>VAR </b></font><b>PORTC</b>.<font color="#800000"><b>1
</b></font><b>LCD_RS </b><font color="#008000"><b>VAR </b></font><b>PORTD</b>.<font color="#800000"><b>4
</b></font><b>LCD_E </b><font color="#008000"><b>VAR </b></font><b>PORTA</b>.<font color="#800000"><b>1
</b></font><b>LCD_Lines </b><font color="#008000"><b>CON </b></font><font color="#800000"><b>2 </b></font><font color="#0000FF"><b><i>' # of Lines on LCD, 1 or 2 (Note: use 2 for 4 lines)
</i></b></font><b>LCD_DATAUS </b><font color="#008000"><b>CON </b></font><font color="#800000"><b>50 </b></font><font color="#0000FF"><b><i>' Data delay time in us
</i></b></font><b>LCD_COMMANDUS </b><font color="#008000"><b>CON </b></font><font color="#800000"><b>2000 </b></font><font color="#0000FF"><b><i>' Command delay time in us

</i></b></font><font color="#008000"><b>INCLUDE </b></font><font color="#FF0000">&quot;LCD_AnyPin.pbp&quot; </font><font color="#0000FF"><b><i>; *** Include MUST be AFTER LCD Pin assignments ****</i></b></font>

wildbilly
- 1st December 2007, 23:08
Hi Darrel. I added the list below and no longer have the error but no longer have a display on
the LCD. I only have two black bars.

'LCD_DB4 VAR PORTB.0
'LCD_DB5 VAR PORTB.1
'LCD_DB6 VAR PORTB.2
'LCD_DB7 VAR PORTB.3
'LCD_RS VAR PORTB.4
'LCD_E VAR PORTB.7

The list below works fine.

'LCD Parameters
'============
DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' LCD Register Select bit
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 7 ' LCD Enable bit
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' Number of lines on LCD
DEFINE LCD_COMMANDUS 2000 'Command delay time in us
DEFINE LCD_DATAUS 50 'Data delay time in us

My LCD is connected just like your example " http://www.pbpgroup.com/files/2_LCDs.gif

Darrel Taylor
- 1st December 2007, 23:59
Bummer,

OK, let me re-create it here.
Back at ya soon.
<br>

Darrel Taylor
- 2nd December 2007, 03:18
OK,

Just to make sure, I went thru the steps again myself.
Have it working here on a 16F88. One thing I had to add that wasn't mentioned here, although it was in the other thread ...
PAUSE 500 : LCDOUT $FE,1 : PAUSE 250 ; Initialize LCD (You may not need this,
; but some displays are picky)


But so that I can compare Apples to Apples, What PIC are you using?

I bought 25ft of ribbon today, just to make sure. But haven't hooked it up yet.

wildbilly
- 2nd December 2007, 03:22
I added the code
PAUSE 500 : LCDOUT $FE,1 : PAUSE 250 ; Initialize LCD
with the same result. I am using the 16F877a

Darrel Taylor
- 2nd December 2007, 06:38
Apples it is .. :)

Built a 16F877A breadboard. With LCD on the above mentioned ports.
Still haven't hooked up the ribbon yet, just wanted 1 LCD at this point.

Here's the Breadboard.
http://www.pbpgroup.com/files/wildbilly_BB_sm.JPG (http://www.pbpgroup.com/files/wildbilly_BB_Lrg.JPG)
Click image to enlarge

And here's the program it's running.
@ __config _HS_OSC & _WDT_OFF & _LVP_OFF & _CP_OFF

ADCON1 = 7
CMCON = 7

DEFINE OSC 4

;----[ Change these to match your LCD ]---------------------------------------
LCD_DB4 VAR PORTB.0
LCD_DB5 VAR PORTB.1
LCD_DB6 VAR PORTB.2
LCD_DB7 VAR PORTB.3
LCD_RS VAR PORTB.4
LCD_E VAR PORTB.7
LCD_Lines CON 2 ' # of Lines on LCD, 1 or 2 (Note: use 2 for 4 lines)
LCD_DATAUS CON 50 ' Data delay time in us
LCD_COMMANDUS CON 2000 ' Command delay time in us

INCLUDE "LCD_AnyPin.pbp" ; *** Include MUST be AFTER LCD Pin assignments ****

PAUSE 500 : LCDOUT $FE,1 : PAUSE 250 ; Initialize LCD (You may not need this,
; but some displays are picky)

LCDOUT $FE,1,"Hello wildbilly",$FE,$C0,"Must be something",$FE,$94,"In the Hardware"

Main:
; toggle LED
pause 1000
goto Main

Can you see anything I've done different??
<br>

wildbilly
- 2nd December 2007, 13:57
Your apple must be the Macintosh because yours is working and mine is not.
Ok, here is what I have found. I have loaded your code to a new main program and could not compile it. I am getting this error: "opcode expected instead of '_config' "
for this line @ __config _HS_OSC & _WDT_OFF & _LVP_OFF & _CP_OFF

and I get these errors for this line : INCLUDE "LCD_AnyPin.pbp"
"opcode expected instead of 'writeport' "
"opcode expected instead of 'delayus' "
"opcode expected instead of 'outputport' "

I have checked the Hijack code included in the PBPPIC14.lib file and I think it was modified correctly. Any clues?

Thanks

Darrel Taylor
- 2nd December 2007, 19:39
I am getting this error: "opcode expected instead of '_config'
Ah Ha, You aren't using MPASM as the assembler.

Almost anything written with ASM mixed in the program, needs to be compiled with MPASM. The assembler that comes with PBP is OK for PBP itself, but it just doesn't have the capabilities needed for ASM, even though sometimes it will compile OK.

Here's a hex file for mine if you want to try it.
If yours isn't runnung at 4Mhz, I'll change it to your crystal.
<br>

Ioannis
- 2nd December 2007, 20:12
Apples it is .. :)

Built a 16F877A breadboard. With LCD on the above mentioned ports.
Still haven't hooked up the ribbon yet, just wanted 1 LCD at this point.
<br>

I can't add anything more on Darrels suggestions, but have to admit that the breadboard is very tidy good looking! An art in breadboarding!

The background that seems like a pcb, what is it?

Ioannis

Darrel Taylor
- 2nd December 2007, 20:58
Thanks for noticing Ioannis,

The first breadboard I ever bought came with a box of 3M pre-cut jumpers.
I just thought that's the way it's supposed to be done.

Thanks to my "Glowing Eyed Monsters" (http://www.picbasic.co.uk/forum/showthread.php?p=31448),
I also learned to trim the leads off of the parts so they sit flat on the breadboard.
There's another breadboard of mine in that thread too. Same style.

I never knew how bad a breadboard could be till I ran across this ... :eek:
http://cs.nyu.edu/~jhan/ledtouch/
<br>

wildbilly
- 2nd December 2007, 20:59
Yeah! He is indeed very neat. I am inspired to do the same. The background looks like a chair seat. Darrel your wildbilly.hex file ran ok. I have never used MPASM. I should try and get it going.

Thank you.

Darrel Taylor
- 2nd December 2007, 21:25
The background looks like a chair seat.

DING! Give that man a cigar. :)
I forgot to answer it. oops.


I have never used MPASM. I should try and get it goingJust go here... at the bottom of the page, install the MPLAB IDE v8.00 Full Release Zipped Installation
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002

Are you using MicroCode Studio for the IDE?
<br>

mister_e
- 2nd December 2007, 21:40
one of the less neat prototype i've never ever saw ...
http://www.botmag.com/articles/bionic_stamp.shtml

:D

wildbilly
- 3rd December 2007, 00:23
Hi Darrel. I am using Microcode Studio.

Darrel Taylor
- 3rd December 2007, 00:47
Great. That makes it easy.

After installing MPLAB ...

In MCS, go to the View | Compile and Program Options | Assembler Tab

Click the Find Manually ... button and point it to
C:\program files\microchip\mpasm suite

Then check the Use MPASM checkbox.

You should be good to go.
<br>

Darrel Taylor
- 3rd December 2007, 00:55
OOPs, one more thing to get that to compile.

In your PBP folder, open the 16F877A.INC file, and comment out the __config line with a semicolon ;

Now you should be good to go.


mister_e,

At least now I know where to go if I need some extra wire.
Sheesh. :)
<br>

wildbilly
- 3rd December 2007, 02:40
Hi Darrel. I have installed MPLAB IDE v8.00 Full Release and setup was done as mentioned.
Now when compiled I get the MPASM window showing the process and then shows 18 errors.
This goes by very fast and starts green and then goes red. The errors are similar to what I had before. Here are a few. I have omitted the path for each error.

205 : Found label after column 1. (WritePort)
205 : Illegal opcode(_Char)
234 : Illegal opcode(_LCD_DATAUS)
249 : Found label after column 1.(DelayUS)
267 : Illegal opcode(LCD_COMMANDUS)

and many more

Darrel Taylor
- 3rd December 2007, 03:24
Arrrrgh!

Sorry to put you thru all this, it shouldn't be that hard.

I can't really say what's happening from the errors you showed.
I could probably see what's wrong if you could send the .LST file.

It'll be too big to post, but you could email it to
darrel at pbpgroup.com

It should've worked :o
<br>

nomad
- 3rd December 2007, 13:08
you all must have cringed when i posted my first blinky on bread board. lol mine are true ratsnests. guess it's time to buy some neato jumpers and stop being a disgrace. sniff lol

mister_e
- 3rd December 2007, 15:11
mister_e,

At least now I know where to go if I need some extra wire.
Sheesh. :)
<br>

Have a look at the last lines of the link... About The Author.. :eek: i'm afraid

mackrackit
- 3rd December 2007, 15:54
Have a look at the last lines of the link... About The Author.. i'm afraid

And to think I did not have to go to school to be that messy:)

dideco
- 4th December 2007, 09:10
A CMOS chip as a buffer (such as 4050) can be added to the parallel cable to use longer wires. Also some resistors will help to make a kind of current loop by placing 2.2-4.7 Kohms close to inputs of the LCD unit.

LCD_Lines CON 2 ' # of Lines on LCD, 1 or 2 (Note: use 2 for 4 lines)
LCD_DATAUS CON 50 ' Data delay time in us
LCD_COMMANDUS CON 2000 ' Command delay time in us

"Data delay time" should be longer, such as 500 microseconds or longer. This will help the commads to reach display safely. Pulse decreases because of cable capacitance and resistance (RC time constant). LCD displays can load data in its register buffers in a very short period but cannot execute it as fast as loading. Thats why command delay time is 40 times longer.

wildbilly
- 8th December 2007, 19:06
Thanks Dideco for your input, I will carry on with Darrel's method for now as I find it quite interesting and I have been at it for a while. Darrel, here is what I have found so far. I have been able to get your Hijack routines to work without any errors. I am now able to see a perfect display on long lengths of cable. I have tried 20 to 40 ft of 22 awg multi-cable and the display is perfect. I did not need to adjust any delays. I have not been able though, to get the displays to switch properly using the method you described for your 2 LCD's on one pic display method. Have a look at Display_1 and you will see the display is correct using your sample code. On Display_2 you will notice that there are problems on both displays when using the hijack routines.

Thanks.

Darrel Taylor
- 8th December 2007, 20:43
HI wildbilly,

Sounds like your up to speed with me now. http://www.picbasic.co.uk/forum/images/icons/icon14.gif

I've been bogged down all week with work, so I'm kind of glad you had problems.
I'm sure it's not the same from your point of view.

So anyhow, I've found that the resistors used to select each display seem to act as a filter with the extra capacitance of the ribbon. The enable line gets rounded off pretty bad.

Fortunately, with "HighJack", we're not limited to just one Enable pin anymore.
We can have as many as needed. And that's the next step.

We'll use the previous "Disable" pins as the "Enable" line for each LCD. The resistors are no longer needed. Then instead of Disabling the display you don't want to write to, you'll Enable the one's you do want.

This takes a few modifications, but it's not too bad.

First, in the main program, change the LCD definitions to this ...
;----[ Change these to match your LCD ]---------------------------------------
LCD_DB4 VAR PORTB.0
LCD_DB5 VAR PORTB.1
LCD_DB6 VAR PORTB.2
LCD_DB7 VAR PORTB.3
LCD_RS VAR PORTB.4

LCD_E1 VAR PORTB.5
LCD_E2 VAR PORTB.6
LCDEN VAR BYTE BANK0 ; Enable bits for each LCD
LCD1EN VAR LCDEN.0
LCD2EN VAR LCDEN.1

LCD_Lines CON 2 ; # of Lines on LCD, 1 or 2 (Note: use 2 for 4 lines)
LCD_DATAUS CON 50 ; Data delay time in us
LCD_COMMANDUS CON 2000 ; Command delay time in us

INCLUDE "LCD_AnyPin.pbp" ; *** Include MUST be AFTER LCD Pin assignments ****

LOW LCD_E1 ; Start with Enables OUTPUT LOW
LOW LCD_E2


Next, in the LCD_AnyPin file, there's a section that says "DO NOT Change anything below this line".
Change it to this ... :)

ASM
LCD_Port_HNIB macro ; Port definition for LCD High Nibble
Vbit LCDCDFLAG, _LCD_RS ; Select Command/Data register
DelayUS 2
NOP
Vpin 4, _LCD_DB4 ; Put the High Nibble on the bus
Vpin 5, _LCD_DB5
Vpin 6, _LCD_DB6
Vpin 7, _LCD_DB7
DelayUS 2

btfsc _LCD1EN ; Set enable(s) High
bsf _LCD_E1
btfsc _LCD2EN
bsf _LCD_E2
DelayUS 5 ; hold for 5us
bcf _LCD_E1 ; Enable(s) Low - Clocks data
bcf _LCD_E2
endm
;-----------------------
LCD_Port_LNIB macro ; Port definition for LCD Low Nibble
Vpin 0, _LCD_DB4 ; Put the Low Nibble on the bus
Vpin 1, _LCD_DB5
Vpin 2, _LCD_DB6
Vpin 3, _LCD_DB7
DelayUS 2

btfsc _LCD1EN ; Set enable(s) High
bsf _LCD_E1
btfsc _LCD2EN
bsf _LCD_E2
DelayUS 5 ; hold for 5us
bcf _LCD_E1 ; Enable(s) Low - Clocks data
bcf _LCD_E2
endm
ENDASM


And finally, also in the LCD_AnyPin file, change LCD_Init to this ...
;----[Initialize the LCD]-------------------(DO NOT Change)-------------------
LCD_Init:
@ OutputPort LCD_Port_HNIB ; Set LCD bus to OUTPUT
LCDEN = 1 + 2
LOW LCD_RS ; Start with RS LOW
Char = 3 : gosub LCDsendShortCOM : @ DelayUS 6000
gosub LCDsendShortCOM : @ DelayUS 1000
gosub LCDsendShortCOM : @ DelayUS 1000
Char = 2 : gosub LCDsendShortCOM : @ DelayUS 1000 ; Start 4-bit mode
Char = $28 : gosub LCDsendCOM ; Function Set, 4-bit, 2-line, 5x7
Char = $0C : gosub LCDsendCOM ; Display ON
Char = $01 : gosub LCDsendCOM ; Clear Screen
Char = $06 : gosub LCDsendCOM ; Entry Mode
LCD_Initialized = 1 ; LCD has been Initialized
goto LCDAfterInit


http://www.pbpgroup.com/files/100_0279_sm.JPG (http://www.pbpgroup.com/files/100_0279.JPG)
Click image to enlarge.

P.S. Until now I thought that 6 inches was the limit for LCD's. Just because somebody told me that once.
This is really cool. Thanks for the interesting things to play with.<hr>

ADDED: Oops, forgot to show you how to use it..
LCDEN = 1
LCDOUT $FE,1, "Display 1"

LCDEN = 2
LCDOUT $FE,1, "Display 2"

LCDEN = 1 + 2
LCDOUT $FE,$C0, "Both Displays"

wildbilly
- 9th December 2007, 03:47
Thanks Darrel. I have it working. I just need to check it again on the long cable. The displays are flashing. How do I stop that? I suppose that is something in the "LCD_AnyPin" file.

Darrel Taylor
- 9th December 2007, 03:52
If it's a Fast Flash?
Are the LCDOUT statements running in a loop?

If so, try using $FE,$80 instead of $FE,1
<br>

wildbilly
- 9th December 2007, 04:14
Thanks Darrel. That did it. I will check the long cable in the morning. Thank you for your help.

wildbilly
- 9th December 2007, 04:18
I am going to try and add a third display. I will let you know how I make out. In your original sample code I had modofied it for three displays and it worked ok. I will give it a try.

Darrel Taylor
- 9th December 2007, 10:10
<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=2185&stc=1&d=1197194944" />

Ioannis
- 10th December 2007, 07:08
Hi Darrel!

How long is that flat cable on the second LCD? It seems really long!

Ioannis

Darrel Taylor
- 10th December 2007, 07:15
25 Ft.

I think wildbilly's going to run it at 40 Ft.
<br>

Ioannis
- 10th December 2007, 07:33
That's impressive! About 8,5 meters! Lets see what wildbilly will do on the 40ft.
Great code Darrel.

Ioannis

wildbilly
- 28th December 2007, 17:52
Merry Christmas to all and a happy new year. Hi Darrel. I have not been able to do much since you gave me the "Hex". Remember those two fingers? OK, seriously your code works flawlessly. I have been able to run both LCD's on 40ft of cable. Thanks very much for your time and code. I learned a lot this year from this forum, thanks to all especially Darrel.
Hopefully much more projects in the new year.

Darrel Taylor
- 28th December 2007, 20:16
That's Great wildbilly.
And Happy New Year to you too.

I was hoping it would go the 40ft. but wasn't sure.

Don't want to ruin it for you if you're still trying to do 3 LCD's, but I can show you how, if you give up. :)

regards,

wildbilly
- 29th December 2007, 20:00
Hi Darrel. I would like to know how to do 3 LCD's. I won't turn down a chance of learning more. Thanks

Darrel Taylor
- 31st December 2007, 08:23
OK, let's go with the learning ... idea ... :)

Here's the changes to add 1 more display to what we already have.
Mostly, it's just "more of the same".

These are the same 3 sections that were modified the last time.
New changes are in red ...

Main Program
;----[ Change these to match your LCD ]---------------------------------------
LCD_DB4 VAR PORTB.0
LCD_DB5 VAR PORTB.1
LCD_DB6 VAR PORTB.2
LCD_DB7 VAR PORTB.3
LCD_RS VAR PORTB.4

LCD_E1 VAR PORTB.5
LCD_E2 VAR PORTB.6
LCD_E3 VAR PORTD.0

LCDEN VAR BYTE BANK0 ; Enable bits for each LCD
LCD1EN VAR LCDEN.0
LCD2EN VAR LCDEN.1
LCD3EN VAR LCDEN.2

LCD_Lines CON 2 ; # of Lines on LCD, 1 or 2 (Note: use 2 for 4 lines)
LCD_DATAUS CON 50 ; Data delay time in us
LCD_COMMANDUS CON 2000 ; Command delay time in us

INCLUDE "LCD_AnyPin.pbp" ; *** Include MUST be AFTER LCD Pin assignments ****
LOW LCD_E1 ; Start with Enables OUTPUT LOW
LOW LCD_E2
LOW LCD_E3


LCD_AnyPin.pbp

ASM
LCD_Port_HNIB macro ; Port definition for LCD High Nibble
Vbit LCDCDFLAG, _LCD_RS ; Select Command/Data register
DelayUS 2
NOP
Vpin 4, _LCD_DB4 ; Put the High Nibble on the bus
Vpin 5, _LCD_DB5
Vpin 6, _LCD_DB6
Vpin 7, _LCD_DB7
DelayUS 2

btfsc _LCD1EN ; Set enable(s) High
bsf _LCD_E1
btfsc _LCD2EN
bsf _LCD_E2
btfsc _LCD3EN
bsf _LCD_E3
DelayUS 5 ; hold for 5us
bcf _LCD_E1 ; Enable(s) Low - Clocks data
bcf _LCD_E2
bcf _LCD_E3
endm
;-----------------------
LCD_Port_LNIB macro ; Port definition for LCD Low Nibble
Vpin 0, _LCD_DB4 ; Put the Low Nibble on the bus
Vpin 1, _LCD_DB5
Vpin 2, _LCD_DB6
Vpin 3, _LCD_DB7
DelayUS 2

btfsc _LCD1EN ; Set enable(s) High
bsf _LCD_E1
btfsc _LCD2EN
bsf _LCD_E2
btfsc _LCD3EN
bsf _LCD_E3
DelayUS 5 ; hold for 5us
bcf _LCD_E1 ; Enable(s) Low - Clocks data
bcf _LCD_E2
bcf _LCD_E3
endm
ENDASM



LCD_AnyPin.pbp

;----[Initialize the LCD]-------------------(DO NOT Change)-------------------
LCD_Init:
@ OutputPort LCD_Port_HNIB ; Set LCD bus to OUTPUT
LCDEN = %111 ; Initialize all LCD's at the same time
LOW LCD_RS ; Start with RS LOW
Char = 3 : gosub LCDsendShortCOM : @ DelayUS 6000
gosub LCDsendShortCOM : @ DelayUS 1000
gosub LCDsendShortCOM : @ DelayUS 1000
Char = 2 : gosub LCDsendShortCOM : @ DelayUS 1000 ; Start 4-bit mode
Char = $28 : gosub LCDsendCOM ; Function Set, 4-bit, 2-line, 5x7
Char = $0C : gosub LCDsendCOM ; Display ON
Char = $01 : gosub LCDsendCOM ; Clear Screen
Char = $06 : gosub LCDsendCOM ; Entry Mode
LCD_Initialized = 1 ; LCD has been Initialized
goto LCDAfterInit


And then, to use it.
It still works the same as before.
But now it's easier to treat the Enable bits like a binary number.
With each bit representing a different display ...

LCDEN = %001
LCDOUT $FE,$80, "Display 1"

LCDEN = %010
LCDOUT $FE,$80, "Display 2"

LCDEN = %100
LCDOUT $FE,$80, "Display 3"

LCDEN = %111
LCDOUT $FE,$C0, "ALL Displays"
And that should be it.<hr>
Now, Even though this all works fine ...
I don't like it.

After making all the changes to get 3 LCD's to work.
It's still limited to 3 LCD's.
If you want 4, then you have to go modify it again.
Then if you want to use 2 LCD's on another project. It'll throw a bunch of errors, that won't make sense 6 months from now.

Then there's the Timing options.
What if the cable is longer? Or shorter? How do you adjust the delays?

So what I've done, is create a new module that should incorporate everything learned here, and allow everyone to have up to 8 LCD's on long or short cables without to much hassle.

But it takes longer to post the thread, than it does to write the program. :eek:
And I Gotta work tomorrow too. :(

Feel free to use the code I just posted (it should work)
Or you may want to wait for my next post in the PBP Extensions forum. (day or two)<hr>
P.S. It's unfortunate that we still won't know the answer to your first question.

What is the maximum cable length of cable that can be used between Pic and LCD?
Uhhh, 40 ft, as far as we can say.
But who knows?
<br>

skimask
- 31st December 2007, 09:25
Question from the sidelines...maybe an idea...not sure...haven't looked into it yet...

Couldn't the LCDOUT command itself be 'hi-jacked' inside on of the macros to change the E line assignment dynamically? As far as I know, LCDs won't do squat unless the E line is pulsed.
Maybe something like:
LCDOUT $fe , $fe , 0 , "First LCD"
LCDOUT $fe , $fe , 1 , "Second LCD"
LCDOUT $fe , $fe , 2 , "Third LCD"
....and so on and so on...
As far as I know, there aren't any character LCDs any wider than 40 characters. If the second character in the 'string' was anything above $FC, it could be a 'hijack' command...
or something like that anyways...
As for myself, like I said before, I'm running 3 different types of LCDs on my OBD interface right now (16x2 parallel, 122x32 graphic mode, and a 130x130 Nokia color knockoff).
Guess which one is the easiest to interface with? :)

Darrel Taylor
- 31st December 2007, 11:07
Maybe something like:
LCDOUT $fe , $fe , 0 , "First LCD"
LCDOUT $fe , $fe , 1 , "Second LCD"
...

Sure,

With complete control of the LCDOUT command, you can do pretty much whatever you want.

And, It's not a bad idea.

So, with the existing code from this thread.
Changing the LCDsend routine like this ...
;----[Send a byte to the Virtual LCD PORT]------------(DO NOT Change)---------
TempChar var byte
Char VAR Byte
LCD_Initialized VAR FLAGS.1
RSS VAR FLAGS.0 ; LCD RS State
HJ_Command VAR BIT

;----[ This routine is called once for every character sent by LCDOUT ]-------
LCDsend:
@ MOVE?AB _TempChar ; Get char sent by LCDOUT, in WREG
if !LCD_Initialized then LCD_Init ; Make sure LCD was Initialized
LCDAfterInit:

IF HJ_Command then LCDEN = TempChar : HJ_Command = 0 : goto LCDsendDone
IF RSS then NO_HJcheck
IF TempChar = $FE then RSS = 1 : HJ_Command = 1 : goto LCDsendDone
NO_HJcheck:

if TempChar = $FE then RSS=0 : goto LCDsendDone ; next char is Command
Char = TempChar
LCDsendCOM:
@ WritePort _Char, LCD_Port_HNIB ; send the High Nibble
LCDsendShortCOM:
@ WritePort _Char, LCD_Port_LNIB ; send the Low Nibble

IF RSS = 0 then ; Is a Command
IF Char = 1 then CommandDelay ; Long delay for Clear Screen
IF Char = 2 then CommandDelay ; Long delay for Home
@ DelayUS _LCD_DATAUS ; Short delay for everything else
goto DelayDone
else
@ DelayUS _LCD_DATAUS ; Short delay for Data
goto DelayDone
endif
CommandDelay:
@ DelayUS _LCD_COMMANDUS
DelayDone:
if LCD_Initialized then RSS = 1 ; Set RS to Data next time
LCDsendDone:
return

Then you can embed the LCD selection inside the LCDOUT statements...

LCDOUT $FE,$FE,%001, $FE,$80, "Display 1"
LCDOUT $FE,$FE,%010, $FE,$80, "Display 2"
LCDOUT $FE,$FE,%100, $FE,$80, "Display 3"
LCDOUT $FE,$FE,%111, $FE,$C0, "ALL Displays"

And it still works the original way too. (Choices)

LCDEN = %001
LCDOUT $FE,$80, "Display 1"

LCDEN = %010
LCDOUT $FE,$80, "Display 2"

LCDEN = %100
LCDOUT $FE,$80, "Display 3"

LCDEN = %111
LCDOUT $FE,$C0, "ALL Displays"


Now I really gotta go to bed.

skimask
- 31st December 2007, 23:03
And, It's not a bad idea.
I get 'em once in a great while...


So, with the existing code from this thread.................
and here I spent the better part of a few hours last night messing with the core macros.
I'm digging this idea much better. (Yes, I said 'digging' :D)

Darrel Taylor
- 31st December 2007, 23:33
Maybe you'll Dig this idea too.

GLCD's using LCDOUT. :eek:
<br>

skimask
- 1st January 2008, 10:03
Maybe you'll Dig this idea too.

GLCD's using LCDOUT. :eek:
<br>

Well, I don't exactly use LCDOUT for the GLCD, but I do the 'printstr' from awhile back to do the display with it, and I modified a version for the Nokia ('printstr2', original eh?), and I used that 'copystr' from awhile back, modified another couple of versions into 'printvar' and 'printvar2', defined a dedicated string, use it only with those macros, handle it outside of the printvar routines, and send it out when I want it, along with the x,y. Works for me...

I suppose it wouldn't be that hard, relatively speaking anyways, to hijack the lcdout command further...maybe a predefined types (i.e. DEFINE LCDTYPE $00 ; low nybble = lcd number, high nybble = lcd type, this case, first lcd, parallel, another case DEFINE LCDTYPE $11; low nybble = second lcd, high nybble = 122x32,SED1520 type, and so on...).

Great...more crap to do...

Question: How would one go about turning this sort of thing into a 'One Stop Shop' solution for extending PBP's capabilities? One that wouldn't involve modifying libraries, macro sets, or other files... A single include file or would this involve some sort of remaking the compiler itself? Those printstr and printvar macros I've got are all in-line with my normal code in all my programs. Yes, those could easily be done with a single 'include' file. But, would there be an easy way to add these 'extensions' by default? Not only for this LCD modification, but for the matrix keypad, SD card access, IDE access, '1820 reading, etc?

mister_e
- 1st January 2008, 19:00
that would be really nice indeed... i think it's more a pre-compiler option, not sure how Melabs could give such compiler access... i know an automated solution, but, it's still in http://www.mister-e.org/Pics/MisterE stage.

Yeah, there's a lot of new things in MisterE land to come in 2008.