NHD0420CW-Ax3 display with Arduino Uno - Tutorials
Hi,
I read some posts asking for use of NHD0420CW-Ax3 display family with Arduino Uno.
So I modified the example supplied by Newhaven and adapted it to Arduino Uno, for tutorial purpose. They are fully tested.
I hope these examples may be useful for beginners.
Tutorial 1 - display connected to Arduino Uno via I2C interface:
/*
* Demo_NHD0420CW-Ax3_I2C.ino
*
* Tutorial sketch for use of character OLED slim display family by Newhaven with Arduino Uno, using
* only Wire (I2C) library. Models: NHD0420CW-Ax3, NHD0220CW-Ax3, NHD0216CW-Ax3. Controller: US2066
* in this example, the display is connected to Arduino via I2C interface.
*
* Displays on the OLED alternately a 4-line message and a sequence of character "block".
* This sketch assumes the use of a 4x20 display; if different, modify the values of the two variables
* ROW_N e COLUMN_N.
* The sketch uses the minimum possible of Arduino's pins; if you intend to use also /RES line,
* the related instructions are already present, it's sufficient to remove the comment markers.
*
* The circuit:
* OLED pin 1 (Vss) to Arduino pin ground
* OLED pin 2 (VDD) to Arduino pin 5V
* OLED pin 3 (REGVDD) to Arduino pin 5V
* OLED pin 4 (SA0) to Vss ground (to assign I2C address 0x3D, connect to VDD 5V)
* OLED pin 5 and 6 to Vss ground
* OLED pin 7 (SCL) to Arduino pin A5 (SCL); 10K pull-up resistor on OLED pin
* OLED pin 8 and 9 (SDAin,SDAout) to Arduino pin A4 (SDA); 10K pull-up resistor on OLED pin
* OLED pin 10 to 15 to Vss ground
* OLED pin 16 (/RES) to Arduino pin Reset or VDD 5V (or to Arduino pin D13, to control reset by sw)
* OLED pin 17 (BS0) to Vss ground
* OLED pin 18 (BS1) to VDD 5V
* OLED pin 19 (BS2) to Vss ground
* OLED pin 20 (Vss) to Vss ground
*
* Original example created by Newhaven Display International Inc.
* Modified and adapted to Arduino Uno 15 Mar 2015 by Pasquale D'Antini
* Modified 19 May 2015 by Pasquale D'Antini
*
* This example code is in the public domain.
*/
#include <Wire.h>
const byte ROW_N = 4; // Number of display rows
const byte COLUMN_N = 20; // Number of display columns
//const byte RES = 13; // Arduino's pin assigned to the Reset line (optional, can be always high)
const byte SLAVE2W = 0x3C; // Display I2C address, in 7-bit form: 0x3C if SA0=LOW, 0x3D if SA0=HIGH
const byte TEXT[4][21] = {"1-Newhaven Display--",
"2-------Test--------",
"3-16/20-Characters--",
"4!@#$%^&*()_+{}[]<>?"}; // Strings to be displayed
byte new_line[4] = {0x80, 0xA0, 0xC0, 0xE0}; // DDRAM address for each line of the display
byte rows = 0x08; // Display mode: 1/3 lines or 2/4 lines; default 2/4 (0x08)
byte tx_packet[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
// Packet to be transmitted (max 20 bytes)
// _______________________________________________________________________________________
void command(byte c) // SUBROUTINE: PREPARES THE TRANSMISSION OF A COMMAND
{
tx_packet[0] = 0x00; // Control Byte; C0_bit=0, D/C_bit=0 -> following Data Byte contains command
tx_packet[1] = c; // Data Byte: the command to be executed by the display
send_packet(2); // Transmits the two bytes
}
// _______________________________________________________________________________________
void data(byte d) // SUBROUTINE: PREPARES THE TRANSMISSION OF A BYTE OF DATA
{
tx_packet[0] = 0x40; // Control Byte; C0_bit=0, D/C_bit=1 -> following Data Byte contains data
tx_packet[1] = d; // Data Byte: the character to be displayed
send_packet(2); // Transmits the two bytes
}
// _______________________________________________________________________________________
void send_packet(byte x) // SUBROUTINE: SEND TO THE DISPLAY THE x BYTES STORED IN tx_packet
{
byte ix = 0; // Bytes index
Wire.beginTransmission(SLAVE2W); // Begin the transmission via I2C to the display with the given address
for(ix=0; ix<x; ix++) // One byte at a time,
{
Wire.write(tx_packet[ix]); // queue bytes for transmission
}
Wire.endTransmission(); // Transmits the bytes that were queued
}
// _______________________________________________________________________________________
void output(void) // SUBROUTINE: DISPLAYS THE FOUR STRINGS, THEN THE SAME IN REVERSE ORDER
{
byte r = 0; // Row index
byte c = 0; // Column index
command(0x01); // Clears display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(TEXT[r][c]); // displays the correspondig string
}
}
delay(2000); // Waits, only for visual effect purpose
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(TEXT[3-r][c]); // displays the correspondig string (in reverse order)
}
}
}
// _______________________________________________________________________________________
void blocks(void) // SUBROUTINE: FILLS THE ENTIRE DISPLAY WITH THE CHARACTER "BLOCK"
{
byte r = 0; // Row index
byte c = 0; // Column index
command(0x01); // Clear display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(0xDB); // displays the character 0xDB (block)
delay(50); // Waits, only for visual effect purpose
}
delay(500); // Waits, only for visual effect purpose
}
}
// _______________________________________________________________________________________
void setup(void) // INITIAL SETUP
{
// pinMode(RES, OUTPUT); // Initializes Arduino pin for the Reset line (optional)
// digitalWrite(RES, HIGH); // Sets HIGH the Reset line of the display (optional, can be always high)
delayMicroseconds(200); // Waits 200 us for stabilization purpose
Wire.begin(); // Initiate the Wire library and join the I2C bus as a master
delay(10); // Waits 10 ms for stabilization purpose
if (ROW_N == 2 || ROW_N == 4)
rows = 0x08; // Display mode: 2/4 lines
else
rows = 0x00; // Display mode: 1/3 lines
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x71); // Function selection A:
data(0x5C); // enable internal Vdd regulator at 5V I/O mode (def. value) (0x00 for disable, 2.8V I/O)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x08); // Display ON/OFF control: display off, cursor off, blink off (default values)
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xD5); // Set display clock divide ratio/oscillator frequency:
command(0x70); // divide ratio=1, frequency=7 (default values)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
if (ROW_N > 2)
command(0x09); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 3/4 lines
else
command(0x08); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 1/2 lines
command(0x06); // Entry Mode set - COM/SEG direction: COM0->COM31, SEG99->SEG0 (BDC=1, BDS=0)
command(0x72); // Function selection B:
data(0x0A); // ROM/CGRAM selection: ROM C, CGROM=250, CGRAM=6 (ROM=10, OPR=10)
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xDA); // Set SEG pins hardware configuration:
command(0x10); // alternative odd/even SEG pin, disable SEG left/right remap (default values)
command(0xDC); // Function selection C:
command(0x00); // internal VSL, GPIO input disable
command(0x81); // Set contrast control:
command(0x7F); // contrast=127 (default value)
command(0xD9); // Set phase length:
command(0xF1); // phase2=15, phase1=1 (default: 0x78)
command(0xDB); // Set VCOMH deselect level:
command(0x40); // VCOMH deselect level=1 x Vcc (default: 0x20=0,77 x Vcc)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x01); // Clear display
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
command(0x80); // Set DDRAM address 0x00 in address counter (cursor home) (default value)
command(0x0C); // Display ON/OFF control: display ON, cursor off, blink off
delay(250); // Waits 250 ms for stabilization purpose after display on
if (ROW_N == 2)
new_line[1] = 0xC0; // DDRAM address for each line of the display (only for 2-line mode)
}
// _______________________________________________________________________________________
void loop(void) // MAIN PROGRAM
{
output(); // Execute subroutine "output"
delay(2000); // Waits, only for visual effect purpose
blocks(); // Execute subroutine "blocks"
delay(2000); // Waits, only for visual effect purpose
}
-
Tutorial 2 - display connected to Arduino Uno via 8-bit 6800 parallel interface:
/*
* Demo_NHD0420CW-Ax3_parallel_6800_8b.ino
*
* Tutorial sketch for use of character OLED slim display family by Newhaven with Arduino Uno, without
* using any library. Models: NHD0420CW-Ax3, NHD0220CW-Ax3, NHD0216CW-Ax3. Controller: US2066
* In this example, the display is connected to Arduino via 8-bit 6800 parallel interface.
*
* Displays on the OLED alternately a 4-line message and a sequence of character "block".
* This sketch assumes the use of a 4x20 display; if different, modify the values of the two variables
* ROW_N e COLUMN_N.
* The sketch uses the minimum possible of Arduino's pins; if you intend to use also R/W, /CS or /RES
* lines, the related instructions are already present, it's sufficient to remove the comment markers.
*
* The circuit:
* OLED pin 1 (Vss) to Arduino pin ground
* OLED pin 2 (VDD) to Arduino pin 5V
* OLED pin 3 (REGVDD) to Arduino pin 5V
* OLED pin 4 (D/C) to Arduino pin D2
* OLED pin 5 (R/W) to Vss ground (always write); to enable also read, connect to Arduino pin D13
* OLED pin 6 (E) to Arduino pin D3
* OLED pin 7 (DB0) to Arduino pin D4
* OLED pin 8 (DB1) to Arduino pin D5
* OLED pin 9 (DB2) to Arduino pin D6
* OLED pin 10 (DB3) to Arduino pin D7
* OLED pin 11 (DB4) to Arduino pin D8
* OLED pin 12 (DB5) to Arduino pin D9
* OLED pin 13 (DB6) to Arduino pin D10
* OLED pin 14 (DB7) to Arduino pin D11
* OLED pin 15 (/CS) to Vss ground (or to Arduino pin D12, in case of use of more than one display)
* OLED pin 16 (/RES) to Arduino pin Reset or VDD 5V (or to Arduino pin D13, to control reset by sw)
* OLED pin 17 (BS0) to Vss ground
* OLED pin 18 (BS1) to Vss ground
* OLED pin 19 (BS2) to VDD 5V
* OLED pin 20 (Vss) to Vss ground
*
* Original example created by Newhaven Display International Inc.
* Modified and adapted to Arduino Uno 16 Mar 2015 by Pasquale D'Antini
* Modified 19 May 2015 by Pasquale D'Antini
*
* This example code is in the public domain.
*/
const byte ROW_N = 4; // Number of display rows
const byte COLUMN_N = 20; // Number of display columns
const byte DC = 2; // Arduino's pin assigned to the D/C line
//const byte RW = 13; // Arduino's pin assigned to the R/W line (optional, can be always low)
const byte E = 3; // Arduino's pin assigned to the E line
//const byte CS = 12; // Arduino's pin assigned to the /CS line (optional, can be always low)
//const byte RES = 13; // Arduino's pin assigned to the Reset line (optional, can be always high)
const byte DATA_PINS[8] = {4, 5, 6, 7, 8, 9, 10, 11}; // Arduino's pins assigned to the data bus
const byte TEXT[4][21] = {"1-Newhaven Display--",
"2-------Test--------",
"3-16/20-Characters--",
"4!@#$%^&*()_+{}[]<>?"}; // Strings to be displayed
byte new_line[4] = {0x80, 0xA0, 0xC0, 0xE0}; // DDRAM address for each line of the display
byte rows = 0x08; // Display mode: 1/3 lines or 2/4 lines; default 2/4 (0x08)
// _______________________________________________________________________________________
void command(byte c) // SUBROUTINE: PREPARES THE TRANSMISSION OF A COMMAND
{
digitalWrite(DC, LOW); // Sets LOW the D/C line of the display -> command
// digitalWrite(RW, LOW); // Sets LOW the R/W line of the display (optional, can be always low)
send8bit(c); // Sends the byte on the data bus
enableCycle(); // Calls the enable signal cycle subroutine
}
// _______________________________________________________________________________________
void data(byte d) // SUBROUTINE: PREPARES THE TRANSMISSION OF A BYTE OF DATA
{
digitalWrite(DC, HIGH); // Sets HIGH the D/C line of the display -> data
// digitalWrite(RW, LOW); // Sets LOW the R/W line of the display (optional, can be always low)
send8bit(d); // Sends the byte on the data bus
enableCycle(); // Calls the enable signal cycle subroutine
}
// _______________________________________________________________________________________
void enableCycle(void) // SUBROUTINE: EXECUTE THE ENABLE SIGNAL CYCLE (DATA LATCH)
{
delayMicroseconds(1); // Waits 1 us (required for timing purpose)
// digitalWrite(CS, LOW); // Sets LOW the /CS line of the display (optional, can be always low)
digitalWrite(E, HIGH); // Sets HIGH the E line of the display
delayMicroseconds(1); // Waits 1 us (required for timing purpose)
digitalWrite(E, LOW); // Sets LOW the E line of the display
// digitalWrite(CS, HIGH); // Sets HIGH the /CS line of the display (optional, can be always low)
delayMicroseconds(1); // Waits 1 us (required for timing purpose)
}
// _______________________________________________________________________________________
void send8bit(byte value) // SUBROUTINE: SENDS THE BYTE ON THE DATA BUS
{
for (byte i = 0; i < 8; i++) // One bit at a time,
{
digitalWrite(DATA_PINS[i], (value >> i) & 0x01); // sets the eight lines of the data bus,
} // to send the character to the display
}
// _______________________________________________________________________________________
void output(void) // SUBROUTINE: DISPLAYS THE FOUR STRINGS, THEN THE SAME IN REVERSE ORDER
{
byte r = 0; // Row index
byte c = 0; // Column index
command(0x01); // Clears display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(TEXT[r][c]); // displays the correspondig string
}
}
delay(2000); // Waits, only for visual effect purpose
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(TEXT[3-r][c]); // displays the correspondig string (in reverse order)
}
}
}
// _______________________________________________________________________________________
void blocks(void) // SUBROUTINE: FILLS THE ENTIRE DISPLAY WITH THE CHARACTER "BLOCK"
{
byte r = 0; // Row index
byte c = 0; // Column index
command(0x01); // Clear display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(0xDB); // displays the character 0xDB (block)
delay(50); // Waits, only for visual effect purpose
}
delay(500); // Waits, only for visual effect purpose
}
}
// _______________________________________________________________________________________
void setup(void) // INITIAL SETUP
{
pinMode(DC, OUTPUT); // Initializes Arduino pin for the D/C line
digitalWrite(DC, LOW); // Sets LOW the D/C line of the display
// pinMode(RW, OUTPUT); // Initializes Arduino pin for the R/W line (optional)
// digitalWrite(RW, LOW); // Sets LOW the R/W line of the display (optional, can be always low)
pinMode(E, OUTPUT); // Initializes Arduino pin for the E line
digitalWrite(E, LOW); // Sets LOW the E line of the display
// pinMode(CS, OUTPUT); // Initializes Arduino pin for the /CS line (optional)
// digitalWrite(CS, HIGH); // Sets HIGH the /CS line of the display (optional, can be always low)
for (byte i=0; i<8; i++)
{
pinMode(DATA_PINS[i], OUTPUT); // Initializes all Arduino pins for the data bus
digitalWrite(DATA_PINS[i], LOW); // Sets LOW the data bus
}
// pinMode(RES, OUTPUT); // Initializes Arduino pin for the Reset line (optional)
// digitalWrite(RES, HIGH); // Sets HIGH the Reset line of the display (optional, can be always high)
delayMicroseconds(200); // Waits 200 us for stabilization purpose
if (ROW_N == 2 || ROW_N == 4)
rows = 0x08; // Display mode: 2/4 lines
else
rows = 0x00; // Display mode: 1/3 lines
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x71); // Function selection A:
data(0x5C); // enable internal Vdd regulator at 5V I/O mode (def. value) (0x00 for disable, 2.8V I/O)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x08); // Display ON/OFF control: display off, cursor off, blink off (default values)
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xD5); // Set display clock divide ratio/oscillator frequency:
command(0x70); // divide ratio=1, frequency=7 (default values)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
if (ROW_N > 2)
command(0x09); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 3/4 lines
else
command(0x08); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 1/2 lines
command(0x06); // Entry Mode set - COM/SEG direction: COM0->COM31, SEG99->SEG0 (BDC=1, BDS=0)
command(0x72); // Function selection B:
data(0x0A); // ROM/CGRAM selection: ROM C, CGROM=250, CGRAM=6 (ROM=10, OPR=10)
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xDA); // Set SEG pins hardware configuration:
command(0x10); // alternative odd/even SEG pin, disable SEG left/right remap (default values)
command(0xDC); // Function selection C:
command(0x00); // internal VSL, GPIO input disable
command(0x81); // Set contrast control:
command(0x7F); // contrast=127 (default value)
command(0xD9); // Set phase length:
command(0xF1); // phase2=15, phase1=1 (default: 0x78)
command(0xDB); // Set VCOMH deselect level:
command(0x40); // VCOMH deselect level=1 x Vcc (default: 0x20=0,77 x Vcc)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x01); // Clear display
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
command(0x80); // Set DDRAM address 0x00 in address counter (cursor home) (default value)
command(0x0C); // Display ON/OFF control: display ON, cursor off, blink off
delay(250); // Waits 250 ms for stabilization purpose after display on
if (ROW_N == 2)
new_line[1] = 0xC0; // DDRAM address for each line of the display (only for 2-line mode)
}
// _______________________________________________________________________________________
void loop(void) // MAIN PROGRAM
{
output(); // Execute subroutine "output"
delay(2000); // Waits, only for visual effect purpose
blocks(); // Execute subroutine "blocks"
delay(2000); // Waits, only for visual effect purpose
}0 -
I have an example for 4-bit 6800 parallel interface, too, but it doesn't run as expected.
There is something wrong I don't see or something I don't know.
In attachment there is the image of the output on the display.UPDATE April 22: thanks to Michael_L, the error has been discovered and the code, fixed, now runs as expected.
Tutorial 3 - display connected to Arduino Uno via 4-bit 6800 parallel interface:/*
* Demo_NHD0420CW-Ax3_parallel_6800_4b.ino
*
* Tutorial sketch for use of character OLED slim display family by Newhaven with Arduino Uno, without
* using any library. Models: NHD0420CW-Ax3, NHD0220CW-Ax3, NHD0216CW-Ax3. Controller: US2066
* In this example, the display is connected to Arduino via 8-bit 6800 parallel interface.
*
* Displays on the OLED alternately a 4-line message and a sequence of character "block".
* This sketch assumes the use of a 4x20 display; if different, modify the values of the two variables
* ROW_N e COLUMN_N.
* The sketch uses the minimum possible of Arduino's pins; if you intend to use also R/W, /CS or /RES
* lines, the related instructions are already present, it's sufficient to remove the comment markers.
*
* The circuit:
* OLED pin 1 (Vss) to Arduino pin ground
* OLED pin 2 (VDD) to Arduino pin 5V
* OLED pin 3 (REGVDD) to Arduino pin 5V
* OLED pin 4 (D/C) to Arduino pin D2
* OLED pin 5 (R/W) to Vss ground (always write); to enable also read, connect to Arduino pin D13
* OLED pin 6 (E) to Arduino pin D3
* OLED pin 7 (DB0) to Vss ground
* OLED pin 8 (DB1) to Vss ground
* OLED pin 9 (DB2) to Vss ground
* OLED pin 10 (DB3) to Vss ground
* OLED pin 11 (DB4) to Arduino pin D8
* OLED pin 12 (DB5) to Arduino pin D9
* OLED pin 13 (DB6) to Arduino pin D10
* OLED pin 14 (DB7) to Arduino pin D11
* OLED pin 15 (/CS) to Vss ground (or to Arduino pin D12, in case of use of more than one display)
* OLED pin 16 (/RES) to Arduino pin Reset or VDD 5V (or to Arduino pin D13, to control reset by sw)
* OLED pin 17 (BS0) to VDD 5V
* OLED pin 18 (BS1) to Vss ground
* OLED pin 19 (BS2) to VDD 5V
* OLED pin 20 (Vss) to Vss ground
*
* Original example created by Newhaven Display International Inc.
* Modified and adapted to Arduino Uno 16 Mar 2015 by Pasquale D'Antini
* Modified 19 May 2015 by Pasquale D'Antini
*
* This example code is in the public domain.
*/
const byte ROW_N = 4; // Number of display rows
const byte COLUMN_N = 20; // Number of display columns
const byte DC = 2; // Arduino's pin assigned to the D/C line
//const byte RW = 13; // Arduino's pin assigned to the R/W line (optional, can be always low)
const byte E = 3; // Arduino's pin assigned to the E line
//const byte CS = 12; // Arduino's pin assigned to the /CS line (optional, can be always low)
//const byte RES = 13; // Arduino's pin assigned to the Reset line (optional, can be always high)
const byte DATA_PINS[4] = {8, 9, 10, 11}; // Arduino's pins assigned to the data bus
const byte TEXT[4][21] = {"1-Newhaven Display--",
"2-------Test--------",
"3-16/20-Characters--",
"4!@#$%^&*()_+{}[]<>?"}; // Strings to be displayed
byte new_line[4] = {0x80, 0xA0, 0xC0, 0xE0}; // DDRAM address for each line of the display
byte rows = 0x08; // Display mode: 1/3 lines or 2/4 lines; default 2/4 (0x08)
// _______________________________________________________________________________________
void command(byte c) // SUBROUTINE: PREPARES THE TRANSMISSION OF A COMMAND
{
digitalWrite(DC, LOW); // Sets LOW the D/C line of the display -> command
// digitalWrite(RW, LOW); // Sets LOW the R/W line of the display (optional, can be always low)
send4bit(c >> 4); // Sends the higher 4 bits on the data bus
enableCycle(); // Calls the enable signal cycle subroutine
send4bit(c); // Sends the lower 4 bits on the data bus
enableCycle(); // Calls the enable signal cycle subroutine
}
// _______________________________________________________________________________________
void data(byte d) // SUBROUTINE: PREPARES THE TRANSMISSION OF A BYTE OF DATA
{
digitalWrite(DC, HIGH); // Sets HIGH the D/C line of the display -> data
// digitalWrite(RW, LOW); // Sets LOW the R/W line of the display (optional, can be always low)
send4bit(d >> 4); // Sends the higher 4 bits on the data bus
enableCycle(); // Calls the enable signal cycle subroutine
send4bit(d); // Sends the lower 4 bits on the data bus
enableCycle(); // Calls the enable signal cycle subroutine
}
// _______________________________________________________________________________________
void enableCycle(void) // SUBROUTINE: EXECUTE THE ENABLE SIGNAL CYCLE (DATA LATCH)
{
delayMicroseconds(1); // Waits 1 us (required for timing purpose)
// digitalWrite(CS, LOW); // Sets LOW the /CS line of the display (optional, can be always low)
digitalWrite(E, HIGH); // Sets HIGH the E line of the display
delayMicroseconds(1); // Waits 1 us (required for timing purpose)
digitalWrite(E, LOW); // Sets LOW the E line of the display
// digitalWrite(CS, HIGH); // Sets HIGH the /CS line of the display (optional, can be always low)
delayMicroseconds(1); // Waits 1 us (required for timing purpose)
}
// _______________________________________________________________________________________
void send4bit(byte value) // SUBROUTINE: SENDS HALF BYTE ON THE DATA BUS
{
for (byte i = 0; i < 4; i++) // One bit at a time,
{
digitalWrite(DATA_PINS[i], (value >> i) & 0x01); // sets the four lines of the data bus,
} // to send the half character to the display
}
// _______________________________________________________________________________________
void output(void) // SUBROUTINE: DISPLAYS THE FOUR STRINGS, THEN THE SAME IN REVERSE ORDER
{
byte r = 0; // Row index
byte c = 0; // Column index
command(0x01); // Clears display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(TEXT[r][c]); // displays the correspondig string
}
}
delay(2000); // Waits, only for visual effect purpose
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(TEXT[3-r][c]); // displays the correspondig string (in reverse order)
}
}
}
// _______________________________________________________________________________________
void blocks(void) // SUBROUTINE: FILLS THE ENTIRE DISPLAY WITH THE CHARACTER "BLOCK"
{
byte r = 0; // Row index
byte c = 0; // Column index
command(0x01); // Clear display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(0xDB); // displays the character 0xDB (block)
delay(50); // Waits, only for visual effect purpose
}
delay(500); // Waits, only for visual effect purpose
}
}
// _______________________________________________________________________________________
void setup(void) // INITIAL SETUP
{
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
pinMode(5, OUTPUT);
digitalWrite(5, LOW);
pinMode(6, OUTPUT);
digitalWrite(6, LOW);
pinMode(7, OUTPUT);
digitalWrite(7, LOW);
pinMode(DC, OUTPUT); // Initializes Arduino pin for the D/C line
digitalWrite(DC, LOW); // Sets LOW the D/C line of the display
// pinMode(RW, OUTPUT); // Initializes Arduino pin for the R/W line (optional)
// digitalWrite(RW, LOW); // Sets LOW the R/W line of the display (optional, can be always low)
pinMode(E, OUTPUT); // Initializes Arduino pin for the E line
digitalWrite(E, LOW); // Sets LOW the E line of the display
// pinMode(CS, OUTPUT); // Initializes Arduino pin for the /CS line (optional)
// digitalWrite(CS, HIGH); // Sets HIGH the /CS line of the display (optional, can be always low)
for (byte i=0; i<4; i++)
{
pinMode(DATA_PINS[i], OUTPUT); // Initializes all Arduino pins for the data bus
digitalWrite(DATA_PINS[i], LOW); // Sets LOW the data bus
}
// pinMode(RES, OUTPUT); // Initializes Arduino pin for the Reset line (optional)
// digitalWrite(RES, HIGH); // Sets HIGH the Reset line of the display (optional, can be always high)
delayMicroseconds(200); // Waits 200 us for stabilization purpose
if (ROW_N == 2 || ROW_N == 4)
rows = 0x08; // Display mode: 2/4 lines
else
rows = 0x00; // Display mode: 1/3 lines
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x71); // Function selection A:
data(0x5C); // enable internal Vdd regulator at 5V I/O mode (def. value) (0x00 for disable, 2.8V I/O)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x08); // Display ON/OFF control: display off, cursor off, blink off (default values)
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xD5); // Set display clock divide ratio/oscillator frequency:
command(0x70); // divide ratio=1, frequency=7 (default values)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
if (ROW_N > 2)
command(0x09); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 3/4 lines
else
command(0x08); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 1/2 lines
command(0x06); // Entry Mode set - COM/SEG direction: COM0->COM31, SEG99->SEG0 (BDC=1, BDS=0)
command(0x72); // Function selection B:
data(0x0A); // ROM/CGRAM selection: ROM C, CGROM=250, CGRAM=6 (ROM=10, OPR=10)
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xDA); // Set SEG pins hardware configuration:
command(0x10); // alternative odd/even SEG pin, disable SEG left/right remap (default values)
command(0xDC); // Function selection C:
command(0x00); // internal VSL, GPIO input disable
command(0x81); // Set contrast control:
command(0x7F); // contrast=127 (default value)
command(0xD9); // Set phase length:
command(0xF1); // phase2=15, phase1=1 (default: 0x78)
command(0xDB); // Set VCOMH deselect level:
command(0x40); // VCOMH deselect level=1 x Vcc (default: 0x20=0,77 x Vcc)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x01); // Clear display
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
command(0x80); // Set DDRAM address 0x00 in address counter (cursor home) (default value)
command(0x0C); // Display ON/OFF control: display ON, cursor off, blink off
delay(250); // Waits 250 ms for stabilization purpose after display on
if (ROW_N == 2)
new_line[1] = 0xC0; // DDRAM address for each line of the display (only for 2-line mode)
}
// _______________________________________________________________________________________
void loop(void) // MAIN PROGRAM
{
output(); // Execute subroutine "output"
delay(2000); // Waits, only for visual effect purpose
blocks(); // Execute subroutine "blocks"
delay(2000); // Waits, only for visual effect purpose
}0 -
Tutorial 4 - display connected to Arduino Uno via SPI interface:
/*
* Demo_NHD0420CW-Ax3_SPI.ino
*
* Tutorial sketch for use of character OLED slim display family by Newhaven with Arduino Uno, without
* using any library. Models: NHD0420CW-Ax3, NHD0220CW-Ax3, NHD0216CW-Ax3. Controller: US2066
* in this example, the display is connected to Arduino via SPI interface.
*
* Displays on the OLED alternately a 4-line message and a sequence of character "block".
* This sketch assumes the use of a 4x20 display; if different, modify the values of the two variables
* ROW_N e COLUMN_N.
* The sketch uses the minimum possible of Arduino's pins; if you intend to use also /RES or /CS lines,
* the related instructions are already present, it's sufficient to remove the comment markers.
*
* The circuit:
* OLED pin 1 (Vss) to Arduino pin ground
* OLED pin 2 (VDD) to Arduino pin 5V
* OLED pin 3 (REGVDD) to Arduino pin 5V
* OLED pin 4 to 6 to Vss ground
* OLED pin 7 (SCLK) to Arduino pin D13 (SCK)
* OLED pin 8 (SID) to Arduino pin D11 (MOSI)
* OLED pin 9 (SOD) to Arduino pin D12 (MISO) (optional, can be not connected)
* OLED pin 10 to 14 to Vss ground
* OLED pin 15 (/CS) to Vss ground (or to Arduino pin D2, in case of use of more than one display)
* OLED pin 16 (/RES) to Arduino pin Reset or VDD 5V (or to Arduino pin D3, to control reset by sw)
* OLED pin 17 (BS0) to Vss ground
* OLED pin 18 (BS1) to Vss ground
* OLED pin 19 (BS2) to Vss ground
* OLED pin 20 (Vss) to Vss ground
*
* Original example created by Newhaven Display International Inc.
* Modified and adapted to Arduino Uno 30 Mar 2015 by Pasquale D'Antini
* Modified 19 May 2015 by Pasquale D'Antini
*
* This example code is in the public domain.
*/
const byte ROW_N = 4; // Number of display rows
const byte COLUMN_N = 20; // Number of display columns
//const byte CS = 2; // Arduino's pin assigned to the /CS line (optional, can be always low)
//const byte RES = 3; // Arduino's pin assigned to the Reset line (optional, can be always high)
const byte SCLK = 13; // Arduino's pin assigned to the SCLK line
const byte SDIN = 11; // Arduino's pin assigned to the SID line
//const byte SDOUT = 12; // Arduino's pin assigned to the SOD line (optional, can be not connected)
const byte TEXT[4][21] = {"1-Newhaven Display--",
"2-------Test--------",
"3-16/20-Characters--",
"4!@#$%^&*()_+{}[]<>?"}; // Strings to be displayed
byte new_line[4] = {0x80, 0xA0, 0xC0, 0xE0}; // DDRAM address for each line of the display
byte rows = 0x08; // Display mode: 1/3 lines or 2/4 lines; default 2/4 (0x08)
// _______________________________________________________________________________________
void command(byte c) // SUBROUTINE: PREPARES THE TRANSMISSION OF A COMMAND
{
byte i = 0; // Bit index
for(i=0; i<5; i++)
{
digitalWrite(SDIN, HIGH);
clockCycle();
}
for(i=0; i<3; i++)
{
digitalWrite(SDIN, LOW);
clockCycle();
}
send_byte(c); // Transmits the byte
}
// _______________________________________________________________________________________
void data(byte d) // SUBROUTINE: PREPARES THE TRANSMISSION OF A BYTE OF DATA
{
byte i = 0; // Bit index
for(i=0; i<5; i++)
{
digitalWrite(SDIN, HIGH);
clockCycle();
}
digitalWrite(SDIN, LOW);
clockCycle();
digitalWrite(SDIN, HIGH);
clockCycle();
digitalWrite(SDIN, LOW);
clockCycle();
send_byte(d); // Transmits the byte
}
// _______________________________________________________________________________________
void send_byte(byte tx_b) // SUBROUTINE: SEND TO THE DISPLAY THE BYTE IN tx_b
{
byte i = 0; // Bit index
for(i=0; i<4; i++)
{
if((tx_b & 0x01) == 1)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
clockCycle();
tx_b = tx_b >> 1;
}
for(i=0; i<4; i++)
{
digitalWrite(SDIN, LOW);
clockCycle();
}
for(i=0; i<4; i++)
{
if((tx_b & 0x1) == 0x1) // <------- Change
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
clockCycle();
tx_b = tx_b >> 1;
}
for(i=0; i<4; i++)
{
digitalWrite(SDIN, LOW);
clockCycle();
}
}
// _______________________________________________________________________________________
void clockCycle(void) // SUBROUTINE: EXECUTE THE CLOCK SIGNAL CYCLE
{
// digitalWrite(CS, LOW); // Sets LOW the /CS line of the display (optional, can be always low)
// delayMicroseconds(1); // Waits 1 us (required for timing purpose)
digitalWrite(SCLK, LOW); // Sets LOW the SCLK line of the display
delayMicroseconds(1); // Waits 1 us (required for timing purpose)
digitalWrite(SCLK, HIGH); // Sets HIGH the SCLK line of the display
delayMicroseconds(1); // Waits 1 us (required for timing purpose)
// delayMicroseconds(1); // Waits 1 us (required for timing purpose)
// digitalWrite(CS, HIGH); // Sets HIGH the /CS line of the display (optional, can be always low)
}
// _______________________________________________________________________________________
void output(void) // SUBROUTINE: DISPLAYS THE FOUR STRINGS, THEN THE SAME IN REVERSE ORDER
{
byte r = 0; // Row index
byte c = 0; // Column index
command(0x01); // Clears display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(TEXT[r][c]); // displays the correspondig string
}
}
delay(2000); // Waits, only for visual effect purpose
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(TEXT[3-r][c]); // displays the correspondig string (in reverse order)
}
}
}
// _______________________________________________________________________________________
void blocks(void) // SUBROUTINE: FILLS THE ENTIRE DISPLAY WITH THE CHARACTER "BLOCK"
{
byte r = 0; // Row index
byte c = 0; // Column index
command(0x01); // Clear display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(0xDB); // displays the character 0xDB (block)
delay(50); // Waits, only for visual effect purpose
}
delay(500); // Waits, only for visual effect purpose
}
}
// _______________________________________________________________________________________
void setup(void) // INITIAL SETUP
{
pinMode(SCLK, OUTPUT); // Initializes Arduino pin for the SCLK line
digitalWrite(SCLK, HIGH); // Sets HIGH the SCLK line of the display
pinMode(SDIN, OUTPUT); // Initializes Arduino pin for the SDIN line
digitalWrite(SDIN, LOW); // Sets LOW the SDIN line of the display
// pinMode(SDOUT, INPUT); // Initializes Arduino pin for the SDOUT line (optional, can be not connected)
// pinMode(CS, OUTPUT); // Initializes Arduino pin for the /CS line (optional)
// digitalWrite(CS, HIGH); // Sets HIGH the /CS line of the display (optional, can be always low)
// pinMode(RES, OUTPUT); // Initializes Arduino pin for the Reset line (optional)
// digitalWrite(RES, HIGH); // Sets HIGH the Reset line of the display (optional, can be always high)
delayMicroseconds(200); // Waits 200 us for stabilization purpose
if (ROW_N == 2 || ROW_N == 4)
rows = 0x08; // Display mode: 2/4 lines
else
rows = 0x00; // Display mode: 1/3 lines
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x71); // Function selection A:
data(0x5C); // enable internal Vdd regulator at 5V I/O mode (def. value) (0x00 for disable, 2.8V I/O)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x08); // Display ON/OFF control: display off, cursor off, blink off (default values)
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xD5); // Set display clock divide ratio/oscillator frequency:
command(0x70); // divide ratio=1, frequency=7 (default values)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
if (ROW_N > 2)
command(0x09); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 3/4 lines
else
command(0x08); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 1/2 lines
command(0x06); // Entry Mode set - COM/SEG direction: COM0->COM31, SEG99->SEG0 (BDC=1, BDS=0)
command(0x72); // Function selection B:
data(0x0A); // ROM/CGRAM selection: ROM C, CGROM=250, CGRAM=6 (ROM=10, OPR=10)
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xDA); // Set SEG pins hardware configuration:
command(0x10); // alternative odd/even SEG pin, disable SEG left/right remap (default values)
command(0xDC); // Function selection C:
command(0x00); // internal VSL, GPIO input disable
command(0x81); // Set contrast control:
command(0x7F); // contrast=127 (default value)
command(0xD9); // Set phase length:
command(0xF1); // phase2=15, phase1=1 (default: 0x78)
command(0xDB); // Set VCOMH deselect level:
command(0x40); // VCOMH deselect level=1 x Vcc (default: 0x20=0,77 x Vcc)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x01); // Clear display
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
command(0x80); // Set DDRAM address 0x00 in address counter (cursor home) (default value)
command(0x0C); // Display ON/OFF control: display ON, cursor off, blink off
delay(250); // Waits 250 ms for stabilization purpose after display on
if (ROW_N == 2)
new_line[1] = 0xC0; // DDRAM address for each line of the display (only for 2-line mode)
}
// _______________________________________________________________________________________
void loop(void) // MAIN PROGRAM
{
output(); // Execute subroutine "output"
delay(2000); // Waits, only for visual effect purpose
blocks(); // Execute subroutine "blocks"
delay(2000); // Waits, only for visual effect purpose
}« Last Edit: May 19, 2015, 04:40:59 AM »0 -
Thanks for sharing your code! As for your question in your 3rd tutorial, try changing the value after command DA is sent to 0x10 instead of 0x00.
;)
0 -
Thank you very much, Michael.
I did so many tests and attempts that I didn't see I had swapped two lines
Code fixed and post updated.
Thanks again.« Last Edit: April 22, 2015, 04:09:02 PM »0 -
can you share your display pinout.
I have yet to get my display to work.
I have another i2c display working from the same tutorial from another mfg, so something must be right.0 -
The complete pinout is reported in the comment text at the beginning of each tutorial.
The examples are all tested with two Newhaven display.0 -
thanks! too many sleepless nights!
0 -
Thanks for the great work on this. Just got it running tonight. I'm trying to change the brightness of the display, tried changing the contrast value, (0x7F is the default) but it doesn't seem to have any effect; am I missing something else?
0 -
Please try this code, let me know if the contrast changes.
https://github.com/NewhavenDisplay/NHD_US2066//---------------------------------------------------------
/*
NHD_0216AW_XB3.ino
Program for writing to Newhaven Display Slim OLEDs based on US2066 controller.
Pick one up today in the Newhaven Display shop!
------> http://www.newhavendisplay.com/oled-slim-character-oleds-c-119_825.html
This code is written for the Arduino Mega.
Copyright (c) 2015 - Newhaven Display International, LLC.
Newhaven Display invests time and resources providing this open source code,
please support Newhaven Display by purchasing products from Newhaven Display!
*/
//---------------------------------------------------------
#include <SPI.h>
#include <Arduino.h>
#include <Wire.h>
#include <avr\io.h>
#include "NHD_US2066.h"
unsigned char text1[] = {" Please Support "};
unsigned char text2[] = {" Open-Source "};
unsigned char text3[] = {" Hardware & "};
unsigned char text4[] = {" Software !! "};
unsigned char text5[] = {"Newhaven Display"};
unsigned char text6[] = {" 2X16 Character "};
unsigned char text7[] = {" Slim Design "};
unsigned char text8[] = {"----------------"};
void output()
{
int i;
command(0x01);
delay(2);
for(i=0;i<16;i++){
data(text1[i]);
}
command(0xA0);
for(i=0;i<16;i++){
data(text2[i]);
}
delay(2000);
command(0x01);
delay(2);
for (i=0;i<16;i++){
data(text3[i]);
}
command(0xA0);
for (i=0;i<16;i++){
data(text4[i]);
}
delay(3500);
command(0x01);
delay(2);
for(i=0;i<16;i++){
data(text5[i]);
}
command(0xA0);
for(i=0;i<16;i++){
data(text6[i]);
}
delay(2000);
command(0x01);
delay(2);
for (i=0;i<16;i++){
data(text7[i]);
}
command(0xA0);
for (i=0;i<16;i++){
data(text8[i]);
}
}
void blocks()
{
int i;
command(0x01);
delay(2);
for(i=0;i<16;i++){
data(0x1F);
}
command(0xA0);
for(i=0;i<16;i++){
data(0x1F);
}
}
void setup()
{
init_oled();
}
void loop()
{
while(1)
{
//output();
blocks();
command(0x78);
command(0x2A);
command(0x79);
command(0x81); //set contrast control
command(0x01); //set contrast control
delay(2000);
command(0x81); //set contrast control
command(0xFF); //set contrast control
delay(2000);
}
}« Last Edit: December 06, 2016, 02:19:13 PM by Michael_L »0 -
In order for you to send the “Set Contrast Control” command RE and SD must be set to 1, please see the attachment.
E.g. The following commands set RE – SD to the appropriate values before setting the contrast.
command(0x78);
command(0x2A);
command(0x79);
I recommend you review the US2066 datasheet, this will give you a better understanding on how to send commands.https://newhavendisplay.com/content/app_notes/US2066.pdf
Hope this helps ;)
0 -
Appreciate the help on this one, but still having issues. I'm running the code in tutorial 1, I2C interface, 5v, Arduino Uno. Tried changing the contrast value in the code and it has no effect. Tried adding the code above and that has no effect either. Sometimes the display dims a little, but it's not consistent. I should be able to dim this right down to almost nothing. The most change in brightness I've seen is maybe from 100% to 80%. Was troubleshooting again tonight and now the display won't turn on. Ran an I2C Scanner sketch and can see the I2C address of 3C for the display, So it's communicating. Rechecked all input pins and they getting power and ground in the right places. Tried reloading Tutorial 1 sketch to no effect. Anyone have any ideas?
0 -
Hi,
Would you be able to post the code snipped of how you are adjusting the contrast?0 -
Hello all!
First of all I want to send out huge thanks to Pasquale for providing these examples, they made it very easy for me to get started with the 20x4 character OLED. However I noticed that the SPI example used bit banged software SPI, which is rather slow and filling the screen with characters take about 40 ms.
Not completely satisfied by this I decided change the implementation to use HW SPI. And after a few hours of struggling I finally got it working! It is also super fast. Filling the screen now takes slightly less than 1 ms, which is even faster then using the 4 bit 6800 interface (11 ms to fil the screen).
So, without more ado, here is the code for a HW SPI implementation./*
* Demo_NHD0420CW-Ax3_SPI_HW.ino
*
* Tutorial sketch for use of character OLED slim display family by Newhaven with Arduino Uno, without
* using any library. Models: NHD0420CW-Ax3, NHD0220CW-Ax3, NHD0216CW-Ax3. Controller: US2066
* in this example, the display is connected to Arduino via SPI interface.
*
* Displays on the OLED alternately a 4-line message and a sequence of character "block".
* This sketch assumes the use of a 4x20 display; if different, modify the values of the two variables
* ROW_N e COLUMN_N.
* The sketch uses the minimum possible of Arduino's pins; if you intend to use also /RES or /CS lines,
* the related instructions are already present, it's sufficient to remove the comment markers.
*
* The circuit:
* OLED pin 1 (Vss) to Arduino pin ground
* OLED pin 2 (VDD) to Arduino pin 5V
* OLED pin 3 (REGVDD) to Arduino pin 5V
* OLED pin 4 to 6 to Vss ground
* OLED pin 7 (SCLK) to Arduino pin D13 (SCK)
* OLED pin 8 (SID) to Arduino pin D11 (MOSI)
* OLED pin 9 (SOD) to Arduino pin D12 (MISO) (optional, can be not connected)
* OLED pin 10 to 14 to Vss ground
* OLED pin 15 (/CS) to Vss ground (or to Arduino pin D2, in case of use of more than one display)
* OLED pin 16 (/RES) to Arduino pin Reset or VDD 5V (or to Arduino pin D3, to control reset by sw)
* OLED pin 17 (BS0) to Vss ground
* OLED pin 18 (BS1) to Vss ground
* OLED pin 19 (BS2) to Vss ground
* OLED pin 20 (Vss) to Vss ground
*
* Original example created by Newhaven Display International Inc.
* Modified and adapted to Arduino Uno 30 Mar 2015 by Pasquale D'Antini
* Modified 19 May 2015 by Pasquale D'Antini
* Modified to use hardware SPI 1 April 2016 by Joakim Sandström
*
* This example code is in the public domain.
*/
// inslude the SPI library:
#include <SPI.h>
const byte ROW_N = 4; // Number of display rows
const byte COLUMN_N = 20; // Number of display columns
//const byte RES = 3; // Arduino's pin assigned to the Reset line (optional, can be always high)
const byte TEXT[4][21] = {"1-Newhaven Display--",
"2-------Test--------",
"3-16/20-Characters--",
"4!@#$%^&*()_+{}[]<>?"
}; // Strings to be displayed
byte new_line[4] = {0x80, 0xA0, 0xC0, 0xE0}; // DDRAM address for each line of the display
byte rows = 0x08; // Display mode: 1/3 lines or 2/4 lines; default 2/4 (0x08)
// _______________________________________________________________________________________
void command(byte c) // SUBROUTINE: PREPARES THE TRANSMISSION OF A COMMAND
{
SPI.transfer(0x1F);
send_byte(c); // Transmits the byte
}
// _______________________________________________________________________________________
void data(byte d)
{
SPI.transfer(0x5F);
send_byte(d);
}
// _______________________________________________________________________________________
void send_byte(byte tx_b)
{
//Split the bytes into two and pad the last four bits with 0s
byte tx_b1 = tx_b & 0x0F;
byte tx_b2 = (tx_b >> 4) & 0x0F;
//Or together the bytes
int tx_int = (tx_b2<<8)|tx_b1;
//transfer it
SPI.transfer16(tx_int);
}
// _______________________________________________________________________________________
void output(void) // SUBROUTINE: DISPLAYS THE FOUR STRINGS, THEN THE SAME IN REVERSE ORDER
{
unsigned long lastTime = 0;
unsigned long temp;
byte r = 0; // Row index
byte c = 0; // Column index
command(0x01); // Clears display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r = 0; r < ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c = 0; c < COLUMN_N; c++) // One character at a time,
{
data(TEXT[r][c]); // displays the correspondig string
}
}
delay(2000); // Waits, only for visual effect purpose
lastTime = millis();
for (r = 0; r < ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c = 0; c < COLUMN_N; c++) // One character at a time,
{
data(TEXT[3 - r][c]); // displays the correspondig string (in reverse order)
}
}
temp = millis() - lastTime;
Serial.println(temp);
}
// _______________________________________________________________________________________
void blocks(void) // SUBROUTINE: FILLS THE ENTIRE DISPLAY WITH THE CHARACTER "BLOCK"
{
byte r = 0; // Row index
byte c = 0; // Column index
command(0x01); // Clear display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r = 0; r < ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c = 0; c < COLUMN_N; c++) // One character at a time,
{
data(0xDB); // displays the character 0xDB (block)
delay(50); // Waits, only for visual effect purpose
}
delay(500); // Waits, only for visual effect purpose
}
}
// _______________________________________________________________________________________
void setup(void) // INITIAL SETUP
{
// pinMode(RES, OUTPUT); // Initializes Arduino pin for the Reset line (optional)
// digitalWrite(RES, HIGH); // Sets HIGH the Reset line of the display (optional, can be always high)
SPI.begin();
SPI.setBitOrder(LSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setDataMode(SPI_MODE3);
delayMicroseconds(200); // Waits 200 us for stabilization purpose
if (ROW_N == 2 || ROW_N == 4)
rows = 0x08; // Display mode: 2/4 lines
else
rows = 0x00; // Display mode: 1/3 lines
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x71); // Function selection A:
data(0x5C); // enable internal Vdd regulator at 5V I/O mode (def. value) (0x00 for disable, 2.8V I/O)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x08); // Display ON/OFF control: display off, cursor off, blink off (default values)
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xD5); // Set display clock divide ratio/oscillator frequency:
command(0x70); // divide ratio=1, frequency=7 (default values)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
if (ROW_N > 2)
command(0x09); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 3/4 lines
else
command(0x08); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 1/2 lines
command(0x06); // Entry Mode set - COM/SEG direction: COM0->COM31, SEG99->SEG0 (BDC=1, BDS=0)
command(0x72); // Function selection B:
data(0x0A); // ROM/CGRAM selection: ROM C, CGROM=250, CGRAM=6 (ROM=10, OPR=10)
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xDA); // Set SEG pins hardware configuration:
command(0x10); // alternative odd/even SEG pin, disable SEG left/right remap (default values)
command(0xDC); // Function selection C:
command(0x00); // internal VSL, GPIO input disable
command(0x81); // Set contrast control:
command(0x7F); // contrast=127 (default value)
command(0xD9); // Set phase length:
command(0xF1); // phase2=15, phase1=1 (default: 0x78)
command(0xDB); // Set VCOMH deselect level:
command(0x40); // VCOMH deselect level=1 x Vcc (default: 0x20=0,77 x Vcc)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x01); // Clear display
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
command(0x80); // Set DDRAM address 0x00 in address counter (cursor home) (default value)
command(0x0C); // Display ON/OFF control: display ON, cursor off, blink off
delay(250); // Waits 250 ms for stabilization purpose after display on
if (ROW_N == 2)
new_line[1] = 0xC0; // DDRAM address for each line of the display (only for 2-line mode)
Serial.begin(115200); //For performance measurement
}
// _______________________________________________________________________________________
void loop(void) // MAIN PROGRAM
{
output(); // Execute subroutine "output"
delay(2000); // Waits, only for visual effect purpose
blocks(); // Execute subroutine "blocks"
delay(2000); // Waits, only for visual effect purpose
}0 -
Hi
Can anyone help me test this code, simply don't have the 2 OLED displays hardware do to it right now.
Transactional SPI setup with 2 NHD0420CW-Ax3 OLED displays.
1st OLED running on 8MHz.
2nd OLED running on 4MHz./*
* Demo_NHD0420CW-Ax3_SPI_HW.ino
*
* Tutorial sketch for use of character OLED slim display family by Newhaven with Arduino Uno, with
* using HW SPI library. Models: NHD0420CW-Ax3, NHD0220CW-Ax3, NHD0216CW-Ax3. Controller: US2066
* in this example, the display is connected to Arduino via SPI interface.
*
* Displays on the OLED alternately a 4-line message and a sequence of character "block".
* This sketch assumes the use of a 4x20 display; if different, modify the values of the two variables
* ROW_N e COLUMN_N.
* The sketch uses the minimum possible of Arduino's pins; if you intend to use also /RES or /CS lines,
* the related instructions are already present, it's sufficient to remove the comment markers.
*
* The circuit:
* OLED pin 1 (Vss) to Arduino pin ground
* OLED pin 2 (VDD) to Arduino pin 5V
* OLED pin 3 (REGVDD) to Arduino pin 5V
* OLED pin 4 to 6 to Vss ground
* OLED pin 7 (SCLK) to Arduino pin D13 (SCK)
* OLED pin 8 (SID) to Arduino pin D11 (MOSI)
* OLED pin 9 (SOD) to Arduino pin D12 (MISO) (optional, can be not connected)
* OLED pin 10 to 14 to Vss ground
* OLED pin 15 (/CS) to Vss ground (or to Arduino Pin D10(1st device) ~ Pin D9(2nd device), in case of use of more than one display)
* OLED pin 16 (/RES) to Arduino pin Reset or VDD 5V (or to Arduino pin D3, to control reset by sw)
* OLED pin 17 (BS0) to Vss ground
* OLED pin 18 (BS1) to Vss ground
* OLED pin 19 (BS2) to Vss ground
* OLED pin 20 (Vss) to Vss ground
*
* Original example created by Newhaven Display International Inc.
* Modified and adapted to Arduino Uno 30 Mar 2015 by Pasquale D'Antini
* Modified 19 May 2015 by Pasquale D'Antini
* Modified to use hardware SPI 1 April 2016 by Joakim Sandström
* HW SPI transaction 3 April 2016 by Cris O.
*
* This example code is in the public domain.
*/
// inslude the SPI library:
#include <SPI.h>
/*
* The SPI protocol allows for a range of transmission speeds ranging from 1Mhz to 100MHz.
* SPI slaves vary in the maximum speed at which they can reliably work.
* For a SPI chip rated up to 20 MHz, use 20000000.
* NOTE:
* Arduino Pro Mini (3.3 V / 8MHz) can only have SPI at 4 MHz as fastest speed, 1/2 the system clock speed.
* Arduino UNO (5 V / 16MHz) can only have SPI at 8 MHz as fastest speed, 1/2 the system clock speed.
*/
// Transactional SPI configuration
// Set up SPI transaction method for all devices
// Set up the speed, data order and data mode
SPISettings NHD0420CW_A(8000000, LSBFIRST, SPI_MODE3); // 8 MHz
SPISettings NHD0420CW_B(4000000, LSBFIRST, SPI_MODE3); // 4 MHz
/* Multiple SPI devices use the same SPI SCK, MISO and MOSI signals but each device will need it's own SS pin. */
// set the Slave Select Pins, using two SPI devices, A and B.
const int CS_A_Pin = 10; // (1st device)
const int CS_B_Pin = 9; // (2nd device)
/* Slave Select Signal:
* Any digital pin can be used for a SS (slave select) signal.
* The SPI library does not control the SS signals,
* because devices differ on when this is used,
* whether it is held low for multiple transfers or for each individual transfer,
* and so on. Control SS with digitalWrite().
* However, the SS pin must either be configured as an output,
* or if it is an input, it must remain low during the SPI transfer.
* Unconfigured pins default to input, and a pin with no signal can easily "float"
* to random voltages due to electrical noise.
* Always configure the SS pin as an output, or make sure it remains low.
*
* Most SPI devices are designed to work together with others,
* where SCK, MISO, and MOSI are shared. Each chip needs a separate SS signal.
* Only the selected chip will communicate. The others ignore SCK and MOSI,
* and avoid driving MISO when they are not selected.
*/
//const byte RES = 3; // Arduino's pin assigned to the Reset line (optional, can be always high)
// 1ST OLED
const byte ROW_N_1 = 4; // Number of display rows
const byte COLUMN_N_1 = 20; // Number of display columns
const byte TEXT_1[4][21] = {"1-Newhaven Display--",
"2-------Test-Oled-1-",
"3-16/20-Characters--",
"4!@#$%^&*()_+{}[]<>?"
}; // Strings to be displayed
byte new_line_1[4] = {0x80, 0xA0, 0xC0, 0xE0}; // DDRAM address for each line of the display
byte rows_1 = 0x08; // Display mode: 1/3 lines or 2/4 lines; default 2/4 (0x08)
// 2ND OLED
const byte ROW_N_2 = 4; // Number of display rows
const byte COLUMN_N_2 = 20; // Number of display columns
const byte TEXT_2[4][21] = {"1-Newhaven Display--",
"2-------Test-Oled-2-",
"3-16/20-Characters--",
"4!@#$%^&*()_+{}[]<>?"
}; // Strings to be displayed
byte new_line_2[4] = {0x80, 0xA0, 0xC0, 0xE0}; // DDRAM address for each line of the display
byte rows_2 = 0x08; // Display mode: 1/3 lines or 2/4 lines; default 2/4 (0x08)
// __
void command(byte c, byte device) // SUBROUTINE: PREPARES THE TRANSMISSION OF A COMMAND
{
switch (device) {
case 1: // (1st device)
SPI.beginTransaction(NHD0420CW_A);
// take the CS pin low to select the chip:
digitalWrite (CS_A_Pin, LOW); /* (most chips use LOW during the transfer) */
SPI.transfer(0x1F);
send_byte(c); // Transmits the byte
// take the CS pin high to de-select the chip:
digitalWrite (CS_A_Pin, HIGH);
SPI.endTransaction();
break;
case 2: // (2nd device)
SPI.beginTransaction(NHD0420CW_B);
// take the CS pin low to select the chip:
digitalWrite (CS_B_Pin, LOW); /* (most chips use LOW during the transfer) */
SPI.transfer(0x1F);
send_byte(c); // Transmits the byte
// take the CS pin high to de-select the chip:
digitalWrite (CS_B_Pin, HIGH);
SPI.endTransaction();
break;
case 3:
Serial.println("Error No device 3 specified");
break;
default:
Serial.print("Error Unknown Device:");
Serial.println(device);
break;
}
}
// _______________________________________________________________________________________
void data(byte d, byte device)
{
switch (device) {
case 1: // (1st device)
SPI.beginTransaction(NHD0420CW_A);
// take the CS pin low to select the chip:
digitalWrite (CS_A_Pin, LOW);
SPI.transfer(0x5F);
send_byte(d);
// take the CS pin high to de-select the chip:
digitalWrite (CS_A_Pin, HIGH);
SPI.endTransaction();
break;
case 2: // (2nd device)
SPI.beginTransaction(NHD0420CW_B);
// take the CS pin low to select the chip:
digitalWrite (CS_B_Pin, LOW); /* (most chips use LOW during the transfer) */
SPI.transfer(0x5F);
send_byte(d);
// take the CS pin high to de-select the chip:
digitalWrite (CS_B_Pin, HIGH);
SPI.endTransaction();
break;
case 3:
Serial.println("Error No device 3 specified");
break;
default:
Serial.print("Error Unknown Device:");
Serial.println(device);
break;
}
}
// _______________________________________________________________________________________
void send_byte(byte tx_b)
{
//Split the bytes into two and pad the last four bits with 0s
byte tx_b1 = tx_b & 0x0F;
byte tx_b2 = (tx_b >> 4) & 0x0F;
//Or together the bytes
int tx_int = (tx_b2 << 8) | tx_b1;
//transfer it
SPI.transfer16(tx_int);
}
// _______________________________________________________________________________________
void output(byte device) // SUBROUTINE: DISPLAYS THE FOUR STRINGS, THEN THE SAME IN REVERSE ORDER
{
// 1ST OLED ---------------------------------------------------------------------------------------
if (device == 1) {
unsigned long lastTime1 = 0;
unsigned long temp1;
byte r1 = 0; // Row index
byte c1 = 0; // Column index
command(0x01, device); // Clears display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r1 = 0; r1 < ROW_N_1; r1++) // One row at a time,
{
command(new_line_1[r1], device); // moves the cursor to the first column of that line
for (c1 = 0; c1 < COLUMN_N_1; c1++) // One character at a time,
{
data(TEXT_1[r1][c1], device); // displays the correspondig string
}
}
delay(2000); // Waits, only for visual effect purpose
lastTime1 = millis();
for (r1 = 0; r1 < ROW_N_1; r1++) // One row at a time,
{
command(new_line_1[r1], device); // moves the cursor to the first column of that line
for (c1 = 0; c1 < COLUMN_N_1; c1++) // One character at a time,
{
data(TEXT_1[3 - r1][c1], device); // displays the correspondig string (in reverse order)
}
}
temp1 = millis() - lastTime1;
Serial.print("OLED 1: ");
Serial.println(temp1);
}
// 2ND OLED -----------------------------------------------------------------------------------------
if (device == 2) {
unsigned long lastTime2 = 0;
unsigned long temp2;
byte r2 = 0; // Row index
byte c2 = 0; // Column index
command(0x01, device); // Clears display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r2 = 0; r2 < ROW_N_2; r2++) // One row at a time,
{
command(new_line_2[r2], device); // moves the cursor to the first column of that line
for (c2 = 0; c2 < COLUMN_N_2; c2++) // One character at a time,
{
data(TEXT_2[r2][c2], device); // displays the correspondig string
}
}
delay(2000); // Waits, only for visual effect purpose
lastTime2 = millis();
for (r2 = 0; r2 < ROW_N_2; r2++) // One row at a time,
{
command(new_line_2[r2], device); // moves the cursor to the first column of that line
for (c2 = 0; c2 < COLUMN_N_2; c2++) // One character at a time,
{
data(TEXT_2[3 - r2][c2], device); // displays the correspondig string (in reverse order)
}
}
temp2 = millis() - lastTime2;
Serial.print("OLED 2: ");
Serial.println(temp2);
}
}
// _______________________________________________________________________________________
void blocks(byte device) // SUBROUTINE: FILLS THE ENTIRE DISPLAY WITH THE CHARACTER "BLOCK"
{
// 1ST OLED ---------------------------------------------------------------------------------------
if (device == 1) {
byte r1 = 0; // Row index
byte c1 = 0; // Column index
command(0x01, device); // Clear display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r1 = 0; r1 < ROW_N_1; r1++) // One row at a time,
{
command(new_line_1[r1], device); // moves the cursor to the first column of that line
for (c1 = 0; c1 < COLUMN_N_1; c1++) // One character at a time,
{
data(0xDB, device); // displays the character 0xDB (block)
delay(50); // Waits, only for visual effect purpose
}
delay(500); // Waits, only for visual effect purpose
}
}
// 2ND OLED -----------------------------------------------------------------------------------------
if (device == 2) {
byte r2 = 0; // Row index
byte c2 = 0; // Column index
command(0x01, device); // Clear display (and cursor home)
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r2 = 0; r2 < ROW_N_2; r2++) // One row at a time,
{
command(new_line_2[r2], device); // moves the cursor to the first column of that line
for (c2 = 0; c2 < COLUMN_N_2; c2++) // One character at a time,
{
data(0xDB, device); // displays the character 0xDB (block)
delay(50); // Waits, only for visual effect purpose
}
delay(500); // Waits, only for visual effect purpose
}
}
}
// _______________________________________________________________________________________
void setup(void) // INITIAL SETUP
{
// pinMode(RES, OUTPUT); // Initializes Arduino pin for the Reset line (optional)
// digitalWrite(RES, HIGH); // Sets HIGH the Reset line of the display (optional, can be always high)
// set the Slave Select Pins as outputs:
pinMode (CS_A_Pin, OUTPUT); // Pin 10
pinMode (CS_B_Pin, OUTPUT); // Pin 9, optional 2ND device.
// initialize SPI:
SPI.begin();
/* Deprecated SPI configuration
Used by older versions of the SPI library, this method was not interrupt safe and
depended on your sketch doing low-level SPI configuration management.
SPI.setBitOrder(LSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setDataMode(SPI_MODE3);
*/
delayMicroseconds(200); // Waits 200 us for stabilization purpose
OledInit(1); // OLED init (1st device)
OledInit(2); // OLED init (2nd device)
Serial.begin(115200); //For performance measurement
}
// _______________________________________________________________________________________
void OledInit(byte device)
{
// OLED init
// 1ST OLED
if (ROW_N_1 == 2 || ROW_N_1 == 4)
rows_1 = 0x08; // Display mode: 2/4 lines
else
rows_1 = 0x00; // Display mode: 1/3 lines
// 2ND OLED
if (ROW_N_2 == 2 || ROW_N_2 == 4)
rows_2 = 0x08; // Display mode: 2/4 lines
else
rows_2 = 0x00; // Display mode: 1/3 lines
if (device == 1) {
command(0x22 | rows_1, device); // Function set: extended command set (RE=1), lines #
command(0x71, device); // Function selection A:
data(0x5C, device); // enable internal Vdd regulator at 5V I/O mode (def. value) (0x00 for disable, 2.8V I/O)
command(0x20 | rows_1, device); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x08, device); // Display ON/OFF control: display off, cursor off, blink off (default values)
command(0x22 | rows_1, device); // Function set: extended command set (RE=1), lines #
command(0x79, device); // OLED characterization: OLED command set enabled (SD=1)
command(0xD5, device); // Set display clock divide ratio/oscillator frequency:
command(0x70, device); // divide ratio=1, frequency=7 (default values)
command(0x78, device); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
if (ROW_N_1 > 2)
command(0x09, device); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 3/4 lines
else
command(0x08, device); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 1/2 lines
command(0x06, device); // Entry Mode set - COM/SEG direction: COM0->COM31, SEG99->SEG0 (BDC=1, BDS=0)
command(0x72, device); // Function selection B:
data(0x0A, device); // ROM/CGRAM selection: ROM C, CGROM=250, CGRAM=6 (ROM=10, OPR=10)
command(0x79, device); // OLED characterization: OLED command set enabled (SD=1)
command(0xDA, device); // Set SEG pins hardware configuration:
command(0x10, device); // alternative odd/even SEG pin, disable SEG left/right remap (default values)
command(0xDC, device); // Function selection C:
command(0x00, device); // internal VSL, GPIO input disable
command(0x81, device); // Set contrast control:
command(0x7F, device); // contrast=127 (default value)
command(0xD9, device); // Set phase length:
command(0xF1, device); // phase2=15, phase1=1 (default: 0x78)
command(0xDB, device); // Set VCOMH deselect level:
command(0x40, device); // VCOMH deselect level=1 x Vcc (default: 0x20=0,77 x Vcc)
command(0x78, device); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
command(0x20 | rows_1 , device); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x01, device); // Clear display
delay(2); // After a clear display, a minimum pause of 1-2 ms is required
command(0x80, device); // Set DDRAM address 0x00 in address counter (cursor home) (default value)
command(0x0C, device); // Display ON/OFF control: display ON, cursor off, blink off
delay(250); // Waits 250 ms for stabilization purpose after display on
}
if (device == 2) {
command(0x22 | rows_2, device); // Function set: extended command set (RE=1), lines #
/*i had to remove the comments cause of
The message exceeds the maximum allowed length (20000 characters).*/
command(0x71, device);
data(0x5C, device);
command(0x20 | rows_2, device);
command(0x08, device);
command(0x22 | rows_2, device);
command(0x79, device);
command(0xD5, device);
command(0x70, device);
command(0x78, device);
if (ROW_N_2 > 2)
command(0x09, device);
else
command(0x08, device);
command(0x06, device);
command(0x72, device);
data(0x0A, device);
command(0x79, device);
command(0xDA, device);
command(0x10, device);
command(0xDC, device);
command(0x00, device);
command(0x81, device);
command(0x7F, device);
command(0xD9, device);
command(0xF1, device);
command(0xDB, device);
command(0x40, device);
command(0x78, device);
command(0x20 | rows_2 , device);
command(0x01, device);
delay(2);
command(0x80, device);
command(0x0C, device);
delay(250);
}
if (ROW_N_1 == 2)
new_line_1[1] = 0xC0;
if (ROW_N_2 == 2)
new_line_2[1] = 0xC0;
}
// _______________________________________________________________________________________
void loop(void) // MAIN PROGRAM
{
output(1); // OLED 1 Execute subroutine "output"
output(2); // OLED 2
delay(2000); // Waits, only for visual effect purpose
blocks(1); // OLED 1 Execute subroutine "blocks"
blocks(2); // OLED 2
delay(2000); // Waits, only for visual effect purpose
}0 -
Awesome, thanks for sharing your code!
0 -
Hi all,
I'm hoping someone might be able to assist. I have just hooked up a new NHD-0420CW-AG3 display to Arduino uno (compatible) and uploaded the I2C code directly from 'oldmaker' first post. Works fine, except for screen banding. The very first time the code was uploaded the screen had three vertical bands, which reduced to one after about 5 minutes. Now there is consistently two vertical bands, one at character 9 and the other at character 16.
I've also tried this with SPI code - same two vertical bands at the same position.
So, firstly, is this a software or hardware issue?
If software (somewhere in the initialization perhaps?), can someone assist in diagnosing the issue?
When replying please keep in mind that I am a relatively new hobbyist with only basic coding knowledge. Complex responses will baffle my underqualified brain!0 -
This sounds like it could be a hardware issue, would it be possible to post a picture of what you have on your display?
0 -
After 3 days pouring over the US2066 datasheet I've made a few 'tweaks' to the code - and have made huge leaps in understanding what the code is doing. I now don't seem to have any banding. I'm not really confident my changes did a whole lot, they seem quite minor.
All changes occurred in the initialisation as follows:
command(0x7F) --> command(0xFF); - increases contrast
command(0x40) --> command(0x30); - reduces Vcomh to 0.83, though I'm a little fuzzy as to what this does
I've also changed:
data(0x5C) --> data(0x00) - I want to run of 3.3v rather than 5v. I hope this is correct?0 -
oh, I also changed the bitwise operator and removed the 'if' statement that set the number of rows. :
command(0x22 | 0x08) --> command(0x2A);
Again, I can't see how this should have changed anything!0
Please sign in to leave a comment.
Comments
20 comments