Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Extra safe LCD module interface circuitry.

Status
Not open for further replies.

()blivion

Active Member
Hello all, getting directly to the point...

A while back, I was developing a project that used a PIC and a LCDM together, and for no apparent reason the two devices destroyed each other. After investigating the situation, I could only conclude that my PIC asm code must have made a port pin zig when it should have zaged. In other words, one line was logic high on one end of the wire, and logic low on the other. With both push-pull drivers having low-Z and thus nothing to stop massive current from flowing, mutual destruction of the die for each IC in sued.

This unfortunate incident got me thinking about how I had the PIC attached to the LCDM directly and how to go about changing the interface to make it intrinsically safe should such code failure ever happen again. Here is a picture of the I/O circuit for the chip out of the STU066U datasheet. . . I assume the PIC I/O is similar.

View attachment 68884

I was thinking about just a 500~1000 Ohm resistor in series with all the lines to limit current to the max each driver should be able to handle. But I'm worried about slew rate and impedance matching and such things, though I honestly don't know if that will apply to something like this. It can only run at >500Khz I believe, but don't quote me. It's in the datasheet I'm sure.

Any incite and useful advice would be appreciated. Thanks for your time.
-()b
 
Last edited:
All of the lines on an LCD are normally inputs unless you want to read from the LCD memory. This isn't normally used, so if R/W (read/write) is tied to ground, it should operate as expected and it will never be configured with outputs.

In my experience, LCD modules take a lot of abuse without complaint. No harm came to the module while troubleshooting when I forgot to tie R/W to ground....it just didn't work until I corrected the problem.
 
OK, so.... I'm not an expert in this particular field of EEing, but here is what I have figured to fix the problem so far, let me know if this looks incorrect at all.

According to the datasheet, the fastest timing requirement for the receiving circuit is the "E" pin, with a maximum Vih-Vil -> rise/fall time of 25ns. So it looks like the slowest a pin can ever transition from 0.6V to 3.5V and vice versa (5V supply) is in 25ns or less. Here is an amalgamation of all the relevant data and charts from the datasheet that I used to come to this conclusion.

View attachment 68898

My solution and preliminary simulation shows that a 4K7 ohm resistor with a 1nF speed up cap in parallel allows for this transition time with a wide range of stray capacitance's, inductance's, and frequency's, while still limiting any prolonged DC current to ~1mA. Here is a schematic of my solution and the simulation showing the results. If you can think of anything that looks wrong with this, please let me know.

View attachment 68899

Notes:
(1) The left half of the circuit is simulating a PIC output driver running at 1Mhz.
(2) The switch on the driver is to simulate a soft fault that leads to current sinking.
(3) The inductor and capacitors on the left represent the minimum stray values expected.
(4) The center is the current limit resistor and speed up cap. The 50m R is for the sim.
(5) The inductor and capacitors on the right represent the maximum stray values expected.
(6) The right is to simulate a High-Z input, with pull-up. The switch is to simulate fault.
(7) The 1 Ohm resistors on Vin are there because the sim simulates infinite current.
(8) The smallest grid square in the scope view is 10ns horizontal, 1 volt vertical.
 
Last edited:
I was/am reading from the LCDM. (polling the busy flag)

My advice would be don't do that. Apart from the extra complication in code you also need to switch the PIC data pins from outputs to inputs etc, which is another chance of things going bad if your code has issues.

Just drive the LCD as "dumb" from outputs only and make sure you allow a little bit of time for those few operations that require time.

Regarding the transition times for the LCD E pin etc, just driving it from a PIC output should work fine, there's no need for special driving circuitry. In the event that your LCD needs to be quite far from the PIC you can use a serial LCD and send serial comms or put another small PIC at the LCD and send your own comms (basically the same thing, but may be cheaper and will be more flexible).
 
My advice would be don't do that. Apart from the extra complication in code you also need to switch the PIC data pins from outputs to inputs etc, which is another chance of things going bad if your code has issues.

LOL, you would have to poopoo my plans wouldn't you? :p Your advice is well received in any case.

Regarding the transition times for the LCD E pin etc, just driving it from a PIC output should work fine, there's no need for special driving circuitry.

I think you misunderstand.

The line filter/safety is not about tuning the waveforms for normal use. As you pointed out, you can drive them perfectly fine with just a straight through connection. It's the fact that by adding a current limiting resistor, I have also unintentionally increased the parasitic RC delay by (probably) several orders of magnitude, which degrades the rise/fall time of an otherwise good signal. The extra circuitry is just to correct for this.

Also in case this is actually what you were picking at, note that the CMOS buffer on the left is a model for the output buffer internal to the PIC. It is not extra parts that would be added to the line. Neither are the inductors and their respective capacitors. This was covered in the notes under the schematic image in case you missed it.

To read, or not to read.
I have two main reasons for wanting/needing to read from the LCDM.

(1) I have need to absolutely maximize the speed of the screen.
(2) I need to read the state of any one of the chars at any time.

Let me explain a little...

I am planning to do some very tricky things with a 20x4 screen. I was inspired by a YouTube demo video I saw, name escapes me ("LCD mega demo", or something like that). They did some interesting animation and things with custom characters. Many of these things could be and probably were done without needing to read anything I'm sure, but I want to go farther than what they did. And to do that I will need the capability's outlined above.

At Point (1). Me and my brother were discussing the before mentioned video and were going over how they made the LCDM effectively a low DPI pixel matrix. It was neat that they were doing reasonably good looking, if not primitive graphics and animation with it. The thing we were discussing the most is that they used just the top and bottom halves of a character as the pixels. I want to try and use either all of the pixels on a whole character, or at least the four quadrants. This will require so much speed/bandwidth that it will likely hit a wall at how fast the screen can even refresh.

As for (2), To get maximum capability's of the system I want to conserve memory in the PIC by not mirroring any data in any registers if and when I can. The LCDM has it's own RAM and remembers what characters are where at any given time. You can even modify the data as it is in the LCDM, you don't have to refresh it every time you want new data in it. I would like to take advantage of this if the theory is applicable to my projects. I would likely do this by garbage collecting the PIC's RAM after a character is sent, and relying on the fact that it is going to be in the LCDM somewhere still. But to do any of this, you more than likely need to be able to read from the device. At the very least it will be a lot easier.

Now I know I could/should use a proper character screen when I want to do graphics, but these character modules are more convenient to work with for various reasons. Namely that the processor requirements to drive a full graphics screen are much higher than these simple modules require. Also, these modules have far less pins that I have to deal with.

And I could upgrade the μC to something with more goods rather than use the LCDM's resources. But I already have the units I have as always seems to be the case. And I know I can use what I have as I have outlined above. Plus there is no reason I couldn't still do the above even with a better μC. I see no reason to waste resources that are already there, even if they are "free".

Conclusion
In the end, even if I don't ever use reads, I'm not satisfied with restricting myself to writes as the only safety net for not getting any outputs crossed. I want intrinsically short circuit safe if at all possible.

I don't know that it will work for sure, but my thus far proposed circuit limits the short circuit current to a maximum of just over 1mA, while still maintaining a respectable rise/fall time (I still want to call it slew rate). The only possible problems I see in it are. . .

(1) I don't know that my model for stray values is anything close to reality.
(2) When shorted, the instantaneous current can be fairly high.
(3) Possibility for LC ringing with the right stray component values.

To combat (1), I varied the values for the stray components over a wide range, insuring that it was fairly consistent for the most extreme situations I thought were possible. I am not sure (2) is a problem at all because it only popped up with very high value stray capacitance. Also, CMOS dictates MOSFET's, which are usually very good about pulsed current. Often times handling x10 the constant current. (3) is frequency and filter dependent, different resistance in series with the speed up cap fix this easily.

