Shift registers, LCD and LEDs

Hi-

Software engineer here with a request for any feedback the hardware types might have regarding a design to augment the base I/O capability of my design. I have a plan, but so did Custer (well actually I don't think he did, but I digress), so I thought I would pose it here for a sort-of review if you will. I'm designing a hand-held device that will have a 4x4 membrane keypad (will use the keypad library for that), a HD44780 LCD and 8 LEDs to represent system state.

And as is seemingly-customary with these projects, I have exhausted the available I/O in my current design. I'm using an Amtel 1284, but despite the 32 I/O pins that are available OOTB, by the time a couple of internal components plus the general SPI and I2C pins were allocated, I only had 14 pins remaining. In summarization my needs follow:

8 pins for keypad
6 pins for LCD (using 4-bit data transfer, 1 for RS, 1 for EN)
8 pins for the LEDs

That brought my total to 22 pins that I would need to implement the UI components. 14 - 22 = a problem. So as I mentioned, I came up with a solution that involves two shift registers (SN74HC595) that I plan on daisy-chaining together using a common latch pin. With this design, I could even use 8-bit data transfer for the LCD, so I thought 'why not?' and made that change too. This changed the allocation of the 14 remaining pins thus:

8 pins for keypad (unchanged, will use direct digital pins for this)
3 pins for the LCD and LEDs

Totalling 11. 14 - 11 = much better story. So that's the introduction. Now a quick rundown of how I plan to implement the LCD/LED stuff. Really, the problem is made simple because I plan to put the shift registers on the SPI network and use the SPI.transfer() method to shift-in data. Thus the already-existing MOSI line is used for the data in to the first shift register and I'll chain the output of that one to the input of the second, and the SCLK line goes without mention. As for the 3 pins required from the MCU, the first will be the common latch pin that I will run in parallel to each shift register. The second will be a dedicated pin for the RS input to the LCD and similarly for the LCD EN pin. The idea being that whenever I want to send display data to the LCD, I simply pull the latch pin low, SPI.transfer() in the data, pull it high and then the data goes over SPI to the LCD. I will modify the existing LiquidCrystal library for my application to perform this type of operation in the sending function. I've looked and the mods for that are straightforward. Again, since they're available, I would just use all 8 pins from the first shift register as the data pins for 8-bit transfer to the LCD, while the RS and EN pins remained as separate, dedicated pins directly from the MCU. And I will connect the output from all of these pins to the LC'sD PCB via male headers (pins) on both my primary PCB and the LCD's PCB via ribbon cable and female ribbon cable connectors. And just for completion, the LCD I plan on using is like this one: Standard LCD 20x4 + extras [white on blue] : ID 198 : $17.95 : Adafruit Industries, Unique & fun DIY electronics and kits

And then of course for the LEDs, you simply add a second SPI.transfer() of data so that the first is the LED data and the second is the LCD stuff, no problem. I'll have a software buffer for each such that I can reload the shift registers with the old data if nothing changes for one of them. I decided on that because I'm not certain if these critters are susceptible to interference such that unwanted data could be pulled in during the period when the latch pin was pulled low, thus changing the output in an undesirable and inaccurate manner. The scenario I had in mind for that was needing to update the LCD but not the LEDs. With a common latch pin, if I only shift in 1 byte of data, that only affects the LCD output. However if interference was a possibility, then while the LED shift register was pulled low and LCD data was loaded into the LCD shift register, then bogus LED output states could be displayed. Seems improbable to me somehow, intuition-wise, but what do I as a software type know, right? Hah!

A better solution seems to be to separate the latch pins for the two shift registers, but I am holding all available MCU pins in reserve for now, 'cause you never seem to have enough pins. If in the end I have one to spare, then I will indeed separate the latch pins, not worry about the "interference issue".

So. The basic questions here are:

  1. Has anyone done this before (I'm guessing "many times" is the answer) and thus would this general approach work?

  2. Is the "interference issue" really an issue or am I just being overly cautious (ahem!) and worrying about nothing?

  3. Would there be any issue sending the shift register output (which I assume is either +5V/HIGH or GND/LOW) through a jumper (male header), over ribbon cable and to the input pins on the LCD's PCB, which will be placed about 3 to 5 inches away from my primary PCB?

Thanks!

av8or1:

  1. Has anyone done this before (I'm guessing "many times" is the answer) and thus would this general approach work?

Yes.

av8or1:
2) Is the "interference issue" really an issue or am I just being overly cautious (ahem!) and worrying about nothing?

When you chain shift registers, you have to update the entire chain every time you want to change any output.

av8or1:
3) Would there be any issue sending the shift register output (which I assume is either +5V/HIGH or GND/LOW) through a jumper (male header), over ribbon cable and to the input pins on the LCD's PCB, which will be placed about 3 to 5 inches away from my primary PCB?

No.

av8or1:
Hi-

Software engineer here with a request for any feedback the hardware types might have regarding a design to augment the base I/O capability of my design. I have a plan, but so did Custer (well actually I don't think he did, but I digress), so I thought I would pose it here for a sort-of review if you will. I'm designing a hand-held device that will have a 4x4 membrane keypad (will use the keypad library for that), a HD44780 LCD and 8 LEDs to represent system state.

And as is seemingly-customary with these projects, I have exhausted the available I/O in my current design. I'm using an Amtel 1284, but despite the 32 I/O pins that are available OOTB, by the time a couple of internal components plus the general SPI and I2C pins were allocated, I only had 14 pins remaining. In summarization my needs follow:

8 pins for keypad
6 pins for LCD (using 4-bit data transfer, 1 for RS, 1 for EN)
8 pins for the LEDs

That brought my total to 22 pins that I would need to implement the UI components. 14 - 22 = a problem. So as I mentioned, I came up with a solution that involves two shift registers (SN74HC595) that I plan on daisy-chaining together using a common latch pin. With this design, I could even use 8-bit data transfer for the LCD, so I thought 'why not?' and made that change too. This changed the allocation of the 14 remaining pins thus:

8 pins for keypad (unchanged, will use direct digital pins for this)
3 pins for the LCD and LEDs

Totalling 11. 14 - 11 = much better story. So that's the introduction. Now a quick rundown of how I plan to implement the LCD/LED stuff. Really, the problem is made simple because I plan to put the shift registers on the SPI network and use the SPI.transfer() method to shift-in data. Thus the already-existing MOSI line is used for the data in to the first shift register and I'll chain the output of that one to the input of the second, and the SCLK line goes without mention. As for the 3 pins required from the MCU, the first will be the common latch pin that I will run in parallel to each shift register. The second will be a dedicated pin for the RS input to the LCD and similarly for the LCD EN pin. The idea being that whenever I want to send display data to the LCD, I simply pull the latch pin low, SPI.transfer() in the data, pull it high and then the data goes over SPI to the LCD. I will modify the existing LiquidCrystal library for my application to perform this type of operation in the sending function. I've looked and the mods for that are straightforward. Again, since they're available, I would just use all 8 pins from the first shift register as the data pins for 8-bit transfer to the LCD, while the RS and EN pins remained as separate, dedicated pins directly from the MCU. And I will connect the output from all of these pins to the LC'sD PCB via male headers (pins) on both my primary PCB and the LCD's PCB via ribbon cable and female ribbon cable connectors. And just for completion, the LCD I plan on using is like this one: Standard LCD 20x4 + extras [white on blue] : ID 198 : Adafruit Industries, Unique & fun DIY electronics and kits

And then of course for the LEDs, you simply add a second SPI.transfer() of data so that the first is the LED data and the second is the LCD stuff, no problem. I'll have a software buffer for each such that I can reload the shift registers with the old data if nothing changes for one of them. I decided on that because I'm not certain if these critters are susceptible to interference such that unwanted data could be pulled in during the period when the latch pin was pulled low, thus changing the output in an undesirable and inaccurate manner. The scenario I had in mind for that was needing to update the LCD but not the LEDs. With a common latch pin, if I only shift in 1 byte of data, that only affects the LCD output. However if interference was a possibility, then while the LED shift register was pulled low and LCD data was loaded into the LCD shift register, then bogus LED output states could be displayed. Seems improbable to me somehow, intuition-wise, but what do I as a software type know, right? Hah!

A better solution seems to be to separate the latch pins for the two shift registers, but I am holding all available MCU pins in reserve for now, 'cause you never seem to have enough pins. If in the end I have one to spare, then I will indeed separate the latch pins, not worry about the "interference issue".

So. The basic questions here are:

  1. Has anyone done this before (I'm guessing "many times" is the answer) and thus would this general approach work?

  2. Is the "interference issue" really an issue or am I just being overly cautious (ahem!) and worrying about nothing?

  3. Would there be any issue sending the shift register output (which I assume is either +5V/HIGH or GND/LOW) through a jumper (male header), over ribbon cable and to the input pins on the LCD's PCB, which will be placed about 3 to 5 inches away from my primary PCB?

Thanks!

Seems fairly well thought out but you are doing it the hard way i think

Why not use i2c (TWI) etc ?

You can get LCD modules with i2c interfaces for dirt cheap (or look at Liudrs Serial LCD module)
You can get 8 and 16 bit i2c expansion modules for LEDs
and I am sure though have not done one you can get i2c keypad modules

Craig

Thanks to everyone for the feedback. I decided to go with this approach, though I switched from SN74HC595s to TPIC6C595s per the advice of CrossRoads. I have it wired and routed on my board now. DRC and ERC pass cleanly, so that's something. :wink:

I didn't go the I2C route, except for the RTC, with this design simply because the 1284 provides a fair amount of I/O pins, so might as well use 'em. Also, I wanted to get some experience with shift registers.

Anyway, thanks again!

av8or1:
Thanks to everyone for the feedback. I decided to go with this approach, though I switched from SN74HC595s to TPIC6C595s per the advice of CrossRoads. I have it wired and routed on my board now. DRC and ERC pass cleanly, so that's something. :wink:

I didn't go the I2C route, except for the RTC, with this design simply because the 1284 provides a fair amount of I/O pins, so might as well use 'em. Also, I wanted to get some experience with shift registers.

Anyway, thanks again!

NO worries - when complete you should post up for others to learn

Craig

craigcurtin:
NO worries - when complete you should post up for others to learn

Craig

Craig-

Sure, glad to pass on information, but not sure what I could comment on further. That said, I did one learn one important lesson about shift registers. And how! As I mentioned, I made the switch from SN74HC595s to TPIC6C595s for both the LCD and LED shift registers. Well there is a problem with that. What I learned is that the TPIC6C595 is a sinking shift register, meaning that it sinks current from the device through the shift register and to GND. That design doesn't work well with an LCD when you are supplying the data pins on that LCD from the shift register. lol

But it does make sense to use the TPIC6C595 for the LEDs, so I retained that idea. Switched the LCD shift register back to the SN74HC595.

The most recent version of the board had this malformed design on it, so I cannot comment just yet as to whether or not this works, but I suspect it will. I have modified the Arduino Liquid Crystal library for my own needs for this project. Or I should say that I created an entirely new library that uses the fundamental core routines from Liquid Crystal library, but is a much shorter, tailor-made library to meet the needs of this design. I received the new boards from ITead Studio over the holiday and will get them assembled this week. Will try to update the thread when I have verified that the approach is valid.

Attached are a couple of snippets from the schematic that shows how the shift registers were ultimately implemented on my board, at least as they stand at present. :slight_smile:

Hope this helps others.

Thanks

Ok I may have to heed Craig's suggestion and look into I2C for the LCD. Why? BECAUSE THE FRIGGIN LCD still doesn't work! lol

The LED backlight varies in intensity, causing to appear to flicker. Thought it might be the pins on the header to which it is connected, but those showed +4.87V and 0.00V GND so that seemed ok. Still, I plugged the two pins on the LCD that provide power to the LED backlight to +5V and GND on the primary power header for the board as a whole. Same result. Flickering, different intensities. Then there's the display itself. I finally got text to show up, but it isn't the text that I sent (Hello World!). Instead I get some kind of random garbage. So it's crap. I've tried to isolate the problem, but I just can't pinpoint the cause; is it the board, the LCD, or something screwy I am doing in the library? Dunno, but it's something therein because the same LCD works on an UNO using the standard Liquid Crystal library. I've hosed something, conceptually or practically.

So. I want to finish the board ASAP, therefore I am considering other options for the LCD stuff.

But just for pseudo-completeion, tell me: was I just way the heck off base thinking that I could use the SN74HC595 shift register to do the data, while the remainder of the pins came straight from the uC? Thus it's a conceptual issue. I'm thinking so, but can't be sure. The summarization of the design was to use 2 uC pins for RS and EN, RW was grounded, contrast was done standardly via a POT, +5V and GND for the LCD PCB and the LED backlight came directly from the power bus.

I don't know what would be involved to make the switch to LCD via I2C on a custom board (don't wanna use a breakout obviously, but could replicate that circuitry on my board), but it does seem like it's a better idea/approach. One that is proven technology that should work out-of-the box, right? The other downside is that it would mean a new stencil fee because the board would change. But if it got me to the finish line quicker, it might be worth it.

Anyway, any thoughts would be appreciated. I'm headed off to research the LCD I2C stuff....

ps-The LED stuff via the TPIC6C595 do indeed work now on the most recent version of the board, so that is something...

Ok so I looked at the I2C stuff. I downloaded the schematics and board layouts for the breakouts (thanks Adafruit!). As it turns out the approach used there is much the same as I was planning on using. So that was pseudo-confirmation that the original idea I had was valid. And that made sense because the original idea made sense to me too. So I decided to go back and take an even closer look at where I might be going wrong.

The two problems:

  1. Flickering LED backlight
  2. Garbage text on the LCD

I pulled the LCD and its PCB from the breadboard. Noticed that one of the header pins was a different height from the others. Played with it a bit and readily determined that a solder joint had been compromised. I could push the pin all the way through the header! So I fired up the soldering iron, put the pin in its correct location and resoldered. Connected the PCB back to the uC PCB, loaded the sketch and BOOM! Works fine now. No more garbage text.

Sheesh. All that for this? lol

I still see occasional flickering of the LED backlight. I don't know what that's about because the +5V and GND connections show correct readings on the DVMM. It does remain stable if I don't move anything, or at least for the most part. As I recall; it was about 1:30 in the morning.

Anyway, thought I'd reply and let anyone who might be reading this at some point in the future know that the design approach is valid and does work. SPI is faster than I2C, so I'd prefer this approach in the abstract. So I'll go with it. Just glad to get something working! :wink:

Thanks

Progress! Good to see that you're moving ahead. Too bad it was in a bit of a frustrating manner due to someone elses poor workmanship, but that's how it goes sometimes.