Pages: [1] 2 3 4   Go Down
Author Topic: analog in to 4 bit LCD driver  (Read 11841 times)
0 Members and 1 Guest are viewing this topic.
Oakland California
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all,
I combined and modified some of the tutorials to allow driving an LCD display in 4 bit mode, to save digital pins. The result is a program that can display temperature on an LCD and turn a digital pin on and off, to control a heater or other device. I'd post it in the playground but I haven't figured out how to create a new page.

Enjoy!

Dave

/* Analog in to LCD 4 bits
 * ---------
 * Adapted from the "analog_read_send" and "lcd_8bits" tutorials.
 * This example uses 4 less pins on the Arduino than the 8 bit example.
 * It will take a reading from a 'K' Type thermocouple ice point reference chip
 * on Analog Input 2 and display the temperature in degrees Centigrade on the LCD.
 * One can also set a target temperature for turning a relay off, say for a heater,
 * at a given setpoint temperature. This is done on digital pin 4.
 *
 * These are the pins used on the LCD:
 *
 * - DI(register select), RW, DB4..DB7, Enable (7 in total)
 *
 * the pinout for LCD displays is standard and there is plenty
 * of documentation to be found on the internet.
 *
 * 2006, Dave Sopchak  glasspusher at outofoptions dot net
 *
 */
 
int DI = 12; // register select
int RW = 11;
int DB[] = {7, 8, 9, 10};
int Enable = 6;

int temperaturePin = 2;    // select the input pin for the temperature
int ledPin = 13;           // pin for the LED

void tickleEnable()
{
 // send a pulse to enable
 digitalWrite(Enable,HIGH);
 delayMicroseconds(1);  // pause 1 ms according to datasheet
 digitalWrite(Enable,LOW);
 delayMicroseconds(1);  // pause 1 ms according to datasheet
}

void cmdWriteSet()
{
 digitalWrite(Enable,LOW);
 delayMicroseconds(1);  // pause 1 ms according to datasheet
  digitalWrite(DI,0);
  digitalWrite(RW,0);
}
void LcdCommandWrite(int value)
{
 int i = 0;

  for (i=DB[3]; i >= DB[0]; i--) // high nybble first
  {
    digitalWrite(i, value & 128);
    value <<= 1;
  }
    cmdWriteSet();
    tickleEnable();

  for (i=DB[3]; i >= DB[0]; i--) // low nybble next
  {
    digitalWrite(i, value & 128);
    value <<= 1;
  }
    cmdWriteSet();
    tickleEnable();
}

void LcdDataWrite(int value)
{
 int i = 0;
 
 digitalWrite(DI, HIGH);
 digitalWrite(RW, LOW);
  
  for (i=DB[3]; i >= DB[0]; i--) // high nybble first
  {
    digitalWrite(i, value & 128);
    value <<= 1;
  }
    tickleEnable();

  for (i=DB[3]; i >= DB[0]; i--) // low nybble next
  {
    digitalWrite(i, value & 128);
    value <<= 1;
  }
    tickleEnable();
}

void setup (void)
{
 int i;
 for (i=Enable; i <= DI; i++)
   pinMode(i,OUTPUT);

 delay(100);
 // initiatize lcd after a short pause
 // needed by the LCDs controller
 LcdCommandWrite(0x28);  // function set:
  delay(64);             // 4-bit interface, 2 display lines, 5x7 font
                         // other interaces:
                         // 0x20 = 4 bit, 1 display line

 LcdCommandWrite(0x28);  // function set:
  delay(64);             // 4-bit interface, 2 display lines, 5x7 font
 
  LcdCommandWrite(0x06);  // entry mode set:
                         // increment automatically, no display shift
 delay(20);                      
 LcdCommandWrite(0x0E);  // display control:
                         // turn display on, cursor on, no blinking
 delay(20);                      
 LcdCommandWrite(0x01);  // clear display, set cursor position to zero  
 delay(100);                      
 LcdCommandWrite(0x80);  // display control:
                         // turn display on, cursor on, no blinking
 delay(20);      
}

