Go Down

Topic: 128x64 GLCD ST7920 Wiring and controlling help needed (Read 6 times) previous topic - next topic


Aug 19, 2011, 07:55 am Last Edit: Aug 19, 2011, 08:23 am by ekto Reason: 1

I recently bought an arduino mega 2560, some components and this screen:

From the webshop page I can see, that there are some libraries for it:

This is how I tried to get the screen to light up:

Nothing happend. I then read some topic about connecting the backlight to it. This should be done by the K- and A- pins. Somewhere it said, that you should not connect them directly, since it might burn the led.

Here are the pins:

Can someone give me advise how to connect this screen correctly? What pins needs to go where? Do I need to put some components between the pins?

Edit: I'm trying to connect it by serial interface.


No thoughts how to connect this? The PDF-has nothing regarding these pins...

Well I'm going to try the K- and A-pins.

I'm assuming that the K-pin is the ground and A-pin is +5v. If these pins go to a led, wrong polarity should not do any damage? Since led is a diode?

I think I need to limit the current for +5v? I need to put a resistor inline? Some resistor calculator gave me a 100 Ohm suggestion, with 3,3 voltage drop and 20ma current, which are default values, when dealing with unknown led.


Guessing how to hook up wires and hooking them up incorrectly can potentially damage the module.
I think the issue you are running into in this case is that the datasheet you referenced is not
a datasheet for the module you have. It is a datasheet for the ST7920 chip on the module you have.

Look at the back of the module and see if you can find a reference number. This will help locate
a datasheet for the module.

But to help clarify things up a bit.
"A" means anode - which for these modules is positive power
"K" means "cathode" = which for these modules is negative power.

In terms of a series limiting resistor, it is hard to say since there is no data sheet.
Some need them and some don't. Some need very small values like < 10 ohms and
some need them in the 100-200 ohm range.
However, for some modules that need a current limiting resistor,
if you hook up power without one, it can instantly burn up the LED.
Some backlights can use as little as 50ma while others can use as much as 400ma.

Given the variation it is kind of difficult to say what is needed for a backlight current limiting resistor.
I guess the safer thing to do if you can't find a data sheet
would be to start high ~500 ohms and then go lower until you get a
brightness that looks ok and try to keep the current under about 200ma.

As an aside, note that this display is not compatible with the current GLCD v3 library.
--- bill


Okey, I managed to get it wired. I changed to parallel connection...

The code is just a print out.

Code: [Select]

#include "LCD12864R.h"
#define AR_SIZE( a ) sizeof( a ) / sizeof( a[0] )

unsigned char show1[]="ppm:780";//
unsigned char show2[]=" RPM:25%";//
unsigned char show3[]="Normaali";//

void setup()
LCDA.Initialise(); // INIT SCREEN

void loop()

Here is what I would like to see on the screen:

I made this before I hooked up the unit, so it's just a rough presentation.

How could I add a integer after the text?
So that the RPM and ppm values vould come from some calculation?

How could I draw a line on the right side of the screen that would be the ppm value from 600 (lenght 1px) to 1200 (lenght 32px)? There was some vector command on the library, but I cannot find any examples for it.
How could I make a dot to a right side of the screen?

If these are not library functions, can I do it somehow as an ascii? Like those images are done?


For creating formatted text I would use  sprintf().
sprintf() formats text into a buffer to be printed later.
There is tons of stuff about it if you google as it is a standard C library function.
Just keep in mind that floating point formatting won't work if you are using the
arduino IDE as it requires using a floating point
version of sprintf() that requires a different C library and the Arduino IDE won't
allow you to change the linker options to select the floating point version of sprintf().

In your case you would probably do something like:

char lcdbuffer[10]; // declare buffer

sprintf(lcdbuffer, "RPM: %02d%", rpmvalue);

sprintf(lcdbuffer, "ppm: %03d", ppmvalue);

in sprintf() %d is for printing integers and something like
%03d will print a 3 digit decimal number that is filled in with zero.
i.e. 001, 0020 vs <space><space>1 if you used %3d

Then use the lcd API calls to print the formatted string:

In C, strings are normally terminated by a NULL character automatically so if you wanted to make
it a bit simpler you could modify the library function or create a new one to
use a null terminated string rather than have to pass down the string length:

Code: [Select]
void LCD12864R::DisplayStringnew(int X,int Y,uchar *ptr)
  int i;

     case 0:  Y|=0x80;break;

     case 1:  Y|=0x90;break;

     case 2:  Y|=0x88;break;

     case 3:  Y|=0x98;break;

     default: break;
  WriteCommand(Y); // ¶¨Î»ÏÔʾÆðʼµØÖ·


Then you could simply call the function without having to tell it how large the string was:

As far as graphing goes, that will be quite difficult because while the module
itself has many graphic capabilities, that particular library is quite minimal
and only provides the ability to draw simple text and full screen bitmaps.
There are no library functions to draw anything else.

So the only way to deal with that would be write code to treat the "bitmap" as
a frame buffer. Then write the code necessary to update the frame buffer with all
your desired text/graphics/images etc...
and then call their DrawFullScreen() function to use the framebuffer to update the display.
Not really an easy programming task.

Alternatively, since that display supports downloadable fonts, if you could download
a cp437 font to the device, you could simulate graphics using that font.
That would work quite well, and would not require any graphic API calls or the use of a frame buffer,
but unfortunately, that library does not support downloading or using the downloaded fonts.

--- bill


Agenst all odds, I got it done  8)

These pictures have couple minutes between them:

When the screen is full, it just drops the last (left) line and starts a new on the right side.

The number is the value of the last line.
The whole thing works by an array. It moves an array value 1 to 0, 2 to 1, 3 to 2, etc...
Then it randoms (this will be the sensor value later) a number to the arrays last value.
Then it takes the array value 0, converts it around (lcd y0 is up) and draws a line to buffer.
Then it takes the value 1, moves one in X and does the same. etc...

Here's the code:
Code: [Select]

#include <LCD12864.h>
#include <LCDSprite.h>

int viivat[128];
int kaannos = 0;
int uusi = 1;
int paikka = 32;
int tulos = 0;

void setup() {
  LCDA.Initialise(); // INIT SCREEN

  delay(500); // Some delay
  LCDA.Render(); // Start the Rendering process
   for (int i=0; i <= 127; i++){
   viivat[i] = 1;


void numbertobinary(char num) { // Convert the number to binary for the scores
if (num == 0)
else if (num == 1)
else if (num == 2)
else if (num == 3)
else if (num == 4)
else if (num == 5)
else if (num == 6)
else if (num == 7)
else if (num == 8)
else if (num == 9)
else if (num == 10){
else if (num == 11){
LCDA.setPins(1,0,0,0,1,1,0,0,0,1); }
else if (num == 12){
LCDA.setPins(1,0,0,0,1,1,0,0,1,0); }
else if (num == 13){
LCDA.setPins(1,0,0,0,1,1,0,0,1,1); }
else if (num == 14){
LCDA.setPins(1,0,0,0,1,1,0,1,0,0); }
else if (num == 15){
LCDA.setPins(1,0,0,0,1,1,0,1,0,1); }
else if (num == 16){
LCDA.setPins(1,0,0,0,1,1,0,1,1,0); }
else if (num == 17){
LCDA.setPins(1,0,0,0,1,1,0,1,1,1); }
else if (num == 18){
LCDA.setPins(1,0,0,0,1,1,1,0,0,0); }
else if (num == 19){
LCDA.setPins(1,0,0,0,1,1,1,0,0,1); }
else if (num == 20){
LCDA.setPins(1,0,0,0,1,1,0,0,0,0); }
else if (num == 21){
LCDA.setPins(1,0,0,0,1,1,0,0,0,1); }
else if (num == 22){
LCDA.setPins(1,0,0,0,1,1,0,0,1,0); }
else if (num == 23){
LCDA.setPins(1,0,0,0,1,1,0,0,1,1); }
else if (num == 24){
LCDA.setPins(1,0,0,0,1,1,0,1,0,0); }
else if (num == 25){
LCDA.setPins(1,0,0,0,1,1,0,1,0,1); }
else if (num == 26){
LCDA.setPins(1,0,0,0,1,1,0,1,1,0); }
else if (num == 27){
LCDA.setPins(1,0,0,0,1,1,0,1,1,1); }
else if (num == 28){
LCDA.setPins(1,0,0,0,1,1,1,0,0,0); }
else if (num == 29){
LCDA.setPins(1,0,0,0,1,1,1,0,0,1); }
else if (num == 30){
LCDA.setPins(1,0,0,0,1,1,0,0,0,0); }
else if (num == 31){

void loop(){
for (int i = 0; i <= 126; i++){
   viivat[i] = viivat[i + 1];
viivat[127] = random(1,31);
for (int i = 0; i <= 127; i++){
   kaannos = map(viivat[i], 1, 31, 31, 1);
   delay (10);
paikka = 32;
tulos = viivat[127];

Can I add my numbertobinary-function to the library some how?
How could I identify, how many numbers an integer holds?
How can I brake them to singles so that I can run the numbertobinary, for each number?

This way I would not need to have the binary for each number, like 22, 44, or 249.
I could brake the 249 to 2, 4, and 9. Then I would get the binaries for 2, 4, and 9.

In the real application, the number should represent a ppm value ranging from 600 to 1200...


What library code are you using? I ask because the headers and the functions you are using do not match
the library code from the initial link you provided.
It looks like the code you are using has additional capabilities.
Can you post a link to the library code you are using?

As far as making a generic character printing routine for numbers, yes you can do that.
The code you have now is essentially pushing the ASCII value of each digit.
You could extract each digit value then convert it to ascii than have a common
routine to print characters.
In order to do that you will first need to convert the number to something like BCD
which is a number that is composed of individual binary digits rather than a single binary number.
Then you have to extract each digit and convert that digit to ASCII.
Not overly difficult but it will involve some bit level manipulation.

You could also use modulo 10 and divide by ten math in a loop to extract each digit
and then convert each digit to ASCII.

So for example:
digit_value = value % 10;

will return the lowest digit of the value. (will be number 0 to 9)
Then if you divide value by 10, you can do it again to get the next digit.
You can put this in a loop to extract all the digits.
You will be extracting the digits from right to left from the number
so you will have to buffer them up before you print them left to right
on the display.

To convert from a binary digit to ascii you simply add '0' to the value.
Example: ascii_char = digitvalue + '0';

Or you could take the easy way out and use sprintf() to extract the digits, do the ascii conversion, and buffer
them up and then call the DisplayString() function to display it on the glcd.

--- bill


It's a different library. This is the first that can handle numbers easily:
Makeing numbers and letters is dead easy:
Code: [Select]


Not shure about wath the AR_SIZE does.
This library can also handle the Y-axis, wich the second library can not when doing letters.

This one can draw lines etc:

I just started to think, that would it be possible to unite those two libraries?
Could I somehow copy the number function from the first library and paste it to the second one?
If it would be possible, could you tell me how. I don't understand libraries so well yet...


I cleaned the code and added the second library text calls and comments:
Code: [Select]
#include <LCD12864.h>
#include <LCDSprite.h>
#define AR_SIZE( a ) sizeof( a ) / sizeof( a[0] )//Dont know what this is

unsigned char show1[]="ppm:780";//just text
unsigned char show2[]=" RPM:25%";//just text
unsigned char show3[]="Normaali";//just text

int viivat[128];//array for the lines
int kaannos = 0;//to be used in map-function
int paikka = 32;//to be used in draw function.

void setup() {
  LCDA.Initialise(); // INIT SCREEN
  delay(500); // Some delay
  LCDA.Render(); // Start the Rendering process

   for (int i=0; i <= 127; i++){//this makes every array value to one
   viivat[i] = 1;


void loop(){
for (int i = 0; i <= 126; i++){//this copies array values
   viivat[i] = viivat[i + 1];//value 0= value 1, value 1 = value 2,........ value 126 = value 127

viivat[127] = random(1,31);//This generates the "sensor" value and saves it to the arrays last position, value 128
//This array has 128 values, since the first position is zero, last is 127

for (int i = 0; i <= 127; i++){//This will draw all the array values as lines
   kaannos = map(viivat[i], 1, 31, 31, 1); //since the Y0 is at the top-side, we need to invert the numbers
   LCDA.DrawBrLine(paikka,kaannos,paikka,32);//line draw function.
   delay (10);//Just to make shure it has time to write
   paikka++;//adds to X-coordinate integer by one

paikka = 32;//resets the X-coordinate. For some reason, first X is 32.
LCDA.RenderScreenBuffer(2);//This will now render the buffer
LCDA.DumpScreenBuffer();//This cleans the buffer


LCDA.DisplayString(0,0,show1,AR_SIZE(show1));;//These are functions from the second library
LCDA.DisplayString(0,4,show2,AR_SIZE(show1));;//These are functions from the second library
LCDA.DisplayString(1,2,show3,AR_SIZE(show1));;//These are functions from the second library



delay(1000);//in the final program, there would not be a delay here.

Here's my best shot of uniting the libraries:
Code: [Select]

#ifndef LCD12864_h
#define LCD12864_h
#include <avr/pgmspace.h>
#include <inttypes.h>

class LCD12864 {
typedef unsigned char byte;
typedef unsigned char uchar;



void Initialise(void);
void selectCS1(void);
void setPins(uint8_t tRS, uint8_t tRW, uint8_t tD7, uint8_t tD6, uint8_t tD5, uint8_t tD4, uint8_t tD3, uint8_t tD2, uint8_t tD1, uint8_t tD0);
void delayns(void);
void VectorConverter(uint8_t vector);
void VectorConvertermany(uint8_t vector, uint8_t amount);

void WriteCommand(int CMD);
void WriteData(int CMD);

void CLEAR(void);
void DisplayString(int X,int Y,uchar *ptr,int dat);
void DisplaySig(int M,int N,int sig);
void DrawFullScreen(uchar *p);

int ScreenBuffer[16][32];

void Render(void);
void DrawPixel(uint8_t startX, uint8_t startY);
void DrawBrLine(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);
void DrawCircle(uint8_t x0, uint8_t y0, uint8_t radius);
void DrawRectangle(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height);
void FillRectangle(uint8_t x0, uint8_t y0, uint8_t width, uint8_t height);

//void DrawScreenBuffer(uint8_t X,uint8_t Y);
void Duplicate(bool x);
void Draw(bool t, uint8_t x, uint8_t y);
void setdelay(uint8_t newtime);
void DrawSprite(uint8_t xPos, uint8_t yPos);

void RenderScreenBuffer(uint8_t screen);
void RenderScreenBuffer(uint8_t startX, uint8_t startY, uint8_t maxX, uint8_t maxY);

void DumpScreenBuffer(void);
void DumpScreenBuffer(uint8_t startX, uint8_t startY, uint8_t maxX, uint8_t maxY);

byte ScreenBuffer[16][32];

byte checkAND[8];

byte delaytime;

static const int RS = 51;
static const int RW = 49; 
static const int EN = 47; 
static const int D0  = 45; 
static const int D1  = 43;
static const int D2  = 41; 
static const int D3  = 39; 
static const int D4  = 37;
static const int D5  = 35; 
static const int D6  = 33; 
static const int D7  = 31;
static const byte CSEL1  = 14;

byte currentXpos;
byte currentYpos;

byte temp[8];

extern LCD12864 LCDA;   

And here's by error codes:
Code: [Select]
In file included from melkein_.cpp:1:
C:\arduino-0022\libraries\LCD12864/LCD12864.h:57: error: declaration of 'unsigned char LCD12864::ScreenBuffer [16][32]'
C:\arduino-0022\libraries\LCD12864/LCD12864.h:34: error: conflicts with previous declaration 'int LCD12864::ScreenBuffer [16][32]'


Aug 31, 2011, 02:15 pm Last Edit: Aug 31, 2011, 02:21 pm by agentgates Reason: 1
Hi Folks,

I've got a 128x64 KS0108 panel connected to a mega2560 by the "B" pinout according to the GLCD playground description. I'm having trouble with either wiring or settings, I am not sure which is the case. I have uploaded the GLCDExample to the board. It doesn't do anything when I press reset but after power down+up it goes crazy. It blinks/flashes very fast for 3 sec in an alternating fashion between the 2 chips and lives one or more horizontal lines when it calms down (as seen in the photo attached).

I have verified the wiring multiple times, I found no error. Of course no soldering glitches or so and I din't change anything in the original file. I tried other KS0108 programs, same result.

Could anybody help me out?

Many thanks


Make sure you have glcd v3 (it supports the 2560) then run the diags sketch.
But report your diag results and ask further questions on the glcd v3 library
thread instead of using this unrelated thread:

--- bill

Go Up