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 » Change the lcd.c / lcd.h

March 31, 2011
by lnino
lnino's Avatar

Hi at all.

After I was able to realize the scrolling text on my 4x20 NK display I thought it would be nice to put the code into the lcd.c. So you don't have to write many lines of code to have just one scrolling text. So you can call your function with scroll_line_two("Scrolling Text") if you want a scrolling text.

First i made a seperated project with main und while(1) and put the code of the scrolling text in a function which I call in the main. This worked really great. After I was sure that my code works I wanted to put the function in the lcd.c and lcd.h.

But when I did that I got an error when I tried to start the make command. Can somebody tell me what I did wrong?

Error Message:

avr-gcc -g -Os -Wall -mmcu=atmega168  -o lcd.o -c lcd.c
lcd.c: In function 'scroll_line_two':
lcd.c:212: error: invalid initializer
lcd.c:212: error: (near initialization for 'linetwo')
make: *** [lcd.o] Error 1

Code in my lcd.c:

Scrolling Text

Code of my function in the lcd.h (ifndef and define are missing):

void lcd_set_type_data();
void lcd_set_type_command();
void lcd_write_nibble(char c);
void lcd_write_byte(char c);
void lcd_clear_and_home();
void lcd_home();
void lcd_write_data(char c);
void lcd_write_int16(int16_t in);
void lcd_write_int16_centi(int16_t in);
void lcd_write_string(const char *x);
void lcd_line_one();
void lcd_line_two();
void lcd_line_three();
void lcd_line_four();
void lcd_goto_position(uint8_t row, uint8_t col);
void lcd_init();
void scroll_line_two(char a);

#include <stdio.h>
int lcd_putchar(char x, FILE *stream);

#endif
March 31, 2011
by bretm
bretm's Avatar

PSTR() requires a string literal (it points to a string in program memory) and you're passing it a char in SRAM (on the stack).

If you're trying to create a function that takes a PROGMEM string then you need to use char* instead of char as the function argument, and you don't need PSTR because the caller will have already done that part. Also, I would put "_P" at the end of the function name so the caller knows to pass in a PSTR.

But you may also want to create a version that reads strings from SRAM instead of PROGMEM so that you can scroll strings that are created at run-time.

April 01, 2011
by lnino
lnino's Avatar

Hi bretm,

many thanks for your reply.

Hmm I think I don't understand that.

Can you explain it more simple why the code of the function works great in my scrollingext.c and don't work when I put it in my lcd.c to call it form scrollingtext.c?

Thanks for helping.

April 02, 2011
by lnino
lnino's Avatar

Hi bretm,

i tried it like you said (I hope I got it right), but it won't work. I only see horizontal lines in line two.

Here is the way like I tried without having the function in the ldc.c (That worked great)

Code of my scrolling_text_function.c:

// for NerdKits with ATmega168

#define F_CPU 14745600

#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

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

    // prototypes
    void scroll_line_two(char);

int main() {

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

  scroll_line_two(" Your NerdKits hardware is OK!       ");

// Main loop. 
while(1) {

}

  return 0;
}

void scroll_line_two(char a)
{
    int8_t scrollPos=0;

    uint8_t i;

    const char *linetwo = PSTR(a);

    uint8_t linetwolen = strlen_P(linetwo);

        while(1) {

        lcd_line_two();

            for(i=0; i<20; i++) {      
            lcd_write_data(pgm_read_byte(linetwo + ((scrollPos+i)%linetwolen)));   
            }

        scrollPos = (scrollPos + 1) % linetwolen;

        delay_ms(200); 
        }
}

But when I try to put the function in the lcd.c and the prototype in lcd.h it won't work. First the error with invalid initializer. After that I corrected the code like you said, but I am only getting horizontal lines in line two.

Did I made somthing wrong?

Here is the code of the function in lcd.c und lcd.h

lcd.c

    void scroll_line_two(char* a)
    {

    // Variable to hold our current scroll offset. 
    int8_t scrollPos=0;

    // Variable to iterate through the 20-wide LCD screen. 
    uint8_t i;

    // This is our actual string, longer than the LCD width, 
    // stored in program memory (flash). 
    const char *linetwo = a;

    uint8_t linetwolen = strlen_P(linetwo);

        while(1) {   
        // Move to the 2nd line of the LCD.   
        lcd_line_two();

            for(i=0; i<20; i++) {        
            lcd_write_data(pgm_read_byte(linetwo + ((scrollPos+i)%linetwolen)));   
            }

        scrollPos = (scrollPos + 1) % linetwolen;

        // Delay about 1/5th of a second before re-displaying.   
        delay_ms(200); 
        }
}

lcd.h