void loop (void)
{
  int i, val = 0;
  
  for(i = 0; i < 20; ++i)
  {
        val += analogRead(temperaturePin);    // read the value from the sensor
        delay(50);
  }
  
  val /= 4.06;      // conversion value to millivolts
  
  digitalWrite(ledPin, HIGH);  // turn the ledPin on
  delay(500);                  // stop the program for some time
  digitalWrite(ledPin, LOW);   // turn the ledPin off
  
  if(val > 175 * 10)   // temperature in deg C times 10, since we're measuring to tenths of a degree
      digitalWrite(4,LOW);
   else
     digitalWrite(4,HIGH);

    LcdCommandWrite(0x02);  // set cursor position to zero  
  delay(10);                    
  firstDisplay(val);
}

void firstDisplay(int value)
{
  int first,second, third, fourth;
  
  first = value / 1000;    //
  second = (value - 1000 * first)/ 100;
  third = (value - 1000 * first - 100 * second)/ 10;
  fourth = (value - 1000 * first - 100 * second - 10 * third);
 
      LcdDataWrite('T');
      LcdDataWrite('e');
      LcdDataWrite('m');
      LcdDataWrite('p');
      LcdDataWrite(' ');
      LcdDataWrite('=');
      LcdDataWrite(' ');

      LcdDataWrite(value > 999 ? first + 48 :  ' ');  // begin onscreen
      LcdDataWrite(value > 99 ? second + 48 : ' ');
      LcdDataWrite(third + 48);
      LcdDataWrite('.');
      LcdDataWrite(fourth + 48);

      LcdDataWrite(' ');
      LcdDataWrite('C');
      LcdDataWrite(' ');
      LcdDataWrite(' ');
}
Logged

London
Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Great!  Just finished working on the 4-bit thing myself!  

Here's a wiki page i've started on LCDs.  
http://www.arduino.cc/playground/Code/LCD

Perhaps you can add your code as an attachment there.  Better still, if you find the 4-bit LCD library there acceptable, we can fold the two together.

Wish I'd had your work available smiley  At least after our efforts no newbies should be stuck on this stuff!

Adding a wiki page is as simple as accessing the page-to-be's URL with ?action=edit added to the end of the url.  e.g.
http://www.arduino.cc/playground/Main/GlasspusherTestPage?action=edit
would create the page "GlasspusherTestPage" in group "Main".
You'll need to sign up for a contributor account, but that takes all of 10 seconds:
http://www.arduino.cc/playground/Main/Participate#requestaccess

Going to read your code over now, and see what glaring errors I've made in my ver of the library.

neill
Logged

Oakland California
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey Neill,

I was playing around this weekend, trying to get everything to work well on a cold power up, and the following seems to work every time- works on a 20x4 LCD screen, and should also work on 1 and 2 line screens, although a 16x2 screen starts the second line at the 40th character. a 20x4 display does the first line, then the third, then the second, then the 4th...fyi.

the following does best in the setup function.

 int i;
 for (i=Enable; i <= DI; i++)
   pinMode(i,OUTPUT);

delay(200);

  LcdCommandWrite(2);  // set cursor to home
                        
 delay(200);                      
 LcdCommandWrite(2);  // do it again for good measure
                        
 delay(33);                      
 LcdCommandWrite(14);  // flat cursor, no blinking
 
 delay(50);                    
 
LcdCommandWrite(1);  // erase screen (if desired)
                      
 delay(20);    
Logged

Oakland California
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey Neill,


I'll give your code a look and see if we can't get the best of both of ours together (it might end up being all your's!) smiley-wink
Logged

London
Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Dave,

Thanks for the 4-line display tip.  

As it stands, does that 4bit library work for your 4-line LCD display without changing the code, if you just run it in 1 or 2 line mode and don't try to access the other positions?

I'm not too worried about the cursorTo() function yet.  I imagine a lot of people would comment that function out to save space, anyway.  If we can't easily make an across-the-board implementation of it, so be it.

The HD44780 standard is probably as much as I'd have the LCD4Bit library support, for now, and it doesn't seem to cover >2-line displays. People can always send a custom command to change the display mode AFTER lcd.init(), I guess.  My understanding is that the only crucial thing that HAS to be right in a 4-bit library is the sequence indicating 4-bit (not 8-bit).  If that's wrong then all subsequent commands are incorrectly interpreted.
Do you have a link to your 4-line LCD's datasheet?

One thing I'm keen on is that eventually there's a direct mapping between what's written on a datasheet and what's being done in our init().  It's so much better, for learners in particular, when one can follow that link and understand all the code, line for line.  I wasted energy following my component-specific datasheet in developing the 4-bit version of the lib, but I'll come back to the code this week and try to find a definitive source for the HD standard.

LCD-tech aside, one small thing I noted in your code was the extra work you were doing to convert the multidigit decimal number to a string on the lcd.

You can use the standard function atoi() to convert an integer to a string.  (That function isn't big, unlike sprintf, which uses about 1.5k!)

Code:
 int heat = 451;      
  char heat_str[4] = "   ";  //reserve the string space first
  itoa(heat, heat_str, 10);
  lcd.printIn(heat_str);

  //todo: make sure number can be notated within str length.

This assumes you make a string-printing function (here printIn()) for the lcd.  This can simply be a wrapper to multiple calls to your character printing fn.  (As seen in the original tutorial).

Neill
« Last Edit: October 16, 2006, 11:45:55 pm by neillzero » Logged

Oakland California
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey Neill,
I haven't tried your 4 bit library yet. The newer init code I posted above works fine for either a 2 or 4 line display. A quick glance at the excellent links you have on the LCD's processor's internal init functions leads me to believe that it probably isn't necessary to do a hard init of an LCD unless you want it to do a mode other than its native format (ie getting a 2 line display to only do 1 line). I don't have a 1 line display so I can't check that configuration. Thanks for the tip on the integer to string function. One thing I do enjoy about the Arduino is actually having to worry about keeping code lean and mean! Reminds me of the "good" old days with my Timex Sinclair smiley-wink

I could see people either using the "clear screen" or "reset to home" commands depending on what they want to do. "reset to home" sometimes looks nicer because it doesn't have the slight flicker that the "clear screen" function has.

Another interesting thing I found this weekend, after writing a little mac app to talk to the Arduino and set stuff on the LCD (if anyone's interested I'd be happy to post it) is that the serial(USB) port only seems to take in 65 bytes max at any one time? Is this a limitation of the hardware or the serial library?

At this rate, I might not get a chance to mess around with this until the weekend, but I've got plenty of stuff to read and try, thanks to you. Good show.

Dave
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i gave me a try on an LCD display today. but i failed  :'(
the display just got damn hot and nothing else. guess it's broken now, so i will buy a new one and try again.  :-/
i need the LCD for a present that has to be ready until first days of december, so i am kind of under pressure  smiley-wink
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

just wanted to say: AWESOME THREAD!! smiley

Thanx for your wiki link neillzero smiley

just wondered what LCD display I should get to start with.....
Logged

London
Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Westbam,

Where are you?  In the UK I recently bought a maplin "N27AZ" 16x2 with a backlight - expensive at 10 pounds.  That's what I tested the 4-bit library against during development.  Note that these seem to be web-only components at maplin now.

I plan to make a short tutorial about a simple device I made which incorporates this display (but we all make plans...)

If size is a factor, I'd be tempted to try to make do with a 1x8, as the 16 character displays are significantly longer than your arduino board.  Then again, it's nice to have a bit more space on the display for debugging a lot of stuff (when serial is tied up).

A backlight is going to drain a battery more quickly, but normally you can decide not to wire it up.

I'd get something cheap for your first build.  Then you'll learn what you can live with and what you're really missing.

Make sure it is HD44780-compatible.
« Last Edit: October 30, 2006, 09:40:41 am by neillzero » Logged

massachusetts
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was able to get the LiquidCrystal library to work okay with this:
http://www.sparkfun.com/commerce/product_info.php?products_id=791

Since it only works with 1 of the 2 lines, I wanted to try the LCD4Bit library instead.
(and of course I'd like to use less pins)

The example doesn't work - I haven't changed any of the wiring but looking at the code,
it seems that it uses the same pines as LiquidCrystal.

Anyone else used this specific display or am I out of luck with LCD4Bit?

Thanks for any info,
Rob
« Last Edit: November 17, 2006, 12:39:52 pm by rahji » Logged

London
Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Rob, I wrote the 4-bit library, so would be keen to help you get it to work.  I've only tested it so far on two devices (and they were from the same family).

I think maybe you've not tied RW low.  There are two things to watch for when using this library:
1. get the pins right (In your case, I don't think this is the problem)
2. tie RW low

1. Get the pins right:
I intentionally kept the pins the same between the LiquidCrystal library and 4BitLCD library, so if you have your circuit working with LiquidCrystal library, you should have to make only two changes:
- unplug the four unused databus lines DB0, DB1, DB2, DB3.
- tie the LCD's RW input to ground (see point #2 below).

Here are the default arduino digital pins the 4bit library expects you to use.  They can be found in LCD4Bit.cpp.

int RS = 12;
int RW = 11;  //irrelevant if USING_RW is false.
int Enable = 2;
//4-bit data bus should be a sequence of pins
int DB[] = {7, 8, 9, 10};  //wire these to DB4~7 on LCD.

Ideally, when someone creates an instance of LCD4Bit, they should be able to specify the pins they want to use.  Early days.

2. Tie RW low.
I wrote the 4-bit library for people who want to save on arduino pins.  As most applications only need to write data to the LCD and never read, we can save another pin by hard-wiring the LCD RW input to low (or whatever indicates a write-operation in your LCD data sheet).  The LCD4bit library expects this wiring and won't try to control the RW pin (by default).  You can disable this behaviour in LCD4bit.cpp by finding the line
int USING_RW = false;
and setting it to true.

Making changes to the library
If you make changes in LCD4Bit.cpp, be sure to delete LCD4Bit.o before recompiling your arduino sketch - this will force recompilation of the library.

GDM1602K datasheet
By the way, looks like there's a more comprehensive data sheet for that product here:
http://www.xmocular.com/pdf/GDM1602K.pdf
not that you should need it.

What else to try
If the above ideas don't help, try using glasspusher or massimo's 4-bit code, too.  This would give us the confidence that we can get your display working somehow, and I'll look at the 4bit library initialisation code again as I have a feeling it's not perfect.  If we can get the LCD4Bit library tested successfully on many devices, we should be able to distribute it with the arduino IDE alongside the main LiquidCrystal library, making this much easier for all the other arduino users.

All comments here apply to LCD4Bit library v0.1 (16th Oct 2006). YMMV with other versions.

General LCD documentation on the arduino playground:
http://www.arduino.cc/playground/Code/LCD

good luck for now!
neill
« Last Edit: November 18, 2006, 11:30:46 am by neillzero » Logged

massachusetts
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hey neill,

thanks a lot for the info - sorry it took so long to take another stab at it.
i definitely did not have RW tied low so i made that change and your random fruit example is working now!
you can add this device to your HCL i guess.  smiley  (at least, it works with one of the two display lines)

also, being new to datasheets (and microcontrollers, and electronics, and...), i'm having a hard time figuring out how to get the backlighting for this thing to work.  the datasheet is sort of confusing to me - it seems like I can use pins 1&2 *OR* 15&16 *OR* the two pads on the side of the display?  

also, it seems to say that it wants 4.2V for the backlight.  i had read somewhere that i could use the ~.7V voltage drop of pretty much any diode to get me in that range from our normal 5V.  my multimeter is saying that i'm at 5.06V without a diode and 4.8V with the diodes i've tried - a little too high?  maybe i've already fried the backlighting because i think i may have given it the 4.8V while i was playing around -  i remember seeing backlighting for a moment at some point.  smiley

thanks again for the help,
rob
« Last Edit: December 05, 2006, 02:01:19 pm by rahji » Logged

London
Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Rob,
Great!
So it was really my fault for not documenting that tie-low requirement.  Ouch.  Sorry for the wasted time.  I've just now improved the documentation with a wiki page here:
http://www.arduino.cc/playground/Code/LCD4BitLibrary
Please feel free to add corrections and improvements.

Regarding the backlight questions, I haven't used one of those displays but have a look at landon's useful post in this recent thread:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1164517397/3#3

neill
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

your library is excelent,but I have a little question, how can I visualize the ADC in Decimal format?, Now I can see the result but only in ASCII code, how can I translate it to Decimal?

thanks fpr your answer and exuse mefor my bad english

greetings from Colombia !
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

 smiley-razz I forgot  another question...

I need to modified the library in order to use the LCD from 2 to 8 pin.. but when I make the changes it doesn`t work if I delete the .o file it doesn´t apear again...

thanks for the answer
Logged

Pages: [1] 2 3 4   Go Up
Jump to: