Newhaven Display Forum

Newhaven Products => OLEDs => Topic started by: wb2dyb on March 16, 2015, 11:23:21 PM

Title: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on March 16, 2015, 11:23:21 PM
I found a library that works very nicely with the 420CW displays.

https://github.com/gadjet/1602-OLED-Arduino-Library/blob/master/OLedI2C.cpp

There is one modification needed,

original:
 void OLedI2C::cursPos(uint8_t col, uint8_t row)
 {
 int row_offsets[] = { 0x00, 0x20};
 sendCommand(0x80 | (col + row_offsets[row]));
 }
 
The above works fine with two lines.

For four lines:

 void OLedI2C::cursPos(uint8_t col, uint8_t row)
 {
 int row_offsets[] = { 0x00, 0x20, 0x40, 0x60 };//**************THIS WAS THE CHANGE FOR 4 LINES
 sendCommand(0x80 | (col + row_offsets[row])); //was 0x80
 }
 

And the init has an error:

original:


 // **** Set OLED Characterization *** //
sendCommand(0x2A); // **** Set "RE"=1
sendCommand(0x79); // **** Set "SD"=1
// **** CGROM/CGRAM Management *** //
sendCommand(0x72); // **** Set ROM
sendCommand(0x00); // **** Set ROM A and 8 CGRAM

needed this change:

 // **** CGROM/CGRAM Management *** //
 sendCommand(0x72);     // **** Set ROM
 sendData(B00000011);     // **** Set ROM A and 8 CGRAM This selects CGROM A, 00000000 selects CGROM C
 // **** Set OLED Characterization *** //
 sendCommand(0x2A);     // **** Set "RE"=1
 sendCommand(0x79);     // **** Set "SD"=1

The only missing function, at least one I'd like to see is a custom character. Most controllers allow for this, and the NHD420CW does. Just not in this library. And I speak entirely about Arduino Uno. But it is doing what I needed, with the exception of needing 8 custom characters I need to represent with letters. I tried adding it but while I think I got the character creation right, for all I've looked, I cannot see how to select a custom character (anybody give me a pointer on THAT??

GeorgeC


Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Paul_B on March 17, 2015, 07:45:13 AM
Hello George,

Thanks for sharing and posting your solution!

Regarding custom characters please have a look at the displays controller spec, see page 28. User defined characters can be loaded via 512 bits (8 characters) Character Generator RAM (CGRAM).

Link: http://www.newhavendisplay.com/app_notes/US2066.pdf

You will need to call the Set CGRAM address command, also take a look at the command description listed on page 39.

Hope this helps and please keep me posted on your progress  :)
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on March 18, 2015, 04:49:30 PM
Hi Paul, I understand that, but I'm not a programmer. I tried some copying from others for this same purpose but part of a different controller's library. (HD44780). But I just don't have what it takes to figure this out. Also, when I thought I had that part working I spent hours and just didn't see how to access a custom font. I know default CGROM is the third one "C", and eventually figured out how to change that, but I just didn't see how to get "at it". I'll eventually figure it out. And the project I wanted this for is now working on breadboard with the OLedI2C (modified for four line) library.

It's fun anyhow! And at 62 I'm learning...

