openGLCD Unexpected Results

I’m currently developing a project that uses 2 4x40 character LCDs and 2 64x128 graphic LCDs, each pair connected by separate data buses with a SparkFun Mega Pro.

I use the openGLCD library to control the graphic displays, and LiquidCrystal to control the character displays.

I’ve modified the openGLCD ManualConfig_ks108.h file to map the pins that I am using for the GLCD data bus and control signals.

Example sketches from LiquidCrystal and openGLCD work perfectly when uploaded, but I see some unexpected behavior when I try to write data to both types of displays in the same sketch.

In the test sketch included below, the character LCDs show the appropriate text on all (8) lines for a fraction of a second. The correct information continues to be displayed on lcd2, lcd3, and lcd4, but the information on lcd1 (the first 2 lines) goes blank, and is replaced by what appears to be the last digit of the millis()/100 on all 40 characters of the first line, and nothing on the second.

The Graphic LCD displays the line and the millis()/100 as expected.

If I comment out the openGLCD lines, the character LCDs display as expected.

This behavior is not what I expected - is there a fault in my logic, or are the two libraries sharing a resource that I do not know about?

I’ve attached a sketch that exhibits the behaviour.

Thank you for your time.

-Randel

/*

  • LCD RS pin to digital pin 44
  • LCD Enable pin to digital pin 40, 41, 42, 43
  • LCD D4 pin to digital pin 37
  • LCD D5 pin to digital pin 36
  • LCD D6 pin to digital pin 35
  • LCD D7 pin to digital pin 34
  • LCD R/W pin to ground
    */

// include the library code:
#include <LiquidCrystal.h>

#include <openGLCD.h>
#include <openGLCD_Buildinfo.h>
#include <openGLCD_Config.h>

// include the library header
// no font headers have to be included
#include <openGLCD.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd1(44, 40, 37, 36, 35, 34);
LiquidCrystal lcd2(44, 41, 37, 36, 35, 34);
LiquidCrystal lcd3(44, 42, 37, 36, 35, 34);
LiquidCrystal lcd4(44, 43, 37, 36, 35, 34);

void setup() {
// Initialize the GLCD
GLCD.Init();

// set up the LCD’s number of columns and rows:
lcd1.begin(40, 2);
lcd2.begin(40, 2);
lcd3.begin(40, 2);
lcd4.begin(40, 2);

// Print a message to the LCD.
lcd1.setCursor(0, 0);
lcd1.print(“lcd1 (0,0)”);
lcd1.setCursor(0, 1);
lcd1.print(“lcd1 (0,1)”);

lcd1.setCursor(20, 0);
lcd1.print(“lcd1 (20,0)”);
lcd1.setCursor(20, 1);
lcd1.print(“lcd1 (20,1)”);

lcd2.setCursor(0, 0);
lcd2.print(“lcd2 (0,0)”);
lcd2.setCursor(0, 1);
lcd2.print(“lcd2 (0,1)”);

lcd2.setCursor(20, 0);
lcd2.print(“lcd2 (20,0)”);
lcd2.setCursor(20, 1);
lcd2.print(“lcd2 (20,1)”);

lcd3.setCursor(0, 0);
lcd3.print(“lcd3 (0,0)”);
lcd3.setCursor(0, 1);
lcd3.print(“lcd3 (0,1)”);

lcd3.setCursor(11, 0);
lcd3.print(“The quick brown fox”);
lcd3.setCursor(11, 1);
lcd3.print(“jumped over the lazy dog.”);

lcd4.setCursor(0, 0);
lcd4.print(“lcd4 (0,0)”);
lcd4.setCursor(0, 1);
lcd4.print(“lcd4 (0,1)”);

lcd4.setCursor(11, 0);
lcd4.print(“ABCDEFGHIJKLMNOPQRSTUVWXYZ”);
lcd4.setCursor(11, 1);
lcd4.print("!@#$%^&*()_+={}?><123456789");

// Select the font for the default text area
GLCD.SelectFont(SystemFont5x7);

// GLCD.print(F(“hello, world!”)); // keep string in flash on AVR boards with IDE 1.x
// GLCD.Puts(F(“hello, world!”)); // Puts() supports F() with any version of IDE

// print() below uses RAM on AVR boards but works
// on any version of IDE with any processor
// note: Same is true for Puts()
//GLCD.CursorTo(0, 2);
// GLCD.print(“the quick brown fox jumped over the lazy dog - THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG”);

GLCD.DrawLine(0,0,127,63);

}

void loop() {

// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
GLCD.CursorTo(0, 7);

// print the number of seconds since reset:
GLCD.print(millis()/100);

lcd2.setCursor(11, 1);
lcd2.print(millis()/100);

}

Interesting problem. It isn't what I'd expect either.

I don't have a mega so I can't try the sketch.

I need to fully understand your configuration and setup.

Which version of the IDE and how have you modified the openGLCD configuration files? And how is everything wired up? soldered, length of wires etc...? Can you post a photo of your setup?

I'm running Arduino Version 1.6.3.

The wiring runs are pretty short - 8" ribbon cables off of board headers, and the shield layout is pretty sensible - copper ground planes, etc.

Here's a photo of the setup:

|500x375

Here's a photo of the sketch running:

|500x375

Here's a photo of the sketch running with the openGLCD calls commented out:

|500x375

Here's a photo of the demo openGLCD demo sketch running:

|500x375

Here’s my config file.

I’m only using one graphic LCD at the moment.


/*

  • ManualConfig_Modagm1264f.h - User specific configuration for openGLCD library
  • Use this file to set io pins and LCD panel parameters
  • This configuration file is for the AGM1264F module manufactured by
  • AZ Displays.
  • This module uses 2 ks0108 chips each controlling one half of the display.
  • This is the 128x64 GLCD that was sold by BGmicro
  • The datasheet can be downloaded from here:
  • http://docs.bgmicro.com/pdf/lcd1030.pdf
  • View From Front of LCD
  • <-------------------------------- 128 Pixels -------------------------------->
  • ±-------------------------------------±------------------------------------+
  • | | | ^
  • |<------------ 64 Pixels ------------->| | |
  • | | | |
  • | | | |
  • | | | |
  • | | | 64 pixels
  • | Chip 0 controls these pixels | Chip 1 Controls these pixels | |
  • | | | |
  • | | | |
  • | | | |
  • | | | |
  • | | | |
  • | | | v
  • ±-------------------------------------±------------------------------------+
  • | |20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| |
  • ±---------------------------------------------------------------------------+
  • ±------------------------------------------+
  • |Pin|Symbol| Function | Hook To
  • ±------------------------------------------+
  • | 1 | Vss | Ground | Gnd
  • ±------------------------------------------+
  • | 2 | Vdd | +5v (15ma max) | +5v ---------------------+
  • ±------------------------------------------+ |
  • | 3 | Vo | LCD contrast adjust |--------------------+ |
  • ±------------------------------------------+ | |
  • | 4 | DI | H = Data, L=instruction/Status | AVR Pin | |
  • ±------------------------------------------+ | |
  • | 5 | RW | H = Read, L = Write | AVR Pin | |
  • ±------------------------------------------+ | |
  • | 6 | E | Enable signal | AVR Pin | |
  • ±------------------------------------------+ | |
  • | 7 | DB0 | Data Bit 0 | AVR Pin | |
  • ±------------------------------------------+ | |
  • | 8 | DB1 | Data Bit 1 | AVR Pin | |
  • ±------------------------------------------+ | |
  • | 9 | DB2 | Data Bit 2 | AVR Pin | |
  • ±------------------------------------------+ | |
  • |10 | DB3 | Data Bit 3 | AVR Pin //////|
  • ±------------------------------------------+ | (10-20k)
  • |11 | DB4 | Data Bit 4 | AVR Pin |
  • ±------------------------------------------+ | Contrast Pot
  • |12 | DB5 | Data Bit 5 | AVR Pin |
  • ±------------------------------------------+ |
  • |13 | DB6 | Data Bit 6 | AVR Pin |
  • ±------------------------------------------+ |
  • |14 | DB7 | Data Bit 7 | AVR Pin |
  • ±------------------------------------------+ |
  • |15 | CS1 | H = chip 0 selected | AVR Pin |
  • ±------------------------------------------+ |
  • |16 | CS2 | H = chip 1 selected | AVR Pin |
  • ±------------------------------------------+ |
  • |17 | RST | L = Reset | AVR Pin |
  • ±------------------------------------------+ |
  • |18 | VEE | LCD contrast power supply |--------------+
  • ±------------------------------------------+
  • |20 | BL- | Backlight -/gnd | Gnd or connect to BL circuit for s/w control
  • ±------------------------------------------+
  • |20 | BL+ | Backlight + (560ma max) | 4-10+ ohm Resistor to +5v
  • ±------------------------------------------+

*/
#ifndef GLCD_PANEL_CONFIG_H
#define GLCD_PANEL_CONFIG_H

/*

  • define name for configuration file
    */
    #define glcd_ConfigName “AGM1264F-Manual”

//
/
Configuration for LCD panel specific configuration /
/
/
#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 64

// panel controller chips
#define CHIP_WIDTH 64 // pixels per chip
#define CHIP_HEIGHT 64 // pixels per chip

//
/
Configuration for assigning LCD bits to Arduino Pins /
/
/

/*

  • Pins can be assigned using arduino pin numbers 0-n
  • Pins on AVR devices can also be assigned using PIN_Pb
  • where P is port A-L and b is bit 0-7
  • Example: port D pin 3 is PIN_D3

*/

/*

  • Data pin definitions
    */
    #define glcdPinData0 22
    #define glcdPinData1 23
    #define glcdPinData2 24
    #define glcdPinData3 25
    #define glcdPinData4 26
    #define glcdPinData5 27
    #define glcdPinData6 28
    #define glcdPinData7 29

/*

  • Arduino pins used for control
    */
    #define glcdPinCSEL1 31
    #define glcdPinCSEL2 30

#define glcdPinRW 13
#define glcdPinDI 38
#define glcdPinEN 39
// Reset - uncomment the next line if glcd reset is connected to an Arduino pin
//#define glcdPinRES 19 // optional s/w Reset control

//#define glcdPinBL XX // optional backlight control pin controls BL circuit

//
/
Chip Select pin assignments /
/
/

/*

  • Two Chip panel using two select pins
    */

#define glcd_CHIP0 glcdPinCSEL1,HIGH, glcdPinCSEL2,LOW
#define glcd_CHIP1 glcdPinCSEL1,LOW, glcdPinCSEL2,HIGH

/*

  • Define for Backlight Control
    */
    // BLpin on off
    #define glcd_BLctl glcdPinBL, HIGH, LOW

/*

  • The following defines are for panel specific low level timing.
  • See your data sheet for the exact timing and waveforms.
  • All defines below are in nanoseconds.
    */

#define GLCD_tDDR 320 /* Data Delay time (E high to valid read data) /
#define GLCD_tAS 140 /
Address setup time (ctrl line changes to E high) /
#define GLCD_tDSW 200 /
Data setup time (data lines setup to dropping E) /
#define GLCD_tWH 450 /
E hi level width (minimum E hi pulse width) /
#define GLCD_tWL 450 /
E lo level width (minimum E lo pulse width) */

// calculate number of chips & round up if width is not evenly divisable
#define glcd_CHIP_COUNT (((DISPLAY_WIDTH + CHIP_WIDTH - 1) / CHIP_WIDTH) * ((DISPLAY_HEIGHT + CHIP_HEIGHT -1) / CHIP_HEIGHT))

#include “device/ks0108_Device.h”
#endif //GLCD_PANEL_CONFIG_H

hmm... I don't see anything obvious. Often when there is something odd like this there is s/w pin collision. From looking at the pin usage, there doesn't seem to be any pin collisions between the pins handed to LiquidCrystal and those handed to openGLCD.

If you run the openGLCD diagnostic sketch does it work ok? Look carefully at the output from the diagnostic sketch and make sure that the library is using all the correct pins that you specified.

Is it possible there there is a PCB trace error or trace short on the PCB? Specifically on the traces for Arduino pins 40 and 39? I would take a very close look at the traces on those two pins.

Another thing to try might be to turn off the raw port i/o in openGLCD to see if that effects it. I wouldn't think it would given that the demo sketches seem to be working. If you want to try this, you can go in and edit the main openGLCD config file openGLCD_Config.h Enable the define: GLCDCFG_FORCE_CORECODE In your case it will still use the same config file since you are not use the autoconfiguration files.

--- bill

Bill-

Thank you for your time and your suggestions.

I've ohmed out the traces for pins 40 and 39, and they are fine. In fact, I wrote "blink" to every pin used by the LCDs, and verified the output with a meter as part of my earlier troubleshooting process.

Turning off the raw i/o did not change the outcome.

By adding a second of delay before the GLCD.Init(); I can verify that this command is what is causing the character LCD to behave unexpectedly.

Oddly, if I physically unplug the GLCD (Newhaven Display NHD-12864WG-BTFH-V#N) from it's header, the character LCDs display properly, so I might have a hardware/wiring gremlin after all, although it has me stumped at the moment.

I'll keep you posted...

GLCD.init() initalizes the GLCD so it does lots of pin wiggling and bi-directional i/o.
If you unplug the GLCD, the initalization code will fail pretty early on so much of the pin i/o won’t be done.
The first thing the code does is read the status register of the GLCD to make sure that the device has completed its reset and is ready to accept commands.
If there is no GLCD attached, it will not see the status bits and will abort with an error after just a few 10’s of milliseconds.

Another question would be does the GLCD display properly if you disconnect the other LCDs?
while running your test sketch.

Does the openGLCD diag sketch pass? (with the other LCDs physically attached)
Can you post the output of one pass of the diag sketch serial output so I can verify the pin mappings?

When posting the text from the diags, can you wrap the text in Teletype tags so it will use a fixed width font?
Select the text and then click the Tt button at the top of the reply window.
(For posting code it is best to use code tags which is the </> button)

— bill

Bill-

I’m an idiot.

I suppose that in all fairness, my eyes aren’t what they used to be, but at your suggestion to revisit the wiring was spot on.

The Enable 1 for the first character LCD was shorted to the Register Select of the graphic LCDs with a teensy gossamer thread of a wire strand. I removed it, and all is fine with the world.

This explains the behavior, however bizarre.

I’m sorry to have wasted your time, and appreciate your willingness to get involved - you are a tremendous asset to the Arduino community.

Now to edit the config file for the second GLCD…

-Randel

I feel you. My eyes went down hill fast once I hit 50 a couple of years ago.
Glad it is all working.

It is a bit tricky to get things set up to use a second GLCD since technically openGLCD supports a single glcd instance at this point in time.
As long as the two glcds are identical types (both ks0108 etc) and the same geometry , you can cheat and trick the library into thinking it is larger single glcd.

However, because of this, the sketch can’t use separate glcd objects to talk to the displays like you can with the text displays but rather you will have to use different screen areas on the same glcd object that are defined to use the pixels of the separate physical displays.

Depending on how you define your config file you can create a display that maps the pixels as double high or double wide.
I’d recommend double high because currently the library uses uint8_t types for the coordinates for speed and that limits the maximum pixel coordindate to 255 however, 255 is currently “magic” so if you were to have two 128x64 displays, you would not be able to use the right most column of pixels (your config file will need to declare it as a 255x64 instead of a 256x64 display)
But if you stack the displays vertically you will end up with a 128x128 display.

What are the two GLCD modules and how do you have the two glcds wired up? i.e. which wires are shared vs separate?
Most signals can be shared. The ones to be careful with are the enables and the chip selects.
There are couple of choices there, but usually as long as you don’t share the enables, it should be ok.

— bill

The other thing that may be some what of a pain, depending on what you doing with the displays, is graphics. Right now the defined areas are only for text. i.e. you can't create a virtual area for graphics like you can for text. So for graphics you will end up having to deal with being careful in how you draw the pixels since there is no way to limit the bounds to a single display.

Bill-

Everything works like a champ - thanks for your suggestions and expertise.

The Enable signal is shared with the 2 LCDs, but the Chip Selects are separate - everything as described in the manual config file, and your previous posts in this thread.

I did find that it was necessary to modify the config file for the LCDs that I am using (Newhaven nhd12864wgbtfhvn-p) I had to reverse the HIGH and LOW of the "Defines for Four Chip panel using four select pins" to get things working properly. For reference, my config is below.

Thanks!

/*
 * Defines for Four Chip panel using four select pins - HIGH and LOW Reversed
 */
#elif  (NBR_CHIP_SELECT_PINS == 4 && glcd_CHIP_COUNT == 4) 
#define glcd_CHIP0  glcdPinCSEL1,LOW, glcdPinCSEL2,HIGH,  glcdPinCSEL3,HIGH,  glcdPinCSEL4,HIGH
#define glcd_CHIP1  glcdPinCSEL1,HIGH,  glcdPinCSEL2,LOW, glcdPinCSEL3,HIGH,  glcdPinCSEL4,HIGH
#define glcd_CHIP2  glcdPinCSEL1,HIGH,  glcdPinCSEL2,HIGH,  glcdPinCSEL3,LOW, glcdPinCSEL4,HIGH
#define glcd_CHIP3  glcdPinCSEL1,HIGH,  glcdPinCSEL2,HIGH,  glcdPinCSEL3,HIGH,  glcdPinCSEL4,LOW

Great! Just keep in mind that if you create a 256x64 display that you won't be able to use the right most column of display pixels (x=255) because 255 is a special value internally.

--- bill