Artifacts on 128x64 Serial LCD Screen

I got this strange artifacts in the upper left corner and lower right on every bitmap that I send to this serial LCD from seeedstudio (http://www.seeedstudio.com/depot/serial-graphic-lcd-12864-st756567-ctrl-black-and-white-p-287.html):

This is my code (could be useful for those who bought this lcd screen too because runs natively from arduino ide):

// Demo LCD TOPWAY LM6059BCW
// Author: Erwin Ried
// Webpage: http://erwin.ried.cl
// Based on: http://www.seeedstudio.com/depot/images/product/LM6059BCW-Manual-Rev0.3.pdf

#define CS1 2 // Chip Select (LOW= enable LCD)
#define RST 3 // Reset signal (HIGH= normal, LOW= Init)
#define A0 4  // Register Select (HIGH= Display Data, LOW= Control)
#define CLOCK 7
#define DATA 6

// Example logo
byte logo[]={
    0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,
    0xF8,0x08,0x08,0x00,0xF0,0x08,0x08,0x08,0xF0,0x00,0xF8,0x48,0x48,0x48,0x30,0x00,
    0xF8,0x00,0x80,0x00,0xF8,0x00,0xE0,0x50,0x48,0x50,0xE0,0x00,0x38,0x40,0x80,0x40,
    0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x80,0x10,0x20,0x00,0x60,0x20,0xA0,0x20,0x20,0xA0,0x20,0x60,0x00,0x00,0x00,0xF0,
    0x03,0x00,0xF0,0x00,0x01,0xE2,0x02,0x02,0xF1,0x00,0x83,0x80,0xF0,0x80,0x80,0x20,
    0x21,0xE2,0x21,0x22,0x21,0x20,0x03,0x00,0xC0,0x40,0x53,0xE0,0x40,0x40,0xE3,0x50,
    0x40,0xC0,0x40,0x00,0x40,0x20,0x10,0xE0,0x80,0xF0,0x80,0xE0,0x00,0xF0,0x80,0x80,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x10,0xF9,0x04,0x40,0x44,0x25,0x14,0xFF,0x14,0x24,0x45,0x44,0x00,0x21,0x61,0x3F,
    0x91,0x51,0x3F,0x00,0x00,0x3F,0x00,0x00,0xFF,0x00,0x08,0x88,0xFF,0x04,0x0A,0x04,
    0xFF,0x44,0x44,0x44,0xFC,0x00,0x00,0x02,0x02,0x03,0xFA,0xAB,0xAA,0xAA,0xAB,0xAA,
    0xFB,0x02,0x02,0x00,0x04,0xFE,0x81,0x42,0x3A,0x0A,0x7A,0xA2,0x4F,0x30,0x4F,0x80,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,
    0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,
    0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,
    0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x88,0x54,0x22,0x01,0x00,0x01,0xFA,0x01,0x00,0x01,0x02,
    0xF9,0x70,0x81,0x02,0xC1,0x30,0xF9,0x02,0xE1,0x90,0xB1,0x02,0x01,0xE0,0x11,0x12,
    0xE1,0x00,0xF1,0x92,0x91,0x10,0x01,0xE2,0x11,0x10,0xE1,0x02,0x01,0x80,0x71,0x0A,
    0x71,0x80,0x01,0x02,0x01,0x00,0x01,0x22,0x54,0x88,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x08,0x15,0x22,0x40,0x80,0x40,0x2F,0x48,0x88,0x48,0x28,
    0x4F,0x80,0x47,0x2C,0x47,0x80,0x4F,0x20,0x47,0x88,0x48,0x27,0x40,0x87,0x48,0x28,
    0x47,0x80,0x4C,0x28,0x48,0x87,0x40,0x21,0x4D,0x89,0x47,0x20,0x4C,0x83,0x41,0x21,
    0x41,0x83,0x4C,0x20,0x40,0x80,0x40,0x22,0x15,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0xC0,0x40,0x40,0x40,0x40,0x00,0x80,0x40,0x40,0x40,0x80,0x00,0x40,0x40,0xC0,
    0x40,0x40,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,
    0x00,0x00,0x00,0x80,0x40,0x40,0x40,0x80,0x00,0xC0,0x40,0x40,0x80,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x80,0xC0,0x00,0x00,0x00,0x80,0x40,0x40,0x40,0x80,0x00,0x80,
    0x40,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x40,0x40,0x00,
    0x00,0x00,0x00,0x80,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x40,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0xC0,0x9F,0x02,0x02,0x02,0x00,0x00,0x09,0x12,0x12,0x12,0x0C,0x00,0x00,0x00,0x1F,
    0x00,0x00,0x00,0x1F,0x01,0x02,0x04,0x1F,0x00,0x00,0x00,0x00,0x00,0x1F,0x10,0x10,
    0x10,0x10,0x00,0x0F,0x10,0x10,0x10,0x08,0x00,0x1F,0x10,0x10,0x08,0x07,0x00,0x00,
    0x00,0x00,0x00,0x00,0x10,0x1F,0x10,0x00,0x00,0x10,0x18,0x14,0x12,0x11,0x00,0x0D,
    0x12,0x12,0x12,0x0D,0x00,0x11,0x0A,0x04,0x0A,0x11,0x00,0x0F,0x12,0x12,0x12,0x0C,
    0x00,0x06,0x05,0x04,0x1F,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x05,0x05,0x05,
    0x02,0x00,0x00,0x11,0x1F,0x10,0x00,0x00,0x11,0x0A,0x04,0x0A,0x11,0x00,0x0E,0x15,
    0x15,0x15,0x06,0x00,0x00,0x10,0x1F,0x10,0x00,0x00,0x12,0x15,0x15,0x15,0x88,0xC0
};

// Shift out override (Reverse clock HIGH/LOW)
void shiftOut(uint8_t dataPin, uint8_t clockPin, byte val)
{
    for (int i = 0; i < 8; i++)  {
        digitalWrite(dataPin, !!(val & (1 << (7 - i))));
        digitalWrite(clockPin, LOW);
        digitalWrite(clockPin, HIGH);            
    }
}

// Send Byte as command or data to LCD
void sendByte(byte b, boolean isData)
{
    digitalWrite(CLOCK,HIGH);
    digitalWrite(A0,isData);
    digitalWrite(CS1,LOW);
    shiftOut(DATA, CLOCK, b); 
    digitalWrite(CS1,HIGH);
}

// Send command to LCD
void sendCommand(byte b)
{
   sendByte(b, false);
}

// Send data to LCD
void sendData(byte b)
{
   sendByte(b, true);
}

// Send a whole screen to the LCD (164x64/8 = 1312byte)
void sendScreen(byte screen[]) 
{
    int i,j;

    for(i=0; i<8; i++)
    {
        sendCommand(0xb0 | i); // Data page 0-7
        sendCommand(0x10); // Data Column 4
        sendCommand(0x00);

        for(j=0; j<128; j++) 
            sendData(screen[(i*128)+j]); 
    }
}

byte actualContrast = 0x17;

void setContrast(int level) // 0= set/reset, >0= darker, <0= lighter
{
    if(level>0 && actualContrast<0x3F)
        actualContrast++;
    else
        if(level<0 && actualContrast>0x00)
            actualContrast--;

    sendCommand(0x81);
    sendCommand(actualContrast);
}

void startLcd()
{
    // Initialization
    digitalWrite(RST,HIGH);
    digitalWrite(RST,LOW);
    delay(1);
    digitalWrite(RST,HIGH);
    delay(800);

    sendCommand(0xab);  // New 
    sendCommand(0xaf);  // Display on
    sendCommand(0x40);  // Display start line=0
    sendCommand(0xc8);  // Common output mode select= reverse  
    sendCommand(0xa6);  // Normal display
    sendCommand(0xa4);  // Display all point= off
    sendCommand(0xa3);  // LCD bias = 1/9   a2
    sendCommand(0x2f);  // Power control = all on
    sendCommand(0x25);  // Rab Ratio     26
    setContrast(0);     // Default contrast
}

void setup()
{
    pinMode(CS1,OUTPUT);
    pinMode(RST,OUTPUT);
    pinMode(A0,OUTPUT);
    pinMode(CLOCK,OUTPUT);
    pinMode(DATA,OUTPUT);

    startLcd();
    sendScreen(logo);
}

void loop()
{
    // Something to do...
}

Anyone knows why can this happen? Thanks!

Wish I had some information that could help you, but have you tried posting in the Seeedstudio forums? They've been quick to answer all my questions, there are users and engineers alike, not a great amount, but enough people read it you'll get an answer in a day or two. I didn't see any posts about any of the LCD problems, so just giving a heads up :smiley:

Thanks anyway CaptainObvious, I will post in seeedstudio forums

There is a owner of the http://www.seeedstudio.com/depot/serial-graphic-lcd-12864-st756567-ctrl-black-and-white-p-287.html serial lcd screen who can test my code please?

It is very simple, just copy the code to Arduino IDE and upload it. Connect the lcd as shown here (using seeedstudio cables of course :mrgreen:):

LCD Pins <-> Arduino Pins
1,2,3 <-> 2,3,4
13,12 <-> 6,7 (clock, data)
14,16 <-> to 3,3 Volts
15 <-> to GND

I wish to know if my lcd is the faulty or my code, please someone.

I don't have that display and can't offer much advice other than if you have an oscilloscope you might want to check the timing of the data and control signals to make sure they agree with the data sheet.

I suspect that this might not be the case though as 90% of the display comes out ok, and if the the display looks the same with the same garbage consistently every time it is probably a data/control problem. A timing error is likely to cause random errors but it is worth checking.

Is something screwing up when switching between sending commands and sending data?

Thanks letaage, I waiting for my seeeduino's osciloscope to check what you say.

It is almost constant, but if I modify some timers the noise changes a bit.

eried, I used your code and my display looks good, with no artifacts

I am confused as to why my image looks different than yours though. That leads me to believe we aren't seeing the image contained in the code. How did you create it, I'm having trouble replacing it with my own image.

Hooray! I found bmp2glcd which works well..

This weekend I found time to get some text to display on this thing.. Here is some scratchpad code that somebody may find helpful, or may want to help improve on: (It displays milli seconds and microseconds of time since bootup)

#define LCD_CS1 2 // Chip Select (LOW= enable LCD)
#define LCD_RST 3 // Reset signal (HIGH= normal, LOW= Init)
#define LCD_A0 4 // Register Select (HIGH= Display Data, LOW= Control)
#define LCD_CLOCK 7
#define LCD_DATA 6

#include <avr/pgmspace.h>
#include "WProgram.h"

struct digit {
char c;
byte d[6];
};
static digit digits[] = {
{ 'A', {0x3e,0x12,0x12,0x12,0x3e,0x00} },
{ 'B', {0x3e,0x2a,0x2a,0x2a,0x36,0x00} },
{ 'C', {0x3e,0x22,0x22,0x22,0x22,0x00} },
{ 'D', {0x3e,0x22,0x22,0x22,0x1c,0x00} },
{ 'E', {0x3e,0x2a,0x2a,0x2a,0x22,0x00} },
{ 'F', {0x3e,0x0a,0x0a,0x02,0x02,0x00} },
{ 'G', {0x3e,0x22,0x22,0x2a,0x3a,0x00} },
{ 'H', {0x3e,0x08,0x08,0x08,0x3e,0x00} },
{ 'I', {0x22,0x22,0x3e,0x22,0x22,0x00} },
{ 'J', {0x30,0x20,0x20,0x22,0x3e,0x00} },
{ 'K', {0x3e,0x08,0x08,0x14,0x22,0x00} },
{ 'L', {0x3e,0x20,0x20,0x20,0x20,0x00} },
{ 'M', {0x3e,0x04,0x08,0x04,0x3e,0x00} },
{ 'N', {0x3e,0x04,0x08,0x10,0x3e,0x00} },
{ 'O', {0x1c,0x22,0x22,0x22,0x1c,0x00} },
{ 'P', {0x3e,0x0a,0x0a,0x0a,0x04,0x00} },
{ 'Q', {0x1e,0x12,0x32,0x12,0x1e,0x00} },
{ 'R', {0x3e,0x0a,0x0a,0x0a,0x34,0x00} },
{ 'S', {0x2e,0x2a,0x2a,0x2a,0x3a,0x00} },
{ 'T', {0x02,0x02,0x3e,0x02,0x02,0x00} },
{ 'U', {0x3e,0x20,0x20,0x20,0x3e,0x00} },
{ 'V', {0x06,0x18,0x20,0x18,0x06,0x00} },
{ 'W', {0x1e,0x20,0x18,0x20,0x1e,0x00} },
{ 'X', {0x22,0x14,0x08,0x14,0x22,0x00} },
{ 'Y', {0x06,0x08,0x30,0x08,0x06,0x00} },
{ 'Z', {0x22,0x32,0x2a,0x26,0x22,0x00} },
{ '0', {0x00,0x1c,0x22,0x22,0x1c,0x00} },
{ '1', {0x00,0x00,0x02,0x3e,0x00,0x00} },
{ '2', {0x00,0x32,0x2a,0x2a,0x24,0x00} },
{ '3', {0x00,0x22,0x2a,0x2a,0x14,0x00} },
{ '4', {0x00,0x18,0x14,0x3e,0x10,0x00} },
{ '5', {0x00,0x2e,0x2a,0x2a,0x12,0x00} },
{ '6', {0x00,0x1c,0x2a,0x2a,0x10,0x00} },
{ '7', {0x00,0x02,0x32,0x0a,0x06,0x00} },
{ '8', {0x00,0x14,0x2a,0x2a,0x14,0x00} },
{ '9', {0x00,0x04,0x2a,0x2a,0x1c,0x00} },
{ ' ', {0x00,0x00,0x00,0x00,0x00,0x00} }
};

void shiftOut(uint8_t dataPin, uint8_t clockPin, byte val);

void sendByte(byte b, boolean isData);
void sendCommand(byte b);
void sendData(byte b);

void initLcd();
void clearScreen();
void putChar (char ch);
void putString (char* outstr, byte n = 0);

void setup () {

pinMode(LCD_CS1,OUTPUT);
pinMode(LCD_RST,OUTPUT);
pinMode(LCD_A0,OUTPUT);
pinMode(LCD_CLOCK,OUTPUT);
pinMode(LCD_DATA,OUTPUT);

initLcd();
clearScreen();

}

void loop () {
int ret = 0;
char outtxt[25];

sendCommand(0xb0); // Data page 0
sendCommand(0x10); // Data Column 0
sendCommand(0x00);
sendCommand(0x40);

unsigned long time;

time = millis();
sprintf (outtxt, "MILLI %10lu", time);
putString (outtxt,0);

time = micros();
sprintf (outtxt, "MICRO %10lu", time);
putString (outtxt, 1);

delay (250);
}

void initLcd() {
digitalWrite(LCD_RST,HIGH);
digitalWrite(LCD_RST,LOW);
delay(1);
digitalWrite(LCD_RST,HIGH);
delay(800);

sendCommand(0xa2); // LCD bias = 1/9
sendCommand(0xa0); // ADC = Normal (No flip on X-dir [SEG])
sendCommand(0xc8); // SHL = Reverse (Flip on Y-dir [COM])
sendCommand(0x40); // Initial Display Line = 0
sendCommand(0x2c); // Turn on voltage converter
delay (50);
sendCommand(0x2e); // Turn on voltage regulator
delay (50);
sendCommand(0x2f); // Turn on voltage follower
delay (50);
sendCommand(0x26); // Set the built-in regulator resistor ratio
sendCommand(0x81); // Set reference voltage mode
sendCommand(0x1a); // Set reference voltage resistor
sendCommand(0xaf); // Display ON
sendCommand(0xb0); // Set page address to 0
sendCommand(0x10); // Specify display data ram column address 0 (Upper)
sendCommand(0x0); // (Lower)
// Now write some data
}

void clearScreen() {
int i,j;

for(i=0; i<8; i++) {
sendCommand(0xb0 | i); // Data page 0-7
sendCommand(0x10); // Data Column 0
sendCommand(0x00);
sendCommand(0x40);

for(j=0; j<128; j++) {
sendData( 0 );
}
}

sendCommand(0xb0 | i); // Data page 0-7
sendCommand(0x10); // Data Column 0
sendCommand(0x00);
sendCommand(0x40);
}

// Shift out override (Reverse clock HIGH/LOW)
void shiftOut(uint8_t dataPin, uint8_t clockPin, byte val) {
for (int i = 0; i < 8; i++) {
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
digitalWrite(clockPin, LOW);
digitalWrite(clockPin, HIGH);
}
}

// Send Byte as command or data to LCD
void sendByte(byte b, boolean isData) {
digitalWrite(LCD_CLOCK,HIGH);
digitalWrite(LCD_A0,isData);
digitalWrite(LCD_CS1,LOW);
shiftOut(LCD_DATA, LCD_CLOCK, b);
digitalWrite(LCD_CS1,HIGH);
}

// Send command to LCD
void sendCommand(byte b) {
sendByte(b, false);
}

// Send data to LCD
void sendData(byte b) {
sendByte(b, true);
}

void putChar (char ch) {
int i = 0;
struct digit* dg = &digits[0];
while (dg->c != ' ' && ch != dg->c) {
dg++;
}
for (i=0; i < 6; i++) {
sendData (dg->d*);*

  • }*
    }
    void putString (char* outstr, byte n) {
  • int i;*
  • sendCommand(0x10); // Data Column 0*
  • sendCommand(0x00);*
  • if (n) {*
  • if (n < 0)*
  • n = 0;*
  • if (n > 7)*
  • n = 7;*
  • sendCommand(0xb0 + n);*
  • }*
    _ for (i = 0; outstr != '\0'; i++) {_
    _ putChar(outstr*);
    }
    }
    [/quote]*_

It's corruption due to the fact it's trying to stuff all the data into ram (I suspect it's the stack and variables being stamped over the top that are being displayed) . Use PROGMEM lib to stash it in PROG Memory, Problem solved.

#include <avr/pgmspace.h>

// Example logo

byte logo[] PROGMEM ={ .... data ..... };

sendData(pgm_read_byte(&logo[(i*128)+j]));

The Mega has enough RAM to cope hence why it works.

Nod.

Glad to know you have sovle out the problem,