NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » LCD horizontal scrolling

August 10, 2010
by UthReal
UthReal's Avatar

I I am trying to build a function to add to the LCD that will allow for a command line looking output. As an example, when you press return on dos it goes to the next line, and when all the lines are full it begins to rotate the lines upward. I have never programmed in c before I got the kit so there are a lot of things I am having trouble with. Primarily changing the value of variables containing text. The only way I have found to print a string to the LCD is by making what I am assuming an array.

char st[20] = "My string"

What I have done is set a variable to each line, 2-4. When I use my function print(var), it goes into a switch that will allow for the first 2 lines to write as normal, changing to the next line by adding to the switch.

void print(char st[20]) {
  // scrolling output for lines 2-4
  int currentline=2;

                  //12345678901234567890
  char clear[20] = "                    ";
  char line2[20];
  char line3[20];
  char line4[20];

  switch (currentline) {
    case 2:
     lcd_line_two();
     fprintf_P(&lcd_stream, PSTR("%s"), clear);
     lcd_line_two();
     fprintf_P(&lcd_stream, PSTR("%s"), st);
     currentline = 3;
     line2 = st;
     break;
    case 3:
     lcd_line_three();
     fprintf_P(&lcd_stream, PSTR("%s"), clear);
     lcd_line_three();
     fprintf_P(&lcd_stream, PSTR("%s"), st);
     currentline = 4;
     line3 = st;
      break;
    case 4:
     lcd_line_four();
     fprintf_P(&lcd_stream, PSTR("%s"), clear);
     lcd_line_four();
     fprintf_P(&lcd_stream, PSTR("%s"), st);
     line4 = st;
     currentline = 5;

     break;
    case 5:

       lcd_line_two();
       fprintf_P(&lcd_stream, PSTR("%s"), clear);
       lcd_line_two();
       fprintf_P(&lcd_stream, PSTR("%s"),line3);
       lcd_line_three();
       fprintf_P(&lcd_stream, PSTR("%s"), clear);
       lcd_line_three();
       fprintf_P(&lcd_stream, PSTR("%s"),line4);
       lcd_line_four();
       fprintf_P(&lcd_stream, PSTR("%s"), clear);
       fprintf_P(&lcd_stream, PSTR("%s"), st);
     break;
  }
}

I have no idea if this will work, but the trouble I am having is how to set the variable to hold the string for each line. I am currently using line# = st to set the variable. Now I am getting an incompatible data type error. So can anyone offer a work around?

My second question is how do I get the courser to come on? And is it possible to light the entire row of coursers on line 1?

I don't yet have a final goal for my kit, I am just adding features to it to see what it will turn into.

August 11, 2010
by Rick_S
Rick_S's Avatar

I don't believe you can use the pound sign in a variable name. Also, if your string length is greater than 19 characters, the screen will continue on the other half of the line. 4 x 20 LCD's are actually wired like a 2 x 40 so line one will wrap to line 3 and line 2 will wrap to line 4. You'll have to keep this in mind when programming and create a method of wrapping like you would expect to see it.

Rick

August 11, 2010
by Ralphxyz
Ralphxyz's Avatar

Since you are experimenting and learning you should search the Nerdkit forums for "scroll".

You find a lot of helpful discussions.

Ralph

August 11, 2010
by UthReal
UthReal's Avatar

LOL, I guess I messed up in naming this post, I am actually looking for a line by line vertical scroll. Much like what is seen in a command prompt when the screen is full. I have searched the forums for scroll and, I can only seem to find a horizontal, not vertical. A marquee, to put it simply.

Thanks for the tip about the LCD being 2x40, it should shed a little more light on the situation. I think I am going to take a closer look at the LCD.c and LCD.h files to see if I can get a better grasp of how the LCD actually functions.

And the "#" was only used as a wild-card during the explanation, not as an actual variable name.

August 11, 2010
by Ralphxyz
Ralphxyz's Avatar

Here is a really simple vertical scrolling thread. Vertical Scrolling

And now I am going to do something really incredulous and post some code to answer someone's question.

Is this progress or what?

#define F_CPU 14745600
#include <stdio.h>
#include <avr/io.h>
#include <inttypes.h>

#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
//#include <avr/delay.h>
#include <util/delay.h>

#include "../libnerdkits/io_328p.h"
#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"