GeorgeC
Title: Re: Library that works fine on the NHD-0420CW-A*3 sample photos
Post by: wb2dyb on March 18, 2015, 04:58:32 PM
Here's what it looks like.
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 20, 2015, 10:36:35 PM
Quote
The only missing function, at least one I'd like to see is a custom character. Most controllers allow for this, and the NHD420CW does. Just not in this library. And I speak entirely about Arduino Uno. But it is doing what I needed, with the exception of needing 8 custom characters I need to represent with letters. I tried adding it but while I think I got the character creation right, for all I've looked, I cannot see how to select a custom character (anybody give me a pointer on THAT??

Hi
I hope this will help.
It's for my arduino-matrixorbital
A software emulator for Matrix Orbital character display commands on Arduino.
Example sketch that uses Matrix Orbital type commands, look at case 78: // Define custom character

Code: [Select]
#include <OLEDFourBit.h> // Works with NewHAVEN NHD-0420DZW-AY5-ND
// Added fixes by Chris O. to OLEDFourBit library, Compatibility with previous versions of IDE. NOTE tested on Aduino 023 IDE <---> Aduino 1.0.4 IDE
// NOTE: Arduino Micro Pin Mapping i used.
OLEDFourBit lcd(12, A0, A1, A2, A3, A4, A5); //with rw pin (12, 11, 10, 5, 4, 3, 2);
//OLEDFourBit lcd(12, 14, 15, 16, 17, 18, 19);

// these constants won't change.  But you can change the size of
// your LCD using them:
const int numRows = 4; // 4x20 LCD
const int numCols = 20;
//
byte rxbyte = 0; // incoming data storage

void setup() {
  Serial.begin(19200); // Default baudrate.
  lcd.begin(numCols, numRows); // Change this for other screen sizes. 
  lcd.print("Arduino Emulator for");
  lcd.setCursor(1, 1);
  lcd.print("Matrix Orbital!");
  lcd.setCursor(2, 2);
  lcd.print("Character Display!");
  lcd.command(0b00010000); //Moves the cursor back one space before the blinking cursor
  lcd.command(0b00001101); // 0b00001DCB Show Blinking Block Cursor with out Underscore

  delay(5000); //delay 5 sec
  // while (serial_getch() == 0 ){   //delay [ Wait for OS to load ]
  //   rxbyte = serial_getch();
  //}
  lcd.command(0b00001100); //Turn off the blinking cursor: on exit
  //lcd.noBlink(); // Turn off the blinking cursor: on exit / no good it will turn off the display ????????? lib. problem?

  lcd.clear(); // clear the screen
  lcd.setCursor(0,0);
}
void loop() {
  // incoming data storage
  byte temp; // Parameter storage
  byte temp2; //2nd Parameter storage

  rxbyte = serial_getch(); //get byte and store in rxbyte

  if (rxbyte == 254) { //Matrix Orbital uses 254 prefix for commands
    switch (serial_getch()) { //get byte

    case 71:  //set cursor position
      temp = (serial_getch() - 1);  //get column byte
      switch (serial_getch())  //get row byte
      {
        //line 1 is already set up
      case 2:
        temp += 0x40;
        break;
      case 3:
        temp += 0x14;
        break;
      case 4:
        temp += 0x54;
        break;
      default:
        break;
      }
      lcd.command(0b10000000 + temp);
      delay(1);
      break;

    case 72: // Cursor home (doesn't clear the screen!)
      //lcd.home();
      lcd.setCursor(0,0);
      break;

    case 76: // Move cursor left  0b00010000 / dec16 /hex10
      lcd.command(16);//Cursor/Display Shift  hex(0x10); //set cursor position one character to the left
      break;

    case 77: // Move cursor right 0b00010100 / dec20 /hex14
      lcd.command(20);
      break;

    case 78: // Define custom character (2 parameters, id, data)
      lcd.command(64 + (serial_getch() * 8));
      for (temp = 8; temp != 0; temp--) {
        lcd.write(serial_getch()); //works with Adafruit_CharacterOLED library
      }
      break;
    }
    return; // Stop and start again.
  }

  // Otherwise its a plain char so we print it to the LCD.
  //lcd.write(rxbyte);
  lcd.print((char)rxbyte);  //otherwise a plain char so we print it to lcd
} // END of main loop

// ***********************************************************************************************************
// *           Get byte
// *             
// *           Waits for a byte to be available, reads and returns it.
// *
// ***********************************************************************************************************
byte serial_getch() { // Get byte from Serial
  while (Serial.available() == 0);
  return Serial.read();
}

NOTE: This is not a complete code its missing many commands.
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on March 21, 2015, 11:18:35 PM
Chris, I found similar language from a VFD display using HD44780 controller.

 // Allows us to fill the first 8 CGRAM locations
// with custom characters
void OLedI2C::createChar(uint8_t location, uint8_t charmap[]) {
  location &= 0x7; // we only have 8 locations 0-7
  sendCommand(VFD_SETCGRAMADDR | (location << 3));
  for (int i=0; i<8; i++) {
   write(charmap);
 }

My problem is that "write" isn't defined anywhere, and in the library it came from VFD_SPI.cpp it isn't defined, I just don't know where that would come from
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 22, 2015, 06:13:15 PM
Hmm ok
Can you try this.

Code: [Select]
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

byte newChar[8] = {
        B00000,
        B00000,
        B10101,
        B11101,
        B11101,
        B10101,
        B00000,
        B00000
};

void setup() {
    lcd.createChar(0, newChar);
    lcd.begin(20, 4);
    lcd.write(0);
}

void loop() {}
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 22, 2015, 06:52:13 PM
Two Custom Characters
Code: [Select]

#include <OLEDFourBit.h> //  NewHAVEN NHD-0420DZW-AY5-ND
//#include <LiquidCrystal.h>
OLEDFourBit lcd(7, 4, 10, 5, A3, A4, A5);
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

byte newChar1[8] = {
  B00000,
  B00000,
  B10101,
  B11101,
  B11101,
  B10101,
  B00000,
  B00000
};

byte newChar2[8] = {
  B10000,
  B01000,
  B00101,
  B00100,
  B00100,
  B00101,
  B01000,
  B10000
};

void setup() {
  lcd.createChar(0, newChar1);
  lcd.createChar(1, newChar2);
  lcd.begin(20, 4);
 

}
void loop() {
  lcd.setCursor(2,0);
  lcd.write(0); //PRINT
  lcd.setCursor(2,1);
  lcd.write(1); //PRINT

  delay(1000);
}
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 22, 2015, 07:03:52 PM
Liquid Crystal Display Custom Character Designer

http://mikeyancey.com/hamcalc/lcd_characters.php (http://mikeyancey.com/hamcalc/lcd_characters.php)
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 22, 2015, 08:52:57 PM
This is other way of printing a  char
lcd.print((char)1); //print char

Code: [Select]
#include <OLEDFourBit.h> // Works with NewHAVEN NHD-0420DZW-AY5-ND
//#include <LiquidCrystal.h>
OLEDFourBit lcd(7, 4, 10, 5, A3, A4, A5);
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

byte newChar0[8] = {
  B00000,
  B00000,
  B10101,
  B11101,
  B11101,
  B10101,
  B00000,
  B00000
};

byte newChar1[8] = {
  B10000,
  B01000,
  B00101,
  B00100,
  B00100,
  B00101,
  B01000,
  B10000
};

byte newChar15[8] = {
  B10001,
  B01010,
  B01110,
  B00100,
  B00100,
  B01110,
  B01010,
  B10001
};
void setup() {
  lcd.createChar(0, newChar0);
  lcd.createChar(1, newChar1);
  lcd.createChar(15, newChar15);
  lcd.begin(20, 4);


}
void loop() {
  lcd.setCursor(2,0); //line 1
  lcd.write(1); //PRINT
  lcd.setCursor(0,1); ////line 2

  lcd.write(0); //PRINT
  lcd.setCursor(0,2); //line 3
  lcd.print("lcd.print((char)15)");
  lcd.setCursor(10,3); //line 4
  lcd.print((char)15); //other way of printing a  char
  delay(1000);
}
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on March 23, 2015, 01:08:56 AM
Not sure if this makes a diff, but I'm using the OLedI2C library, needed to use no more then 3 lines to the diaplay. Though, what's in the cpp file for create craracter I did put in the OLedI2C.cpp file, but it errors on compile on the "write(charmap);" The library I used was for the one wire link. That part works fine, except the custom character part.Thanks for the poiinters, one of them has the lines I'm already trying to use, but I really need I2C communication.

GeorgeC

Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 25, 2015, 10:11:48 PM
Hi

I do not own this display so it's hard to do testing.
Please test this sketch for me, not sure if this will print H and then Clear the display.
Code: [Select]
// Test print [ H ] and then Clear display with Wire Library.

// Wire Library, This library allows you to communicate with I2C / TWI devices
// Board           I2C / TWI pins
// Uno, Ethernet   A4 (SDA), A5 (SCL)
// Mega2560        20 (SDA), 21 (SCL)
// Leonardo         2 (SDA),  3 (SCL)
// Due             20 (SDA), 21 (SCL), SDA1, SCL1
#include <Wire.h>
#define I2C_ADDR 0x3c  // Define I2C Address, For the US2066 0x3c or 0x3d
// NOTE: Important to include Wire.h before OLedI2C.h
#include <OLedI2C.h>  // OLedI2C library http://gadjetsblog.blogspot.com/2013/09/oled-1602-display-and-library-for.html
//library by Phil Grant 2013 www.gadjet.co.uk
OLedI2C LCD;


void setup() {
  Wire.begin(); // Start Wire Library
  LCD.init(); // initialize the lcd
}

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("Test print >", 4, 0);    //("String", col, row)
  delay(2000); //2sec

  // test 1 / print H
  // For the US2066, the slave address is either “b0111100”/0x3c or “b0111101”/0x3d
  Wire.beginTransmission(I2C_ADDR); // start condition + Define I2C Address where the US2066 is, and set  R/W# bit to logic “0” write mode.

  // 5) After the transmission of the slave address, either the control byte or the data byte may be sent across the SDA. A control
  // byte mainly consists of Co and D/C# bits following by six “0”’s.
  // a. If the Co bit is set as logic “0”, the transmission of the following information will contain data bytes only.
  // b. The D/C# bit determines the next data byte is acted as a command or a data. If the D/C# bit is set to logic “0”,
  // it defines the following data byte as a command. If the D/C# bit is set to logic “1”, it defines the following data
  // byte as a data which will be stored at the DDRAM. The DDRAM address counter will be increased by one
  // automatically after each data write.

  // Co bit is set as logic “0”data bytes only,  D/C# bit is set to logic “1”[data]
  ////////////cd+6“0”’s.  // Co & D/C# bits
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B01001000); // print H  [8bit (hi bit 0100/low bit 1000
  Wire.endTransmission(); // stop condition, 7) The write mode will be finished when a stop condition is applied.
  delay(5000); // 5sec. delay

  // test 2 / Clear display
  LCD.sendString("Clear dis.in 2sec.", 1, 1);
  delay(2000);
  //Clear display
  Wire.beginTransmission(I2C_ADDR); //Define I2C Address where the US2066 is
  // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B10000000); //  Co bit is set to logic “1”, D/C# bit is set to logic “0”, it defines the following data byte as a command.
  Wire.write(B00000001);  // Clear display
  Wire.endTransmission(); // stop condition.
  delay(5000); // 5sec. delay
}
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on March 29, 2015, 03:34:10 PM
Chris, thanks for the effort. I need to figure out the addressing for this, how to store custom font data in those 8 memory locations. I am not 100% sure how to but I think I can see how to get them out after they are stored. But the command structure seems limited, or I'm just not getting how to set either/or IS RE SD RW or DC. I thank you for the help. I'm just not getting how to "command" it to store the 8 8(really 5) bit font info, and exactly how to get it back when writing text to the display. I think I see that I can use Wire.write to accomplish it, but now sure what the addressing would be then unsure of addressing or commands to use the character. You definitely seeded some ideas, but I fear I'm just not getting it.

Thanks!

GeorgeC
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 29, 2015, 10:42:44 PM
Hay, don't worry
I was just trying to figure out how to use the i2c wire library,  it just a hobby of mine. ;)

Does the arduino sketch work?
Print H and then Clear the display?

Yes / no ?
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 29, 2015, 10:58:00 PM
By the way  I've just spent a day trying to figure out how to use 1Mbit MR25H10MDF Magnetoresistive random-access memory (MRAM) with SPI on Teensy 3.0 ARM dev board..
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on March 29, 2015, 11:15:31 PM
Chris, forgot to answer your question. Works fine. Just as written. The initial delay fooled me, compiled/loaded and it was dark then as I was typing something the display lit up. That 5 second delay got me.

See, my hangup on hacking on the OLedI2C.cpp file is the use of write, or rather Wire.write to send the binary patterns for the special fonts to the display. And of course, getting them back out. It would have been ideal (In my mind) if they'd just occupy the bottom 8 memory locations and be addressed like any other character.

Thanks, Chris.

GeorgeC
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 30, 2015, 09:44:24 PM
Chris, forgot to answer your question. Works fine. Just as written. The initial delay fooled me, compiled/loaded and it was dark then as I was typing something the display lit up. That 5 second delay got me.

See, my hangup on hacking on the OLedI2C.cpp file is the use of write, or rather Wire.write to send the binary patterns for the special fonts to the display. And of course, getting them back out. It would have been ideal (In my mind) if they'd just occupy the bottom 8 memory locations and be addressed like any other character.

Thanks, Chris.

GeorgeC

Getting custom fonts back out its easy, i think this will do it.
Code: [Select]
// Test print [ custom fonts ].

// Wire Library, This library allows you to communicate with I2C / TWI devices
// Board           I2C / TWI pins
// Uno, Ethernet   A4 (SDA), A5 (SCL)
// Mega2560        20 (SDA), 21 (SCL)
// Leonardo         2 (SDA),  3 (SCL)
// Due             20 (SDA), 21 (SCL), SDA1, SCL1

#include <Wire.h>
#define I2C_ADDR 0x3c  // Define I2C Address, For the US2066 0x3c or 0x3d
// NOTE: Important to include Wire.h before OLedI2C.h
#include <OLedI2C.h>  // OLedI2C library http://gadjetsblog.blogspot.com/2013/09/oled-1602-display-and-library-for.html
//library by Phil Grant 2013 www.gadjet.co.uk
OLedI2C LCD;

byte newChar0[8] = {
  B00000,
  B00000,
  B10101,
  B11101,
  B11101,
  B10101,
  B00000,
  B00000
};

byte newChar1[8] = {
  B10000,
  B01000,
  B00101,
  B00100,
  B00100,
  B00101,
  B01000,
  B10000
};

byte newChar2[8] = {
  B10001,
  B01010,
  B01110,
  B00100,
  B00100,
  B01110,
  B01010,
  B10001
};

void setup() {
  LCD.createChar(0, newChar0); // Store custom font data in 420CW Oled
  LCD.createChar(1, newChar1);
  LCD.createChar(2, newChar2);
 
  Wire.begin(); // Start Wire Library
  LCD.init(); // initialize the lcd
}

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("Print custom font", 1, 0);    //("String", col, row)
  LCD.cursPos(1,1); //(col,row)
 
  // Test 1 / Print custom font
  Wire.beginTransmission(I2C_ADDR); // start condition + Define I2C Address where the US2066 is, and set  R/W# bit to logic “0” write mode.

  // Print custom font 1
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B00000000); // print custom font 0  [8bit (hi bit 0000/low bit 0000
 
  //Print custom font 2
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B00000001); // print custom font 1  [8bit (hi bit 0000/low bit 0001

  //Print custom font 3
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B00000010); // print custom font 2  [8bit (hi bit 0000/low bit 0010
 
  //Print custom font 4
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B00000011); // print custom font 3  [8bit (hi bit 0000/low bit 0011

  //Print custom font 5
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B00000100); // print custom font 4  [8bit (hi bit 0000/low bit 0100

  //Print custom font 6
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B00000101); // print custom font 5  [8bit (hi bit 0000/low bit 0101

  //Print custom font 7
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B00000110); // print custom font 6  [8bit (hi bit 0000/low bit 0110

  //Print custom font 8   
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B00000111); // print custom font 7  [8bit (hi bit 0000/low bit 0111
 
  Wire.endTransmission(); // stop condition / 7) The write mode will be finished when a stop condition is applied.

  delay(5000); // 5sec. delay
  LCD.clearLcd();
}

Now can you add this to OLedI2C.h
void createChar(uint8_t, uint8_t[]); // NEW 03-23-2015 / Allows us to fill the first 8 CGRAM locations with custom characters

Code: [Select]
// 1602-OLED-Arduino-Library/OLedI2C.h

/*
OLedI2C.h
OLED 1602 Library for the I2C
OLED display from WIDE.HK
Also my first attempt at a Library
Phil Grant Sept 2013
www.gadjet.co.uk
Scrolling contributed by Nathan Chantrell http://nathan.chantrell.net/
Updated 06/11/2013 to include the cursPos data within the sendString function.
*/
#ifndef OLedI2C_h
#define OLedI2C_h
#include "Arduino.h"
#include "Wire.h"

class OLedI2C {
public:
OLedI2C();
~OLedI2C();
void init();
void sendCommand(unsigned char command);
void sendString(const char *String, uint8_t col, uint8_t row);
void sendFloat(float digit, uint8_t dec, uint8_t nad, uint8_t col, uint8_t row);
void sendData(unsigned char data);
void clearLcd();
void cursPos(uint8_t, uint8_t); // cloumn, row
                //void setCursor(uint8_t, uint8_t); // NEW 03-23-2015 / cloumn, row / setCursor
void scrollString(char* message, byte row, unsigned int time); //written by Nathan Chantrell http://nathan.chantrell.net/
void lcdOff();
void lcdOn();
void setContrast(unsigned char contrast); // contrast should be the hex value between 0x00 and 0xFF
void createChar(uint8_t, uint8_t[]); // NEW 03-23-2015 / Allows us to fill the first 8 CGRAM locations with custom characters
};
#endif

And add this to OLedI2C.cpp
NOTE: Not sure if this will work.

// NEW 03-23-2015
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void OLedI2C::createChar(uint8_t location, uint8_t charmap[])
{
  location &= 0x7; // we only have 8 locations 0-7
  Wire.beginTransmission(OLED_Address);
    Wire.write(OLED_Data_Mode | (location << 3)); // SETCGRAMADDR 0x40  [ Wire.write(B01000000); ]
    delayMicroseconds(30);
    //Wire.write(location);
  for (uint8_t i = 0 ; i < 8 ; i++) {
    Wire.write(charmap);
    //Wire.write(OLED_Data_Mode);
    delayMicroseconds(40);
  }
  Wire.endTransmission();
  delay(50);
}

Code: [Select]
// 1602-OLED-Arduino-Library/OLedI2C.cpp
// keywords.txt / OLedI2C.cpp / OLedI2C.h
// The 3 files should be in %your arduino dir%\libraries\OLedI2C\
// The directory name must match the library name for libraries to work.

/*
This is my first Library to make writing to the OLED 1602
Display much easier, the display is based on the SSD1311.
The display has 16 characters and 2 lines.
The library is far from complete and may be prone to errors.
Feedback welcome, visit www.gadjet.co.uk
Phil Grant 2013
Scrolling contributed by Nathan Chantrell http://nathan.chantrell.net/
Updated 06/11/2013 to include the cursPos data in the sendString function
sendString("string", col, row)
*/
#include "OLedI2C.h"

// NEW
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "Arduino.h"

#include "Wire.h"
#define OLED_Address 0x3c
#define OLED_Command_Mode 0x80
#define OLED_Data_Mode 0x40

OLedI2C::OLedI2C(){}
OLedI2C::~OLedI2C(){}


