Problem with HD44780 Display

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello All,

 

I am a first time poster so I hope that this is in the correct spot!

 

I am having some difficulties with my HD44780 LCD display. When I write to line 1, it writes without issue; however, it takes whatever is written to line 1 and writes it to line 2 and shifted over 8 positions (please see the attached picture). I have some information below. Please let me know if there is anything else that I can add.

 

The Setup:

  • I am using an ATmega 328P on an Arduino Uno
  • Using a 10k pot for the contrast
  • R/~W is tied to ground
  • Enable has a 68k ohm pull-down resistor

 

Possible problems I have excluded:

  • I have tried two separate LCDs, which tells me it is the code.

 

Also, I cannot write to line 2.

 

Any help would be greatly appreciated. I have sifted through the web and the datasheet to no avail!

#define F_CPU 16000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
#include <stdio.h>
#include "hd44780.h"

uint8_t whoop_count = 23;
char display_count[16];
char padding[16];
extern char lcd_string_array[];
char* display = &lcd_string_array[0];
char* pad = &lcd_string_array[16];
char i;
*/

/*******************************************************************************************/
//				tcnt0_init
/*******************************************************************************************/

void tcnt0_init(void) {
	TIMSK0 |= (1 << TOIE0); //enable TCNT0 overflow interrupt
	TCCR0B |= (1 << CS01) | (1 << CS00);
}

void tcnt1_init(void) {
		
		TIMSK1 |= (1 << OCIE1A);
		TCCR1A |= (1 << COM1A1);
		TCCR1B |= (1 << CS12) | (1 << WGM12);
		OCR1A = 0xFF;	
}

ISR(TIMER1_COMPA_vect) {
	sprintf(display_count, "whoop count:%d", whoop_count);
	//sprintf(padding, "               ");
	strncpy(display, display_count, 16);
	//strncpy(pad, padding, 16);
	refresh_lcd(lcd_string_array);
	
}

int main(void)
{
	lcd_init();
	tcnt1_init();
   	sei();

    while (1) {}
}

//////////////HEADER FILE////////////////////////////////
//hd44780.h

//HD44780 command summary
/*
clear display 	                                0x01
Return cursor to home, and un-shift display 	0x02
move cursor right, don’t shift display 	        0x04
move cursor right, do shift display (left) 	0x05
move cursor right, don’t shift display  	0x06
move cursor right, do shift display (left) 	0x07
turn display off 	                        0x08
display on, cursor off, 	                0x0C
display on, cursor on, steady cursor 	        0x0E
display on, cursor on, blinking cursor 	        0x0F
shift cursor left 	                        0x10
shift cursor right 	                        0x14
shift display left 	                        0x18
shift display right 	                        0x1C
set cursor position                             0x80+position
*/

//some commands that are defined
#define SET_DDRAM_ADDR  0x80    // must "OR" in the address
#define RETURN_HOME     0x02
#define CLEAR_DISPLAY   0x01
#define LCD_1602_ADDR 0x3F

#include "stdint.h"
//assumes timing specified at LCD Vdd=4.4-5.5v

#define CURSOR_VISIBLE 0 //Set 1 for visible cursor,  0 for invisible
#define CURSOR_BLINK   0 //Set 1 for blinking cursor, 0 for continuous

#define CMD_BYTE  0x00
#define CHAR_BYTE 0x01

//The hardware port configuration for 4-bit operation is assumed
//to be all on one port.  Control lines are assumed to be in the
//lower nibble.  The control lines may be in another order but
//must still be within the lower nibble on the same port. The data
//lines are asuumed to be in the upper nibble with MSB of LCD
//aligned with the port MSB. (bit 7 is MSB on both) Bit zero of
//LCD_PORT is unused.
#define LCD_PORT           PORTD
#define LCD_PORT_DDR       DDRD
#define LCD_CMD_DATA_BIT   1    //zero is command, one is data //0?? R/S
#define LCD_RDWR_BIT       2    //zero is write,   one is read //1?? R/~W
#define LCD_STROBE_BIT     3    //active high strobe           //2??

//Set to the width of the display, assumption is a two line display
#define NUM_LCD_CHARS 16

//Set the the lcd interface mode. One indicates SPI mode, zero
//indicates 4-bit mode. SPI mode assumes lcd is write only and
//that the SPI port is already initalized. 4-bit mode initalizes
//the RW bit as write. Busy flag reads will set it to read for
//as long as the Busy bit is read.
#define SPI_MODE          1

void send_lcd(uint8_t cnd_or_char, uint8_t data);
void send_lcd_8bit(uint8_t cnd_or_char, uint8_t data, uint16_t wait);
void set_custom_character(uint8_t data[], uint8_t address);
void set_cursor(uint8_t row, uint8_t col);
void uint8_8_8_8_8_8_8_8_2lcd(uint8_t number);
void uint16_2lcd(uint16_t number);
void int2lcd(int8_t number);
void cursor_on(void);
void cursor_off(void);
void shift_right(void);
void shift_left(void);
void cursor_home(void);
void line1_col1(void);
void line2_col1(void);
void fill_spaces(void);
void string2lcd(char *lcd_str);
void strobe_lcd(void);
void clear_display(void);
void char2lcd(char const a_char);
void lcd_init(void);
void refresh_lcd(char const lcd_string_array[]);
void lcd_int32(int32_t l, uint8_t fieldwidth, uint8_t decpos, uint8_t bSigned, uint8_t bZeroFill);
void lcd_int16(int16_t l, uint8_t fieldwidth, uint8_t decpos, uint8_t bZeroFill);
void set_DDRAM_addr16(void);
void set_DDRAM_addr0(void);

///////////////LCD_C_FILE//////////////////////////////
//hd44780.cpp
//A set of useful functions for writing LCD characer displays
//that utilize the Hitachi HD44780 or equivalent LCD controller.
//This code also includes adaptation for 4 bit LCD interface.
//Right now support only exists or 2x16 displays.


//Original source by R. Traylor ~2006
//Refactored by R. Traylor 10.7.09
//New features added by Kirby Headrick 11.20.09
//lcd_send with delay added by William Dillon 10.8.10
//Refactored, and cleaned up again by R. Traylor 12.28.2011, 12.30.2014

#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
#include <stdlib.h>
#include "hd44780.h"

#define NUM_LCD_CHARS 16

//If using an interrupt driven, one char at a time style lcd refresh
//for a 2x16 display, use this array to place anything to be displayed
char lcd_string_array[32];  //holds two strings to refresh the LCD

char lcd_str[16];  //holds string to send to lcd

//-----------------------------------------------------------------------------
//                               send_lcd
//
// Sends a command or character data to the lcd. First argument of 0x00 indicates
// a command transfer while 0x01 indicates data transfer.  The next byte is the
// command or character byte.
//
// This is a low-level function usually called by the other functions but may
// be called directly to provide more control. Most commonly controlled
// commands require 37us to complete. Thus, this routine should be called no more
// often than every 37us.
//
// Commnads that require more time have delays built in for them.
//
void send_lcd(uint8_t cmd_or_char, uint8_t byte){
  if(cmd_or_char==0x01){LCD_PORT |=  (1<<LCD_CMD_DATA_BIT);} //data
  else                 {LCD_PORT &= ~(1<<LCD_CMD_DATA_BIT);} //command
  uint8_t temp = LCD_PORT & 0x0F;     //perserve lower nibble, clear top nibble
  LCD_PORT   = temp | (byte & 0xF0);  //output upper nibble first
  strobe_lcd();                       //send to LCD
  LCD_PORT   = temp | (byte << 4);    //output lower nibble second
  strobe_lcd();                       //send to LCD
}