It's an all around good project IMO, make a PIC and LCDM system practically indestructible from any one line short circuiting. And do so without sacrificing speed.
 
Thanks for explaining what you are doing, I understand much better now.

Re max speed, I think you may get better speed just writing to the display as you don't need a read operation, and writing chars to the display is very fast. I think it is only the setaddress command than needs a delay? And even that can delay be fine tuned by testing to be "enough" delay without any read overhead.

I also think using read mode on a 2x20 display to save 40 PIC RAM bytes seems like false economy, but again that's just my opinion and I don't know how much RAM you have or how precious it is. :)

Anyway I don't use LCD read mode so I'll shut up on the subject. Some people here were in the habit of using read mode on Hitachi text LCDs (was it Pommie?) so they might have some real experience to offer on the matter.
 
Order of operations is key here.

If you want a setup that polls the busy flag rather than running a delay loop, have your data port on the PIC default to tri-state (hi Z). Only enable the PIC port output drivers AFTER you have dropped the R/W pin low (run a short 100uS delay after dropping R/W to allow for set up time). As soon as you are done sending data, tri-state the PIC port again and return from the LCD Send function.

Order of Operations -

* Drop R/W Low
* 1uS delay
* Clear PIC port TRIS register (enable PIC port output drivers)
* Send Data
* Write 0xFF to PIC port TRIS register (tri-state PIC port)
* Return
 
Agreed @ Jon Wilder.

My motivation for the content of this thread is not based on it's hard to do reads safely, but rather that it's fairly easy to mess up. In a good day I may turnover and rewrite a piece of code and burn to a chip 100+ times while working on a project. Little changes, an extra NOP here, a better way to do a branch there, this bit shouldn't get set here, maybe this would be better as XOR, etc. Working code like this gives lots and lots of places for those "one bit mistakes" to pop in unnoticed, and that's all it takes sometimes. But this is how the μC development process works as far as I know.

I suspect the above is the main reason why Mr RB suggested that one just not do reads at all. And though I agree that it is safer, it could still find a way to short even if you're not doing reads. Anything could happen, but to make the lines intrinsically safe from shorts is a much better protection mechanism from bad code or any glitches the LCDM may experience. No short circuit faults should cause irreversible damage to anything if my theory can be practically realized.

Mr RB said:
Re max speed, I think you may get better speed just writing to the display as you don't need a read operation, and writing chars to the display is very fast. I think it is only the setaddress command than needs a delay? And even that delay can be fine tuned by testing to be "enough" delay without any read overhead.

Remember that checking the busy flag only has overhead in the μC, as the LCDM is already busy by nature, otherwise the busy flag wouldn't be clear. And by using interrupts with an IoC pin on the busy flags line, you can do other things with the μC until the LCDM causes an interrupt. So using the busy flag is truthfully much faster all around.

Mr RB said:
I also think using read mode on a 2x20 display to save 40 PIC RAM bytes seems like false economy, but again that's just my opinion and I don't know how much RAM you have or how precious it is.

Probably true, My PICs have like... 128~256 bytes of RAM. So a 1/3rd to 1/6th RAM boost could be had. That is assuming you can reed and write to it at the same speed as system RAM, which is almost certainly not true. But know that I am not attempting to use LCDM RAM as program RAM. It's more about not having a ~40 byte video buffer in the PIC taking up space when the LCDM has it's own buffer.


Anyway. I have some things to do, so I may not be able to do any EEing right this second. But when I get back to it I am probably going to just try the "line protectors" and see what happens. I am satisfied with how it simulates and no one has chimed in to say it won't work, so I'm confident... for now.

I will post my results when I have them.
-()b
 
Last edited:
You sound like my kinda code writer. I code in both Intel and Microchip assembly, and my motto is to write the code as tight as possible. Saves code memory space and runs much faster...makes the code the most efficient.

