graphical lcd (nokia 3310)

http://www.display3000.com/html/screen-shots.html
http://www.shop-en.display3000.com/

did anyone figure out a code that will work with arduino yet???

Hi,

there seem to be lots of pages describing how to hook one of these 3310 lcd's up but can anyone give me some pointers on how to go about to physically connect the darned thing? I followed the procedure on this page: http://www.microsyl.com/nokialcd/nokialcd.html , but simply couldn't get those wires soldered to the tiny connector! And made 2 of those little bits come off so now I need to look for another one :frowning:

How do you guys wire the thing up?!?

Hi Bas-l,

read the thread. it's basically all in there. the way i did it ( and how it worked for me) was basically like on the diagram and in the code. you just have to make sure that the voltage is around 3,3V max on the dipsplay.

i'd really like to help you more. But i gave away my prototype (it was a gift) and back then i didn't think it was necessary to document it... well.

i still have some displays around. i hope i'll find the time to do it again.

the code works though.

good luck,
kuk

Hi Kuk,

maybe I wasn't clear. My question is: how do you manage to physically connect wires to those teeny weeny small connectors on the display? I tried soldering wires directly on to them and I failed miserably, destroying 2 connectors (or rather 2 "pins", out of the 8 on the bottom/back of the display).

Are there connectors for sale somewhere that you can snap on that are easier to solder wires onto? If not, what's the trick to solder wires onto the display's connector?

I got 2 new 3310 lcd's off of ebay, for about 1$ each. Pretty cheap but would hate to ruin them as well :wink:

Thanks,

Bas.

oh i see,

i know that there are at least to versions of the same display around. one is designed to be placed with its contacts on some conducting rubber. the contacts on those are not solderable, or at least not as far as i know. you can buy this "conductive rubber" and put it between the display and a custom pcb. it is not at all cheap but you only need half of a sq.centimetre. and i once saw someone offering these small pieces on ebay.

the displays i have all come from a 3310. its contacts are small copper springs. they're small but i had no problems soldering them since it's copper.

hope that helped you more.

//kuk

I still would like to know if the CODE has been posted anywhere? Or if it would be possible for someone to send me a copy?

Thanks!

ok, so here the working code.
part 1 because its to long for one reply...

#define LCD_X_RES                  84
#define LCD_Y_RES                  48



#define LCD_CACHE_SIZE             ((LCD_X_RES * LCD_Y_RES) / 8)

/*--------------------------------------------------------------------------------------------------
 Type definitions
 --------------------------------------------------------------------------------------------------*/



#define    LCD_CMD  0
#define    LCD_DATA  1

#define    PIXEL_OFF   0
#define    PIXEL_ON    1
#define    PIXEL_XOR   2

#define    FONT_1X  1
#define    FONT_2X  2


typedef unsigned int               word;
//  Mega8 port B pinout for LCD.
int CONTROL_LED=12;
int LCD_POWER_PIN      =       11;
int LCD_DC_PIN         =        2; //  PB0  4  Data Command
int LCD_CE_PIN         =        3; //  PB2  5  /CS   active low chip select ??
int SPI_MOSI_PIN       =        4; //  PB3  3  Serial   line
int LCD_RST_PIN        =        5; //  PB4  8   /RES RESET
int SPI_CLK_PIN        =        6; //  PB5  2  CLOCK

int voltometer        =         9;
// Public function prototypes

void LcdInit       ( void );
void LcdClear      ( void );
void LcdUpdate     ( void );
void LcdGotoXY     ( byte x, byte y );
void LcdChr        ( int size, byte ch );
void LcdStr        ( int size, byte *dataPtr );
void LcdPixel      ( byte x, byte y, int mode );
void LcdLine       ( byte x1, byte y1, byte x2, byte y2, int mode );
void LcdSendCmd ( byte data, int cd );


// This table defines the standard ASCII characters in a 5x7 dot format.


// Global Variables

byte  LcdCache [ LCD_CACHE_SIZE ];

int   LcdCacheIdx;
int   LoWaterMark;

int   HiWaterMark;
boolean  UpdateLcd;
 char sign;
  byte ser= 0; //from serial port

// This table defines the standard ASCII characters in a 5x7 dot format.
static const byte FontLookup [][5] =
{
  { 
    0x7E, 0x11, 0x11, 0x11, 0x7E     }
  ,   // A
  { 
    0x7F, 0x49, 0x49, 0x49, 0x36     }
  ,   // B
  { 
    0x3E, 0x41, 0x41, 0x41, 0x22     }
  ,   // C
  { 
    0x7F, 0x41, 0x41, 0x22, 0x1C     }
  ,   // D
  { 
    0x7F, 0x49, 0x49, 0x49, 0x41     }
  ,   // E
  { 
    0x7F, 0x09, 0x09, 0x09, 0x01     }
  ,   // F
  { 
    0x3E, 0x41, 0x49, 0x49, 0x7A     }
  ,   // G
  { 
    0x7F, 0x08, 0x08, 0x08, 0x7F     }
  ,   // H
  { 
    0x00, 0x41, 0x7F, 0x41, 0x00     }
  ,   // I
  { 
    0x20, 0x40, 0x41, 0x3F, 0x01     }
  ,   // J
  { 
    0x7F, 0x08, 0x14, 0x22, 0x41     }
  ,   // K
  { 
    0x7F, 0x40, 0x40, 0x40, 0x40     }
  ,   // L
  { 
    0x7F, 0x02, 0x0C, 0x02, 0x7F     }
  ,   // M
  { 
    0x7F, 0x04, 0x08, 0x10, 0x7F     }
  ,   // N
  { 
    0x3E, 0x41, 0x41, 0x41, 0x3E     }
     // O

  ,   // Y
  { 
    0x61, 0x51, 0x49, 0x45, 0x43     }
    //Z
};
/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdSendCmd
 
 Description  :  Sends data to display controller.
 
 Argument(s)  :  data -> Data to be sent
 cd   -> Command or data (see/use enum)
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdSendCmd ( byte data, int cd )
{


  byte i = 8;

  byte mask;



  //

  if ( cd == LCD_DATA )
  {
    digitalWrite(LCD_DC_PIN,HIGH);
  }
  else
  {
    digitalWrite(LCD_DC_PIN,LOW) ;
  }




  while(0 < i) {

    mask = 0x01 << --i; // get bitmask and move to least significant bit
    // cause edge to fall
    digitalWrite(SPI_CLK_PIN,LOW); // tick
    delayMicroseconds(400);
    // set out byte
    if(data & mask){ // choose bit

      digitalWrite(SPI_MOSI_PIN,HIGH); // send 1

    }
    else{

      digitalWrite(SPI_MOSI_PIN,LOW); // send 0

    }

    // cause edge to rise

    digitalWrite(SPI_CLK_PIN,HIGH); // tock
    delayMicroseconds(400);





  }


}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdInit
 
 Description  :  Performs MCU SPI & LCD controller initialization.
 
 Argument(s)  :  None.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdInit ( void )
{

  int m;


  //  Toggle display reset pin.
  digitalWrite(LCD_RST_PIN,LOW);
  delay(40);
  digitalWrite(LCD_RST_PIN,HIGH);

  //  Enable SPI port: No interrupt, MSBit first, Master mode, CPOL->0, CPHA->0, Clk/4
  // SPCR = 0x50;



  LcdSendCmd( 0x21, LCD_CMD );  // LCD Extended Commands.
  LcdSendCmd( 0xB3, LCD_CMD );  // Set LCD Vop (Contrast). //B1
  LcdSendCmd( 0x04, LCD_CMD );  // Set Temp coefficent. //0x04

  LcdSendCmd( 0x13, LCD_CMD );  // LCD bias mode 1:48. //0x13
  LcdSendCmd( 0x20, LCD_CMD );  // LCD Standard Commands, Horizontal addressing mode.

  LcdSendCmd( 0x0C, LCD_CMD );  // LCD in normal mode. 0x0d for inverse
  // LcdSendCmd( 0x0D, LCD_CMD );

  //  Reset watermark pointers.
  LoWaterMark = LCD_CACHE_SIZE;
  HiWaterMark = 0;
  


  
    LcdClear();
  LcdUpdate();
}

part 2:

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdContrast
 
 Description  :  Set display contrast.
 
 Argument(s)  :  contrast -> Contrast value from 0x00 to 0x7F.
 
 Return value :  None.
 
 Notes        :  No change visible at ambient temperature.
 
 --------------------------------------------------------------------------------------------------*/
void LcdContrast ( byte contrast )
{
  //  LCD Extended Commands.
  LcdSendCmd( 0x21, LCD_CMD );

  // Set LCD Vop (Contrast).
  LcdSendCmd( 0x80 | contrast, LCD_CMD );

  //  LCD Standard Commands, horizontal addressing mode.
  LcdSendCmd( 0x20, LCD_CMD );
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdClear
 
 Description  :  Clears the display. LcdUpdate must be called next.
 
 Argument(s)  :  None.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdClear ( void )
{
  int i;

  for ( i = 0; i < LCD_CACHE_SIZE; i++ )
  {
    LcdCache[i] = 0x00;
  }

  //  Reset watermark pointers.
  LoWaterMark = 0;
  HiWaterMark = LCD_CACHE_SIZE - 1;

  UpdateLcd = true;
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdGotoXY
 
 Description  :  Sets cursor location to xy location corresponding to basic font size.
 
 Argument(s)  :  x, y -> Coordinate for new cursor position. Range: 1,1 .. 14,6
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdGotoXY ( byte x, byte y )
{
  LcdCacheIdx = (x - 1) * 6 + (y - 1) * 84;
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdChr
 
 Description  :  Displays a character at current cursor location and increment cursor location.
 
 Argument(s)  :  size -> Font size. See enum.
 ch   -> Character to write.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdChr ( int size, byte ch )
{
  byte i, c;
  byte b1, b2;
  int  tmpIdx;

  if ( LcdCacheIdx < LoWaterMark )
  {
    //  Update low marker.
    LoWaterMark = LcdCacheIdx;
  }

  if ( (ch < 0x20) || (ch > 0x7b) )
  {
    //  Convert to a printable character.
    ch = 65;
  }

  if ( size == FONT_1X )
  {
    for ( i = 0; i < 5; i++ )
    {
      LcdCache[LcdCacheIdx++] = FontLookup[ch - 65][i] << 1;
    }
  }
  else if ( size == FONT_2X )
  {
    tmpIdx = LcdCacheIdx - 84;

    if ( tmpIdx < LoWaterMark )
    {
      LoWaterMark = tmpIdx;
    }

    if ( tmpIdx < 0 ) return;

    for ( i = 0; i < 5; i++ )
    {
      c = FontLookup[ch - 32][i] << 1;
      b1 =  (c & 0x01) * 3;
      b1 |= (c & 0x02) * 6;
      b1 |= (c & 0x04) * 12;
      b1 |= (c & 0x08) * 24;

      c >>= 4;
      b2 =  (c & 0x01) * 3;
      b2 |= (c & 0x02) * 6;
      b2 |= (c & 0x04) * 12;
      b2 |= (c & 0x08) * 24;

      LcdCache[tmpIdx++] = b1;
      LcdCache[tmpIdx++] = b1;
      LcdCache[tmpIdx + 82] = b2;
      LcdCache[tmpIdx + 83] = b2;
    }

    //  Update x cursor position.
    LcdCacheIdx += 11;
  }

  if ( LcdCacheIdx > HiWaterMark )
  {
    //  Update high marker.
    HiWaterMark = LcdCacheIdx;
  }

  //  Horizontal gap between characters.
  LcdCache[LcdCacheIdx++] = 0x00;
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdStr
 
 Description  :  Displays a character at current cursor location and increment cursor location
 according to font size.
 
 Argument(s)  :  size    -> Font size. See enum.
 dataPtr -> Pointer to null terminated ASCII string to display.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdStr ( int size, byte *dataPtr )
{
  while ( *dataPtr )
  {
    LcdChr( size, *dataPtr++ );
  }
}

part 3 and final:

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdPixel
 
 Description  :  Displays a pixel at given absolute (x, y) location.
 
 Argument(s)  :  x, y -> Absolute pixel coordinates
 mode -> Off, On or Xor. See enum.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdPixel ( byte x, byte y, int mode )
{
  word  index;
  byte  offset;
  byte  data;

  if ( x > LCD_X_RES ) return;
  if ( y > LCD_Y_RES ) return;

  index = ((y / 8) * 84) + x;
  offset  = y - ((y / 8) * 8);

  data = LcdCache[index];

  if ( mode == PIXEL_OFF )
  {
    data &= (~(0x01 << offset));
  }
  else if ( mode == PIXEL_ON )
  {
    data |= (0x01 << offset);
  }
  else if ( mode  == PIXEL_XOR )
  {
    data ^= (0x01 << offset);
  }

  LcdCache[index] = data;

  if ( index < LoWaterMark )
  {
    //  Update low marker.
    LoWaterMark = index;
  }

  if ( index > HiWaterMark )
  {
    //  Update high marker.
    HiWaterMark = index;
  }
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdLine
 
 Description  :  Draws a line between two points on the display.
 
 Argument(s)  :  x1, y1 -> Absolute pixel coordinates for line origin.
 x2, y2 -> Absolute pixel coordinates for line end.
 mode   -> Off, On or Xor. See enum.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdLine ( byte x1, byte y1, byte x2, byte y2, int mode )
{
  int dx, dy, stepx, stepy, fraction;

  dy = y2 - y1;
  dx = x2 - x1;

  if ( dy < 0 )
  {
    dy    = -dy;
    stepy = -1;
  }
  else
  {
    stepy = 1;
  }

  if ( dx < 0 )
  {
    dx    = -dx;
    stepx = -1;
  }
  else
  {
    stepx = 1;
  }

  dx <<= 1;
  dy <<= 1;

  LcdPixel( x1, y1, mode );

  if ( dx > dy )
  {
    fraction = dy - (dx >> 1);
    while ( x1 != x2 )
    {
      if ( fraction >= 0 )
      {
        y1 += stepy;
        fraction -= dx;
      }
      x1 += stepx;
      fraction += dy;
      LcdPixel( x1, y1, mode );
    }
  }
  else
  {
    fraction = dx - (dy >> 1);
    while ( y1 != y2 )
    {
      if ( fraction >= 0 )
      {
        x1 += stepx;
        fraction -= dy;
      }
      y1 += stepy;
      fraction += dx;
      LcdPixel( x1, y1, mode );
    }
  }

  UpdateLcd = true;
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdUpdate
 
 Description  :  Copies the LCD cache into the device RAM.
 
 Argument(s)  :  None.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdUpdate ( void )
{
  int i;
  
//always update everything for the moment
LoWaterMark = 0;
HiWaterMark = LCD_CACHE_SIZE - 1;


  if ( LoWaterMark < 0 ){
    LoWaterMark = 0;
  }
  else if ( LoWaterMark >= LCD_CACHE_SIZE ){
    LoWaterMark = LCD_CACHE_SIZE - 1;
  }

  if ( HiWaterMark < 0 ){
    HiWaterMark = 0;
  }
  else if ( HiWaterMark >= LCD_CACHE_SIZE ){
    HiWaterMark = LCD_CACHE_SIZE - 1;
  }

  //  Set base address according to LoWaterMark.
  LcdSendCmd( 0x80 | (LoWaterMark % LCD_X_RES), LCD_CMD );
  LcdSendCmd( 0x40 | (LoWaterMark / LCD_X_RES), LCD_CMD );

  //  Serialize the video buffer.
  for ( i = LoWaterMark; i <= HiWaterMark; i++ )
  {
    LcdSendCmd( LcdCache[i], LCD_DATA );
  }

  //  Reset watermark pointers.
  LoWaterMark = LCD_CACHE_SIZE - 1;
  HiWaterMark = 0;

  UpdateLcd = false;
}




void setup() {

  beginSerial(19200);
  //power the control led
  pinMode(CONTROL_LED,OUTPUT); 


  pinMode(LCD_RST_PIN,OUTPUT); 
  pinMode(LCD_DC_PIN ,OUTPUT);
  pinMode(LCD_CE_PIN ,OUTPUT);
  pinMode(SPI_MOSI_PIN ,OUTPUT);
  pinMode(SPI_CLK_PIN,OUTPUT);
 pinMode(voltometer,OUTPUT);



  //power the display
  pinMode(LCD_POWER_PIN,OUTPUT); 
  //start
  digitalWrite(CONTROL_LED, HIGH); 
  analogWrite(voltometer, 150);
  LcdInit();
  




}

void loop() {
 
LcdClear();
delay(100);
LcdGotoXY ( 7, 3 );   
     
LcdStr(1, "OK");

LcdUpdate();

delay(500);




}

hope you can work with it.

Thank you for the code
I have got a problem when I compile my sketch

In function 'void loop()':
error: invalid conversion from 'const char*' to 'byte*'

could you help me ?

#include <lcdnokia.h>
void setup() 
{
  beginSerial(19200);
  //power the control led
  pinMode(CONTROL_LED,OUTPUT);


  pinMode(LCD_RST_PIN,OUTPUT);
  pinMode(LCD_DC_PIN ,OUTPUT);
  pinMode(LCD_CE_PIN ,OUTPUT);
  pinMode(SPI_MOSI_PIN ,OUTPUT);
  pinMode(SPI_CLK_PIN,OUTPUT);
 pinMode(voltometer,OUTPUT);

  //power the display
  pinMode(LCD_POWER_PIN,OUTPUT);
  //start
  digitalWrite(CONTROL_LED, HIGH);
  analogWrite(voltometer, 150);
  LcdInit();

}

void loop() 
  {
    LcdClear();
    delay(100);
    LcdGotoXY ( 7, 3 );
    LcdStr(1, "ok");
    LcdUpdate();
    delay(500);
 }

I use Kuk header's file:
http://alx.alxblog.com/arduino/

Yup. You just need to cast your (character) string to a byte string like this:

LcdStr(1, (byte *)"ok");

kuk-- I might suggest a slight modification to LcdStr as follows, since probably many people would use that to print static (char) strings, right?

void LcdStr (int size, const char *dataPtr )
{
  while ( *dataPtr )
  {
    LcdChr( size, (byte)*dataPtr++ );
  }
}

Mikal

hi i'm having no luck with this lcd :S
i used kuk's code and the stuff on the playground linky and nothing is showing up on the screen :frowning:
the screen is fresh out of a 3310, and was functioning fine, has only been powered from a 3.3v run RBBB and all soldering is good..

anyone know why i am getting nothing? screen should be working perfectly :S

What's on your VOUT from the LCD? I needed to have a 4.7uf capacitor on mine for it to work. (though if it was disconnected entirely it did work somewhat)

Vout -----Cap-----Gnd

Hi all, I've got this lcd working using schematics and demo code from nuelectronics' Nokia 3310 LCD shield v1.0. Now I have one question and one problem.
The question is that in this thread is duscussed how to properly set i/o signals to 3.3v level. The nuelectronics' schematic does not use any level shifts and there is note on schematic saying "VCC -3.3V - 5V All logic I/O compatible with 5V & 3.3V logic level". I've powered my lcd direct from 5v line from Arduino board and no level shifts on i/o lines. And everything worked. How could you explain this differencies?
Everything worked until I started to move SPI SS signal from default PB2 pin to PD6 pin (as I want to add SD-shield later where SS pin to PB2 is hardwired). The problem that characters are output turned up side down or mirror reflected against vertical axis. I have not figured it out yet which code modification gives either view but it always screwed somehow. I have read many threads like "two SPI devices on a bus" on the forum and tried few suggestions from there without further progress on the output. What may cause such a behaviour of the lcd?
Thanks in advance.

Updates: mirror reflectance was my mistake - left test changes. Characters turned half round - suppose some bugs in initialization.
Now display is working, will try to figure what changes were so critical.

I'm trying to get this LCD screen working too, and no joy. Is there a way I can test my screen besides getting it to actually work? Something like getting it to scan all black?

I think I've got everything connected right, but without it working I can't be sure. This link in the playground Arduino Playground - PCD8544 mentions 5 pins, 3.3v and ground and no other electronics. Does this mean a cap is not needed on the VOUT pin 7? I've tried with and without a cap (10uf) and nothing either way.

some news regarding this lcd using playground directions?

could any one post complete program and the circuit diagram for interfacing here???

i want to put this display in my car....!! :slight_smile: :slight_smile: :slight_smile: