BS2p driving I2C display problem
john_s
Posts: 369
in BASIC Stamp
I have this I2C 16x2 LCD (at 0x27) that I'm trying to interface to BS2p.
Plenty of samples of how to use bit-banging or LCDOUT commands but I plan on using I2COUT instead.
I have no luck with my code (see attached) so I hope that somebody can easily spot what am I doing wrong. Thanks
Plenty of samples of how to use bit-banging or LCDOUT commands but I plan on using I2COUT instead.
I have no luck with my code (see attached) so I hope that somebody can easily spot what am I doing wrong. Thanks
Comments
Chris, here's the schematic. The SDA is connected to pin 8 of BS2p, the SCL goes to pin 9 of BS2.
Honestly with this type of interface you're saving I/O pins at the cost of more/complex code to drive it. I have seen some examples of driving a parallel display from such a device so you might be able to find some existing code. If you do I would recommend creating a subroutine that handles all the heavy lifting for you so that you can just send commands/data by setting a couple of variables and calling a subroutine (GOSUB).
That I understand, however I am not able to come up with the correct sequence for the HD44780.
EDIT oops, missed the P3 connection to the backlight. Thanks for pointing that out Hal.
Based on the HD44780U data sheet it looks like you need to send at least 2 bytes for every 4 bits of data, so 4 bytes for each character to be displayed.
I am willing to help out with the commands that need to be sent, but I do not have that lcd so it may be a very slow process. See the attached drawing for the function of each output bit sent to the SPI chip along with a timing diagram of reads and writes.
Now that you (and we) know how the 8574 is connected to the LCD that knowledge can be used to build your code. But first you have to understand the bit structure of the character to be transferred. Your code has to specifically build the character to be transferred so that the LCD can recognize and act upon that character.
In your case the bit structure is as follows;
bit 0: RS must be set to 0 if an instruction (or command) and set to 1 if this is a data operation.
bit 1: R/W must be set to 1 if reading data from LCD back to the Stamp, or set to 0 when writing from the Stamp to the LCD. (Almost always will be 0)
bit 2: CS called E everywhere else. This has to be 0 for the first toggle transfer, and then set to 1 for the 2nd toggle transfer. If this is not toggled down and up the LCD ignores everything.
bit 3: P3 called BL for backlight everywhere else. When set to 1 it will turn on the LCD backlight. (obviously, 0 will turn it off)
bits 4-7: data bits. 4 data bits or 1 nibble to be sent to the LCD. The first "chunk" will be the upper nibble of the data you wish to transfer. The second "chunk" will be the lower nibble of the character.
Each "toggle" transfer is an I2COUT transfer with the character in the data field between the brackets [ ] made specifically for that transfer.
Each "chunk" is actually two "toggle" transfers. Remember, if you don't toggle the CS bit, NOTHING will happen.
Did Chris & I not tell you this configuration is not trivial to program?
The address is correct and verified as 0x27
Okay, so you have all three jumpers off then and not shorted.
Looks like the product page is here: http://www.sunrom.com/p/i2c-lcd-backpack-pcf8574
Also note there are multiple threads on these forums about this: http://forums.parallax.com/search?Search=LCD+I2C+PCF8574
Kwin, not sure I understand but I'm eager to see a sequence of commands that does what you've just said and test it. Thanks!
Hal, in regards to all those LCD lines other then D5-D7; aren't they taken care by the PCF8574 without our need to "tell" it anything ?
No. Hal's post was right on the mark. The PCF8574 doesn't know anything about what it's connected to or what the pins need to do. You must be implicit in everything you send to it.
bit 0: RS = 1, which means this is a data input sequence, something to display.
bit 1: R/W = 0, which means this is a write from the stamp to the LCD.
bit 2: CS = 0, which means this is the first half of the CS toggle.
bit 3: P3 = 0, backlight is off
bits 4 - 7: data bits 4 -7 = 0000, places 0000 to the data input lines.
Now let us look at sending $01 shifted left 4 times;
Understand that shifting left 4 times leaves bits 0 - 3 all at zero.
bit 0: RS = 0, which means this is now a command operation
bit 1: R/W = 0, which means this is a write to the LCD from the Stamp
bit2: CS = 0, first half of CS toggle
bit3: p3 =0, backlight is still off
bits 4-7: data bits 4 - 7 are now set to 0001
In either case, nothing happens because you have not toggled the CS line ( it has to transition from 0 to 1 in order for the LCD do anything), and so far only half of a character or command has been sent.
here is the sequence for sending a $01 command to the LCD so that it will be acted upon with your configuration.
1: set up the output character so that it reads '00001001' and send it over the I2C bus. Data bits are the upper nibble of $01 and CS is 0, backlight is on
2: change the output character so that the CS bit is now 1, '00001101' and send it over the bus. The LCD "sees" the CS toggle and accepts the first half of this command, backlight is on.
3: change the output character to read '00011001" and send it over the bus. Data bits are now the lower nibble of $01 and CS is 0, backlight is on
4: change the output character to read '00011101" and send it over the bus. again the LCD "sees" the CS toggle and accepts the 2nd half of the command, sees that it is $01 and clears the display, backlight is on.
The 8574 will not, on it's own, toggle the CS line. You have to do that.
Since you are essentially bit-banging the display, you have to know the details on what has to be done.
I made a slight error in the example sequence for sending a $01 command to the LCD. Bit 0 of the output character, RS, the rightmost bit, should be 0 for a command operation, not 1, which is for data input. My apologies if this caused you any confusion.
Hal, I keep reading and still cannot spot the place where you've "made a slight error". Can you help and highlight where it was? Thanks
You can send a single string like "Hello world" using the string formatter. See page 232 of the "BASIC Stamp Syntax and Reference Manual Version 2.2"
Actually in this case that won't work. If you create a subroutine to handle to individual writes, you can also create a string subroutine to take a zero-delimited string and send it one character at a time calling the data subroutine.