DFRobot LCD shield

Has anybody heard of the DFRobot's LCD + buttons arduino shield? (you can find it here http://www.robotshop.us/dfrobot-lcd-keypad-shield-arduino-1.html) I was considering buying it and I was wondering if anybody could give info on how to program it before I buy it. :stuck_out_tongue:

Looks similar to the one from nuelectronics:
http://www.nuelectronics.com/estore/index.php?main_page=product_info&cPath=1&products_id=2

It looks almost the same! But one of the buttons is moved and I think the screen is different. :frowning: Maybe I can learn something from it anyway.

Functionally, I think they should be identical.
If you buy the one from nuelectronics, you have sketches that worked guaranteed (I tried, successfully, the lcdsmart app with nuelectronics LCD shield).

You can find the manual for this LCD Shield at
http://www.yerobot.com/download/mannual/Arduino%20LCD%20%20shield%20Manual.pdf

You'll find that shield is fairly easy to develop for. You'll need the 4Bit library.

The only complex bit is the button handling - They use timers IIRC to handle data reading which is a little confusing for newbies.

Just a thought but you may prefer building one of these by hand. I found it quite interesting. If you select the right module it's also very simple. Check out Adafruits guides

I have one of this shields, and notice that pin 10 (not documented in the manual) is the backlight led controll, so if you send diferent values of PWM to that pin you can dim the backlight.

Althought I got a problem, if not sending anything to that the white dots from the display have normal intensity, but has soon you play with pin 10 PWM even sending 255 I never managed to got the same intensity.

Anyone face this problem or know a work around to get back the maximum intensity?

I don't like powering backlights on LCD's with just the pin, the 4x20 LCD I have, backlight runs close to 60ma!! That's a bit too much for the Arduino pins, I generally choose a transistor.

Just wanted to point out, if you want to use your Arduino with LCD-Smartie, you can use the code from nuelectronics.com, here's the code I've used so far, it works fairly good but only supports Hardware serial atm:
(you can ignore the first 3 commands, I added those so I can control the LCD with an Arduino, and still read the analog ports and use the eeprom on board:D)
Here's the library required for the sketch:
http://www.nuelectronics.com/download/projects/LCD4Bit_mod.zip
You can edit the pins through the library, and here's where I borrowed the sketch. (I took out the buttons and such, since it's a standalone controller)
http://www.nuelectronics.com/download/projects/lcd_smartie_v1.pde

After you've got it uploaded, download LCD-smartie http://lcdsmartie.sourceforge.net/
Install, blah blah, then run the setup, choose Matrix.dll, then put in your com port and speed the arduino is using. (for more instructions:
http://www.nuelectronics.com/estore/index.php?main_page=project_lcdsmartie)

#include "LCD4Bit_mod.h"
#include <EEPROM.h>
//#include <Streaming.h>
const byte backLight = 13;

//create object to control an LCD.  
//number of lines in display=1
LCD4Bit_mod lcd = LCD4Bit_mod(2); 


void setup() { 
  pinMode(backLight, OUTPUT);  //we'll use the debug LED to output a heartbeat
  digitalWrite(backLight,HIGH);
  Serial.begin(9600);

  lcd.init();
  lcd.clear();
  lcd.printIn("   LCD Ready: ");
}


byte serial_getch(){

  int incoming;  
  while (Serial.available()==0){
  }
  // read the incoming byte:
  incoming = Serial.read();

  return (byte) (incoming &0xff);
}



void loop(){

  byte rxbyte;
  byte temp;
  byte addr;
  byte pin;
  int myVal;
  int val;

  rxbyte = serial_getch();

  if (rxbyte == 254) //Matrix Orbital uses 254 prefix for commands
  {
    switch (serial_getch())
    {

      case 50: // Read analog pin, then send value back
      pin = serial_getch();
      myVal = analogRead(pin)/4;
      delay(10);
      Serial.print(myVal, BYTE);
      break;
    case 64: // EEPROM Write (address, value) 
      addr = serial_getch();
      delay(10);
      val = serial_getch();
      EEPROM.write(addr, val);
      break;

    case 65: // EEPROM Read  (address)
      addr = serial_getch(); // EEPROM address
      val = EEPROM.read(addr); //
      Serial.print(val, BYTE);
      break;

    case 69: //backlight on (at previously set brightness)
      // not implemented      
      digitalWrite(backLight, HIGH);                  
      break;

    case 70: //backlight off
      // not implemented      
      digitalWrite(backLight, LOW);                  
      break;

    case 71:  //set cursor position
      temp = (serial_getch() - 1);  //get column byte
      switch (serial_getch())  //get row byte
      {
        //line 1 is already set up
      case 2:
        temp += 0x40;
        break;
      case 3:
        temp += 0x14;
        break;
      case 4:
        temp += 0x54;
        break;
      default:
        break;
      }
      lcd.commandWrite(0b10000000 + temp);
      break;

    case 72:  //cursor home (reset display position)
      lcd.commandWrite(2);
      break;

    case 74:  //show underline cursor
      lcd.commandWrite(0b00001110);
      break;

    case 75:  //underline cursor off

    case 84:  //block cursor off
      lcd.commandWrite(0b00001100);
      break;

    case 76:  //move cursor left
      lcd.commandWrite(16);
      break;

    case 77:  //move cursor right
      lcd.commandWrite(20);
      break;

    case 78:  //define custom char
      lcd.commandWrite(64 + (serial_getch() * 8));  //get+set char address
      for (temp = 7; temp != 0; temp--)
      {
        lcd.print(serial_getch()); //get each pattern byte
      }
      break;

    case 83:  //show blinking block cursor
      lcd.commandWrite(0b00001111);
      break;
    case 86:  //GPO OFF
      //implement later
      break;

    case 87:  //GPO ON
      /*temp = serial_getch();
                               if (temp == 1)
                               {
                                     GPO1 = GPO_ON;
                               }*/
      break;

    case 88:  //clear display, cursor home
      lcd.commandWrite(1);
      break;

      /*###############################################################      
       case 152: //set and remember (doesn't save value, though)
       case 153: //set backlight brightness
       //not implemented
       break;
       //these commands ignored (no parameters)
       //case 35: //read serial number //USING FOR EEPROM//
       //case 36: //read version number
       case 55: //read module type
       case 59: //exit flow-control mode
       //case 65: //auto transmit keypresses
       case 96: //auto-repeat mode off (keypad)
       case 67: //auto line-wrap on
       case 68: //auto line-wrap off
       case 81: //auto scroll on
       case 82: //auto scroll off
       case 104: //init horiz bar graph
       case 109: //init med size digits
       case 115: //init narrow vert bar graph
       case 118: //init wide vert bar graph
       break;
       ###############################################################*/

    default:
      //all other commands ignored and parameter byte discarded
      temp = serial_getch();  //dump the command code
      break;
    }
    return;
  } //END OF COMMAND HANDLER

  //change accented char to plain, detect and change descenders
  //NB descenders only work on 5x10 displays. This lookup table works
  //  with my DEM-20845 (Display Elektronik GmbH) LCD using KS0066 chip.
  switch (rxbyte)
  {
    //chars that have direct equivalent in LCD charmap
    /*            case 0x67: //g
                       rxbyte = 0xE7;
                       break;
                 case 0x6A: //j
                       rxbyte = 0xEA;
                       break;
                 case 0x70: //p
                       rxbyte = 0xF0;
                       break;
                 case 0x71: //q
                       rxbyte = 0xF1;
                       break;
                 case 0x79: //y
                       rxbyte = 0xF9;
                       break;
     */  case 0xE4: //ASCII "a" umlaut
    rxbyte = 0xE1;
    break;
  case 0xF1: //ASCII "n" tilde
    rxbyte = 0xEE;
    break;
  case 0xF6: //ASCII "o" umlaut
    rxbyte = 0xEF; //was wrong in v0.86
    break;
  case 0xFC: //ASCII "u" umlaut
    rxbyte = 0xF5;
    break;

    //accented -> plain equivalent
    //and misc symbol translation
  case 0xA3: //sterling (pounds)
    rxbyte = 0xED;
    break;
    /*            case 0xB0: //degrees symbol
                       rxbyte = 0xDF;
                       break;
     */  case 0xB5: //mu
    rxbyte = 0xE4;
    break;
  case 0xC0: //"A" variants
  case 0xC1:
  case 0xC2:
  case 0xC3:
  case 0xC4:
  case 0xC5:
    rxbyte = 0x41;
    break;
  case 0xC8: //"E" variants
  case 0xC9:
  case 0xCA:
  case 0xCB:
    rxbyte = 0x45;
    break;
  case 0xCC: //"I" variants
  case 0xCD:
  case 0xCE:
  case 0xCF:
    rxbyte = 0x49;
    break;
  case 0xD1: //"N" tilde -> plain "N"
    rxbyte = 0x43;
    break;
  case 0xD2: //"O" variants
  case 0xD3:
  case 0xD4:
  case 0xD5:
  case 0xD6:
  case 0xD8:
    rxbyte = 0x4F;
    break;
  case 0xD9: //"U" variants
  case 0xDA:
  case 0xDB:
  case 0xDC:
    rxbyte = 0x55;
    break;
  case 0xDD: //"Y" acute -> "Y"
    rxbyte = 0x59;
    break;
    /*            case 0xDF: //beta  //mucks up LCDSmartie's degree symbol??
                       rxbyte = 0xE2;
                       break;
     */  case 0xE0: //"a" variants except umlaut
  case 0xE1:
  case 0xE2:
  case 0xE3:
  case 0xE5:
    rxbyte = 0x61;
    break;
  case 0xE7: //"c" cedilla -> "c"
    rxbyte = 0x63;
    break;
  case 0xE8: //"e" variants
  case 0xE9:
  case 0xEA:
  case 0xEB:
    rxbyte = 0x65;
    break;
  case 0xEC: //"i" variants
  case 0xED:
  case 0xEE:
  case 0xEF:
    rxbyte = 0x69;
    break;
  case 0xF2: //"o" variants except umlaut
  case 0xF3:
  case 0xF4:
  case 0xF5:
  case 0xF8:
    rxbyte = 0x6F;
    break;
  case 0xF7: //division symbol
    rxbyte = 0xFD;
    break;
  case 0xF9: //"u" variants except umlaut
  case 0xFA:
  case 0xFB:
    rxbyte = 0x75;
    break;
  default:
    break;
  }

  lcd.print(rxbyte);  //otherwise a plain char so we print it to lcd
  return;


}

If you're considering LCD smartie, I'd suggest connecting it directly to a parallel port. It's actually a fairly simple process and saves you a $30 arduino :wink:

Parallel port? Who has those nowdays?:smiley:

You can always buy some Atmega8's (I got 5 for $10), some max232's(even cheaper) and then you're ready to go! Well, assuming you have a serial port, or a usb-to-rs232 cable, but either way, probably more likely than this so called "parallel port" :stuck_out_tongue:

so I made my own serial-controlled LCD with LCD smartie for about $20, including the LCD :smiley: But I guess it depends what you have laying around, and what you're willing to sacrifice :slight_smile:

And this way, you can unplug it from the computer, and use it as a Serial controlled LCD, via only 1 wire! (2 if you include ground, and 3 if you want to use the analog read, eeprom read/write functions, you need the RX hooked up)

@CaptainObvious

You missed my point or I didn't explained correctly.
My problem is not controling the LCD backlight, that I can do with:

analogWrite(backLight,value); // value from 0 to 255

puting 255 I get the same intensity on backlight led as when if I don't do nothing after power on Arduino.

The real problem is the intensity on the LCD digits/pixels witch after and if I used analogWrite with any value even sending 255 (maximum again I presume) I never got tha same intensity on them as after I power on Arduino and do nothing of analogWrite on backlight pin.
Conclusion if any analogWrite used on backlight led's control pin, pixels on lcd never became to have the same intensity, so anything is messing up that.

Anyway the backlight led's for the LCD RF-Robot shield are power by a transitor as you can see here on they schematic:

http://www.robotshop.us/content/PDF/dfrobot-lcd-keypad-shield-schematic.pdf

That was probably my fault.

But now I'm confused. Is it the backlight that doesn't have the same intensity? Or is it the pixels?

The contrast (of the pixels) is controlled via, uhh VO. (VEE on other LCD's, had to make sure, lol) Have you tried adjusting the trimmer pot on the top left of the shield? That's what controls the Contrast.

You should try connecting the backlight to 5v instead, and play with the contrast, check that to make sure. :slight_smile:

But that's pretty nifty the backlight is controlled by a transistor for you.

The problem is realy the pixels, as I said not doing anything on the Arduino pin 10 where acording to they schematic is the control of backlight, they have normal intensity and off course the trimmmer pot was regulated once and never again touched after.

But as soon and any analogWrite to that pin, the pixels stop having normal brightness, the only way to go back normal is cutting Arduino power and back on again.

EDIT: Sorry... problem solved !!! For some reason after using D10 pin for sending PWM to dim the LCD backlight I was facing that pixels low brightness problem, I just retune the contrast pot and now all his ok in any option. ::slight_smile:

I tried simply turning the backlight on and off with pin D10
pinMode(10, OUTPUT); //remember to enable it as an output

digitalWrite(10, LOW);
digitalWrite(10, HIGH);

When it went low the backlight went off fine, however when it went high it caused a lot random flickering in the display. It didn't really mess up the display but it flickered and blinked. It was a lot different than when it was simply tri-stated when pin 10 was not set to an output. So, I checked the schematic to discover a bad design. D10 is directly driving the base of an NPN transistor with the emiter to ground! So, no wonder it is acting all crazy. I beleive that is too much of a current load on the output pin. The pull up resistor in the schematic is 4.7K so I think a diode in series with D10 would make it work better. You would have to cut the connector stacking pin or bend it out of the way then add the diode in series polarized with the cathode towards the Arduino board. I bet the PWM would work for you with a diode in series. http://www.robotshop.com/content/PDF/dfrobot-lcd-keypad-shield-schematic.pdf

I had a big problem with switch bounce. There are 6 buttons one is just a hardwired reset. The others are scanned by analog channel 0. I modified the demo program like this:
Now it never gives me the wrong key push results.

int read_LCD_buttons() // read the buttons keyboard voltage test routine. Returns int ex: 'btnSELECT' is #defined as '4'
// button returned values centered at these values: 002, 130, 306, 478, 720 added approx 50 for buffer zone
{
adc_key_in = analogRead(0); // read the value from the sensor for keypad and then test the value for button levels.
delay(10); //switch debounce delay. Increase this delay if incorrect switch selections are returned.
if (adc_key_in != analogRead(0)) return btnNONE; // double checks the keypress. If the two readings are not equal after debounce delay, it tries again.
if (adc_key_in > 770) return btnNONE; // This is the 1st option for speed reasons since it will be the most likely result.
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 180) return btnUP;
if (adc_key_in < 355) return btnDOWN;
if (adc_key_in < 530) return btnLEFT;
if (adc_key_in < 770) return btnSELECT;
}