void OLedI2C::init() {
   // *** I2C initial *** //
 delay(100);
 sendCommand(0x2A); // **** Set "RE"=1 00101010B
 sendCommand(0x71);
 sendCommand(0x5C);
 sendCommand(0x28);

 sendCommand(0x08); // **** Set Sleep Mode On
 sendCommand(0x2A); // **** Set "RE"=1 00101010B
 sendCommand(0x79); // **** Set "SD"=1 01111001B

 sendCommand(0xD5);
 sendCommand(0x70);
 sendCommand(0x78); // **** Set "SD"=0  01111000B

 sendCommand(0x08); // **** Set 5-dot, 3 or 4 line(0x09), 1 or 2 line(0x08)

 sendCommand(0x06); // **** Set Com31-->Com0  Seg0-->Seg99

 // original:
 // **** Set OLED Characterization *** //
 // sendCommand(0x2A);  // **** Set "RE"=1
 // sendCommand(0x79);  // **** Set "SD"=1
 // **** CGROM/CGRAM Management *** //
 // sendCommand(0x72);  // **** Set ROM
 // sendCommand(0x00);  // **** Set ROM A and 8 CGRAM

 // **** CGROM/CGRAM Management *** //
 sendCommand(0x72);     // **** Set ROM
 sendData(B00000011);     // **** Set ROM A and 8 CGRAM This selects CGROM A, 00000000 selects CGROM C
 // **** Set OLED Characterization *** //
 sendCommand(0x2A);     // **** Set "RE"=1
 sendCommand(0x79);     // **** Set "SD"=1

 sendCommand(0xDA); // **** Set Seg Pins HW Config
 sendCommand(0x10);   

 sendCommand(0x81);  // **** Set Contrast
 sendCommand(0xFF);

 sendCommand(0xDB);  // **** Set VCOM deselect level
 sendCommand(0x30);  // **** VCC x 0.83

 sendCommand(0xDC);  // **** Set gpio - turn EN for 15V generator on.
 sendCommand(0x03);

 sendCommand(0x78);  // **** Exiting Set OLED Characterization
 sendCommand(0x28);
 sendCommand(0x2A);
 //sendCommand(0x05); // **** Set Entry Mode
 sendCommand(0x06); // **** Set Entry Mode
 sendCommand(0x08); 
 sendCommand(0x28); // **** Set "IS"=0 , "RE" =0 //28
 sendCommand(0x01);
 sendCommand(0x80); // **** Set DDRAM Address to 0x80 (line 1 start)

 delay(100);
 sendCommand(0x0C);  // **** Turn on Display
 }
 
 // void OLedI2C::cursPos(uint8_t col, uint8_t row)
 // {
 // int row_offsets[] = { 0x00, 0x40 };
 // sendCommand(0x80 | (col + row_offsets[row]));
 // }

 void OLedI2C::cursPos(uint8_t col, uint8_t row)
 {
 int row_offsets[] = { 0x00, 0x20, 0x40, 0x60 };// **************THIS WAS THE CHANGE FOR 4 LINES
 sendCommand(0x80 | (col + row_offsets[row])); //was 0x80
 }
 
 // NEW 03-23-2015
 // cloumn, row / setCursor
  //void OLedI2C::setCursor(uint8_t col, uint8_t row)
  //{
  // int row_offsets[] = { 0x00, 0x20, 0x40, 0x60 };// **************
  //sendCommand(0x80 | (col + row_offsets[row]));
  //}
 
void OLedI2C::clearLcd()
{
sendCommand(0x01);
}

void OLedI2C::lcdOff()
{
sendCommand(0x08);  // **** Turn on Off
}

void OLedI2C::lcdOn()
{
sendCommand(0x0C);  // **** Turn on On
}

 void OLedI2C::sendCommand(unsigned char command)
{
    Wire.beginTransmission(OLED_Address); // **** Start I2C
    Wire.write(OLED_Command_Mode);      // **** Set OLED Command mode
    Wire.write(command);
    Wire.endTransmission();                  // **** End I2C
      delay(10);
}
void OLedI2C::sendFloat(float digit, uint8_t dec, uint8_t nad, uint8_t col, uint8_t row)
{
char line[10];//Ten characters, I hope that's enough
dtostrf(digit,dec,nad,line);//Convert the float value to a string
sendString(line, col, row);

}

 void OLedI2C::setContrast(unsigned char contrast) // contrast as 0x00 to 0xFF
{
     //Set OLED Command set
sendCommand(0x2A);
sendCommand(0x79);

sendCommand(0x81);  // Set Contrast
sendCommand(contrast); // send contrast value
sendCommand(0x78);  // Exiting Set OLED Command set
   sendCommand(0x28);

}

void OLedI2C::sendString(const char *String, uint8_t col, uint8_t row)
{
  cursPos(col, row);
  unsigned char i=0;
  while(String[i])
  {
    sendData(String[i]);      // *** Show String to OLED
    i++;
  }
}
void OLedI2C::sendData(unsigned char data)
{
  Wire.beginTransmission(OLED_Address);  // **** Start I2C
  Wire.write(OLED_Data_Mode);      // **** Set OLED Data mode
  Wire.write(data);
  Wire.endTransmission();                     // **** End I2C
}
void OLedI2C::scrollString(char* message, byte row, unsigned int time)//written by Nathan Chantrell http://nathan.chantrell.net/
{
 char buffer[16];
 for (byte i=0;i<strlen(message)+16;i++) {
  byte pos = i+1;
  for (byte j=0;j<16;j++) {
   if ((pos<16)||(pos>strlen(message)+15)) { // pad and trail with blank spaces
     buffer[j]=' ';
   }
   else buffer[j]=message[pos-16];
   pos++;
  }
 //cursPos(0,row); removed by PG
 sendString(buffer, 0, row); //Edited by PG tho include the cursor pos within the sendString command
 delay(time);
 }
}

// NEW 03-23-2015
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void OLedI2C::createChar(uint8_t location, uint8_t charmap[])
{
  location &= 0x7; // we only have 8 locations 0-7
  Wire.beginTransmission(OLED_Address);
    Wire.write(OLED_Data_Mode | (location << 3)); // SETCGRAMADDR 0x40  [ Wire.write(B01000000); ]
    delayMicroseconds(30);
    //Wire.write(location);
  for (uint8_t i = 0 ; i < 8 ; i++) {
    Wire.write(charmap[i]);
    //Wire.write(OLED_Data_Mode);
    delayMicroseconds(40);
  }
  Wire.endTransmission();
  delay(50);
}


keywords.txt / OLedI2C.cpp / OLedI2C.h
The 3 files should be in %your arduino dir%\libraries\OLedI2C\
The directory name must match the library name for libraries to work.

keywords.txt

Code: [Select]
#######################################
# Syntax Coloring Map For OLedI2C
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################

OLedI2C KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################

init KEYWORD2
sendCommand KEYWORD2
sendString KEYWORD2
sendData KEYWORD2
clearLcd KEYWORD2
cursPos KEYWORD2
createChar KEYWORD2

#######################################
# Constants (LITERAL1)
#######################################
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on March 31, 2015, 01:12:46 PM
My OLedI2C.cpp attached, with your mod at the bottom. I used your version of the file and while it compiled ok, nothing displayed.
Couldn't wait. Just tried it. Got this error:

  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.
Arduino: 1.0.5 (Windows 7), Board: "Arduino Uno"
C:\Users\georgec\Documents\Arduino\libraries\OLEDArduinoLibrarymaster\OLedI2C.cpp: In member function 'void OLedI2C::createChar(uint8_t, uint8_t*)':
C:\Users\georgec\Documents\Arduino\libraries\OLEDArduinoLibrarymaster\OLedI2C.cpp:265: error: call of overloaded 'write(uint8_t*&)' is ambiguous
C:\Program Files (x86)\Arduino\libraries\Wire/Wire.h:64: note: candidates are: virtual size_t TwoWire::write(uint8_t) <near match>
C:\Program Files (x86)\Arduino\libraries\Wire/Wire.h:86: note:                 size_t TwoWire::write(long unsigned int) <near match>
C:\Program Files (x86)\Arduino\libraries\Wire/Wire.h:87: note:                 size_t TwoWire::write(long int) <near match>
C:\Program Files (x86)\Arduino\libraries\Wire/Wire.h:88: note:                 size_t TwoWire::write(unsigned int) <near match>
C:\Program Files (x86)\Arduino\libraries\Wire/Wire.h:89: note:                 size_t TwoWire::write(int) <near match>
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:49: note:                 size_t Print::write(const char*) <near match>



My OLedI2C.cpp file:

/*
This is my first Library to make writing to the OLED 1602
Display much easier, the display is based on the SSD1311.
The display has 16 characters and 2 lines.
The library is far from complete and may be prone to errors.
Feedback welcome, visit www.gadjet.co.uk
Phil Grant 2013
Scrolling contributed by Nathan Chantrell http://nathan.chantrell.net/

Updated 06/11/2013 to include the cursPos data in the sendString function
sendString("string", col, row)

*/
#include "OLedI2C.h"
#include "Wire.h"
#define OLED_Address 0x3c
#define OLED_Command_Mode 0x80
#define OLED_Data_Mode 0x40

OLedI2C::OLedI2C(){}
OLedI2C::~OLedI2C(){}


void OLedI2C::init() {
   // *** I2C initial *** //
 delay(100);
 sendCommand(0x2A);   // **** Set "RE"=1   00101010B
 sendCommand(0x71);
 sendCommand(0x5C);
 sendCommand(0x28);

 sendCommand(0x08);   // **** Set Sleep Mode On
 sendCommand(0x2A);   // **** Set "RE"=1   00101010B
 sendCommand(0x79);   // **** Set "SD"=1   01111001B

 sendCommand(0xD5);
 sendCommand(0x70);
 sendCommand(0x78);   // **** Set "SD"=0  01111000B

 sendCommand(0x09);   // **** Set 5-dot, 3 or 4 line(0x09), 1 or 2 line(0x08)

 sendCommand(0x06);   // **** Set Com31-->Com0  Seg0-->Seg99


 // **** CGROM/CGRAM Management *** //
 sendCommand(0x72);     // **** Set ROM
 sendData(B00000011);     // **** Set ROM A and 8 CGRAM

 
 // **** Set OLED Characterization *** //
 sendCommand(0x2A);     // **** Set "RE"=1
 sendCommand(0x79);     // **** Set "SD"=1

 sendCommand(0xDA);    // **** Set Seg Pins HW Config
 sendCommand(0x10);   

 sendCommand(0x81);     // **** Set Contrast
 sendCommand(0xFF);

 sendCommand(0xDB);     // **** Set VCOM deselect level
 sendCommand(0x30);     // **** VCC x 0.83

 sendCommand(0xDC);     // **** Set gpio - turn EN for 15V generator on.
 sendCommand(0x03);

 sendCommand(0x78);     // **** Exiting Set OLED Characterization
 sendCommand(0x28);
 sendCommand(0x2A);
 //sendCommand(0x05);    // **** Set Entry Mode
 sendCommand(0x06);    // **** Set Entry Mode
 sendCommand(0x09); 
 sendCommand(0x28);    // **** Set "IS"=0 , "RE" =0 //28
 sendCommand(0x01);
 sendCommand(0x80);    // **** Set DDRAM Address to 0x80 (line 1 start)





 delay(100);
 sendCommand(0x0C);     // **** Turn on Display
 }
 

 
 
 void OLedI2C::cursPos(uint8_t col, uint8_t row)
 {
 int row_offsets[] = { 0x00, 0x20, 0x40, 0x60 };//**************THIS WAS THE CHANGE FOR 4 LINES
 sendCommand(0x80 | (col + row_offsets[row])); //was 0x80
 }
 
void OLedI2C::clearLcd()
{
sendCommand(0x01);
}

void OLedI2C::lcdOff()
{
sendCommand(0x08);     // **** Turn on Off
}


 // Allows us to fill the first 8 CGRAM locations
// with custom characters




void OLedI2C::lcdOn()
{
sendCommand(0x0C);     // **** Turn on On
}

 void OLedI2C::sendCommand(unsigned char command)
{
    Wire.beginTransmission(OLED_Address);     // **** Start I2C
    Wire.write(OLED_Command_Mode);            // **** Set OLED Command mode
    Wire.write(command);
    Wire.endTransmission();                     // **** End I2C
      delay(10);
}
void OLedI2C::sendFloat(float digit, uint8_t dec, uint8_t nad, uint8_t col, uint8_t row)
{
char line[10];//Ten characters, I hope that's enough
dtostrf(digit,dec,nad,line);//Convert the float value to a string
sendString(line, col, row);

}

 void OLedI2C::setContrast(unsigned char contrast) // contrast as 0x00 to 0xFF
{
     //Set OLED Command set
   sendCommand(0x2A);
   sendCommand(0x79);
   
   sendCommand(0x81);     // Set Contrast
   sendCommand(contrast);   // send contrast value
   sendCommand(0x78);     // Exiting Set OLED Command set
   sendCommand(0x28);
   
}

void OLedI2C::sendString(const char *String, uint8_t col, uint8_t row)
{
  cursPos(col, row);
  unsigned char i=0;
  while(String)
  {
    sendData(String);      // *** Show String to OLED
    i++;
  }
}
void OLedI2C::sendData(unsigned char data)
{
  Wire.beginTransmission(OLED_Address);     // **** Start I2C
  Wire.write(OLED_Data_Mode);           // **** Set OLED Data mode
  Wire.write(data);
  Wire.endTransmission();                     // **** End I2C
}
void OLedI2C::scrollString(char* message, byte row, unsigned int time)//written by Nathan Chantrell http://nathan.chantrell.net/
{
 char buffer[16];
 for (byte i=0;i<strlen(message)+16;i++) {
  byte pos = i+1;
  for (byte j=0;j<16;j++) {
   if ((pos<16)||(pos>strlen(message)+15)) { // pad and trail with blank spaces
     buffer[j]=' ';
   }
   else buffer[j]=message[pos-16];
   pos++;
  }
 //cursPos(0,row); removed by PG
 sendString(buffer, 0, row); //Edited by PG tho include the cursor pos within the sendString command
 delay(time);
 }
}
// NEW 03-23-2015
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void OLedI2C::createChar(uint8_t location, uint8_t charmap[])
{
  location &= 0x7; // we only have 8 locations 0-7
  Wire.beginTransmission(OLED_Address);
    Wire.write(OLED_Data_Mode | (location << 3)); // SETCGRAMADDR 0x40  [ Wire.write(B01000000); ]
    delayMicroseconds(30);
    //Wire.write(location);
  for (uint8_t i = 0 ; i < 8 ; i++) {
    Wire.write(charmap);
    //Wire.write(OLED_Data_Mode);
    delayMicroseconds(40);
  }
  Wire.endTransmission();
  delay(50);
}
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 31, 2015, 04:29:15 PM
Add this to OLedI2C.ccp

/*
This is my first Library to make writing to the OLED 1602
Display much easier, the display is based on the SSD1311.
The display has 16 characters and 2 lines.
The library is far from complete and may be prone to errors.
Feedback welcome, visit www.gadjet.co.uk
Phil Grant 2013
Scrolling contributed by Nathan Chantrell http://nathan.chantrell.net/
Updated 06/11/2013 to include the cursPos data in the sendString function
sendString("string", col, row)
*/
#include "OLedI2C.h"

// NEW
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

#if (ARDUINO <  100)
#include <WProgram.h>
#else
#include <Arduino.h>
#endif

#include "Wire.h"
#define OLED_Address 0x3c
#define OLED_Command_Mode 0x80
#define OLED_Data_Mode 0x40
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 31, 2015, 06:28:05 PM
OK here's a new idea

Replace this:
// NEW 03-23-2015
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void OLedI2C::createChar(uint8_t location, uint8_t charmap[])
{
  location &= 0x7; // we only have 8 locations 0-7
  Wire.beginTransmission(OLED_Address);
    Wire.write(OLED_Data_Mode | (location << 3)); // SETCGRAMADDR 0x40  [ Wire.write(B01000000); ]
    delayMicroseconds(30);
    //Wire.write(location);
  for (uint8_t i = 0 ; i < 8 ; i++) {
    Wire.write(charmap);
    //Wire.write(OLED_Data_Mode);
    delayMicroseconds(40);
  }
  Wire.endTransmission();
  delay(50);
}


With that in OLedI2C.ccp

// NEW 03-31-2015
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void OLedI2C::createChar(uint8_t location, uint8_t charmap[])
{
   location &= 0x7;            // we only have 8 locations 0-7
   
   sendCommand(0x40 | (location << 3));
   delayMicroseconds(30);
   
   for (int i=0; i<8; i++)
   {
      sendData(charmap);      // call the virtual write method
      delayMicroseconds(40);
   }
}

EDIT: it should be like this
Code: [Select]
// NEW 03-31-2015
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void OLedI2C::createChar(uint8_t location, uint8_t charmap[])
{
   location &= 0x7;            // we only have 8 locations 0-7
   
   sendCommand(0x40 | (location << 3));
   delayMicroseconds(30);
   
   for (int i=0; i<8; i++)
   {
      sendData(charmap[i]);      // you're missing [i] in you're code // call the virtual write method
      delayMicroseconds(40);
   }
}

The above change still needs
void createChar(uint8_t, uint8_t[]); // NEW 03-23-2015 / Allows us to fill the first 8 CGRAM locations with custom characters
in OLedI2C.h
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on March 31, 2015, 10:51:45 PM
Thanks Chris. The first suggestions made earlier prompted me to just start fresh in a library directory. So made all those changes and now while it compiles nothing happens, and anything on display from previous helloworld stuff freezez till power cycle.

Now the most recent suggestions gets this error:


C:\Program Files (x86)\Arduino\libraries\OLedI2C\OLedI2C.cpp: In member function 'void OLedI2C::createChar(uint8_t, uint8_t*)':
C:\Program Files (x86)\Arduino\libraries\OLedI2C\OLedI2C.cpp:206: error: invalid conversion from 'uint8_t*' to 'unsigned char'
C:\Program Files (x86)\Arduino\libraries\OLedI2C\OLedI2C.cpp:206: error:   initializing argument 1 of 'void OLedI2C::sendData(unsigned char)'


Line 206 is:
     sendData(charmap);      // call the virtual write method






Totally lost now. I sorta followed what you were doing...

GeorgeC
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on March 31, 2015, 11:14:58 PM
I think I used the wrong OLedI2C.h file. I need to clean this mess up.

So back to where it just sits there blank after loading your test file.

GeorgeC
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 31, 2015, 11:49:01 PM
hmmm i see a bug.


Code: [Select]
// NEW 03-31-2015
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void OLedI2C::createChar(uint8_t location, uint8_t charmap[])
{
   location &= 0x7;            // we only have 8 locations 0-7
   
   sendCommand(0x40 | (location << 3));
   delayMicroseconds(30);
   
   for (int i=0; i<8; i++)
   {
      sendData(charmap[i]);      // you're missing [i] in you're code // call the virtual write method
      delayMicroseconds(40);
   }
}
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on March 31, 2015, 11:52:44 PM
if you don't use the insert code tag on this forums it will eat this:
Code: [Select]
[i]
from
Code: [Select]
      sendData(charmap[i]);      // call the virtual write method
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on April 01, 2015, 12:15:44 AM
Something tells me that while the writing of the character might be working something is missing in getting it to display.

  // Print custom font 1
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B00000000); // print custom font 0  [8bit (hi bit 0000/low bit 0000
 

Here's where the US2066 data is slim in detail, certainly for the newcomer.

The first line above only sets the CGRAM address to 0x00
The next line, depending on DC or RW can mean to write to B00000000

But shouldn't there be a 0x72 sent before B00000000?

Just not enough in that data...

GeorgeC
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on April 01, 2015, 12:36:14 AM
Not sure if this will work but try it anyway.
  LCD.sendData(0); //Print custom font 1

  LCD.sendData(char(1)); //Print custom font 2


Code: [Select]
// Test print [ custom fonts ].

// Wire Library, This library allows you to communicate with I2C / TWI devices
// Board           I2C / TWI pins
// Uno, Ethernet   A4 (SDA), A5 (SCL)
// Mega2560        20 (SDA), 21 (SCL)
// Leonardo         2 (SDA),  3 (SCL)
// Due             20 (SDA), 21 (SCL), SDA1, SCL1

#include <Wire.h>
#define I2C_ADDR 0x3c  // Define I2C Address, For the US2066 0x3c or 0x3d
// NOTE: Important to include Wire.h before OLedI2C.h
#include <OLedI2C.h>  // OLedI2C library http://gadjetsblog.blogspot.com/2013/09/oled-1602-display-and-library-for.html
//library by Phil Grant 2013 www.gadjet.co.uk
OLedI2C LCD;

byte newChar0[8] = {
  B00000,
  B00000,
  B10101,
  B11101,
  B11101,
  B10101,
  B00000,
  B00000
};

byte newChar1[8] = {
  B10000,
  B01000,
  B00101,
  B00100,
  B00100,
  B00101,
  B01000,
  B10000
};

byte newChar2[8] = {
  B10001,
  B01010,
  B01110,
  B00100,
  B00100,
  B01110,
  B01010,
  B10001
};

void setup() {
  Wire.begin(); // Start Wire Library
  LCD.init(); // initialize the lcd
  LCD.createChar(0, newChar0); // Store custom font data in 420CW Oled
  LCD.createChar(1, newChar1);
  LCD.createChar(2, newChar2);
 

}

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("test 1 Wire.h", 0, 0);    //("String", col, row)
  LCD.cursPos(1,1); //(col,row)
 
  // Test 1 / Print custom font 1
  Wire.beginTransmission(I2C_ADDR); // start condition + Define I2C Address where the US2066 is, and set  R/W# bit to logic “0” write mode.
  // Print custom font 1
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B00000000); // print custom font 0  [8bit (hi bit 0000/low bit 0000
  Wire.endTransmission(); // stop condition / 7) The write mode will be finished when a stop condition is applied.

  delay(3000); // 3sec. delay
  LCD.clearLcd();
  delay(1000);
 
  LCD.sendString("test 2 sendData", 0, 0);    //("String", col, row)
  LCD.cursPos(1,1); //(col,row)
  // Zero-based numbering
  LCD.sendData(0); //Print custom font 1
  LCD.sendData(char(1)); //Print custom font 2
 
  delay(3000); // 3sec. delay
  LCD.clearLcd();
  delay(1000);
}
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on April 01, 2015, 08:08:20 AM
Well, that was very different. Attached are pix of the two messages.

What it is displaying is 0000:0000 and 0000:0001 from ROM C in the built in CG

GeorgeC
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on April 01, 2015, 05:09:08 PM
OK
Pictures are upside down but that's not a problem.

So the print  Wire.write(Bxxxxxxxx); or  LCD.sendData(x); works good.

Next custom font will be The infinity symbol ∞.
// Zero-based numbering
LCD.sendData(2); //Print custom font 3



Look in US2066 datasheet P.56
(http://i1068.photobucket.com/albums/u449/diesel-pl/12.3%20ROM%20c.jpg)

Now the problem is it did not store the custom fonts for some reasons.
perhaps you should try to switch the ROM C to ROM A and then try again.

Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on April 01, 2015, 05:29:24 PM
I found this:
http://www.circuitvalley.com/2012/02/lcd-custom-character-hd44780-16x2.html

I know the way this is done is pretty much identical as in the HD44780 controller, among others.

I have to study this more later. It looks like the part to store the character is pretty much the same. The getting it back out part is the issue...

I have to run, back at it in about 5 hours

George
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on April 01, 2015, 05:47:13 PM
Problem is ROM C
It's actually in the datasheets
P.29 Function Selection B
zero CGRAM available.
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on April 01, 2015, 06:29:34 PM
What does CGRAM stand for?
Acronym     Definition
CGRAM     Character Generator RAM -Random-access memory

In OLedI2C.cpp
Yours is actually setting  // **** Set ROM A and 0 CGRAM / 256 CGROM
But clearly it was on ROM C ?

Change this:
Code: [Select]
// **** CGROM/CGRAM Management *** //
 sendCommand(0x72);     // **** Set ROM
 sendData(B00000011);     // **** Set ROM A and 8 CGRAM This selects CGROM A, 00000000 selects CGROM C


To:
Code: [Select]
  // CGROM/CGRAM Management
  sendCommand(0x72);     // **** Set ROM // Function Selection B
  sendData(B00000001);   // **** Set ROM A and 8 CGRAM / 248 CGROM
Restart your Arduino IDE and try agine.
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on April 01, 2015, 07:01:03 PM
LCD.sendData(0)

Sends that character from ROM C

LCD.sendData(1)

Likewise sends that from ROM C, if I make it

LCD.sendData(8)

It sends the lefty pointing arrow, etc

George
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on April 01, 2015, 08:31:26 PM
I am not sure if it matters, but you change the i2c initialization sequence.
Code: [Select]
// original:
 // **** Set OLED Characterization *** //
 // sendCommand(0x2A);  // **** Set "RE"=1
 // sendCommand(0x79);  // **** Set "SD"=1
 // **** CGROM/CGRAM Management *** //
 // sendCommand(0x72);  // **** Set ROM
 // sendCommand(0x00);  // **** Set ROM A and 8 CGRAM

 // **** CGROM/CGRAM Management *** //
 sendCommand(0x72);     // **** Set ROM
 sendData(B00000011);     // **** Set ROM A and 8 CGRAM This selects CGROM A, 00000000 selects CGROM C
 // **** Set OLED Characterization *** //
 sendCommand(0x2A);     // **** Set "RE"=1
 sendCommand(0x79);     // **** Set "SD"=1
Perhaps setting the **** Set OLED Characterization *** should be first
Then set the **** CGROM/CGRAM Management ***
Just as it was in the original code.
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on April 01, 2015, 09:33:06 PM
New test  ;) code
Let's try change Function Selection B on the fly, in void setup(); .

Code: [Select]
// Test print [ custom fonts ].

// Wire Library, This library allows you to communicate with I2C / TWI devices
// Board           I2C / TWI pins
// Uno, Ethernet   A4 (SDA), A5 (SCL)
// Mega2560        20 (SDA), 21 (SCL)
// Leonardo         2 (SDA),  3 (SCL)
// Due             20 (SDA), 21 (SCL), SDA1, SCL1

#include <Wire.h>
#define I2C_ADDR 0x3c  // Define I2C Address, For the US2066 0x3c or 0x3d
// NOTE: Important to include Wire.h before OLedI2C.h
#include <OLedI2C.h>  // OLedI2C library http://gadjetsblog.blogspot.com/2013/09/oled-1602-display-and-library-for.html
//library by Phil Grant 2013 www.gadjet.co.uk
OLedI2C LCD;

byte newChar0[8] = {
  B00000,
  B00000,
  B10101,
  B11101,
  B11101,
  B10101,
  B00000,
  B00000
};

byte newChar1[8] = {
  B10000,
  B01000,
  B00101,
  B00100,
  B00100,
  B00101,
  B01000,
  B10000
};

byte newChar2[8] = {
  B10001,
  B01010,
  B01110,
  B00100,
  B00100,
  B01110,
  B01010,
  B10001
};

byte newChar3[8] = {
  B11111,
  B11111,
  B11111,
  B00100,
  B00100,
  B11111,
  B11111,
  B11111
};

void setup() {
  Wire.begin(); // Start Wire Library
  LCD.init(); // initialize the lcd
 
 
  delay(100);
  // TEST
  // change Function Selection B on the fly
  // CGROM/CGRAM Management
  LCD.sendCommand(0x72);     // **** Set ROM // Function Selection B
  LCD.sendData(B00000001);   // **** Set ROM A and 8 CGRAM / 248 CGROM

  delay(100);
  LCD.createChar(0, newChar0); // Store custom font data in 420CW Oled
  delay(100);
  LCD.createChar(1, newChar1);
  delay(100);
  LCD.createChar(2, newChar2);
  delay(100);
  LCD.createChar(3,newChar3);
  delay(100);
}

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("test 1 Wire.h", 0, 0);    //("String", col, row)
  LCD.cursPos(1,1); //(col,row)
 
  // Test 1 / Print custom font 4
  Wire.beginTransmission(I2C_ADDR); // start condition + Define I2C Address where the US2066 is, and set  R/W# bit to logic “0” write mode.
  // Print custom font 4
  Wire.write(B01000000); // control byte or the data byte, Co and D/C# bits following by six “0”’s.
  Wire.write(B00000011); //DEC 3 // print custom font 4  [8bit (hi bit 0000/low bit 0011
  Wire.endTransmission(); // stop condition / 7) The write mode will be finished when a stop condition is applied.

  delay(3000); // 3sec. delay
  LCD.clearLcd();
  delay(1000);
 
  LCD.sendString("test 2 sendData", 0, 0);    //("String", col, row)
  LCD.cursPos(1,1); //(col,row)
  // Zero-based numbering
  LCD.sendData(0); //Print custom font 1
  LCD.sendData(char(1)); //Print custom font 2
 
  delay(3000); // 3sec. delay
  LCD.clearLcd();
  delay(1000);
}
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: wb2dyb on April 01, 2015, 11:56:26 PM
Success! I was getting no results yet. So I cut and paste the init from the OLED pdf instead of what I had. Your last app ran first time, pictures enclosed...

My cpp file: (it's a real mess, but it works

Code: [Select]
// 1602-OLED-Arduino-Library/OLedI2C.cpp
// keywords.txt / OLedI2C.cpp / OLedI2C.h
// The 3 files should be in %your arduino dir%\libraries\OLedI2C\
// The directory name must match the library name for libraries to work.

/*
This is my first Library to make writing to the OLED 1602
Display much easier, the display is based on the SSD1311.
The display has 16 characters and 2 lines.
The library is far from complete and may be prone to errors.
Feedback welcome, visit www.gadjet.co.uk
Phil Grant 2013
Scrolling contributed by Nathan Chantrell http://nathan.chantrell.net/
Updated 06/11/2013 to include the cursPos data in the sendString function
sendString("string", col, row)
*/
#include "OLedI2C.h"

// NEW
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "Arduino.h"

#include "Wire.h"
#define OLED_Address 0x3c
#define OLED_Command_Mode 0x80
#define OLED_Data_Mode 0x40

OLedI2C::OLedI2C(){}
OLedI2C::~OLedI2C(){}


void OLedI2C::init() {
   // *** I2C initial *** //
 delay(100);
 sendCommand(0x2A); //function set (extended command set)
sendCommand(0x71); //function selection A
sendData(0x00); // disable internal VDD regulator (2.8V I/O). data(0x5C) = enable regulator (5V I/O)
sendCommand(0x28); //function set (fundamental sendCommand set)
sendCommand(0x08); //display off, cursor off, blink off
sendCommand(0x2A); //function set (extended command set)
sendCommand(0x79); //OLED command set enabled
sendCommand(0xD5); //set display clock divide ratio/oscillator frequency
sendCommand(0x70); //set display clock divide ratio/oscillator frequency
sendCommand(0x78); //OLED command set disabled
sendCommand(0x09); //extended function set 4 line
sendCommand(0x06); //COM SEG direction
sendCommand(0x72); //function selection B
sendData(0x00); //ROM CGRAM selection
sendCommand(0x2A); //function set (extended command set)
sendCommand(0x79); //OLED command set enabled
sendCommand(0xDA); //set SEG pins hardware configuration
sendCommand(0x10); //set SEG pins hardware configuration
sendCommand(0xDC); //function selection C
sendCommand(0x00); //function selection C
sendCommand(0x81); //set contrast control
sendCommand(0x7F); //set contrast control
sendCommand(0xD9); //set phase length
sendCommand(0xF1); //set phase length
sendCommand(0xDB); //set VCOMH deselect level
sendCommand(0x40); //set VCOMH deselect level
sendCommand(0x78); //OLED command set disabled
sendCommand(0x28); //function set (fundamental command set)
sendCommand(0x01); //clear display
sendCommand(0x80); //set DDRAM address to 0x00
sendCommand(0x0C); //display ON
 
 /*
sendCommand(0x2A);  //function set (extended command set)
sendCommand(0x71);  //function selection A, disable internal Vdd regualtor
sendCommand(0x00);
sendCommand(0x28);  //function set (fundamental command set)
sendCommand(0x08);  //display off, cursor off, blink off
sendCommand(0x2A);  //function set (extended command set)
sendCommand(0x79);  //OLED command set enabled
sendCommand(0x72);  //function selection B, disable internal Vdd regualtor
sendCommand(0x00);     //ROM CGRAM selection
sendCommand(0xD5);  //set display clock divide ratio/oscillator frequency
sendCommand(0x70);  //set display clock divide ratio/oscillator frequency
sendCommand(0x78);  //OLED command set disabled
sendCommand(0x09);  //extended function set (4-lines)
        sendCommand(0x06);  //COM SEG direction
sendCommand(0x72);  //function selection B, disable internal Vdd regualtor
sendCommand(0x00);     //ROM CGRAM selection
sendCommand(0x2A);  //function set (extended sendCommand set)
sendCommand(0x79);  //OLED sendCommand set enabled
sendCommand(0xDA);  //set SEG pins hardware configuration
sendCommand(0x10);  //set SEG pins hardware configuration   // <--------- Change
sendCommand(0xDC);  //function selection C
sendCommand(0x00);  //function selection C
sendCommand(0x81);  //set contrast control
sendCommand(0xff);  //set contrast control
sendCommand(0xD9);  //set phase length
sendCommand(0xF1);  //set phase length
sendCommand(0xDB);  //set VCOMH deselect level
sendCommand(0x40);  //set VCOMH deselect level
sendCommand(0x78);  //OLED sendCommand set disabled
sendCommand(0x28);  //function set (fundamental sendCommand set)
sendCommand(0x01);  //clear display
sendCommand(0x80);  //set DDRAM address to 0x00
sendCommand(0x0C);  //display ON
 */
 /*
 sendCommand(0x2A); // **** Set "RE"=1 00101010B
 sendCommand(0x71);
 sendCommand(0x5C);
 sendCommand(0x28);

 sendCommand(0x08); // **** Set Sleep Mode On
 sendCommand(0x2A); // **** Set "RE"=1 00101010B
 sendCommand(0x79); // **** Set "SD"=1 01111001B

 sendCommand(0xD5);
 sendCommand(0x70);
 sendCommand(0x78); // **** Set "SD"=0  01111000B

 sendCommand(0x09); // **** Set 5-dot, 3 or 4 line(0x09), 1 or 2 line(0x08)

 sendCommand(0x06); // **** Set Com31-->Com0  Seg0-->Seg99

 // original:
 // **** Set OLED Characterization *** //
 // sendCommand(0x2A);  // **** Set "RE"=1
 // sendCommand(0x79);  // **** Set "SD"=1
 // **** CGROM/CGRAM Management *** //
 // sendCommand(0x72);  // **** Set ROM
 // sendCommand(0x00);  // **** Set ROM A and 8 CGRAM

 // **** CGROM/CGRAM Management *** //
 sendCommand(0x72);     // **** Set ROM
 sendData(B00000011);     // **** Set ROM A and 8 CGRAM This selects CGROM A, 00000000 selects CGROM C
 // **** Set OLED Characterization *** //
 sendCommand(0x2A);     // **** Set "RE"=1
 sendCommand(0x79);     // **** Set "SD"=1

 sendCommand(0xDA); // **** Set Seg Pins HW Config
 sendCommand(0x10);   

 sendCommand(0x81);  // **** Set Contrast
 sendCommand(0xFF);

 sendCommand(0xDB);  // **** Set VCOM deselect level
 sendCommand(0x30);  // **** VCC x 0.83

 sendCommand(0xDC);  // **** Set gpio - turn EN for 15V generator on.
 sendCommand(0x03);

 sendCommand(0x78);  // **** Exiting Set OLED Characterization
 sendCommand(0x28);
 sendCommand(0x2A);
 sendCommand(0x05); // **** Set Entry Mode
 sendCommand(0x06); // **** Set Entry Mode
 sendCommand(0x08); 
 sendCommand(0x28); // **** Set "IS"=0 , "RE" =0 //28
 sendCommand(0x01);
 sendCommand(0x80); // **** Set DDRAM Address to 0x80 (line 1 start)

 */
 
 
 delay(100);
 sendCommand(0x0C);  // **** Turn on Display
 }
 
 // void OLedI2C::cursPos(uint8_t col, uint8_t row)
 // {
 // int row_offsets[] = { 0x00, 0x40 };
 // sendCommand(0x80 | (col + row_offsets[row]));
 // }

 void OLedI2C::cursPos(uint8_t col, uint8_t row)
 {
 int row_offsets[] = { 0x00, 0x20, 0x40, 0x60 };// **************THIS WAS THE CHANGE FOR 4 LINES
 sendCommand(0x80 | (col + row_offsets[row])); //was 0x80
 }
 
 // NEW 03-23-2015
 // cloumn, row / setCursor
  //void OLedI2C::setCursor(uint8_t col, uint8_t row)
  //{
  // int row_offsets[] = { 0x00, 0x20, 0x40, 0x60 };// **************
  //sendCommand(0x80 | (col + row_offsets[row]));
  //}
 
void OLedI2C::clearLcd()
{
sendCommand(0x01);
}

void OLedI2C::lcdOff()
{
sendCommand(0x08);  // **** Turn on Off
}

void OLedI2C::lcdOn()
{
sendCommand(0x0C);  // **** Turn on On
}

 void OLedI2C::sendCommand(unsigned char command)
{
    Wire.beginTransmission(OLED_Address); // **** Start I2C
    Wire.write(OLED_Command_Mode);      // **** Set OLED Command mode
    Wire.write(command);
    Wire.endTransmission();                  // **** End I2C
      delay(10);
}
void OLedI2C::sendFloat(float digit, uint8_t dec, uint8_t nad, uint8_t col, uint8_t row)
{
char line[10];//Ten characters, I hope that's enough
dtostrf(digit,dec,nad,line);//Convert the float value to a string
sendString(line, col, row);

}

 void OLedI2C::setContrast(unsigned char contrast) // contrast as 0x00 to 0xFF
{
     //Set OLED Command set
sendCommand(0x2A);
sendCommand(0x79);

sendCommand(0x81);  // Set Contrast
sendCommand(contrast); // send contrast value
sendCommand(0x78);  // Exiting Set OLED Command set
   sendCommand(0x28);

}

void OLedI2C::sendString(const char *String, uint8_t col, uint8_t row)
{
  cursPos(col, row);
  unsigned char i=0;
  while(String[i])
  {
    sendData(String[i]);      // *** Show String to OLED
    i++;
  }
}
void OLedI2C::sendData(unsigned char data)
{
  Wire.beginTransmission(OLED_Address);  // **** Start I2C
  Wire.write(OLED_Data_Mode);      // **** Set OLED Data mode
  Wire.write(data);
  Wire.endTransmission();                     // **** End I2C
}
void OLedI2C::scrollString(char* message, byte row, unsigned int time)//written by Nathan Chantrell http://nathan.chantrell.net/
{
 char buffer[16];
 for (byte i=0;i<strlen(message)+16;i++) {
  byte pos = i+1;
  for (byte j=0;j<16;j++) {
   if ((pos<16)||(pos>strlen(message)+15)) { // pad and trail with blank spaces
     buffer[j]=' ';
   }
   else buffer[j]=message[pos-16];
   pos++;
  }
 //cursPos(0,row); removed by PG
 sendString(buffer, 0, row); //Edited by PG tho include the cursor pos within the sendString command
 delay(time);
 }
}

/*

// NEW 03-23-2015
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void OLedI2C::createChar(uint8_t location, uint8_t charmap[])
{
  location &= 0x7; // we only have 8 locations 0-7
  Wire.beginTransmission(OLED_Address);
    Wire.write(OLED_Data_Mode | (location << 3)); // SETCGRAMADDR 0x40  [ Wire.write(B01000000); ]
    delayMicroseconds(30);
    //Wire.write(location);
  for (uint8_t i = 0 ; i < 8 ; i++) {
    Wire.write(charmap[i]);
    //Wire.write(OLED_Data_Mode);
    delayMicroseconds(40);
  }
  Wire.endTransmission();
  delay(50);
}
*/

// NEW 03-31-2015
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void OLedI2C::createChar(uint8_t location, uint8_t charmap[])
{
   location &= 0x7;            // we only have 8 locations 0-7
   
   sendCommand(0x40 | (location << 3));
   delayMicroseconds(30);
   
   for (int i=0; i<8; i++)
   {
      sendData(charmap[i]);      // you're missing [i] in you're code // call the virtual write method
      delayMicroseconds(40);
   }
}


Thank you very much.

GeorgeC
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on April 02, 2015, 12:00:38 AM
 :o :)
Title: Re: Library that works fine on the NHD-0420CW-A*3
Post by: Chris O. on April 02, 2015, 12:09:51 AM
I'm glad you figured that out. ;)