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 » Please help me understand why this code works sometimes

November 07, 2010
by gusr205
gusr205's Avatar

I programmed the 328p for the temperature monitor. Then I decided to add a line before the print out so it prints

(LCD Line 1)Temp Monitor (LCD Line2) A/D 132 of 1024 (LCD Line 3)Temperature: +67.1 F

When I use the code below it prints out the following:

(LCD line 1)Temp Monitor (LCD line 2) 024 (LCD Line 3)Temperature: +67.1 F

Somehow it suppresses the the first portion of line 2. In fact if I put anything after lcd_line_two(); the second line prints as above.

// write message to LCD
lcd_home();
lcd_line_one();
fprintf_P(&lcd_stream, PSTR("Temp Monitor   "));
lcd_line_two();
    lcd_write_string(PSTR("A/D: "));
lcd_write_int16(last_sample);
lcd_write_string(PSTR(" of 1024 "));
    lcd_line_three();
fprintf_P(&lcd_stream, PSTR("Temperature: %+3.1f"), temp_avg);
lcd_write_data(0xdf);
lcd_write_string(PSTR("F             "));

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

}

return 0; }

However if I just reverse the order of the print commands (no code changes it prints fine as below)

    // write message to LCD
lcd_home();
lcd_line_one();
fprintf_P(&lcd_stream, PSTR("Temp Monitor   "));
lcd_line_three();
    fprintf_P(&lcd_stream, PSTR("Temperature: %+3.1f"), temp_avg);
lcd_write_data(0xdf);
lcd_write_string(PSTR("F             "));
    lcd_line_two();
    lcd_write_string(PSTR("A/D: "));
lcd_write_int16(last_sample);
lcd_write_string(PSTR(" of 1024 "));

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

Can someone please explain why this would be? Thank you.

November 07, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi gusr205,

This is a strange issue. If I had to take a guess I would say it is something to do with compiler optimizations. The lcd_write_string() uses the delay functions to do the timing which uses NOPs. In certain situations with the right flags the compiler optimizes them away. At least that is what I think is happening.

To test if that is the case, remove the all optimizations from the compiler by changing the -O flag from -Os to -00 (that is dash capital O zero) in the Makefile on the GCCFLAGS line. Then make sure you remove all the .o and .hex files from your project folder and recompile the program. Let me know us know if that was the cause of the problem.

Humberto

November 08, 2010
by gusr205
gusr205's Avatar

Humberto

If I understood correctly I changed the makefile from -Os to -O0 Capital O zero. I deleted the .o and .hex files.

It did not solve the problem. I would be glad to send you the code file to see if you can verify the problem on your kit.

Regards,

Gusr205

November 08, 2010
by mrobbins
(NerdKits Staff)

mrobbins's Avatar

Hi Gusr205,

Looking at your original code, I think the actual problem is that the spaces from the

lcd_write_string(PSTR("F             "));

line are actually "wrapping around". Due to the weird way the LCD controller manages its own memory space, if you run past line 3, you'll actually start writing over line 2's memory space! That's why if you wrote the spaces first, you'd then immediately overwrite them with your "A/D" line, and it would appear fine.

Thinking about your 20-character wide space:

12345678901234567890
Temperature: +67.1dF
            ^^^^^^
            6 character wide space for number

I think what you actually want to do is:

fprintf_P(&lcd_stream, PSTR("Temperature:%+6.1f"), temp_avg);
lcd_write_data(0xdf);
lcd_write_data('F');

This replaces the lcd_write_string that had the spaces with one that simply prints the letter F and doesn't overflow past the end of line 2. It also allocates 6 spaces to the total temperature number, 1 of which is for the "+" or "-", 1 of which is for the ".", leaving at most 4 for digits (1 after decimal and 3 before). (Also see our printf format strings tutorial if you haven't already.) So the above code will print:

12345678901234567890
Temperature:  +7.1dF
Temperature: +67.1dF
Temperature:+107.1dF

depending on the number of digits of the current temperature. (I have used the letter "d" here instead of the degree sign, but the code above would actually print the degree sign onto the LCD.)

Hope that helps!

Mike

November 08, 2010
by gusr205
gusr205's Avatar

Mike-

Thank you for your quick reply. You are indeed correct. I have proven to myself that the 3rd line does in fact overwrite line 2. That was surprise to me! I thought it might be an overwrite problem but thought line 1 was overwriting line 2.

Anyway thank you again for your help. This fixed the problem!

Regards,

Gusr205

November 08, 2010
by gusr205
gusr205's Avatar

Mike-

Is there a good place to find a programmers manual for the C code used by Nerdkits compiler? I see some syntax in your example that I haven't seen in the tutorials.

Tnx,

Post a Reply

Please log in to post a reply.

Did you know that 20 LEDs can be controlled from 11 microcontroller pins, to make a twinkling heart outline? Learn more...