My I2C LCD display by matrixorbital is all working except for 1 thing: The command to change the start up screen only sends the first 2 letters to the display, and makes the rest of the startup screen a bunch of vertical bars.
This is the line that sets the startupscreen:
lcd.writeStartUpScreen("Welcome");
But this will make the startup screen look like this:
We|||||||||||||||||||||
||||||||||||||||||||||||
It's supposed to handle up to 32 chars. (16 x 2 display)
I can change the "Welcome" to any else, and it will only change the 'We' on the splash screen, and leave the bars.
here's a snipet from the library that doing the work:
I've sent about a dozen other commands to the LCD, and they all work.
Here's the manual: http://www.matrixorbital.ca/manuals/LK_series/LK162-12/LK162-12_Legacy/LK162-12_220.pdf
I've about given up! But I'd like to get rid of the vertical bars...
I've got 2.6K pull-ups on the SDA & SCL.
This is my 1st experience with I2C.
Hope there's a simple solution to this, I've tried everything.
C:\Documents and Settings\x\Desktop\arduino-0022\libraries\LCDI2C_LK162\LCDI2C_LK162-12.cpp: In member function 'void LCDI2C::writeStartUpScreen(char*)':
C:\Documents and Settings\x\Desktop\arduino-0022\libraries\LCDI2C_LK162\LCDI2C_LK162-12.cpp:111: error: invalid conversion from 'char*' to 'uint8_t*'
C:\Documents and Settings\x\Desktop\arduino-0022\libraries\LCDI2C_LK162\LCDI2C_LK162-12.cpp:111: error: initializing argument 1 of 'void TwoWire::send(uint8_t*, uint8_t)'
I'm using this line in my sketch:
lcd.writeStartUpScreen("Hello");
And this is the the CPP file from the library:
/*
LCDI2C v0.4 3/Mar/2009 dale@wentztech.com http://wentztech.com/Radio
PORTED FOR Matrix Orbital LK162-12 display 10/Sept/2010 by Brian Brumfield, brian@thebrumfields.com
What is this?
An arduino library for use with the web4robot.com i2C LCD Display in I2C more
Uses I2c Wires interface
Uses Analog pin 4 - SDA
Uses Analog pin 5 - SCL
Usage:
see the examples folder of this library distribution.
*/
#include <Wire.h>
#include <string.h> //needed for strlen()
#include <inttypes.h>
#include "WConstants.h" //all things wiring / arduino
#include "LCDI2C_LK162-12.h"
#define LCDI2C_MAX_STRLEN 40
#define LCDI2C_PRINT_STR_DELAY 20
//--------------------------------------------------------
// (don't change here - specify on calling constructor)
//how many lines has the LCD?
int g_num_lines = 2;
int g_num_col = 16;
// Defalt address of the display
int g_i2caddress = 0x50;
int g_display = 0;
//stuff the library user might call---------------------------------
//constructor. num_lines must be 1, 2, 3, or 4 currently.
LCDI2C::LCDI2C (int num_lines,int num_col,int i2c_address,int display){
g_num_lines = num_lines;
g_num_col = num_col;
g_i2caddress = i2c_address >>1; // ** 7 bit address
g_display = display;
if (g_num_lines < 1 || g_num_lines > 4){
g_num_lines = 2;
}
if (g_num_col < 1 || g_num_col > 40){
g_num_col = 16;
}
}
// Send a command to the display that is not supported
void LCDI2C::command(int value) {
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(value);
Wire.endTransmission();
delay(CMDDELAY);
}
// I added this:
// Send 2 commands to the display that is not supported
void LCDI2C::command2(int val1, int val2) {
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(val1);
Wire.send(val2);
Wire.endTransmission();
delay(CMDDELAY);
}
// Write Start-Up Screen
void LCDI2C::writeStartUpScreen(char message[32]) {
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x40);
Wire.send(message, strlen(message));
// Wire.send(message);
Wire.endTransmission();
delay(CMDDELAY);
}
//Used by the print library to get information to the display
void LCDI2C::write(uint8_t value) {
Wire.beginTransmission(g_i2caddress);
Wire.send(value);
Wire.endTransmission();
delay(5);
}
//send the clear screen command to the LCD
void LCDI2C::clear(){
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x58);
Wire.endTransmission();
delay(CMDDELAY);
}
//send the Home Cursor command to the LCD ********** Not Working ***************
void LCDI2C::home(){
setCursor(0,0); // The command to home the cursor does not work on the version of the dislay I have
// So we do it this way.
}
//Turn the LCD ON
void LCDI2C::on(int value){
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x42);
Wire.send(value);
Wire.endTransmission();
delay(CMDDELAY);
}
// Turn the LCD OFF
void LCDI2C::off(){
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x46);
Wire.endTransmission();
delay(CMDDELAY);
}
//Turn the Underline Cursor ON
void LCDI2C::cursor_on(){
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x4A);
Wire.endTransmission();
delay(CMDDELAY);
}
//Turn the Underline Cursor OFF
void LCDI2C::cursor_off(){
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x4B);
Wire.endTransmission();
delay(CMDDELAY);
}
//Turn the Underline Cursor ON
void LCDI2C::blink_on(){
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x53);
Wire.endTransmission();
delay(CMDDELAY);
}
//Turn the Underline Cursor OFF
void LCDI2C::blink_off(){
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x54);
Wire.endTransmission();
delay(CMDDELAY);
}
//Move the cursor left 1 space
void LCDI2C::left(){
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x43);
Wire.endTransmission();
delay(CMDDELAY);
}
//Move the cursor right 1 space
void LCDI2C::right(){
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x4D);
Wire.endTransmission();
delay(CMDDELAY);
}
// initiatize lcd after a short pause
//while there are hard-coded details here of lines, cursor and blink settings, you can override these original settings after calling .init()
void LCDI2C::init () {
delay(1000);
Wire.begin();
on(5);
clear();
blink_off();
cursor_off();
home();
}
void LCDI2C::setCursor(int line_num, int x){
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x47);
Wire.send(line_num);
Wire.send(x);
Wire.endTransmission();
delay(100);
}
int LCDI2C::keypad (){
int data = 0;
// Send Keypad read command
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x26);
Wire.endTransmission();
delay(CMDDELAY);
// Connect to device and request byte
Wire.beginTransmission(g_i2caddress);
Wire.requestFrom(g_i2caddress, 1);
if (Wire.available()) {
data = Wire.receive();
}
return data;
}
unsigned char LCDI2C::init_bargraph(unsigned char graphtype)
{
switch (graphtype)
{
case LCDI2C_THICK_VERTICAL_BAR_GRAPH:
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x76);
Wire.endTransmission();
break;
case LCDI2C_THIN_VERTICAL_BAR_GRAPH:
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x73);
Wire.endTransmission();
break;
case LCDI2C_HORIZONTAL_BAR_GRAPH:
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x68);
Wire.endTransmission();
break;
case LCDI2C_HORIZONTAL_LINE_GRAPH:
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x16);
Wire.send(0x01);
Wire.endTransmission();
break;
default:
return 1;
}
return 0;
}
void LCDI2C::draw_horizontal_graph(unsigned char column, unsigned char row, unsigned char direction, unsigned char len)
{
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x7C);
Wire.send(column);
Wire.send(row);
Wire.send(direction);
Wire.send(len);
Wire.endTransmission();
}
void LCDI2C::draw_vertical_graph(unsigned char column, unsigned char len)
{
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x3D);
Wire.send(column);
Wire.send(len);
Wire.endTransmission();
}
void LCDI2C::load_custom_character(unsigned char char_num, unsigned char *rows)
{
unsigned char i;
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x4E);
Wire.send(char_num);
for (i = 0; i < LCDI2C_CUSTOM_CHAR_SIZE; i++)
Wire.send(rows[i]);
Wire.endTransmission();
}
unsigned char LCDI2C::set_backlight_brightness(unsigned char new_val)
{
if ((new_val < LCDI2C_MIN_BRIGHTNESS)
|| (new_val > LCDI2C_MAX_BRIGHTNESS))
return LCDI2C_VALUE_OUT_OF_RANGE;
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x99);
Wire.send(new_val);
Wire.endTransmission();
return 0;
}
unsigned char LCDI2C::set_contrast(unsigned char new_val)
{
if ((new_val < LCDI2C_MIN_CONTRAST)
|| (new_val > LCDI2C_MAX_CONTRAST))
return LCDI2C_VALUE_OUT_OF_RANGE;
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x50);
Wire.send(new_val);
Wire.endTransmission();
return 0;
}
// Overload
void LCDI2C::printstr(const char c[])
{
byte len;
while (*c)
{
len = min(strlen(c), LCDI2C_MAX_STRLEN);
Wire.beginTransmission(g_i2caddress);
Wire.send(0xFE);
Wire.send(0x15);
Wire.send(len);
while (len--)
Wire.send(*c++);
Wire.endTransmission();
if (*c)
delay(LCDI2C_PRINT_STR_DELAY); // More to send. Wait a bit
}
}
Untested, but I think that has a greater chance. I should point out that the maximum you can send in one transmission in I2C is 32 bytes, so since you have sent 0xFE and 0x40 the message couldn't be more than 30 characters.
6.1.7 Load startup screen (254 64 [32 characters])
This command sets and memorizes the startup screen that will appear each time the LK162-12 is turned on. By default the screen shows:
The 40 characters define the two 20 character rows of the screen. They may be any characters from the character set shown in Figure 3-1.
I don't quite get the "[32 characters]" ... "The 40 characters define the two 20 character rows" bit, but leaving that aside, maybe you actually have to supply 32 characters and not less than 32.
This new code compiles, but it still only loads the first 2 characters to the splash screen. I tried sending a 32 character length text like:
lcd.writeStartUpScreen("Greetings folks! here is the rst");
but it only gets the 'Gr' and the rest of the display is vertical bars.
I just heard back form MatrixOrbital, they said:
I understand it appears that the start screen of your LK162-12 is not being changed correctly by your Arduino controller. If the display is having trouble receiving any characters it will NAK the data line, I believe the Arduino endTransmission function will indicate this.
As for the command, you might try padding the string with spaces to make it 32 characters long, the size of the screen.
So I've tried the padding, but 'NAK'??? --does it send some kind of signal back that I can check to see if it's not getting the message? I feel pretty sure it's something in the transmission/timing, but I don't know what. Any other suggestions?
I suggested you might need to send 32 bytes, and you have not, because as I said the 2 control characters make it add up to 34 bytes. The I2C library imposes a limit of 32 for the whole transmission.
You need to edit (or edit a copy of) the I2C library, in particular Wire.h, and change:
#define BUFFER_LENGTH 32
to:
#define BUFFER_LENGTH 34
This may or may not help, of course, but at least then you are sending 32 bytes of welcome screen.
Okay, I've uploaded about 75 test sketches, and here's some stuff I've come up with. First, I had the same results using either of these in the LCDI2C library:
I changed #define BUFFER_LENGTH 32 to #define BUFFER_LENGTH 34
It will upload the first 20 characters*.
I changed the buffer length to 40, and it would still only upload the first 20 characters*. :~
I searched about the wire library, found reference to twowire. So in libraries/wire/utility/twi.h, I changed #define TWI_BUFFER_LENGTH 32 to 60:
And now it loads 26 characters*! XD
There must be some other buffer somewhere that's holding things up, maybe? Any thoughts?
*by this I mean the rest of the screen is filled with vertical bars.
Try making TWI_BUFFER_LENGTH 34 and not 60. It makes a few copies of buffers of that size, you may be running out of memory elsewhere. Your experience is certainly interesting. What value is returned by Wire.endTransmission();?
ps. This sending a splash screen locks things up. Like -- this should loop, but it only prints 4 once. I have to power down the LCD to do anything more.
* Output 0 .. success
* 1 .. length to long for buffer
* 2 .. address send, NACK received
* 3 .. data send, NACK received
* 4 .. other twi error (lost bus arbitration, bus error, ..)
I have 2.7K resistors on A4 and A5 to +5 volts. I'll double check, that their connected good, but their soldered on my custom pcboard, so they should be.
Now, I can't get the splash screen to take anything but the first 2 characters, again!!! No matter what I do, only the first 2 characters stick!
I've found 1 other bug too:
the remember feature on the LCD
lcd.command2(147,1); //turn remember on
lcd.command2(147,0); //turn remember off
I've tested this by inserting the block cursor on or off in between these lines, and the LCD remembers the setting each time it's powered up. Buy I've never gotten it to remember to keep the backlight on indefintely with the command:
lcd.command2(66,0); //turn on backlight for ever
254 66 [minutes] Backlight will stay on for [minutes]. If [minutes]= 0 backlight will stay on permanently.
I got a 4 on the NAK scale... Is that a good grade? What's it mean in layman's terms? Bad wiring? My wiring seems good. I made the harness myself! (Ha, I know what you're thinking...)
Tomorrow I'll triple check my resistors, and use different wires, I'll just use 6 inch jumper wires. I twisted my sda/scl/ground/5 volt wiring all together, --it's only 6 inches long, so that should be a problem...
I'm about ready to got back to the dreaded 7 wire plain old LCD!
Yes, I gathered 4 was bad, I just didn't know 'how bad' it's greek to me.
This will be great if it's just the resisters! I searched that out and found some folk same 4.7, some 1.5. I hope that's the problem!
g'night.
I did some screenshots of the effects of various resistors here:
Now admittedly I used 2.2K there, so perhaps that isn't the issue. The other thing to try is slowing down the I2C transmission. Offhand I can't remember how to do that. I know how to speed it up.
I may be gone for a few days, but don't go away!
I have 2 of these MatrixOrbital displays, I could try the other one. I don't think it's the display because most things are working fine. (I hate to mess up the default splash on the 2nd one, if I can't get something but vertical bars)
I'm going to try all new wiring, new resistors (4.7K), fiddling with TWBR, a new USB cable, and a different AC outlet for my wall wart!