Go Down

Topic: A fast PCD8544 library (Nokia 5110) (Read 26 times) previous topic - next topic

TheCoolest

These numbers are for the FrameBuffered version.
Here's what I get with the non-FB version:

The time it clear the screen is: 1980
The time it took to print 84 chars is: 2628
The time it took to draw a 25x3 (25x18) bitmap is: 276


Current FB version:

The time it clear the screen is: 1708
The time it took draw a rect and 3 lines: 1960
The time it took to print 84 chars is: 2316
The time it took to draw a 25x3 (25x18) bitmap is: 1560
The time it took to run setPixel on all 4032 pixels and render it:    18252

SuperLAVA

Here my 5 cents, if anybody interested:

As different displays required different contrast settings, it is also preferable to have contrast settings available to sketch, I did mod library to have it:


Added to header file declaration of public function
Code: [Select]
void contrast(uint8_t cnt);// argument range 0 to 15
[Added to CPP files, function
Code: [Select]
void PCD8544_SPI::contrast(uint8_t cnt)
{
this->writeLcd(LCD_COMMAND, 0x21); //Tell LCD that extended commands follow
cnt = map(cnt, 0, 15, 0xB0, 0xBF); // full range  = 0x80, 0xFF
    this->writeLcd(LCD_COMMAND, cnt); //Set LCD Vop (Contrast)
this->writeLcd(LCD_COMMAND, 0x20); //We must send 0x20 before modifying the display control mode
this->writeLcd(LCD_COMMAND, 0x0C); //Set display control, normal mode. 0x0D for inverse

}


robtillaart

NIce addition SuperLava,

one change - see code

Code: [Select]

void PCD8544_SPI::contrast(uint8_t cnt)
{
this->writeLcd(LCD_COMMAND, 0x21);          //Tell LCD that extended commands follow
        this->writeLcd(LCD_COMMAND, 0XB0 + cnt);  //Set LCD Vop (Contrast)
this->writeLcd(LCD_COMMAND, 0x20);          //We must send 0x20 before modifying the display control mode
this->writeLcd(LCD_COMMAND, 0x0C);          //Set display control, normal mode. 0x0D for inverse
}
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

TheCoolest

The issue with getting the contrast right is that you may also have to play around with the bias and temp coefficient.
I need to open up the datasheet and see whether this->writeLcd(LCD_COMMAND, 0x0C); is actually needed after the changes.

SuperLAVA

For this display/controller there is no actual CONTRAST function, but in all references I was able to find on the Web, changing of this register used for contrast adjustment. It will change some ref voltage and recalling from data sheet (I read it few weeks ago) thee are limitations to range of these values, they can damage display/controller. The range I did map to appeared to be safe under all conditions and from my experiments it did cover quite a variety of samples, always from very pale to all dark (I've tried 5 displays from different lots), so I assume this range is very sufficient. My values are from 4 to 12. Now, reading again http://arduino.cc/en/Reference/map apparently MAP  still not safe and constrain() must be added to avoid dangerous range of values. Well, unless you are certain that bad argument will never make it to this function.


Code: [Select]

        this->writeLcd(LCD_COMMAND, 0XB0 + cnt);  //Set LCD Vop (Contrast)



If more people using it - let's make it safe. Right?

Temperature coefficient:

Thought to play with it. But in my application it is used as home networked thermostat. By definition, unlike original cellphone application, my project should see very minor changes in temperature and, in addition, I assume default coefficient probably close enough. I don't see problem with it yet, so I don't think it have to be resolved. If each display to get it's own settings - testing it would be difficult without enviromental chamber and messing with it might do more harm. But once again, as this library get more traction, for the rest out there, it might worth to look at.

Good thing about these functions - they are for setup only and do not affect speed of this nice library.  :)

TheCoolest

#35
Sep 15, 2013, 02:18 pm Last Edit: Sep 15, 2013, 02:29 pm by TheCoolest Reason: 1
I have posted version 1.2, with the bug fixes and optimizations pointed out yesterday.

@ SuperLAVA
There is a datasheet here: http://st4.divshare.com/launch.php?f=19490578&s=db2
Read from page 14.
Your code for setting the 'contrast', which is the Vop settings should be as follows:

Code: [Select]
// Valid values are 0x00 - 0x7F.
void PCD8544_SPI::contrast(uint8_t cnt)
{
this->writeLcd(LCD_COMMAND, 0x21);          //Tell LCD that extended commands follow
this->writeLcd(LCD_COMMAND, 0X80 | cnt);  //Set LCD Vop (Contrast)
}

robtillaart

Quote
If more people using it - let's make it safe. Right?

You're right, but that should then be done for all functions including constructor.

The code TheCoolest posted is robust for all values of cnt even above 0x7F - although 0x80 has the same effect as 0x00 etc
by dividing cnt by 2 it becomes (more) natural imho

Code: [Select]

void PCD8544_SPI::contrast(uint8_t cnt)
{
        cnt = cnt/2;
this->writeLcd(LCD_COMMAND, 0x21);          //Tell LCD that extended commands follow
this->writeLcd(LCD_COMMAND, 0X80 | cnt);  //Set LCD Vop (Contrast)
}


@TheCoolest,
Time to add a new youtube?
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

TheCoolest

#37
Sep 15, 2013, 04:54 pm Last Edit: Sep 15, 2013, 05:00 pm by TheCoolest Reason: 1
I don't think that dividing by 2 is really necessary. I haven't really looked at libraries for this display, so I'm not sure whether adjusting Vop, bias and temp coefficient is supported by them or not. The actual Vop data is 7 bits long, therefore 0x00 - 0x7F. But you can still make a call such as lcd.contrast(0xB0); and it will work just fine, making the call with 0x30 as the value will have the same effect.

One thing to note, these displays are not the same as the simpler HD44780 LCDs where you control the contrast with a pot or with a PWM signal (with an LPF). The Bias and temperature coefficient settings are important and I had to play with all 3 values to get the display to look right on my LCD. It may be different in your case. Therefore I think that only allowing the user to change the Vop may not be enough, this is why I've added all three values to the optional begin() method.

@TheCoolest,
Time to add a new youtube?


To show the new and improved performance results?

robtillaart

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

TheCoolest

#39
Sep 15, 2013, 07:17 pm Last Edit: Sep 15, 2013, 09:21 pm by TheCoolest Reason: 1
Cool, I'll update it a bit later.

bumsbert

I am stoked to use this library. :) No flaws so far. Nice information on pin mapping in the .h file. :* Thank you!!!!

SuperLAVA


Quote
If more people using it - let's make it safe. Right?


The code TheCoolest posted is robust for all values of cnt even above 0x7F - although 0x80 has the same effect as 0x00 etc



For "safe" I meant not to exceed Vop (max 8.5V) to avoid damaging displays. With fill range control it is possible to violate requirements and set Vop as high as 10.68V.
You can't use value of 0x00 as MSB for this control must be set to 1 to control Vop, see "Table 1 Instruction set".
0xB0 to 0xBF fits nicely into the range to not exceed Vop under any conditions and apparently provided sufficient contrast range for all conditions. That makes it "safe". So looks like "constrain()" is the right way to do it.

"
from data sheet - 8.9
Caution, as V  increases with lower temperatures,
care must be taken not to set a V  that will exceed the
maximum of 8.5V when operating at -25 °C.
"

TheCoolest

You may be right, but again as I said all displays are different and what works for one doesn't necessarily mean it will work for another.
If you want to 'constrain' the values you can simply do cnt &= 0x0F; and then this->writeLcd(LCD_COMMAND, 0XB0 | cnt);.

SuperLAVA


You may be right, but again as I said all displays are different and what works for one doesn't necessarily mean it will work for another.
If you want to 'constrain' the values you can simply do cnt &= 0x0F; and then this->writeLcd(LCD_COMMAND, 0XB0 | cnt);.


TheCoolest,

I support your statements.

So, will you add contrast control to your next revision?

TheCoolest

I'm not convinced that adding this as an extra function is really needed. You really only have to find the right setup once I think.
Also if you take a look at the datasheet, it says that over 8.5v is dangerous only when your ambient temperature is lower than -25C. Unless you're at the north/south pole, I don't think many will operate such a display in such extreme conditions.
If you read the datasheet again you'll notice that there's a formula to calculate the optimal Vop for your LCD. My LCD works best with a 1:65 bias, putting that into the formula I came up with 0x3F (0xBF) as the optimal Vop, but after some testing I came to the conclusion that at the current ambient temperature 0x37 or 0x38 works best.
So the contrast is directly dependent on the Bias System.
For LCDs using 1:48 the range of 0x30 - 0x3F might be OK, but could potentially be limiting because 0x30 could still be too high.

Go Up