NHD-0216AW-IB3 - User Defined Characters - HOW?
Can anyone provide an Arduino code snippet to show me how to create and use some user defined characters?
Page 23 of the US2066 data sheet suggests that this should be possible. The data sheet for the NHD-0216AW-IB3 is blank on the subject.
Additionally, I can not see any clues in the Arduino library code referenced in the NHD-0216AW-IB3 data sheet.
Regards, Martin
-
Hi Martin,
Please have a look at page 28 of the datasheet.
User defined characters can be loaded via 512 bits (8 characters) Character Generator RAM (CGRAM).
Spec: https://newhavendisplay.com/content/app_notes/US2066.pdf
You will need to call the Set CGRAM adress command, also please see the command description listed on page 39.
Below please find some reference example code.//------------------------------------------------------------------------------------------------
// HS_US2066 OLED Library
// Copyright (c) 2014, 2015, 2016, 2017 by Haute Solutions / Ed Van Every (www.haute-solutions.com)
//
// FUNCTION: This Library is intended to control the Newhaven Display Slim OLEDs based on US2066 controller
//
// - Supports I2C Interface Mode Only
// - Autodetects/configures for both Arduino and Mega I2C Pinouts
// - Supports flexible address, row and column geometry via class construction intitialization
// - Modified from original example code created by Newhaven Display International Inc
//
// LICENSE: This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// <http://www.gnu.org/licenses/>.
//
//------------------------------------------------------------------------------------------------
#define HS_US2066_LIBVER "1.0"
#include <Arduino.h>
#include <Wire.h>
#include "HS_US2066.h"
OLED::OLED(char address=0x3C, int rows=2, int cols=16) {
_Address = address;
_Rows = rows;
_Cols = cols;
}
void OLED::Display( int Center, char *Line1, char *Line2, char *Line3, char *Line4) {
// Center: 0 = No (Left Justify and pad as necessary)
// 1 = Yes (and pad left/right as necessary)
//
// Line1-4: "String" = Will display string (truncated/padded/centered as necessary)
// "" = Will effectively clear the line
// {NULL} = Will ignore the line and leave existing info intact
//
if(Line1) DisplayLine(1, Line1, Center);
if(Line2) DisplayLine(2, Line2, Center);
if(Line3) DisplayLine(3, Line3, Center);
if(Line4) DisplayLine(4, Line4, Center);
}
void OLED::DisplayLine(int Line, char *Text, int Center) {
// Line: = Line Number to Display (1-4 as supported)
//
// Text: "String" = Will display string (truncated/padded/centered as necessary)
// "" = Will effectively clear the line
// {NULL} = Will ignore the line and leave existing info intact
//
// Center: 0 = No (Left Justify and pad as necessary)
// 1 = Yes (and pad left/right as necessary)
int i;
int len;
int char_offset;
char temp[21];
char line_offset[4]={0x80, 0xA0, 0xC0, 0xE0};
if(Line<1 || Line>_Rows) return;
if(Text == NULL) return;
Command(line_offset[Line-1]);
len=strlen(Text);
if(len == 0) {
for(i=0; i<_Cols; i++) temp[i]=' ';
} else if(len > _Cols) {
strncpy(temp,Text,_Cols);
} else {
if(Center) {
char_offset=(_Cols-len)/2;
// if(len%2) char_offset++;
for(i=0; i<char_offset; i++) temp[i]=' ';
strcpy(temp+char_offset,Text);
for(i=len+char_offset; i<_Cols; i++) temp[i]=' ';
} else {
strcpy(temp,Text);
for(i=len; i<_Cols; i++) temp[i]=' ';
}
}
temp[_Cols]='\0';
for(i=0; i<_Cols; i++) Data(temp[i]);
}
void OLED::DisplayChar(int Row, int Col, char C) {
char offset;
if(Row<1 || Row>_Rows) return;
if(Col<1 || Col>_Cols) return;
offset=(0x80 + ((Row-1)*0x20) + (Col-1));
Command(offset);
Data(C);
}
void OLED::Clear() {
Command(0x01);
delay(2);
}
void OLED::Init() {
pinMode(ASCL, OUTPUT); //set Arduino I2C lines as outputs
pinMode(ASDA, OUTPUT); //
digitalWrite(ASCL, LOW); //
digitalWrite(ASDA, LOW); //
pinMode(SCLK, OUTPUT);
pinMode(SDIN, OUTPUT);
pinMode(SDOUT, INPUT);
digitalWrite(SCLK, HIGH);
digitalWrite(SDIN, HIGH);
delay(10);
Wire.begin();
delay(10);
Command(0x2A); //function set (extended command set)
Command(0x71); //function selection A, disable internal Vdd regualtor
Data(0x00);
Command(0x28); //function set (fundamental command set)
Command(0x08); //display off, cursor off, blink off
Command(0x2A); //function set (extended command set)
Command(0x79); //OLED command set enabled
Command(0xD5); //set display clock divide ratio/oscillator frequency
Command(0x70); //set display clock divide ratio/oscillator frequency
Command(0x78); //OLED command set disabled
Command(0x09); //extended function set (4-lines)
Command(0x06); //COM SEG direction
Command(0x72); //function selection B, disable internal Vdd regualtor
Data(0x00); //ROM CGRAM selection
Command(0x2A); //function set (extended command set)
Command(0x79); //OLED command set enabled
Command(0xDA); //set SEG pins hardware configuration
Command(0x10); //set SEG pins ... NOTE: When using NHD-0216AW-XB3 or NHD_0216MW_XB3 change to (0x00)
Command(0xDC); //function selection C
Command(0x00); //function selection C
Command(0x81); //set contrast control
Command(0x7F); //set contrast control
Command(0xD9); //set phase length
Command(0xF1); //set phase length
Command(0xDB); //set VCOMH deselect level
Command(0x40); //set VCOMH deselect level
Command(0x78); //OLED command set disabled
Command(0x28); //function set (fundamental command set)
Command(0x01); //clear display
Command(0x80); //set DDRAM address to 0x00
Command(0x0C); //display ON
delay(100);
}
void OLED::Command(unsigned char c) {
_Packet[0] = 0x00;
_Packet[1] = c;
SendPacket(2);
}
void OLED::Data(unsigned char d) {
_Packet[0] = 0x40;
_Packet[1] = d;
SendPacket(2);
}
void OLED::SendPacket(unsigned char x) {
unsigned char i;
Wire.beginTransmission(_Address);
for(i=0; i<x; i++) Wire.write(_Packet[i]);
Wire.endTransmission();
}
Hope this helps!0 -
No! Not in any way!
The code you offer is from the Arduinio library and that only offers VERY limited functions.
The reference URL given is equally void of any high-level strategy on programming user defined characters.
Sorry but the display is going back in the "interesting but useless" bin.
Regards, Martin0 -
Hello,
I'm sorry the previous example was not helpful.
We have made some example code that has been verified to work.
It was tested with our Slim CW series OLED and it should work with the AW-IB3 modular OLED since both series use the same controller US2066.
It should give the user a good idea on how to program custom characters./*****************************************************************************
*
/ Program for writing to Newhaven Display's 2x16 Character OLED with the US2066 Controller.
/ This code is written for the Arduino Uno R3 using 4-bit Parallel Interface
/
/ Newhaven Display invests time and resources providing this open source code.
/ Please support Newhaven Display by purchasing products from Newhaven Display!
* Copyright (c) 2019, Newhaven Display International
*
* This code is provided as an example only and is not guaranteed by Newhaven Display.
* Newhaven Display accepts no responsibility for any issues resulting from its use.
* The developer of the final application incorporating any parts of this
* sample code is responsible for ensuring its safe and correct operation
* and for any consequences resulting from its use.
*
*****************************************************************************/
/******** INITIAL DEFINITIONS***************/
#define E_Pin 10
#define R_W 9
#define R_S 8
#define C_S 11
#define RES 12
/************************ CHAR STRING**********/
char const text1[] = ("NEWHAVEN DISPLAY");
/************ Functions************/
void latch(){ // command to latch E
digitalWrite(E_Pin, HIGH); // Latch
delay(1);
digitalWrite(E_Pin, LOW);
delay(1);
}
void command(char i){
PORTD = i;
digitalWrite(R_S, LOW); // Command
digitalWrite(R_W, LOW); // Write
latch(); // take 1st 4 bits
i = i<<4;
PORTD = i;
latch(); // take 2nd 4 bits
}
void data(char i){
PORTD = i;
digitalWrite(R_S, HIGH); // Data
digitalWrite(R_W, LOW); // Write
latch(); // take 1st 4 bits
i = i<<4;
PORTD = i;
latch(); // take 2nd 4 bits
}
/***********INITIALIZE DISPLAY************************/
void init1(){
digitalWrite(E_Pin, LOW); //Needed so latch function can work properly.
delay(100); //Wait >15 msec after power is applied
command(0x2A); //function set (extended command set)
command(0x71); //function selection A
data(0x00); //disable internal Vdd regualtor
command(0x2C); //function set (fundamental command set)
command(0x08); //display off, cursor off, blink off
command(0x2A); //function set (extended command set)
command(0x79); //OLED command set enabled
command(0xD5); //set display clock divide ratio/oscillator frequency
command(0x70); //set display clock divide ratio/oscillator frequency
command(0x78); //OLED command set disabled
command(0x08); //extended function set (2-lines)
command(0x06); //COM SEG direction
command(0x72); //function selection B, disable internal Vdd regualtor
data(0x00); //ROM CGRAM selection
command(0x2A); //function set (extended command set)
command(0x79); //OLED command set enabled
command(0xDA); //set SEG pins hardware configuration
command(0x10); //set SEG pins hardware configuration //////////////0x10 on other slim char OLEDs
command(0xDC); //function selection C
command(0x00); //function selection C
command(0x81); //set contrast control
command(0x4F); //set contrast control //CHANGED FROM 0x7F
command(0xD9); //set phase length
command(0xF1); //set phase length
command(0xDB); //set VCOMH deselect level
command(0x40); //set VCOMH deselect level
command(0x78); //OLED command set disabled
command(0x28); //function set (fundamental command set)
command(0x01); //clear display
command(0x80); //set DDRAM address to 0x00
command(0x0C); //display ON
delay(100);
}
void clear_screen(){ // clear display
command(0x01);
}
void ret_home(){ // Return to home position
command(0x02);
}
void disp(){ // DISPLAY TEXT
clear_screen();
ret_home();
for( int i = 0; i<16; i++){ //40 for whole section
data(text1[i]);
}
command(0xC0);
for (int i = 0; i<16; i++){ //40 for whole section
data(text1[i]);
}
}
void Store_Custom_Characters(){
command(0x40); //CGRAM ADDRESS 1: Slot 1
data(0x00);
command(0x41); //CGRAM ADDRESS 1: Slot 2
data(0x00);
command(0x42); //CGRAM ADDRESS 1: Slot 3
data(0x00);
command(0x43); //CGRAM ADDRESS 1: Slot 4
data(0x00);
command(0x44); //CGRAM ADDRESS 1: Slot 5
data(0x00);
command(0x45); //CGRAM ADDRESS 1: Slot 6
data(0x00);
command(0x46); //CGRAM ADDRESS 1: Slot 7
data(0x00);
command(0x47); //CGRAM ADDRESS 1: Slot 8
data(0x0F);
command(0x48); //CGRAM ADDRESS 2: Slot 1
data(0x00);
command(0x49); //CGRAM ADDRESS 2: Slot 2
data(0x00);
command(0x4A); //CGRAM ADDRESS 2: Slot 3
data(0x00);
command(0x4B); //CGRAM ADDRESS 2: Slot 4
data(0x00);
command(0x4C); //CGRAM ADDRESS 2: Slot 5
data(0x00);
command(0x4D); //CGRAM ADDRESS 2: Slot 6
data(0x00);
command(0x4E); //CGRAM ADDRESS 2: Slot 7
data(0x0F);
command(0x4F); //CGRAM ADDRESS 2: Slot 8
data(0x0F);
command(0x50); //CGRAM ADDRESS 3: Slot 1
data(0x00);
command(0x51); //CGRAM ADDRESS 3: Slot 2
data(0x00);
command(0x52); //CGRAM ADDRESS 3: Slot 3
data(0x00);
command(0x53); //CGRAM ADDRESS 3: Slot 4
data(0x00);
command(0x54); //CGRAM ADDRESS 3: Slot 5
data(0x00);
command(0x55); //CGRAM ADDRESS 3: Slot 6
data(0x0F);
command(0x56); //CGRAM ADDRESS 3: Slot 7
data(0x0F);
command(0x57); //CGRAM ADDRESS 3: Slot 8
data(0x0F);
command(0x58); //CGRAM ADDRESS 4: Slot 1
data(0x00);
command(0x59); //CGRAM ADDRESS 4: Slot 2
data(0x00);
command(0x5A); //CGRAM ADDRESS 4: Slot 3
data(0x00);
command(0x5B); //CGRAM ADDRESS 4: Slot 4
data(0x00);
command(0x5C); //CGRAM ADDRESS 4: Slot 5
data(0x0F);
command(0x5D); //CGRAM ADDRESS 4: Slot 6
data(0x0F);
command(0x5E); //CGRAM ADDRESS 4: Slot 7
data(0x0F);
command(0x5F); //CGRAM ADDRESS 4: Slot 8
data(0x0F);
command(0x60); //CGRAM ADDRESS 5: Slot 1
data(0x00);
command(0x61); //CGRAM ADDRESS 5: Slot 2
data(0x00);
command(0x62); //CGRAM ADDRESS 5: Slot 3
data(0x00);
command(0x63); //CGRAM ADDRESS 5: Slot 4
data(0x0F);
command(0x64); //CGRAM ADDRESS 5: Slot 5
data(0x0F);
command(0x65); //CGRAM ADDRESS 5: Slot 6
data(0x0F);
command(0x66); //CGRAM ADDRESS 5: Slot 7
data(0x0F);
command(0x67); //CGRAM ADDRESS 5: Slot 8
data(0x0F);
command(0x68); //CGRAM ADDRESS 6: Slot 1
data(0x00);
command(0x69); //CGRAM ADDRESS 6: Slot 2
data(0x00);
command(0x6A); //CGRAM ADDRESS 6: Slot 3
data(0x0F);
command(0x6B); //CGRAM ADDRESS 6: Slot 4
data(0x0F);
command(0x6C); //CGRAM ADDRESS 6: Slot 5
data(0x0F);
command(0x6D); //CGRAM ADDRESS 6: Slot 6
data(0x0F);
command(0x6E); //CGRAM ADDRESS 6: Slot 7
data(0x0F);
command(0x6F); //CGRAM ADDRESS 6: Slot 8
data(0x0F);
command(0x70); //CGRAM ADDRESS 7: Slot 1
data(0x00);
command(0x71); //CGRAM ADDRESS 7: Slot 2
data(0x0F);
command(0x72); //CGRAM ADDRESS 7: Slot 3
data(0x0F);
command(0x73); //CGRAM ADDRESS 7: Slot 4
data(0x0F);
command(0x74); //CGRAM ADDRESS 7: Slot 5
data(0x0F);
command(0x75); //CGRAM ADDRESS 7: Slot 6
data(0x0F);
command(0x76); //CGRAM ADDRESS 7: Slot 7
data(0x0F);
command(0x77); //CGRAM ADDRESS 7: Slot 8
data(0x0F);
command(0x78); //CGRAM ADDRESS 8: Slot 1
data(0x0F);
command(0x79); //CGRAM ADDRESS 8: Slot 2
data(0x0F);
command(0x7A); //CGRAM ADDRESS 8: Slot 3
data(0x0F);
command(0x7B); //CGRAM ADDRESS 8: Slot 4
data(0x0F);
command(0x7C); //CGRAM ADDRESS 8: Slot 5
data(0x0F);
command(0x7D); //CGRAM ADDRESS 8: Slot 6
data(0x0F);
command(0x7E); //CGRAM ADDRESS 8: Slot 7
data(0x0F);
command(0x7F); //CGRAM ADDRESS 8: Slot 8
data(0x0F);
}
void Show_Custom_Characters(){
ret_home();
delay(2);
data(0x00); //CGRAM ADDRESS 1
data(0x01); //CGRAM ADDRESS 2
data(0x02); //CGRAM ADDRESS 3
data(0x03); //CGRAM ADDRESS 4
data(0x04); //CGRAM ADDRESS 5
data(0x05); //CGRAM ADDRESS 6
data(0x06); //CGRAM ADDRESS 7
data(0x07); //CGRAM ADDRESS 8
}
void disp2(){ // DISPLAY TEXT
clear_screen();
ret_home();
for( int i = 0; i<16; i++){
data(text1[i]);
}
command(0xC0);
for (int i = 0; i<16; i++){
data(text1[i]);
}
}
void setup(){
DDRD = 0xFF; // First 8 pins of PORT D as output
DDRB = 0x1F; // Port B first 5 pins as output
digitalWrite(C_S, LOW);
digitalWrite(RES, HIGH);
init1();
delay(500);
Store_Custom_Characters();
Show_Custom_Characters();
}
void loop() {
}Thank you.
« Last Edit: April 08, 2020, 05:06:52 PM by Alee_S »0 -
Thank you Sergio,
Firstly, my NHD_0216AW_x3B is an I2C device, so to try and get your code to work, I had to cut-out the bit-bashing and use the provided Arduino Library.
Starting with just setup() function, this what I have paired it down to:void setup()
{
Serial.begin(115200);
/*************************************** This section is not relevent - The _3XB is an I2C device
DDRD = 0xFF; // First 8 pins of PORT D as output
DDRB = 0x1F; // Port B first 5 pins as output
digitalWrite(C_S, LOW);
digitalWrite(RES, HIGH);
*/
init1(); //This does NOT clear screen?
//init_oled(); //This DOES! From #include "NHD_US2066.h"
//delay(500);
//Store_Custom_Characters();
//Show_Custom_Characters();
Serial << "I've done SETUP now" << endl;
while (1);
}Fallen at the first step! The init1() function you have provided does not match the published oled_init().
Before wasting any more time, what else does it not do? Which should I use?
I really am trying, but soon I'll solder in it into a project an move on.
Regards, Martin0 -
Thank you Sergio,
Got it at last!
One more moan! Can you do something about your CAPTCHA - I can't read or hear it.
I know it has a function, but it must be the worst example I have seen?0 -
Hi mprowe,
Thanks for the feedback.
Our Web design team is looking into the CAPTCHA function to see if we can improve it's use.
Best Regards,0
Please sign in to leave a comment.
Comments
6 comments