//------------------------------------------------------------------
//                          refresh_lcd
//
//When called, writes one character to the LCD.  On each call it
//increments a pointer so that after 32 calls, the entire lcd is
//written. The calling program is responsible for not calling this
//function more often than every 80us which is the maximum amount
//of time it might take for any operation to take in this function.
//This includes the possibility for a movement to the next line.
//These functions are homeline() or homeline2.
//
//The array is organized as one array of 32 char locations to make
//the index handling easier.  To external functions that write into
//the array it will appear as two separate 16 location arrays by
//using an offset into the array address.
//
//        LCD display character index postions (2x16 display)
//  -----------------------------------------------------------------
//  |  0|  1|  2|  3|  4|  5|  6|  7|  8|  9| 10| 11| 12| 13| 14| 15|
//  -----------------------------------------------------------------
//  | 16| 17| 18| 19| 20| 21| 22| 23| 24| 25| 26| 27| 28| 29| 30| 31|
//  -----------------------------------------------------------------
//
void refresh_lcd(char const* lcd_string_array) {

  static uint8_t i=0;           // index into string array
  static uint8_t null_flag=0;   // end of string flag

  if(lcd_string_array[i] == '\0') null_flag = 1;

  // if a null terminator is found clear the rest of the display
  if(null_flag) send_lcd(CHAR_BYTE, ' ');
  else send_lcd(CHAR_BYTE,lcd_string_array[i]);

  i++;   //increment to next character

  //delays are inserted to allow character to be written before moving
  //the cursor to the next line.
  if(i == 16)
  {
      // goto line2, 1st char
      _delay_us(40);
      line2_col1();
	  null_flag = 0;
  }
  else if(i == 32)
  {
      // goto line1, 1st char
      _delay_us(40);
      line1_col1();
      null_flag=0;
      i=0;
  }
  
}//refresh_lcd

//-----------------------------------------------------------------------------
//                          set_cursor
//
//Sets the cursor to an arbitrary potition on the screen, row is either 1 or 2
//col is a number form 0-15, counting from left to right
void set_cursor(uint8_t row, uint8_t col){
    send_lcd(CMD_BYTE, 0x80 + col + ((row-1)*0x40));
}
//TODO: use this method of moving the cursor in the other cursor moving routines

//-----------------------------------------------------------------------------
//                          uint8_2lcd
//
//Takes a 8bit unsigned and displays it in base ten on the LCD. Leading 0's are
//not displayed.
//TODO: optimize by removing the mod operators
//TODO: Should be renamed uint8_2lcd(). Also, implement a uint16_2lcd() function

void uint8_2lcd(uint8_t number){
    if  (number == 0)  {send_lcd(CHAR_BYTE, 0x30                ); }
    else{
      if(number >= 100){send_lcd(CHAR_BYTE, 0x30+number/100     ); }
      if(number >= 10) {send_lcd(CHAR_BYTE, 0x30+(number%100)/10); }
      if(number >= 1)  {send_lcd(CHAR_BYTE, 0x30+(number%10)    ); }
    }
}

//-----------------------------------------------------------------------------
//                          uint16_2lcd
//
//Takes a 16bit unsigned and displays it in base ten on the LCD. Leading 0's are
//not displayed.
//TODO: optimize by removing the mod operators

void uint16_2lcd(uint16_t number){
    if  (number == 0)  {send_lcd(CHAR_BYTE, 0x30                ); }
    else{
      if(number >= 100){send_lcd(CHAR_BYTE, 0x30+number/100     ); }
      if(number >= 10) {send_lcd(CHAR_BYTE, 0x30+(number%100)/10); }
      if(number >= 1)  {send_lcd(CHAR_BYTE, 0x30+(number%10)    ); }
    }
}
//-----------------------------------------------------------------------------
//                          int2lcd
//
//Takes a 8bit signed and displays it in base ten on the LCD. Leading 0's are
//not displayed.
//
void int2lcd(int8_t number){
    //if < 0, print minus sign, then take 2's complement of number and display
    if(number < 0){send_lcd(CHAR_BYTE, '-'); _delay_us(40); uint8_2lcd(~number+1);}
    else          {uint8_2lcd(number);                                            }
}

//-----------------------------------------------------------------------------
//                          cursor_on
//
//Sets the cursor to display
void cursor_on(void){send_lcd(CMD_BYTE, 0x0E);}

//-----------------------------------------------------------------------------
//                          cursor_off
//
//Turns the cursor display off
void cursor_off(void){send_lcd(CMD_BYTE, 0x0C);}

//-----------------------------------------------------------------------------
//                          shift_right
//
//shifts the display right one character
void shift_right(void){send_lcd(CMD_BYTE, 0x1E);}

//-----------------------------------------------------------------------------
//                          shift_left
//
//shifts the display left one character
void shift_left(void){send_lcd(CMD_BYTE, 0x18);}

//-----------------------------------------------------------------------------
//                          strobe_lcd
//Strobes the "E" pin on the LCD module. How this is done depends on the interface
//style. The 4-bit mode is presently kludged with nop statements to make a suitable
//pulse width for a 4 Mhz clock.
//TODO: make number of nops executed dependent on F_CPU, not hardcoded
//
void strobe_lcd(void){
 LCD_PORT |= (1<<LCD_STROBE_BIT);           //set strobe bit
 asm("nop"); asm("nop"); asm("nop"); asm("nop"); //4 cycle wait
 asm("nop"); asm("nop"); asm("nop"); asm("nop");
 asm("nop"); asm("nop"); asm("nop"); asm("nop");
 asm("nop"); asm("nop"); asm("nop"); asm("nop");
 LCD_PORT &= ~(1<<LCD_STROBE_BIT);          //clear strobe bit
 asm("nop"); asm("nop"); asm("nop"); asm("nop"); //4 cycle wait
 asm("nop"); asm("nop"); asm("nop"); asm("nop");
 asm("nop"); asm("nop"); asm("nop"); asm("nop");
 asm("nop"); asm("nop"); asm("nop"); asm("nop");
}

//-----------------------------------------------------------------------------
//                          clear_display
//
//Clears entire display and sets DDRAM address 0 in address counter. Requires
//1.8ms for execution. Use only if you can withstand the big delay.
//
void clear_display(void){
  send_lcd(CMD_BYTE, CLEAR_DISPLAY);
  _delay_us(1800);   //1.8ms wait for LCD execution
}

//-----------------------------------------------------------------------------
//                          cursor_home()
//
//Sets DDRAM address 0 in address counter. Also returns display from being
//shifted to original position.  DDRAM contents remain unchanged. Requires
//1.5ms to execute. Use only if you can withstand the big delay. Consider
//using line1_col1().
//
void cursor_home(void){
  send_lcd(CMD_BYTE, RETURN_HOME);
  _delay_us(1500);  //1.5ms wait for LCD execution
  }

//-----------------------------------------------------------------------------
//                          line2_col1()
//
//Put cursor at line 2, column 0 by directly maniuplating the DDRAM address
//pointer. 37us required for execution.
//
void line2_col1(void){
  //change DDRAM address to 40, first char in second row, executes in 37us
  send_lcd(CMD_BYTE, (SET_DDRAM_ADDR | 0x40));
}

//-----------------------------------------------------------------------------
//                          line1_col1()
//
//Put cursor at line 1, column 0 by directly maniuplating the DDRAM address
//pointer. 37us required for execution.
//
void line1_col1(void){
  //change DDRAM address to 0, first char in first row, executes in 37us
  send_lcd(CMD_BYTE,(SET_DDRAM_ADDR | 0x00));
}

//-----------------------------------------------------------------------------
//                          fill_spaces
//
//Fill an entire line with spaces.
void fill_spaces(void){
	uint8_t i;
	for (i=0; i<=(NUM_LCD_CHARS-1); i++){
		send_lcd(CHAR_BYTE, ' ');
                _delay_us(40);  //40us wait between characters
	}
}

//----------------------------------------------------------------------------
//                            char2lcd
//
//Send a single char to the LCD.
//usage: char2lcd('H');  // send an H to the LCD
//
void char2lcd(char const a_char){send_lcd(CHAR_BYTE, a_char);}

//----------------------------------------------------------------------------
//                            string2lcd
//
//Send a ascii string to the LCD.
void string2lcd(char *lcd_str){
  uint8_t i;
  for (i=0; i<=(strlen(lcd_str)-1); i++){send_lcd(CHAR_BYTE, lcd_str[i]);
  _delay_us(40);  //execution takes 37us per character
  }
}

//----------------------------------------------------------------------------
//                            lcd_init
//
//Initialize the LCD
//
void lcd_init(void){
  _delay_ms(16);      //power up delay
  LCD_PORT_DDR = 0xF0                    | //initalize data pins to output
                 ((1<<LCD_CMD_DATA_BIT)  | //initalize control pins to output
                  (1<<LCD_STROBE_BIT  )  |
                  (1<<LCD_RDWR_BIT)   );
	//LCD_PORT &= ~(1<<LCD_RDWR_BIT);					 //always in write mode
  //do first four writes in 8-bit mode assuming reset by instruction
  //command and write are asserted as they are initalized to zero
  LCD_PORT = 0x30; strobe_lcd(); _delay_ms(8);  //function set,   write lcd, delay > 4.1ms
  LCD_PORT = 0x30; strobe_lcd(); _delay_us(200);//function set,   write lcd, delay > 100us
  LCD_PORT = 0x30; strobe_lcd(); _delay_us(80); //function set,   write lcd, delay > 37us
  LCD_PORT = 0x20; strobe_lcd(); _delay_us(80); //set 4-bit mode, write lcd, delay > 37us
  //continue initializing the LCD, but in 4-bit mode
  send_lcd(CMD_BYTE, 0x20); _delay_ms(7); //function set: 4-bit, 2 lines, 5x8 font
  //send_lcd(CMD_BYTE, 0x08, 5000);
  send_lcd(CMD_BYTE, 0x01); _delay_ms(7);  //clear display
  
  send_lcd(CMD_BYTE, 0x06);  _delay_ms(5); //cursor moves to right, don't shift display
  send_lcd(CMD_BYTE, 0x0C | (CURSOR_VISIBLE<<1) | CURSOR_BLINK); _delay_ms(5);
}

 

Attachment(s): 

This topic has a solution.

Jesse Harris

Last Edited: Mon. Apr 16, 2018 - 11:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've been mentoring the OP but I'm lost; almost no experience with LCDs. The posting should probably be moved to a more appropriate forum.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your program is too complex. You say you can't write to line 2, so post an example where you just write something to line 2, without ISRs and other complicating factors. Just "hello world" to line 2.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First: Peter Fleury's good old HD44780 lib is often recommended because it "works".

 

If your program does not work, try to make it simpler.

You have probably cut out a lot of code, but it would still be (a bit) better if you also remove the ISR.

Doing (lengthy) stuff such as updating displays from within an ISR is bad practice anyway.

 

When looking at "whoop_count" you just print the same number every time.

Increment your "whoop_count" every time. If the cursor overflows. In a HD44780 it simply wraps around to the next line.

Your send_lcd() has a 37us timing constraint. Add those 37us to send_lcd() to make sure this timing requirement is met.

 

Why all the complicated copying ???

It makes it hard to follow what your code is actually doing.

Start with something simple, like:

int main(void)
{
    char buffer[40];
    int whoop_count = 0;

    lcd_init();
    // No timer, no interrupts.

    while (1) {
        sprintf( "Nr:%d", ++whoop_count);
        string2lcd( buffer);
        _delay_ms( 200);
    }
}

With this code you should see some numbers on the first line, then a delay (Display is written to outside the visible area) and when it r reaches CGRAM address 0x40 you should see some numbers apear on line 2.

 

A lot of the code I see does seem to be badly written. For example the comment about the 37us timing, and then ad-hoc adding those 37us in other functions where they think it might be needed... Putting 3 or 4 statements on a single line after an "if "

It took me a while to understand how "lcd_string_array" is supposed to be used. I think the Idea is that you write data to it from within a "normal" function, and every time the interrupt triggers it writes a single character from the "lcd_string_array" to the LCD.

That also explains why the 37us (40us) delay is not in the send_lcd() function.

Data shared between interrupts and normal code should (almost always) be declared as "volatile".

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Last Edited: Mon. Apr 16, 2018 - 10:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paulvdh wrote:
First: Peter Fleury's good old HD44780 lib is often recommended because it "works".

+1,000,000

 

Save your sanity and use Peters Library!

 

http://homepage.hispeed.ch/peter...

 

Halfway down the page

 

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you. I went ahead and used your suggestion and implemented Fleury's library. This fixed it. Ultimately, however, there was another issue. The header <util/delay.h> was not seeing the F_CPU. Even though I had it defined prior to that initialization. 

 

Thanks for your reply!

 

 

Jesse Harris

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
I've been mentoring the OP

The OP is one lucky person to have such a mentor!!

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is an interesting situation. Its a Senior "Capstone Project" in the ECE School at Oregon State U. There are three students which makes it relatively small for the program. They have to do the electronic and mechanical (ecb and enclosure) as well as plugs, cables, and such to make it a fully useable device. It has to be "presented" to the public at an expo during Engineering Week in May. 

 

The project, itself, happened in a somewhat curious way. There is a young grad student in the department I am associated with. Her father came to her with a very interesting idea. She came to me because she knew nothing about the technology (her father thought that she was smart and could figure it out) and she thought that I might. Now, I am a real pushover when it comes to pleasant, intelligent, young women. Its even worse when they have a potential microcontroller project. Alas, I did not have the time to help her. But, it was right at the time when the ECE School was advertising around campus for ideas for Capstone projects. The grad student and I proposed this particular project, and the three-student group bit. After some negotiating back in October, they were off and running. 

 

This is the program that allows Arduino hardware in the first proof-of-concept stage, but requires a full, original hardware build for the final "product". Even at the proof-of-concept stage, they are allowed to implement only 60% of it using Arduino. They have "3D printed" the enclosure and have designed something that probably is not full IP-65 but not terribly far from that. 

 

As an aside, the original posting was driven by a very common "problem". The poster had written the code, himself, and had put a LOT of time into trying to get it to work. He was really reluctant to scrap all that time and effort to adopt a third-party library. He finally got to the point where he was running out of time and making no visible progress. When he came to me, today, I recommended the Fleury library, but, even then, he was reluctant to make the jump. I think that it was finally the recommendations, here, that convinced him. It only took him an hour or two to get everything running, even the part he had spent well over a day "spinning his wheels".

 

They will probably not be able to demonstrate full function of this thing before it has to be presented. That is only slightly their "fault", however, because it happens to require cooperation of a willing bee hive, and weather is just not suitable, now, to do it.

 

We really don't get much detail about student projects, here, and I thought some of you might be a little interested. This one does seem to be a bit more "real world" and "complete" than what we often seem to get. And, I've had the chance to work with a great group of students. All told, I have very positive vibes about this project.

 

Best wishes

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Tue. Apr 17, 2018 - 05:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
The poster had written the code, himself, and had put a LOT of time into trying to get it to work. He was really reluctant to scrap all that time and effort to adopt a third-party library

I commend the OP for their effort and resiliency.

ka7ehk wrote:
He finally got to the point where he was running out of time and making no visible progress. When he came to me, today, I recommended the Fleury library, but, even then, he was reluctant to make the jump.

Again, the OP is a rare find for a student here around this time of year.  Usually we get the "PLEASE HELP ME!", or "I pay for code"

 

 This thread is also a bit of an odd duck as well.  As you know we get 'oodles' of LCD questions here over the course of the year and the threads can get quite long as the OP is either belligerent to realize they have coded themselves into a corner, or not willing to do the work to resolve anything.  The OP in this case coded himself into a corner, but in a rare form, was willing to concede to recommendations rather than blame everything under the sun for why this or that does not work.  To me, this shows the OP has the maturity to LISTEN to what is being said and takes that information and uses it.  Something that will be needed i real life in his career.  And the thread essentially closed in less than 6 posts!

 

I looked again at the OP's code, and I have to agree with 

 

El Tangas wrote:
Your program is too complex.

 

Had the OP followed the datasheet and simply used the delayms/us() teh init phase should be relatively simple....a few lines of code.  Then its a matter of simply keeping track of where the cursor is and moving to the second line accordingly.  That would have been steps 1 and 2 of rolling your own code.  Step 3 is adding the capability to move the cursor and erasing characters maybe.

 

In the end the OP has done what has been done hundreds(thousands) of times before....Used something that has already been done, and proven.  I mean, how many different ways are there to code a driver for the LCD?  Unless there is a strict, written edict that one must code their own, then I see no reason not to use something that is proven, and openly provided to the public AS LONG as in your source code it clearly states where the code came from.  I used to use Peters driver all the time until I switched to I2C backpack controlled LCD's and switched to Davide Gironis adaptation of Peter Fleurys driver.  In both cases I have it in the source code where I got the driver from.

 

ka7ehk wrote:
This one does seem to be a bit more "real world" and "complete" than what we often seem to get.

No argument there!

 

ka7ehk wrote:
And, I've had the chance to work with a great group of students.

Does not happen very often these days does it?

ka7ehk wrote:
All told, I have very positive vibes about this project.  

Makes it all worthwhile doesn't it?  Hopefully an update will be posted.

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:
switched to Davide Gironis adaptation of Peter Fleurys driver.
   Link please?

 

 

Click Link: Get Free Stock: Retire early!

share.robinhood.com/jamesc3274

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am confused here.

How does this:

ka7ehk wrote:
The poster had written the code, himself,
correlate to this:

//Original source by R. Traylor ~2006
//Refactored by R. Traylor 10.7.09
//New features added by Kirby Headrick 11.20.09
//lcd_send with delay added by William Dillon 10.8.10
//Refactored, and cleaned up again by R. Traylor 12.28.2011, 12.30.2014

 

A long time ago, when I wrote my own HD44780 driver it took me weeks to get the first visible string of ascii on it.

I didn't have a logic analyser back then and not much experience with uC programming at all.

After a long time of searching for solutions I found a reference to some LCD's with an "extended temperature range" which needed a negative voltage on the contrast pin to make them work. And sure enough, when I put -3V on that pin the display came to life.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:

jgmdesign wrote:
switched to Davide Gironis adaptation of Peter Fleurys driver.
   Link please?

 

 

 

http://davidegironi.blogspot.com...

 

Cheers

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paulvdh wrote:
I am confused here.

How does this:

ka7ehk wrote:

The poster had written the code, himself, correlate to this:

 

//Original source by R. Traylor ~2006
//Refactored by R. Traylor 10.7.09
//New features added by Kirby Headrick 11.20.09
//lcd_send with delay added by William Dillon 10.8.10
//Refactored, and cleaned up again by R. Traylor 12.28.2011, 12.30.2014

I thought that odd as well, but considering Dr. W. endorsed the OP I did not question 

 

East Coast Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Had the OP followed the datasheet

You mean like some of us had to do before the Internet was invented? surprise

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

js wrote:

Had the OP followed the datasheet

You mean like some of us had to do before the Internet was invented? surprise

I thought you were a retired pensioner who does not care about this stuff anymore.....devil

 

Just keeping the pot stirred, right? wink

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I admit to not having read the code in detail. "writing it himself" was what I got from the face-face conversation. Clearly, from the attribution, thats not so. At this point, I don't think that it is a crucial detail. I was more interested in the "journey".

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just keeping the pot stirred, right?

Would I do anything like that?

I had a memory flash back of my first LCD project, a long time ago. These things happen at people of certain age even though one may not remember what one had for breakfast.

 

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good one John! Brilliant

East Coast Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user