A fast PCD8544 library (Nokia 5110)

Ok, you have a point :slight_smile: (many actually)
I'll add contrast support into the next version, it should be easy simple enough.
The only question remaining is what do we do with the range? For 'safety' we might want to limit the contrast level to something like 0x20 - 0x3F. But on the other side I also want to give the user full control. Decisions, decisions... Any ideas? Maybe make 2 separate functions, something like contrast() and contrastUnsafe()?

While this library set so many records, I hate to make it heavier even by single line or byte, but I do need contrast.

You can always make code conditional available in the library by preprocessor directives.

#define EXTENDED_PCD8544

...

#ifdef EXTENDED_PCD8544

void ::contrast() ...

#endif

Any ideas? Maybe make 2 separate functions, something like contrast() and contrastUnsafe()?

2 separate functions is maybe more unsafe as people might use the wrong one

users who want another range can mod the library explicitly - so they know they're tweaking -

// warning ...
#define CONTRAST_MIN  ..
#define CONTRAST_MAX ..

::contrast(int value)
{
  value = constrain(value, CONTRAST_MIN, CONTRAST_MAX);
  ...
}

TheCoolest:
Ok, you have a point :slight_smile: (many actually)
I'll add contrast support into the next version, it should be easy simple enough.
The only question remaining is what do we do with the range? For 'safety' we might want to limit the contrast level to something like 0x20 - 0x3F. But on the other side I also want to give the user full control. Decisions, decisions... Any ideas? Maybe make 2 separate functions, something like contrast() and contrastUnsafe()?

I suggest single "contrast" function. For advanced developers you may add different, "extended()" command with no limits on values, especially because other stuff can be controlled by it. Or, single argument contrast() will limit (and map?) values and second argument, only if used, will relax it to full (and unmapped?) range.
As we have quite a crowd here - we can test if safe range is sufficient, you may provide instructions for less advanced coders, how to extend it.
Risking bloating it I can suggest to auto switch contrast range depending on mux ratio and temp curve, ...actually no, this is too much, let "advanced coders" to mess on their own with those, let's keep library light.
My personal preference, for future reuse, to have contrast values mapped to standard range starting from 0 and up. 255 is too much, most steps will do nothing. 15 is good. But as we have already have to think in special ranges for bit map coordinates, in parallel with that mapping is not necessary.

Hi, All!

Pretty dumb question: I've tried not to connect lcd screen via 4050, but to connect it directly. Nothing worked. Double checked all connections. Should I really use 4050?

I've sucessfully ran same 5110 screen with this sketch: http://blog.stuartlewis.com/2011/02/12/scrolling-text-with-an-arduino-and-nokia-5110-screen/ . Any ideas what went wrong?

@Zeddy:
The LCD requires 3.3v signals, it isn't 5v tolerant as far as I know.
I know some people have used 1k or 10k (can't remember exactly) resistors to achieve the same effect, but my personal recommendation is to use a proper voltage level shifter to get things working.
Also note that you MUST connect VCC and backlight to 3.3v output on your Arduino, it won't like 5v on those inputs.

@SuperLAVA:
I'll think of something. Thank you for the input.

What would you suggest me to set PIN_CE to, so i get another free pin? Because i only have one spi device and i need more pins to switch some relays?

The default configuration uses pins D8 - D13. All of the other pins are free.
If you need D10 for some reason, you will have to remap DC and RST pins as well to either D0-D7 or A0 - A5.

I see. I ask because i wonder what happens if i put CE to something non existig. But i dont want the programm to be unsafe.
He says one can put CE to -1 to get one free pin:

Another thing: what about the A6 A7 of the arduino nano board? What bus are they on? http://arduino.cc/en/Hacking/PinMapping168 what is their binary address?

Ok, I see what you mean now. You can simply set PIN_CE to to 0x00 (basically 0).
When you ground the CE pin on the LCD itself it'll always be in "write" mode, so it should work.

A6 and A7 aren't on any port, they are analog inputs only and cannot serve as digital IO.

And that is great news. I can finish my project now. Its awesome. Your library kicks ass! maybe you can add the 0x00 option info to your comments. I guess some more noobs like me could use this info.

TheCoolest:
A6 and A7 aren't on any port, they are analog inputs only and cannot serve as digital IO.

That is funny because I was convinced I killed them because they were not working as digital outputs. :grin: I must have always underread that

Hey guys,

thanks for the libary. First it was working fine, but now I have some problems. The text I want to print in my setup Funktion is not printed. Well if you look in an sharp angel you can see that there is somthing printed, but really light. The same with the other text in the coolTempControll() Funktion. When I add a SPI.setClockDivider(SPI_CLOCK_DIV2); the text in the coolTempControll() Funktion ist printed correctly, but still not the text in my setup funktion.

Do someone of you know were the problem is?

Thanks alot!

//LCD Initialisierung ----------------------------------------------
#include <SPI.h>
#include <PCD8544_SPI.h>
PCD8544_SPI lcd;


//Encoder Initialisierung ----------------------------------------------
#include <Encoder.h>
Encoder myEnc(5, 6);
long oldPosition  = -999;
int number = 0;
int oldNumber = 0;
int control = 0;
int switchValue = 0;
int minValue;
long maxValue;
long encValue;
long encStart;


//Taster------------------------------------------------------------------
const int BUTTON = 4;
long startTime = 0;

//Kühltemperatur-----------------------------------------------------------------
int coolTemp = 10;






void setup(void)
{
        
        SPI.setClockDivider(SPI_CLOCK_DIV2); 
	Serial.begin(9600);
	
        pinMode(BUTTON, INPUT);                    // Pin für Taster
        digitalWrite(BUTTON, HIGH);                // Turn on internal pullup resistor
        
        
        lcd.begin();
        lcd.clear();
        lcd.gotoXY(20,1);
	lcd.print("EUMEL'S");
        lcd.gotoXY(4,2);
        lcd.print("BRAUMASCHINE");
        
	delay(2000);
        lcd.clear();
}



void loop(void) 
{
        
        coolTempControll();
               
        
        //Serial.println(newPosition);
        
        
        /*lcd.clear();
        lcd.gotoXY(4,2);
        lcd.print(newPosition);*/
        
  
}

// Funktion Tastendruck keyPressed-----------------------------------------------
long keyPressed () // returns duration of key_press so far
{
  long duration=0;
  if(digitalRead(BUTTON) == LOW)
  {
    if (startTime > 0) // war schon gedrueckt?
    {
      duration = millis() - startTime;
    } else {
      startTime = millis(); // nicht gedrueckt
    }
  } else {
    startTime = 0;
  }
  return duration;
}

int coolTempControll(){
  
  //lcd.clear();
  lcd.gotoXY(5,1);
  lcd.print("Gaer Waechter");
  coolTemp = switchPos(-3 , 31, 10);
  lcd.gotoXY(5,3);
  lcd.print("soll");
  
  if (coolTemp < 10)  {lcd.gotoXY(35,3); lcd.print(" "); lcd.gotoXY(41,3);}
  if (coolTemp >= 10 || coolTemp < 0)  lcd.gotoXY(35,3);
  
  
  lcd.print(coolTemp);
  
  lcd.gotoXY(5,4);
  lcd.print("ist");
  
  lcd.gotoXY(41,4);
  lcd.print(coolTemp);
  
  
}  

int switchPos(long minValue, long maxValue, long encStart){
       
        
      number = myEnc.read();
   
      if (number >= oldNumber+3){   
        oldNumber = number;
        encValue++;
        
        if (encValue >= maxValue){
          encValue=maxValue;
          myEnc.write(maxValue);
        }
      }
      else if (number <= oldNumber-3){
        oldNumber = number;
        encValue--;
        
        if (encValue <= minValue){
          encValue=minValue;
          myEnc.write(minValue);
        }
      } 
      
      

      
      
      return encValue;
}

First of all, the PCD8544 controller supports SPI speed of 4MHz. This means you have to use SPI_CLOCK_DIV4 or leave it at default.
I tried your sketch and my screen didn't display anything with SPI_CLOCK_DIV2.

The second possible issue is that you don't have any delays/pauses in your loop. If the values change often it won't look right.
One more thing is you might need to play with the contrast values in the PCD8544_SPI::init (or PCD8544_SPI::begin) function.

  • Added a timed refresh for the LCD, twice per second (as the coolest proposed)
  • CTRL-T auto formatting for readability

give it a try

//LCD Initialisierung ----------------------------------------------
#include <SPI.h>

#include <PCD8544_SPI.h>

PCD8544_SPI lcd;


//Encoder Initialisierung ----------------------------------------------
#include <Encoder.h>

Encoder myEnc(5, 6);

long oldPosition  = -999;
int number = 0;
int oldNumber = 0;
int control = 0;
int switchValue = 0;
int minValue;
long maxValue;
long encValue;
long encStart;


//Taster------------------------------------------------------------------
const int BUTTON = 4;
long startTime = 0;

//Kühltemperatur-----------------------------------------------------------------
int coolTemp = 10;


uint32_t lastScreen = 0;

void setup(void)
{
  SPI.setClockDivider(SPI_CLOCK_DIV2); 
  Serial.begin(9600);

  pinMode(BUTTON, INPUT);                    // Pin für Taster
  digitalWrite(BUTTON, HIGH);                // Turn on internal pullup resistor

  lcd.begin();
  lcd.clear();
  lcd.gotoXY(20,1);
  lcd.print("EUMEL'S");
  lcd.gotoXY(4,2);
  lcd.print("BRAUMASCHINE");

  delay(2000);
  lcd.clear();
}

void loop(void) 
{
  if (millis() - lastScreen > 500)
  {
    lastScreen = millis();
    coolTempControll();
  }

  //Serial.println(newPosition);

  /*
  lcd.clear();
  lcd.gotoXY(4,2);
  lcd.print(newPosition);
  */
}

// Funktion Tastendruck keyPressed-----------------------------------------------
long keyPressed () // returns duration of key_press so far
{
  long duration=0;
  if(digitalRead(BUTTON) == LOW)
  {
    if (startTime > 0) // war schon gedrueckt?
    {
      duration = millis() - startTime;
    } 
    else 
    {
      startTime = millis(); // nicht gedrueckt
    }
  } 
  else {
    startTime = 0;
  }
  return duration;
}

int coolTempControll()
{
  //lcd.clear();
  lcd.gotoXY(5, 1);
  lcd.print("Gaer Waechter");
  coolTemp = switchPos(-3 , 31, 10);
  lcd.gotoXY(5, 3);
  lcd.print("soll");

  if (coolTemp < 10)  
  {
    lcd.gotoXY(35, 3); 
    lcd.print(" "); 
    lcd.gotoXY(41, 3);
  }
  if (coolTemp >= 10 || coolTemp < 0)  
  {
    lcd.gotoXY(35, 3);
  }

  lcd.print(coolTemp);

  lcd.gotoXY(5, 4);
  lcd.print("ist");

  lcd.gotoXY(41, 4);
  lcd.print(coolTemp);
}  

int switchPos(long minValue, long maxValue, long encStart)
{
  number = myEnc.read();

  if (number >= (oldNumber+3))
  {   
    oldNumber = number;
    encValue++;

    if (encValue >= maxValue)
    {
      encValue=maxValue;
      myEnc.write(maxValue);
    }
  }
  else if (number <= (oldNumber-3))
  {
    oldNumber = number;
    encValue--;

    if (encValue <= minValue)
    {
      encValue=minValue;
      myEnc.write(minValue);
    }
  } 
  return encValue;
}

I am using Arduino Mega 2560 and MotorShield what renders using the default pins impossible kinda so I have a question.

Could i use pins 51 and 52 as SDIN and CLK instead, there is no definition for them, but looking trough pin mapping
http://arduino.cc/en/Hacking/PinMapping2560 I see that these pins are MOSI and SCK, also pin 47 is capable of PWM so i would use it for SCE.

Thanks in advance.

The library will use the hardware SPI pins on any Arduino, so you have to use the MOSI and SCK pins of your Arduino.
To configure the DC, SCE and RST pins, open PCD8544_SPI.h and read the comments about pin out changing, everything is explained there in detail.
Please let me know if you have any other questions.

As I mentioned, I cant use the default pins, so i would like to use pins 51 and 52, but there is no definition for them.
On Arduino Mega 2560 51 and 52 are marked as MOSI and SCK.

The SPI pins on the mega are exactly what you mentioned. You actually HAVE to use those pins with this library.
You have to modify the header file to change the mapping for the SCE, DC and RST pins.

There are 3 different MOSI pins actually, tyvm for the information, I thought that maybe i have to define them.
Will give it a shot later.

Right, I've never used a Mega chip, but this library uses the Arduino SPI library, so you have to use the SPI pins you usually use with that lib.