I'm also a huge opponent of the TRISbits = 0 means output/TRISbits = 1 means input analogy. I look at it as TRISbits = 1 means output drivers disabled/TRISbits = 0 means output drivers enabled. In tri-state (output drivers disabled) you can use the port as either an input or an open drain output by writing 0's to the port latch and toggling the TRIS bits to opposite states. Matter of fact I do this more often than not as it makes it impossible to blow a pin/fry a chip if you're probing pins for whatever reason and you accidentally short one while doing so.

All sorts of "hidden" tricks you can do with coding and hardware arrangement.
 
Anyway I don't use LCD read mode so I'll shut up on the subject. Some people here were in the habit of using read mode on Hitachi text LCDs (was it Pommie?) so they might have some real experience to offer on the matter.

In this thread (see posts #4 and 10) Pommie gives his justification for reads when doing graphics. I am not sure the same reasons would apply equally to a 2X20 character display.

John
 
I forgot a step in my original Order of Operations -

Order of Operations -

* Write LCD data to port latch (PORT reg)
* Drop R/W Low
* 1uS delay for set up time
* Clear PIC port TRIS register (enable PIC port output drivers)
* 1uS delay for set up time
* Write 0xFF to PIC port TRIS register (tri-state PIC port)
* Return

With the data placed in the port latch, the data will appear on the output pins as soon as you enable the output drivers after clearing the TRIS register. The 1uS delay for set up time gives the LCD time to read the data you're sending it.
 
Last edited:
In this thread (see posts #4 and 10) Pommie gives his justification for reads when doing graphics. I am not sure the same reasons would apply equally to a 2X20 character display.

Thanks for the link Jpanhalt, I read through that thread and remembered it. The KS0108 graphics display can only write 8 pixels at a time so reads can be useful there for sure, but having said that I have used that display in a number of projects and only write to it. ;)

The newer displays TFT colour graphics displays etc that I have been working with seem to have an industry move towards treating displays as "write only" which suits me fine, in most cases a display is an output device and reading from it is a fairly old-fashioned concept.
 
Thanks for the input guys. Very helpful.

Still building a wood stove, prolly done around Thursday. This thread is the first thing I plan to get working on after I'm done with that.
 
*Update*

LOL... Well... I wasn't done by Thursday. Wood stove works great though :p

Anyway, I am back on this project now. Test hardware is built and the firmware is 60~80% done. I'm incorporating Jon Wilder's LCDM read "Order of Operations" into some LCDM code I wrote in 2010. I also have to cut out a bunch of "extra" routines and such from that source and basically re-blank the slate. (I'm back porting a source file from an already finished project.)

SSDD really. I should have meaningful results in a few days time, provided I don't procrastinate (More).
 
(-_-)... Newhaven Display makes some great hardware... but they oughta remove whoever writes the interface programming examples. Below is an excerpt from the datasheet I'm working with, see if you can spot the mistake.

Code:
8-bit Initialization: 
/**********************************************************/ 
void command(char i) 
{ 
      P1 = i;                       //put data on output Port 
      D_I =0;                       //D/I=LOW : send instruction 
      R_W =0;                       //R/W=LOW : Write   
      E  = 1;                              
      Delay(1);                     //enable pulse width  >= 300ns 
      E  = 0;                       //Clock enable: falling edge 
} 
/**********************************************************/ 
void write(char i) 
{ 
      P1 = i;                       //put data on output Port 
      D_I =1;                       //D/I=LOW : send data 
      R_W =0;                       //R/W=LOW : Write   
      E  = 1; 
      Delay(1);                     //enable pulse width  >= 300ns 
      E  = 0;                       //Clock enable: falling edge 
} 
/**********************************************************/ 
void init() 
{ 
      E = 0; 
      Delay(100);                   //Wait >15 msec after power is applied 
      command(0x30);                //command 0x30 = Wake up  
      Delay(30);                    //must wait 5ms, busy flag not available 
      command(0x30);                //command 0x30 = Wake up #2 
      Delay(10);                    //must wait 160us, busy flag not available 
      command(0x30);                //command 0x30 = Wake up #3 
      Delay(10);                    //must wait 160us, busy flag not available 
      command(0x38);                //Function set: 8-bit/2-line 
      command(0x10);                //Set cursor 
      command(0x0c);                //Display ON; Cursor ON 
      command(0x06);                //Entry mode set 
} 
/**********************************************************/

It's insignificant stuff, honestly I'm just being petty. And it's not like I'm perfect with code either, so I probably shouldn't complain. But c-mon, this is supposed to be production grade. *I* of all people shouldn't be catching this crap before someone else does. :sigh: Funny thing is, even though it's mostly copy/past of the above, one part is not wrong in the 4-bit Initialization example code :)/)
 
Last edited:
... see if you can spot the mistake.
...


At a first glance there's a faulty comment on line 16 re LOW not HI, and a couple of iffy comments near the bottom re 160uS that are probably meant to say 1.6mS.

Also I think from memory the datasheet says something about needing a decent delay after function set 0x38 or entry mode set (the code has no delays there), but I didn't check the datasheet.

...
Code:
8-bit Initialization:It's insignificant stuff, honestly I'm just being petty. And it's not like I'm perfect with code either, so I probably shouldn't complain. But c-mon, this is supposed to be production grade. ...[/QUOTE]

You'll get used to that. After doing this for enough years you soon get used to the idea that you are better than the "professionals" and you will likely be right. ;)

One of the older guys here (or on another forum?) worked for NationalSemi and said they used to throw together application circuits for the datasheets almost like it was a joke, to get the boss off their back and finish the datasheets. Then for 30 years people assume that is the "correct" way to use that IC in a circuit. :D
 
Nice RB, you saw what I saw right away. I figured you would.

So...
The first and most important part is the delays, there are none for the last four commands. Unless the clock is really really slow the μC would be hammering the LCDM with command after command before it had time to complete them. Second is that, as you pointed out, 160us could/should be 1.6ms. We can't know from the code shown since they didn't have the forethought to let us know how this "Delay()" function actually works. At a glance it should be 160us per 1 tick, but only they really know.

The last details aren't really deal breakers, they are more conceptual problems. Calling command() three times in a row while passing the same exact data to it each time is inefficient and unnecessary IMO. All that really needs to be done is to load the command once, then just |Delay|->|Strobe E|->|Delay|->|Strobe E|->|Delay|. The label D_I [D/I] is technically incorrect. The pin/control is actually called "RS", though admittedly Data/Instruction is a more accurate name for what the pin is doing IMO. Also, as you pointed out, part of the comment on line 16 is backwards, which is funny as the other part is correct *AND* the whole comment is correct in the copy/paste over to the 4-bit code.

Finally, and I could be totally wrong, but I don't think the entire sequence shown is necessary. I have been down this road with them before, followed their sequence to the letter, couldn't get the thing to work for weeks. I finally broke down and went to their forums where they gave me an entirely different sequence than the suggested one. It worked on the first try.

Edit: I *THINK* it was that you don't have to do all of those pesky "wake up's" like they suggest.

Mr RB said:
One of the older guys here (or on another forum?) worked for NationalSemi and said they used to throw together application circuits for the datasheets almost like it was a joke, to get the boss off their back and finish the datasheets. Then for 30 years people assume that is the "correct" way to use that IC in a circuit.

Interesting. That's when it prolly pays to have a boss that majored in engineering, not business. The former would tend to be more understanding I would imagine.


Anyway, getting back on topic...
I have a cute little "interlock" routine now that I hope works. Just as the name implies, it is designed in such a way that you (mostly) can't do LCD/PORT operations without going through these routines, and there is no combination of calls to them that can lead to both devices being Low-Z simultaneously. I also have two simple checks and a "panic room" catch all that can be used independently should one be forced to bypass the interlock system. I hesitate to share the code as it's unproven, unclean, and specific to my configuration/parts.

Also... my un-spellchecked writing is embarrassing :eek:
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top