void lcd_set_type_data();
void lcd_set_type_command();
void lcd_write_nibble(char c);
void lcd_write_byte(char c);
void lcd_clear_and_home();
void lcd_home();
void lcd_write_data(char c);
void lcd_write_int16(int16_t in);
void lcd_write_int16_centi(int16_t in);
void lcd_write_string(const char *x);
void lcd_line_one();
void lcd_line_two();
void lcd_line_three();
void lcd_line_four();
void lcd_goto_position(uint8_t row, uint8_t col);
void lcd_init();
void scroll_line_two(char* a);

#include <stdio.h>
int lcd_putchar(char x, FILE *stream);

#endif

Does anybody have an idea how I get that working?

Thanks for your help.

April 02, 2011
by bretm
bretm's Avatar

Are you trying to make a subroutine that let's you do scroll_line_two("some text") or to do scroll_line_two(PSTR("some text"))? those are two different things in atmega chips and you're still mixing them together. You got rid of the PSTR but you're still using strlen_P.

Take a look at a PGMSPACE tutorial to learn about the differences.

Don't try to merge it with the nerdkits library. Just make a new library. I'm not saying you, can't, I'm saying you shouldn't.

April 02, 2011
by lnino
lnino's Avatar

Hi bretm,

sorry I forgot to write how to call the function.

Code of my scrolling_text_embedded.c

// for NerdKits with ATmega168

#define F_CPU 14745600

#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

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

int main() {

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

  scroll_line_two(" Your NerdKits hardware is OK!       ");

// Main loop. 
while(1) {

}

  return 0;
}

This is how I use it when I have the function copied in my lcd.c file.

If you say it's better to use a new lib for those I think I will give it a try. :-)

I will have a look for such a tutorial. I want to understand what I write in c. What shall I use instead of strlen_P?

Thanks for your help.

April 04, 2011
by lnino
lnino's Avatar

Hi at all.

If somebody is interested in this, I was now able to solve this challenge. Maybe not the most correct solution but working.

lcd4x20ext.c

// lcd4x20ext.c
// for NerdKits

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include <stdio.h>

#include "lcd.h"
#include "lcd4x20ext.h"
#include "delay.h"

void scroll_line_one(char* lineone)
{
    // Variable to hold our current scroll offset. 
    int8_t scrollPos=0;

    // Variable to iterate through the 20-wide LCD screen.
    uint8_t i;

    // This is our actual string, longer than the LCD width, 
    // stored in program memory (flash).

    uint8_t lineonelen = strlen_P(lineone);

        while(1) {   
        // Move to the 1nd line of the LCD.   
        lcd_line_one();

            for(i=0; i<20; i++) {        
            lcd_write_data(pgm_read_byte(lineone + ((scrollPos+i)%lineonelen)));   
            }

        scrollPos = (scrollPos + 1) % lineonelen;

        // Delay about 1/5th of a second before re-displaying.   
        delay_ms(200); 
        }
}

lcd4x20ext.h

#ifndef __LCD4x20EXT_H
#define __LCD4x20EXT_H

void scroll_line_one(char* lineone);

#include <stdio.h>
int lcd_putchar(char x, FILE *stream);

#endif

scrolling_text_embedded.c

// scrolling_text_embedded.c
// for NerdKits with ATmega168

#define F_CPU 14745600

#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

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

int main() {

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

  scroll_line_one( PSTR("     Line1     ") );

// Main loop. 
while(1) {

}

  return 0;
}

Makefile

GCCFLAGS=-g -Os -Wall -mmcu=atmega168 
LINKFLAGS=-Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm
AVRDUDEFLAGS=-c avr109 -p m168 -b 115200 -P COM7
LINKOBJECTS=../libnerdkits/delay.o ../libnerdkits/lcd.o ../libnerdkits/uart.o ../libnerdkits/lcd4x20ext.o

all:    scrolling_text_embedded-upload

scrolling_text_embedded.hex:    scrolling_text_embedded.c
    make -C ../libnerdkits
    avr-gcc ${GCCFLAGS} ${LINKFLAGS} -o scrolling_text_embedded.o scrolling_text_embedded.c ${LINKOBJECTS}
    avr-objcopy -j .text -O ihex scrolling_text_embedded.o scrolling_text_embedded.hex

scrolling_text_embedded.ass:    scrolling_text_embedded.hex
    avr-objdump -S -d scrolling_text_embedded.o > scrolling_text_embedded.ass

scrolling_text_embedded-upload: scrolling_text_embedded.hex
    avrdude ${AVRDUDEFLAGS} -U flash:w:scrolling_text_embedded.hex:a
June 15, 2012
by live4the1
live4the1's Avatar

When I run this makefile, I get an error indicating that lcd4x20ext.o is missing. How do I get this file?

June 15, 2012
by Ralphxyz
Ralphxyz's Avatar

What are you trying to do run some modified Arduino code?

You would need the lcd4x20ext.c program and then compile that to get the lcd4x20ext.o.

Ralph

June 15, 2012
by Ralphxyz
Ralphxyz's Avatar

Well I actually read the whole thread instead just live4the1's question.

So you have Inino's lcd4x20ext.c and lcd4x20ext.h files so just compile them to get lcd4x20ext.o!

You can use the Nerdkit initialload program MakeFile just substitute lcd4x20ext for initialload.

live4the1, what are trying to do?

Ralph

June 15, 2012
by live4the1
live4the1's Avatar

After I posted, I thought that I probably need to compile the code. I have installed CYGWIN but I'm not sure how to use it yet. How would I go about compiling using CYGWIN?

June 15, 2012
by live4the1
live4the1's Avatar

Right now, I'm just going through the forums and looking at programs that look like something that I may want to work with in the future and try to figure them out. Obviously, I am a newbie at this so I'm just trying to figure things out. I actually tried using a makefile with the substitutions but I was not able to make it work for some reason.

June 16, 2012
by Ralphxyz
Ralphxyz's Avatar

Especially since you are "just starting out", why would you use CYGWIN and not the Nerdkit download package?

You would be up and running two days ago. Especially if you are expecting answers here in the Nerdkit forum, while CYGWIN is "occasionally" mentioned it is not our common compiler environment.

You will probable get your answer about using CYGWIN but a lot more of us would be able to help you if you just used the Nerdkit download.

Once you were able to load the Nerdkit initialload project changing the MakeFile would be all you would need to do and you could be moving on, now you have to wait.

Ralph

June 16, 2012
by raildoc
raildoc's Avatar

I'm bugged! My "control" program is based on tempsensor with digital logic led and lcd outputs. It works fine on a 168, but I was running out of memory-so I switched to a 328p. After making all the Nanoguide changes, I pre-checked it with led-blink and two-line lcd scroll programs-no problem. I loaded my control program on the 328p, and the logic portions for the leds worked OK-but the lcd was garbage. All I get is a line4 string on line 1 and nothing else. I am missing all the ADC and voltage outputs and other text. I am literally double-checking everything: the programs are exact (I think) line and syntax copies (except for the 328p mods); I have two new re-wired USB-powered boards, two working 328s, two program headers-even two lcds. Nada. I've gone through the Forums. The lcd works with the 328 scrolling program, but not my larger control program? Help, please!

June 16, 2012
by Ralphxyz
Ralphxyz's Avatar

Well as missle3944 just found out sometimes you really need to start from scratch and delete all .hex files. You might even delete any new .o files.

Then break you none running program down.

What runs in your program?

Find what runs (individual functions) and then start adding the running functions.

Ralph

June 16, 2012
by missle3944
missle3944's Avatar

Raildoc,

Try to change the make file flag from -0s to -0O

That might help.

Thats a strange problem though,

-Dan

June 16, 2012
by live4the1
live4the1's Avatar

Ralph, I did try compiling it using the procedure in the nerdkits manual but it did not work for some reason so I assumed that it needed to be compiled some other way since it is meant to be used as a library function. I will continue working with it and figure something out. Thanks.

July 11, 2012
by lnino
lnino's Avatar

Hi guys,

i have been on vacation, so I wasn't able to join the discussion. Are there any questions about my code? Or could all problems be solved?

greetings Nino

July 12, 2012
by Ralphxyz
Ralphxyz's Avatar

Boy Inio, that was a long vaction (April 04 - July 12).

There was some compiling errors but they seem to have been fixed, thank you.

Ralph

July 12, 2012
by lnino
lnino's Avatar

Hi Ralph, such a Long vacation would be Great. smile. I meant I was in vacation when the reply of "live4the1" came on 15th of June. But you are right some Time has passed by since the Last Time I was posting here. I have made some nice small projects in the meanwhile combined with geocaching. If there is a interest i can Post the projects. Not that difficult but cute. :-) Great to Hear that the compiling problems in this thread could have been solved.

greetings Nino

July 13, 2012
by Ralphxyz
Ralphxyz's Avatar

I think everybody has a GPS project in the back of their minds if not active projects.

There have been some great GPS code samples and discussions.

I'd be interested in seeing you geocaching projects.

Of course there should be a GPS article added to the Nerdkits Community Library.

Ralph

Post a Reply

Please log in to post a reply.

Did you know that a NerdKit can be used to build an iPhone-controlled R/C car? Learn more...