Need help with 16x2 LCD without library

Hi, i am trying to use 16x2 lcd without using library. I wrote a simple program to drive the lcd.
I have some problem.
When i send a string (LCD_String) , every things works fine.
but when i send an integer(LCD_Int) , the display is not correct (Example:LCD_Int(123456789); , but i got -13035 + some weird symbol on the screen)

I am not sure what the problem is. Can anyone help me?

Sorry for my English.Thanks!

Here is the code:

#define D4 5
#define D5 4
#define D6 3
#define D7 2
#define RS 12
#define E 11


void LCD_Write(byte cmd,int cmddta){
  digitalWrite(RS,cmddta); //Change RS for command/data
  digitalWrite(D4,(cmd & 0b00010000)>>4);
  digitalWrite(D5,(cmd & 0b00100000)>>5);
  digitalWrite(D6,(cmd & 0b01000000)>>6);
  digitalWrite(D7,(cmd & 0b10000000)>>7);
  delay(0.5);
  digitalWrite(E,HIGH);
  delay(0.5);
  digitalWrite(E,LOW);
  delay(0.5);
  digitalWrite(D4,(cmd & 0b00000001)>>0);
  digitalWrite(D5,(cmd & 0b00000010)>>1);
  digitalWrite(D6,(cmd & 0b00000100)>>2);
  digitalWrite(D7,(cmd & 0b00001000)>>3);
  delay(0.5);
  digitalWrite(E,HIGH);
  delay(0.5);
  digitalWrite(E,LOW);
  delay(0.5);
}


void LCD_Char(char character){
  LCD_Write(character,1);
}

void LCD_String(String str){
 char *cstr = new char[str.length()];
 strcpy(cstr, str.c_str());
 while(*cstr) LCD_Char (*cstr++);
}

void LCD_Int(unsigned long n){
  int nDigits = floor(log10(abs(n)))+1 ;
  char c[10];
  sprintf(c, "%d", n);
  for (int i=0;i<nDigits;i++) LCD_Char(c[i]);
}



void LCD_Clear(){
  LCD_Write(0x01,0);
}

void LCD_Init(){
  LCD_Write(0x33,0);
  delay(0.5);
  LCD_Write(0x32,0);
  delay(0.5);
  LCD_Write(0x28,0);
  delay(0.5);
  LCD_Write(0x0C,0);
  delay(0.5);
  LCD_Write(0x06,0);
  delay(0.5);
  LCD_Write(0x01,0);
  delay(0.5);
}

void LCD_SetCursor(int row, int col){
   if (col == 0)LCD_Write((row | 0x80),0);
   if (col == 1)LCD_Write((row | 0x80)+ 0x40,0);
   if (col == 2)LCD_Write((row | 0x80)+ 0x10,0);
   if (col == 3)LCD_Write((row | 0x80)+ 0x50,0);
   delay(0.5);

}



void setup() {
  Serial.begin(9600);
for(int i = 2;i < 13; i++){ //Set pin 2 ,3 ,4, 5 to output mode
  pinMode(i,OUTPUT);
}
delay(50);
LCD_Init();
}

void loop() {
  LCD_SetCursor(0,0);
  LCD_String("Hello World!");
  LCD_SetCursor(1,1);
  LCD_Int(millis());
 }
1 Like

Hi, welcome to the forum.

Why ? why ? why ? (three times "why ?").
The Arduino LiquidCrystal library is a good library, and those displays are not always straightforward to use. Why would you want to write your own code ?

For example, when the Arduino starts, the display might be in 4-bit or in 8-bit mode. It needs a special sequence to capture control of the display. Also the use of the delays has been optimized in the LiquidCrystal library. There are a few other things with the lcd display and they all are solved in the LiquidCrystal library.

About your question, I'm not sure that the 'floor' will work. Since it is a zero-terminated string after the sprintf, just print LCD_Char until c [ i ] is zero. The parameter 'n' is a unsigned long, and you use sprintf with % d, which is for a signed integer.

Hi, Thanks for your reply.
I know LiquidCrystal is a good library ,and i use it a lot.
I need to write my own code because somebody in the planet (AKA teacher) challenge me to not use the library, also i want to challenge(or punish :stuck_out_tongue:) my self to see what can i done.

And I learned a lot of things that i can't if i use the library :smiley:

void LCD_Int(unsigned long n){
 int nDigits = floor(log10(abs(n)))+1 ;
  char c[10];
  sprintf(c, "%d", n);
  for (int i=0;i<nDigits;i++) LCD_Char(c[i]);

My original idea is split the integer and send it one by one to LCD_Char.
floor is used to get the length of n. and use sprintf to split n into array c.
and send it one by one using "for (int i=0;i<nDigits;i++) LCD_Char(c*);"*

Construct your for loop as follows and you can completely remove any referrence to nDigits

for (int i=0;c[i] > 0 ;i++) 
  LCD_Char(c[i]);

And don't miss this : The parameter 'n' is a unsigned long, and you use sprintf with % d, which is for a signed integer.

KenF:
Construct your for loop as follows and you can completely remove any referrence to nDigits

for (int i=0;c[i] > 0 ;i++) 

LCD_Char(c[i]);

Thank you very much :slight_smile:

Peter_n:
And don't miss this : The parameter 'n' is a unsigned long, and you use sprintf with % d, which is for a signed integer.

i tired (int n) sill the same problem

king2deer:
i tired (int n) sill the same problem

LCD_Int(123456789); is passing a long.

you had the function expecting an UNSIGNED long and were handling it like a signed integer....

then you modified the function to expect an int...

The point is... make sure that the number you pass to the function matches what the function can work with and vice versa.

BulldogLowell:
LCD_Int(123456789); is passing a long.

you had the function expecting an UNSIGNED long and were handling it like a signed integer....

then you modified the function to expect an int...

The point is... make sure that the number you pass to the function matches what the function can work with and vice versa.

Sorry my fault....
So how can i do it right?

void LCD_String(String str){
 char *cstr = new char[str.length()];
 strcpy(cstr, str.c_str());
 while(*cstr) LCD_Char (*cstr++);
}

The new operator allocates memory. Where do you free the memory? Nowhere, so that memory becomes unavailable - a memory leak.

There is no excuse for using Strings. But, if you absolutely must, and need access the the individual characters, the [] operator, or the charAt() method, provides that. Extracting the string that the String wraps is just plain useless. Not freeing the memory used is stupid.

PaulS:

void LCD_String(String str){

char *cstr = new char[str.length()];
strcpy(cstr, str.c_str());
while(*cstr) LCD_Char (*cstr++);
}



The new operator allocates memory. Where do you free the memory? Nowhere, so that memory becomes unavailable - a memory leak.

There is no excuse for using Strings. But, if you absolutely must, and need access the the individual characters, the [] operator, or the charAt() method, provides that. Extracting the string that the String wraps is just plain useless. Not freeing the memory used is stupid.

What can i use if i don't use string?

What can i use if i don't use string?

Wrong question.

You should be asking "What can i use if i don't use String?"
Note the capital S on the correct question. The answer is use strings (null terminated char arrays) instead of Strings (objects created by the String library). The latter are generally agreed to use memory less efficiently which is best avoided on a device such as the average Arduino.

Need help with 16x2 LCD without library

Have you tried a Google search for "LCD programming examples".

Don

UKHeliBob:
Wrong question.

You should be asking "What can i use if i don't use String?"
Note the capital S on the correct question. The answer is use strings (null terminated char arrays) instead of Strings (objects created by the String library). The latter are generally agreed to use memory less efficiently which is best avoided on a device such as the average Arduino.

Thanks for your help~
:slight_smile: