Author Topic: 16x2 LCD display duty cycle  (Read 5090 times)

0 Members and 1 Guest are viewing this topic.

Offline KerryTopic starter

  • Jr. Member
  • **
  • Posts: 30
  • Helpful? 0
16x2 LCD display duty cycle
« on: August 10, 2010, 09:50:30 AM »
Hello,

I recently built a clock using a 16x2 LCD display (Newhaven Display variety) to show the date and time.  It worked great for a couple of days, then just stopped working.  When I first noticed it, it was just not updating (time was several hours old and not changing).  I turned it off, waited a while, then turned it back on.  The backlight came on, but no characters were written to the screen.

I noticed in the datasheet when I was building it that the LCD has a duty cycle of 1/16.  I'm not sure what that means (1/16th of what?  What time scale?  LCD being on, or the controller to change the display?) but thought, "eh, lots of other people use these things for clocks" and I didn't worry about it.  Now I'm wondering if that was a mistake and the reason that it stopped working.  I was updating it once/second and rewriting the entire screen (didn't yet figure out how to only rewrite the two characters showing the seconds).

Has anyone else managed to kill an LCD?  I haven't found anyone else with this problem via google.

Thanks,

Kerry

Offline Soeren

  • Supreme Robot
  • *****
  • Posts: 4,672
  • Helpful? 227
  • Mind Reading: 0.0
Re: 16x2 LCD display duty cycle
« Reply #1 on: August 10, 2010, 04:48:31 PM »
Hi,

I noticed in the datasheet when I was building it that the LCD has a duty cycle of 1/16.  I'm not sure what that means (1/16th of what?  What time scale?  LCD being on, or the controller to change the display?)
Download the datasheet for the controller chip on the display and make sure you do the bias correctly. I don't think that this is the reason for it dying though.
Perhaps it will come back alive in a few days if latched up, but updating once a second won't kill it.

Just a thought... Do you make a full initialize of the LCD when resetting the controller?

If you need more help, you need to post the exact LCD (or better, a link to it's datasheet) and the controller you use (and the source to the program).
Regards,
Søren

A rather fast and fairly heavy robot with quite large wheels needs what? A lot of power?
Please remember...
Engineering is based on numbers - not adjectives

Offline KerryTopic starter

  • Jr. Member
  • **
  • Posts: 30
  • Helpful? 0
Re: 16x2 LCD display duty cycle
« Reply #2 on: August 12, 2010, 07:46:22 AM »
Thanks for the help.  I'll post source code when I get home tonight.  I did write it myself, but it's very similar to examples that can be found around the 'net.  Here is the datasheet:  http://www.newhavendisplay.com/specs/NHD-0216K1Z-NSW-FBW-L.pdf

The controller is packaged with the LCD screen (SPLC780D).  Data sheet for the controller is here:  http://www.newhavendisplay.com/app_notes/SPLC780D.pdf

So right where it says 1/16th duty, it also says 1/5 bias.  What does that mean?

Thanks!

-Kerry

Offline KerryTopic starter

  • Jr. Member
  • **
  • Posts: 30
  • Helpful? 0
Re: 16x2 LCD display duty cycle
« Reply #3 on: August 12, 2010, 08:00:24 PM »
Here is the source code used to communicate with the LCD.  I can post the files where the calls are made, too, but I am guessing that isn't necessary - let me know if I'm wrong  :).  To initialize the display, I call the lcd_init() method here, but that only happens on initial application of power.  For each 1 Hz write sequence... well, see the code at the bottom (second code block).

Code: [Select]
/***************************************************************************
*
* File:  lcd.c
* Date:  05/3/2010
* Auth:  K. Loux
*
***************************************************************************/

// Local headers
#include "lcd.h"
#include "utilities.h"

// Initialization function for the LCD display
// After calling this function, text can be sent to the display
void init_lcd(void)
{
// Configure the required ports as outputs
CTRL_DDR |= (1 << READ_WRITE) | (1 << REG_SELECT) | (1 << ENABLE);
DATA_DDR = 0xFF;

// Initialize outputs to OFF
CTRL_PORT &= ~((1 << READ_WRITE) | (1 << REG_SELECT) | (1 << ENABLE));
DATA_PORT = 0x00;

// =============== Begin display start-up sequence ===============
SET_BIT_LOW( CTRL_PORT, ENABLE );
_delay_ms(45);// Wait >40 msec after power is applied
lcd_init_cmd(0x30, 8000); // Command 0x30 = Wake up (wait >5 msec)
lcd_init_cmd(0x30, 200); // Command 0x30 = Wake up #2 (wait >160 usec)
lcd_init_cmd(0x30, 200); // Command 0x30 = Wake up #3 (wait >160 usec)

// Configure LCD display
lcd_cmd(0x38); //Function set: 8-bit/2-line/5x8 pixel characters
lcd_cmd(0x10); //Set cursor
lcd_cmd(0x0c); //Display ON; Cursor OFF
lcd_cmd(0x06); //Entry mode set

// Clear the screen and return home
lcd_clear();

return;
}

// Sends a command to the lcd display, but pauses for the specified interval
// (in usec) instead of checking for the busy flag
void lcd_init_cmd(char i, double delay)
{
// Put the data on the port
DATA_PORT = i;

// Select "instruction mode" and "write mode"
CTRL_PORT &= ~((1 << REG_SELECT) | (1 << READ_WRITE));

// Create falling edge on enable pin
SET_BIT_HIGH( CTRL_PORT, ENABLE );
_delay_us(1);
SET_BIT_LOW( CTRL_PORT, ENABLE );

// Delay the specified number of usec
_delay_us(delay);

return;
}

// Sends a command to the lcd display (register select is low)
// Waits for busy flag to drop before continuing
void lcd_cmd(char i)
{
// Put the data on the port
DATA_PORT = i;

// Select "instruction mode" and "write mode"
CTRL_PORT &= ~((1 << REG_SELECT) | (1 << READ_WRITE));

// Create falling edge on enable pin
SET_BIT_HIGH( CTRL_PORT, ENABLE );
_delay_us(1);
SET_BIT_LOW( CTRL_PORT, ENABLE );

// Pause to allow command to process
wait_for_lcd();

return;
}

// Sends data to the lcd display (register select is high)
void lcd_data(char i)
{
// Put the data on the port
DATA_PORT = i;

// Select "data mode"
SET_BIT_HIGH( CTRL_PORT, REG_SELECT );

// Select "write mode"
SET_BIT_LOW( CTRL_PORT, READ_WRITE );

// Create falling edge on enable pin
SET_BIT_HIGH( CTRL_PORT, ENABLE );
_delay_us(1);
SET_BIT_LOW( CTRL_PORT, ENABLE );

// Pause to allow command to process
wait_for_lcd();

return;
}

// Prints null terminated strings to the LCD display
// Calls lcd_data() to write each character
void lcd_string(const char *s)
{
const int max_len = 32;// 16x2 display can hold maximum of 32 characters
unsigned int i = 0;

// Parse the string, adding each character to the display
while (i < max_len && s[i] != '\0')
{
// Print the next character
lcd_data(s[i]);

// Increment the index
i++;
}

return;
}

// Clears the lcd screen and returns home
void lcd_clear(void)
{
lcd_cmd(0x01); // Clear the screen
lcd_cmd(0x02); // Return home

// Pause to allow the command to complete
wait_for_lcd();

// Wait for another 2 msec
// FIXME:  Not sure why this is needed, but without it, text is jumbled
_delay_ms(2);

return;
}

// Checks to see if the LCD has finished processing the previous command
// Returns 0 for not busy and 1 for busy
// Returns 0 when busy flag is not available during start-up, too
unsigned char lcd_busy(void)
{
// Set the data port to input
DATA_DDR = 0x00;
DATA_PORT = 0x00;

// Select "instruction mode"
SET_BIT_LOW( CTRL_PORT, REG_SELECT );

// Select "read mode"
SET_BIT_HIGH( CTRL_PORT, READ_WRITE );

// Create falling edge on enable pin
SET_BIT_HIGH( CTRL_PORT, ENABLE );
_delay_us(1);
SET_BIT_LOW( CTRL_PORT, ENABLE );

// The MSB on the data port is the busy flag
int busy = (DATA_PORT >> 7);

// Set the data port back to output
DATA_DDR = 0xff;

return busy;
}

void lcd_hex(unsigned char i)
{
unsigned char h, l;
h = i / 16;
l = i - h * 16;

lcd_string("0x\0");
lcd_data(char_to_hex(h));
lcd_data(char_to_hex(l));

return;
}

// Puts cursor on second line
void lcd_newline(void)
{
// Send the command to move the cursor to the next line
lcd_cmd(0xC0);

return;
}

char char_to_hex(unsigned char i)
{
switch (i)
{
case 0:
return '0';
break;

case 1:
return '1';
break;

case 2:
return '2';
break;

case 3:
return '3';
break;

case 4:
return '4';
break;

case 5:
return '5';
break;

case 6:
return '6';
break;

case 7:
return '7';
break;

case 8:
return '8';
break;

case 9:
return '9';
break;

case 10:
return 'A';
break;

case 11:
return 'B';
break;

case 12:
return 'C';
break;

case 13:
return 'D';
break;

case 14:
return 'E';
break;

case 15:
return 'F';
break;
}

return 'X';
}

// Waits for the LCD to not be busy (examines busy flag)
void wait_for_lcd(void)
{
while (lcd_busy())
_delay_us(50);

return;
}

The code called at 1 Hz intervals for updating the display:
Code: [Select]
void update_clock_display(void)
{
// Talk to the DS1307 and get the current time
TIME_STRUCT time;
unsigned char error;
error = get_clock_time(&time);

// Update the global seconds variable
m_seconds = time.sec;

...
// some stuff removed for brevity
// create XXX_string variables, null terminated, representing hours, min, sec, etc.
...

// Clear the LCD display
lcd_clear();

// Update the display with the current time
lcd_string(hour_string);
lcd_data(':');
lcd_string(min_string);
lcd_data(':');
lcd_string(sec_string);
lcd_data(' ');
if (time.am)
lcd_string("AM \0");
else
lcd_string("PM \0");
send_time_zone_string(time_zone);

// Second line
lcd_newline();
send_dotw_string(time.dotw);
lcd_data(' ');
send_month_string(time.month);
lcd_data(' ');
lcd_string(day_string);
lcd_string(", \0");
lcd_string(year_string);

return;
}

Let me know if more information would be useful.

Thanks!

-Kerry

Offline Soeren

  • Supreme Robot
  • *****
  • Posts: 4,672
  • Helpful? 227
  • Mind Reading: 0.0
Re: 16x2 LCD display duty cycle
« Reply #4 on: August 13, 2010, 03:06:29 PM »
Hi,

I cannot see any obvious blunders, but then, it has worked for some days, so there's probably nothing wrong there. Nothing that could kill off the display at least.

If your controller is doing a lot of other stuff, there's a great potential for optimizing the code however (the most obvious inefficiency is that you update the entire date each second).

Personally, I would write it off as a freak accident, perhaps ESD damage at an earlier time manifestating it self and just replace the LCD - don't throw the broken one out, test it at a later day, sometimes these things reanimate with no particular clue to the cause.

If/when you use another LCD, make sure to take precautions against ESD!

You didn't change anything in the code after it ran?
Regards,
Søren

A rather fast and fairly heavy robot with quite large wheels needs what? A lot of power?
Please remember...
Engineering is based on numbers - not adjectives

Offline Soeren

  • Supreme Robot
  • *****
  • Posts: 4,672
  • Helpful? 227
  • Mind Reading: 0.0
Re: 16x2 LCD display duty cycle
« Reply #5 on: August 13, 2010, 03:09:38 PM »
Forgot to mention...
The BIAS arrangement is on p.17 of the controller datasheet.
I assume the 1/16 Duty cycle just means that it updates 1 char each line at a time, but since it isn't discussed further in the datasheet, just let it pass - won't hurt your display.
Regards,
Søren

A rather fast and fairly heavy robot with quite large wheels needs what? A lot of power?
Please remember...
Engineering is based on numbers - not adjectives

Offline paulstreats

  • Supreme Robot
  • *****
  • Posts: 1,381
  • Helpful? 21
Re: 16x2 LCD display duty cycle
« Reply #6 on: August 13, 2010, 03:44:52 PM »
If you have a spare set of jumper cables, try to control it manually to bring up 1 character or something (I did this once a few years ago as a demonstration). It will let you know if the display is defective (refund or free replacement could be possible on a bad unit)

 Also have you checked your pins with a multimeter? You could just have a bad solder joint on the enable pin or signal pin on both the lcd or your microcontroller?

Offline KerryTopic starter

  • Jr. Member
  • **
  • Posts: 30
  • Helpful? 0
Re: 16x2 LCD display duty cycle
« Reply #7 on: August 17, 2010, 06:37:29 AM »
Thanks for the replies!

You didn't change anything in the code after it ran?

Well, I haven't changed it since the version of the code I posted above, but it changed many times during the testing/debugging process.  This was my first LCD project, so I started by just trying to write one character and expanded from there.  What are some ways to kill an LCD with code?

-Kerry

 


Get Your Ad Here

data_list