Pain in the butt LCD

Well I'm going around in circles with my LCD. I thought I'd post my code to see if anyone could spot anything obvious.

I'm using the LCD hooked up to a 595 so it only uses 3 I/O pins and its stackable.
Roughly based off the 3 pin LCD page on the playground (it doesnt use a 595).

Here is the code. Most of the main stuff is unmodified.

// Arduino Pins for the 595
#define DATA 8
#define LATCH 9
#define CLK 10

// Pins on the 595 for the LCD
// Data pins
#define D4 0
#define D5 1
#define D6 2
#define D7 3
// Control pins
#define Enable 4
#define RW 5
#define BL 6 // Backlight
#define RS 7

byte backlight = 1;

// Simplified shiftOut with latch
void shiftOut(byte val)
{
//  val = ~val;
  int i;
  digitalWrite(LATCH, LOW);
  for (i = 0; i < 8; i++)
  {
    digitalWrite(DATA, !!(val & (1 << i)));
    digitalWrite(CLK, HIGH);
    digitalWrite(CLK, LOW);
  }
  digitalWrite(LATCH, HIGH);
}

inline void LcdCommandWrite(byte value) {
  LcdWrite(value, 0);
}

inline void LcdDataWrite(byte value) {
  LcdWrite(value, 1);
}

void LcdWrite(byte value, int data) {
  byte value1 = value;
  byte control = 0;
  if (data)
  {
    control |= 1 << RS;
  }
  if (backlight)
  {
    control |= 1 << BL;
  }
  
  value1 >>= 4;
  value1 &= ~(1 << Enable); // Enable Low
  value1 |= control;
  shiftOut(value1);
  value1 |= 1 << Enable; // Enable High
  Serial.println(value1, BIN);
  shiftOut(value1);
  value1 &= ~(1 << Enable); // Enable Low
  shiftOut(value1);
  
  value &= 15;
  value &= ~(1 << Enable); // Enable Low
  value |= control;
  shiftOut(value);
  value |= 1 << Enable; // Enable High
  Serial.println(value, BIN);
  shiftOut(value);
  value &= ~(1 << Enable); // Enable Low
  shiftOut(value);
  
  Serial.println("Nibbles Sent");
}

void LcdInit() {
  delay(100);
  // initiatize lcd after a short pause
  // needed by the LCDs controller

  /////////// 4 pin initialization
  LcdCommandWrite(0x03); // function set:
  // 4 pin initialization
  delay(64);
  LcdCommandWrite(0x03); // function set:
  // 4 pin initialization
  delay(50);
  LcdCommandWrite(0x03); // function set:
  // 4 pin initialization
  delay(50);
  LcdCommandWrite(0x02); // function set:
  // 4 pin initialization
  delay(50);
  LcdCommandWrite(0x2C); // function set:
  // 4-bit interface, 1 display lines, 5x7 font
  /////////// end of 4 pin initialization 

  delay(20);
  LcdCommandWrite(0x06); // entry mode set:
  // increment automatically, no display shift
  delay(20);
  LcdCommandWrite(0x0F); // display control:
  // turn display on, cursor on, blinking
  delay(20);
  // clear display, set cursor position to zero
  LcdCommandWrite(0x01); 
  delay(100);

  LcdCommandWrite(0x80); // display control:
  delay(20);
}

void setup()
{
  pinMode(DATA, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(LATCH, OUTPUT);
  
  Serial.begin(9600);
  delay(1000);

  LcdInit();
}

void loop () {
  LcdCommandWrite(0x02); // set cursor position to zero
  delay(10);

  // Write the message
  //like this
  LcdDataWrite('L');
  LcdDataWrite('c');
  LcdDataWrite('d');
  delay(200);

  //or like this
  int wrote[] = {
    'D', 'i', 's', 'p', 'l', 'a', 'y', ' '  };
  int count;
  for ( count = 0; count<=7; count++) {
    LcdDataWrite(wrote[count]);
  } 

  LcdDataWrite('w');
  LcdDataWrite('i');
  LcdDataWrite('t');
  LcdDataWrite('h');
  LcdDataWrite(' ');

  LcdDataWrite('P');
  LcdDataWrite('i');
  LcdDataWrite('n');
  LcdDataWrite('s');

  delay(3000);
  while (1)
  {
  }
}

Yes your reading correctly. Software controlled backlight. :slight_smile:
That bit works perfectly.

Also another difference is the pins arent hard coded.
Every single example on the playground uses hard coded constants for stuff like Enable whilst mine computes them based on the defines.

The problem is it does absolutely nothing at the moment.
The backlight turns on after the bootloader is finished and then I get the default filled boxes on rows 1 and 3. Nothing else.
Its a 20x4 display and I have gotten it more or less working before.

Below is the exact bits sent to the 595 excluding the Enable bit which is always 1 in the dump.
It seems fine to me.

1010000
1010011
Nibbles Sent
1010000
1010011
Nibbles Sent
1010000
1010011
Nibbles Sent
1010000
1010010
Nibbles Sent
1010010
1011100
Nibbles Sent
1010000
1010110
Nibbles Sent
1010000
1011111
Nibbles Sent
1010000
1010001
Nibbles Sent
1011000
1010000
Nibbles Sent
1010000
1010010
Nibbles Sent
11010100
11011100
Nibbles Sent
11010110
11010011
Nibbles Sent
11010110
11010100
Nibbles Sent
11010100
11010100
Nibbles Sent
11010110
11011001
Nibbles Sent
11010111
11010011
Nibbles Sent
11010111
11010000
Nibbles Sent
11010110
11011100
Nibbles Sent
11010110
11010001
Nibbles Sent
11010111
11011001
Nibbles Sent
11010010
11010000
Nibbles Sent
11010111
11010111
Nibbles Sent
11010110
11011001
Nibbles Sent
11010111
11010100
Nibbles Sent
11010110
11011000
Nibbles Sent
11010010
11010000
Nibbles Sent
11010101
11010000
Nibbles Sent
11010110
11011001
Nibbles Sent
11010110
11011110
Nibbles Sent
11010111
11010011
Nibbles Sent

Hi,
hard to tell if you send the right data to the Lcd if we don't know the type of controller.
Asuming you have a HD44780 compatible controller my datsheet provides the following init-procedure in 4-Bit mode
for a two line display

//init a HD44780 Lcd in 4-bit mode

//xxxx the first four 'x' are your RS,RW,BL and Enable bits since I assume you know how to set them right
//they are followed by the 4 bit code to be send
xxxx0010 //Switch to 4-bit mode

xxxx0010 //4-bit mode, two lines
xxxx1000 

xxxx0000 //Display on,Cursor on,Cursor blink
xxxx1111 

xxxx0000 //Clear Display,Cursor home
xxxx0001

xxxx0000 //Cursor auto increment
xxxx0110

These commands should at least lead to a blinking cursor on your Lcd.
Otherwise could you please provide a link to the datasheet?

Eberhard

Its me again,
in your shiftOut()-function I found this suspicious line here

for (i = 0; i < 8; i++)
{
  digitalWrite(DATA, !!(val & (1 << i))); //a double negation '!!' ? Is that correct or a copy-n-paste error?
  digitalWrite(CLK, HIGH);
  digitalWrite(CLK, LOW);
}

Eberhard

Thats copy pasted direct from wiring_shift.c
That function is derived from it.

I havent figured out exactly what it does yet. I might do it if I find time.

Whoops didnt see your post.

hard to tell if you send the right data to the Lcd if we don't know the type of controller.

Yeah its a standard HD44780.

Your init is similar but not identical to mine. I'll test it tomorrow.

!!val is a hacky way of turning anything but 0 into 1 while keeping 0 as 0. That is:

!!1 is 1
!!3 is 1
!!0 is 0

Not the most elegant code ever.

backlight is controlled by software... what about the contrast? If you don't set it right, the LCD works but you don't see the characters.

Contrast is set by a potentiometer normally. Thats not the problem.

Heh. Its working. The weird thing is that I didnt change anything. I am literately using the code I posted above.

Thats copy pasted direct from wiring_shift.c
That function is derived from it.

I havent figured out exactly what it does yet. I might do it if I find time.

From my reading and limited knowledge of the 595 it simply sets up a counter to cycle through the 8 serial bits of data and then sends one bit at a time to the serial in pin of the 595 interdispersed with pulsing the 595 clock pin to shift the bit along.

I hope that makes sense.

I hope that makes sense.

I was referring to the double negation actually. :slight_smile:

The simple explanation is you pulse in 8 bits serially and it will send them out parallel.
The datasheet has a nice diagram if you want specifics.

could not get it working cheater... :frowning: are you sure that it works just like that?