Sunday, 29 September 2013

OLED 1602 Display and library for the SSD1311

Following on from the last post, the OLED 2 line 16 character display arrived from Hong Kong.




The display uses I2C to connect to the host and will work at 3.3 or 5V so is ideal to use with an Arduino board.

The supplier WIDE.HK supplies some sample code to get it running in the form of a QR code on the packaging that links to the the code and a couple of PDF datasheets.

The code uses a long winded method to initialise and write to the display, but it gets it working.

I have been thinking it was about time I learned how to create a library and this gave me the reason to give it a go, as well as not being able to find a library for this device anywhere on the web.

The very basic Library can be downloaded here, please remember this is my first attempt at creating a library, it works but I imagine it needs more functions adding before it becomes very useful.

Library updated 7/11/13 see here.

Here is the demo code I wrote using the library: -
/*
Demo sketch to display text on the OLED 1602 display
from Wide.HK. This uses a Lbrary that I've put together
containing some basic functions.
The I2C Address is set to 0x3C in OLedI2C.cpp
Phil Grant 2013 www.gadjet.co.uk

Sketch updated to work with new library 7/11/13
*/
#include  "Wire.h"    
#include  "OLedI2C.h"  
OLedI2C LCD;
void setup()
{
  Wire.begin();
  LCD.init();  
}
void loop()
{
  //Set cursor position to col and row, top row is 0, first col is 0
  // no longer required LCD.cursPos(4,0); //(col,row)
  LCD.sendString("Gadjet's", 4, 0);    //("String", col, row)
  // no longer required LCD.cursPos(6,1); //Set cursor position to col and row 
  LCD.sendString("BLOG", 6, 1);   //("String", col, row)
  while(1);
}

As usual, feedback welcomed, use the comments if you found this library useful ...... or not.


46 comments:

Nathan Chantrell said...

Looks like a nice little display, like how compact the PCB is compared to the actual display. Had to order one.

Gadjet said...

Yes it's a very compact display, not like the typical 2 line LCD and the contrast is superb.

The only drawback is the current consumption is a bit high, around 70mA.

Anonymous said...

Hi, Thanks for sharing the library.

But I get an error like:

'OLedI2C' does not name a type

I put the filed under into a directory named 'OLedI2C' under libraries directory, but still get the same error messages.

Do you have any advice?

Anonymous said...

Ok. I solve the problem replacing these two lines:

#include Wire.h
#include OLedI2C.h

with these:

#include "Wire.h"
#include "OLedI2C.h"

Now. I'll try to work on.
Thanks.

Gadjet said...

Glad you solved it, I use the <> symbols but the blog engine kept removing them, that's why I added the comment to the first two lines to add them in again, "" will also do.

Nathan Chantrell said...

I've refined my scrolling code for this now, maybe you can roll it into your library Phil?

Code here: https://github.com/nathanchantrell/OLED1602/blob/master/Scroll_demo/Scroll_demo.ino

Gadjet said...

Thanks Nathan, scrolling was my next task but there's too much normal everyday stuff getting in the way.
(clearing the gutters, fixing the shower ....)

I'll add it to the library over the weekend.

Unknown said...

Hello!

I bought this but I can not display that shows temperature data eg. With LCD displays was much easier.
For example, this command is not supported: lcd.print (val);
Can you help?
Thank you!

Gadjet said...

Hello,
The only thing in the library at the moment is sendstring, the library doesn't have the funcionality of the full lcd libraries but I plan to add similar capabilities like print.
Can you convert the value to a string and use sendstring?

Unknown said...

Hello!

Well, I have not much idea of ​​programming with Arduino. I am waiting for you to add more commands.

Gadjet said...

I will always try to improve but it won't be quick..... in the mean time.
If you set a variable to put your data value into and use the "dtostrf()" function you can then send your data to the LCD.
You can google the dtostrf to get the details.

Prior to the setup loop add:

char line[5];


In the main loop code:

dtostrf("your temp data",4,1,line); //Convert you decimal data into a string, including decimal point.

LCD.cursPos(4,0); //(col,row)
LCD.sendString("line");

Gadjet said...

Here is an example to send data as a string to the display. I've also updated the library file on GitHub to pass the cursor position to the sendString function.


#include "Wire.h"
#include "OLedI2C.h"
OLedI2C LCD;
char line[5];
float digit;

void setup()
{
Wire.begin();
LCD.init();
digit = 21.6;
}
void loop()
{
LCD.sendString("Temp",0,0);// now includes the cursor position data (col, row)
dtostrf(digit,4,1,line);//Convert the float value to a string
LCD.sendString(line,7,0);//Send the string to the display
while(1);
}

Unknown said...

Thank you!

Hare Checking if it works and sends the temperature to display.
Not so fast the modification needed in the library. He could wait much longer. Even so, THANK YOU.

Unknown said...

I tried modifying the code with one that had a graphical OLED display.
It works perfectly.

Just need to add code to display the time.

Thank you so much!




#include "Wire.h"
#include "OLedI2C.h"
#include
#include
#define ONE_WIRE_BUS 2
OLedI2C LCD;
char line[5];
float val = 0;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

void setup()

{
Serial.begin(9600);
// Start up the library
sensors.begin();
Wire.begin();
LCD.init();

}


void loop()
{
sensors.requestTemperatures();
float val = sensors.getTempCByIndex(0) ;
LCD.sendString("Temp",0,0);// now includes the cursor position data (col, row)
dtostrf(val,4,1,line);//Convert the float value to a string
LCD.sendString(line,7,0);//Send the string to the display
delay(1);
}

Gadjet said...

Your welcome.

Unknown said...

I can not display the seconds on the screen ... : (
What can be wrong?



#include "Wire.h"
#include "OLedI2C.h"
#include
#include
#include "RTClib.h"
RTC_DS1307 RTC;
#define ONE_WIRE_BUS 2
OLedI2C LCD;
char line[5];
float val = 0;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

void setup()

{
Serial.begin(9600);
// Start up the library
sensors.begin();
Wire.begin();
RTC.begin();
LCD.init();

}


void loop()
{
long start_time = millis();
DateTime now = RTC.now();
sensors.requestTemperatures();
float val = sensors.getTempCByIndex(0) ;
float time = RTC.now(0) ;
LCD.sendString("Temp",0,0);// now includes the cursor position data (col, row)
dtostrf(val,4,1,line);//Convert the float value to a string
dtostrf(time,4,2,line2);//Convert the float value to a string
LCD.sendString(line,7,0);//Send the string to the display
LCD.sendString(time,7,1);//Send the string to the display
LCD.sendString(now.second,0,1);
delay(1000 - (millis() - start_time));
}

Gadjet said...

After a quick look I found some issues: -
Line2 used for time hasn't been declared.
You convert time to line2 but send time not line2
You send now.time but do not convert it to a string first.

I hope that gives you some pointers.

Gadjet said...

On second thoughts, if you have the latest version of the library you cna use sendFloat to send the float values directly the conversion is done for you.

Patrik Thors said...

#include
#include
OLedI2C LCD;
void setup()
{
Wire.begin();
LCD.init();
}
void loop()
{
//Set cursor position to col and row, top row is 0, first col is 0
LCD.cursPos(4,0); //(col,row)
LCD.sendString("ABCD");
LCD.cursPos(6,1); //Set cursor position to col and row
LCD.sendString("1234");
while(1);
}

Just trying to run your basic code. But i get

"no matching function for call to 'OLedI2C::sendString(const char [7])'"

Patrik Thors said...

Oh.. Wire.h and OLedI2C.h disapered in the comment but i have them in the code.

The error appears att line 13..

Gadjet said...

Patrik,
Sorry, I've updated the library, see the latest post, I will update the older post to reflect the changes.
the new function sendString() requires the cursor positions to be added and the cursPos() function is no longer required.
Try
sendString("ABC",4,0);
sendString("1234",6,1);

I hope that explains.

Patrik Thors said...

Got i working, thanks :)

peterpeter said...

I am trying to add contrast function to the library, however it's not working so far. Have you guys had any luck with contrast?

void setContrast(uint8_t contrast);

void OLedI2C::setContrast(uint8_t contrast)
{
sendCommand(0x81); // **** Set Contrast
sendCommand(contrast); // value 0x00-0xFF / 0-255
}

Gadjet said...

Peterpeter,
I must admit to not having done too much with the display other than showing standard text, I did try to edit the contrast but nothing happened I have a suspicion that contrast might not actually work on an OLED and the function is there to support normal LCDs.

Pegasus said...

You must switch to "OLED Command Set". Send commands 0x2a and 0x79 prior using 0x81.
0x28 and 0x78 will return to "Fundamental Command Set" afterwards.

Hope this helps.

Gadjet said...

Thanks for the information, I'll give it a try.

Gadjet said...

Pegasus,
Tried your suggestion and actually realised the contrast setting is already in the initialisation routine in the library so I played with the value and it makes a difference but not a huge one, down at 0x04 it looks less sharp and dimmer.
I'll put the current meter on it later to see if it uses less current.

Gadjet said...
This comment has been removed by the author.
Gadjet said...

Just updated the Library to include three new functions
lcdOn()
lcdOff()
setContrast(contrast) //contrast is between 0x00 and 0xFF.

LCD blink example: -


#include "Wire.h"
#include "OLedI2C.h" //OLED 1602 IC2 support
OLedI2C LCD;

void setup() {
Wire.begin();
// Initialise LCD
LCD.init();
// Write data to LCD
LCD.sendString("Booting",5,0);
}

void loop() {
LCD.setContrast(0x00);
delay(1000);
LCD.setContrast(0xFF);
delay(1000);
}

Rafael said...

Hi,

According to OLED initialisation, you can choose the ROM between A, B or C.

In the code:
sendCommand(0x72); // **** Set ROM
sendCommand(0x05); // **** Set ROM A and 8 CGRAM

But, if you send: sendData(0x11);

You will see a char from ROM C table.

Is ROM C set by hardware configurarion? Or is a timing problem? I am using an arduino UNO. Thanks.

Rafael said...

sendCommand(0x72); // **** Set ROM
sendCommand(0x00); // **** Set ROM A and 8 CGRAM

Still shows chars from ROM C too.

Camacho said...

Now I got it work.

Correct the initialization problem for selecting ROM and more, but now with custom chars.

http://i.imgur.com/EU8mRV1

:)

Gadjet said...

Rafael,
Thanks for the info.

Camacho,
Very nice, I love the Custom characters.

dnbblah said...

@Camacho can you state how you changed the ROM?

Camacho said...

I am Rafael Camacho, sorry for mistake with names in two posts.

So, to resolve the ROM selection problem:

sendCommand(0x72); // **** Set ROM
sendData(0x00); // **** Set ROM A and 8 CGRAM

In the wide.hk example is wrong send the second instruction with command function.

Very hard to find it, but, in the 1000th read of the datasheet I just got it! :(

dnbblah said...

Hey Rafael,

thanks for answering, I tried the approach you stated already a month ago and i could't get it running..

I looked as well at the data sheets and when I print the german sharp S (ß) from ROM A i get the according character of ROM C.. so obviously it didn't change.. :( i used the exact same code to change it as you stated. i even think gadget updated his library to reflect the changes anyway..

http://www.hot.ee/heajook//SSD1311_1.0%20%20IC%20Spec.pdf

its binary val is : 1011 1110

can you try to verify this?

Regards

Camacho said...

Hi,

Try change this:

sendCommand(0x72); // **** Set ROM
sendCommand(0x00); // **** Set ROM A and 8 CGRAM

for this:

sendCommand(0x72); // **** Set ROM
sendData(0x01); // **** Set ROM A and 8 CGRAM

Always remember that the second instruction requires a data input.

Vizli said...

I have the same problem. Only characters from ROM C can by displayed ((
In datasheet I found the following:

3 sets of CGROM (ROM A / B / C –
software or hardware pin selectable)

Maybe it fixed to ROM C using hardware pin?

Gadjet said...

Well I've tried for the last hour trying to set another ROM and I cannot get it to use anything other than ROM C, no matter what I do ....some more thinking required.

Camacho said...

Please check

github.com/rafaelcamacho/Oled-SSD131x

dnbblah said...

@Rafael, thanks for posting your code.
First i thought it was an issue with the I2C cable length, but i could verify your code works. Nevertheless i ported your code into Gadjets Library without success, which is pretty weird. If i have some time im going to try again. Have to merge some code anyway like partial scrolling etc..

It looks like there is an issue with the timing when calling a library.. Thanks again for providing your code so i can narrow down the issue.

Camacho said...

Hi,

Just need to preserve PowerUp method and the time to run it.

When I set up the sequence of powerup, with printed datasheet, tried to respect and understand each delay response of each command.

Артем Груничев said...

> The only drawback is the current consumption is a bit high, around 70mA.

it's for 5 or 3.3 V?

Gadjet said...

5V if I remember correctly.

Артем Груничев said...

thank you. Is it's power consumption depends on how much characters are off?

Gadjet said...

I didn't really investigate the current consumption that closely.