int main() { // LED as output DDRC |= (1<<PC5);

while(1)

{
// fire up the LCD
lcd_init();
lcd_home();

// print message to screen 
lcd_write_string(PSTR("Page1Page1Page1")); 
lcd_line_two(); 
lcd_write_string(PSTR("Page1Page1Page1")); 
lcd_line_three(); 
lcd_write_string(PSTR("Page1Page1Page1")); 
lcd_line_four(); 
lcd_write_string(PSTR("********************"));

delay_ms(1000); 
lcd_line_one(); 
lcd_write_string(PSTR(" Page2Page2Page2")); 
lcd_line_two(); 
lcd_write_string(PSTR(" Page2Page2Page2")); 
lcd_line_three(); 
lcd_write_string(PSTR(" Page2Page2Page2")); 
lcd_line_four();
lcd_write_string(PSTR("MMMMMMMMMMMMMMMMMMMM "));   //space is needed or first line next page is truncated

delay_ms(1000); 
lcd_line_one(); 
lcd_write_string(PSTR("Page3Page3Page3")); 
lcd_line_two();
lcd_write_string(PSTR("  Page3Page3Page3")); 
lcd_line_three(); 
lcd_write_string(PSTR("  Page3Page3Page3")); 
lcd_line_four(); 
lcd_write_string(PSTR("LLLLLLLLLLLLLLLLLLLL"));

delay_ms(1000); 
lcd_line_one(); 
lcd_write_string(PSTR("   Page4Page4Page4")); 
lcd_line_two(); 
lcd_write_string(PSTR("   Page4Page4Page4")); 
lcd_line_three(); 
lcd_write_string(PSTR("   Page4Page4Page4")); 
lcd_line_four(); 
lcd_write_string(PSTR("WWWWWWWWWWWWWWWWWWWW ")); //space is needed or first line next page is truncated

delay_ms(1000); 
lcd_line_one(); 
lcd_write_string(PSTR("Page5Page5Page5")); 
lcd_line_two(); 
lcd_write_string(PSTR("    Page5Page5Page5")); 
lcd_line_three(); 
lcd_write_string(PSTR("    Page5Page5Page5")); 
lcd_line_four(); 
lcd_write_string(PSTR("uuuuuuuuuuuuuuuuuuuu"));
delay_ms(1000);

    // write message to serial port
    // printf_P(PSTR("%.2f degrees F\r\n"), temp_avg);
}
return 0; }

Both of these methods probable are to simple but they do work, and can be further refined.

Ralph

August 11, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi UthReal,

I have a couple of comments that might get you going in the right direction with your idea. You are actually very close, and I think its subtleties of working with strings in C that are tripping you up. Strings in C are really just arrays of char types terminated by a null character. So when you do:

 char clear[20] = "12345678901234567890";

You are actually declaring an array of size 20, but sticking something that is 21 bytes long it since there is a null character at the end of your string literal. It is better practice to declare literal character arrays like this:

 char* clear = "12345678901234567890";

This makes it more apparent that clear is a pointer to a character array. If you are declaring variables for strings to be filled in later like

 char fillLater[21];

You need to make sure you have enough space for the terminating null character. As for your project I think you might benefit a lot from checking out the functions provided in string.h, particularly strcpy. I put together the following code snippet that can uses it and can probably help you.

  char* clear = "                    ";
  char* line1 = "one                 ";
  char* line2 = "two                 ";
  char* line3 = "three               ";
  char* line4 = "four                ";

  while(1)
  {

   //print the stuff to the LCD
  lcd_clear_and_home();
  fprintf_P(&lcd_stream,PSTR("%s"),line1);
  lcd_line_two();
  fprintf_P(&lcd_stream,PSTR("%s"),line2);
  lcd_line_three();
  fprintf_P(&lcd_stream,PSTR("%s"),line3);
  lcd_line_four();
  fprintf_P(&lcd_stream,PSTR("%s"),line4);

  //copy the strings
  strcpy(line4,line3);
  strcpy(line3,line2);
  strcpy(line2,line1);
  strcpy(line1,clear);

  delay_ms(1000);   
  }

Note that for the code snipped above to work I removed the -j .text from the Makefile. This way I can define static strings into RAM.

Your function is definitely in the right direction. Let us know how this idea evolves, I think it is going in a cool direction.

Humberto

August 11, 2010
by UthReal
UthReal's Avatar

Thanks alot for the info!

Humberto, do you know where I can find more information about what files can be included? I know about the string.h but I have no idea what is all avalible with it, or where to find it.

August 12, 2010
by Rick_S
Rick_S's Avatar

This LINK has a list of all the mudules in the standard avr-gcc install. If you select the module at from the list, it will show you a breakdown of what is included in it.

Rick

August 31, 2011
by serkanozkan
serkanozkan's Avatar

//why the fprintf_P string declaration function is makes black rectangular boxes, // where the text suppose to be on the screen ? //According to humberto's examples it is should be working but it did not.

//Sample below;

char* line1 = " www.NerdKits.com "; lcd_clear_and_home(); //print the declared value to the LCD fprintf_P(&lcd_stream,PSTR("%s"),line1);

//But if I make like this not a problem!

Sample ; fprintf_P(&lcd_stream, PSTR(" www.NerdKits.com "));

August 31, 2011
by Ralphxyz
Ralphxyz's Avatar

Notice how much easier it is to read when you use the "Indent Selection as Code Block" button?

//Sample below;
char* line1 = " www.NerdKits.com "; 
lcd_clear_and_home();                                      //print the declared value to the LCD 
fprintf_P(&lcd_stream,PSTR("%s"),line1);

Sample ; 
fprintf_P(&lcd_stream, PSTR(" www.NerdKits.com "));

It "appears" your pointer is not working as expected.

Ralph

Post a Reply

Please log in to post a reply.

Did you know that you can connect digital calipers to a microcontroller? Learn more...