cool
the best thing to do now is to write an article for the playground so that others can use it.
massimo
cool
the best thing to do now is to write an article for the playground so that others can use it.
massimo
Has this been written up and posted anywhere yet?
Very interested in working with the Color LCD that SparkFun sells.
Thanks.
double ditto that!
ñ
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
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
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
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.