Difficulty configuring NHD-0220CW-AB3 for new product
Using code similar to NHD example, to drive display via SPI from Arduino Mini Pro. All characters display as mirrored left/right, and the characters from output() function are not always the same. Also concerning is that a lot of the config commands don't seem to cause any change. Have played with many, but one example is the contrast setting - changing it to 0x01 or 0xFF appears to have no effect. All signals look good and as expected on scope (data stable during rising edge of clock, etc). Hopefully I'm just missing something obvious?
int SCLK = 13; //output to display - SCLK
int SDIN = 11; //output to display - MOSI
int SDOUT = 12; //input to Arduino - MISO
int SEL = 7; //output to display - /SEL
int RST = 9; //output to display - /RST
unsigned char text1[] = {"1234567890"};
unsigned char text2[] = {"ABCDEFGHIJ"};
void setup()
{
noInterrupts(); // added code to slow down system clock 1/4
CLKPR = _BV(CLKPCE); // changed SPI CLK from 12 to 48uS period (verified on scope)
CLKPR = 0x02; // yields SCLK of 48uS when 0x02, and 96uS when 0x03 (12uS when removed)
// so delay(1000) was originally 1000mS, will now be 4000mS when 0x02
// recall forearm board is 64uS when 0x02 (12MHz instead of 16MHz crystal)
interrupts();
pinMode(SEL, OUTPUT); // display chip select input
pinMode(RST, OUTPUT); // display reset input
pinMode(SCLK, OUTPUT); // display clock input
pinMode(SDIN, OUTPUT); // display data input
pinMode(SDOUT, INPUT); // display data output (not used)
digitalWrite(SEL, HIGH); // SEL is normally HIGH when not asserted
digitalWrite(RST, HIGH); // RST is normally HIGH when not asserted
digitalWrite(SCLK, HIGH); // SCLK is normally HIGH
digitalWrite(SDIN, LOW); // MOSI is normally LOW
digitalWrite(RST, LOW);
delay(40);
digitalWrite(RST, HIGH);
delay(40);
digitalWrite(SEL, LOW);
delay(40);
command(0x2A); delay(10); //function set (EXTENDED COMMAND SET)(RE = 1)(2-line display)
command(0x71); delay(10); //function selection A
data(0x5C); delay(10); //enable internal regulator for 5V I/O
command(0x28); delay(10); //function set (FUNDAMENTAL COMMAND SET)(RE = 0)(2-line display)
command(0x08); delay(10); //display off, cursor off, blink off
command(0x2A); delay(10); //function set (EXTENDED COMMAND SET)(RE = 1)(2-line display)
command(0x79); delay(10); //OLED COMMAND SET enabled (SD = 1)
command(0xD5); delay(10); //set display clock divide ratio/oscillator frequency
command(0x70); delay(10); //divide ratio = 1, oscillator frequency = 7 (defaults)
command(0x78); delay(10); //OLED command set disabled (SD = 0)
command(0x08); delay(10); //function set (EXTENDED COMMAND SET)(RE = 1)(5 dots)(B/W invert false)(2-line display)
command(0x07); delay(10); //entry mode set (COM0->COM31)(SEG0->SEG99)(BDC = 1)(BDS = 1)
command(0x72); delay(10); //function selection B
data(0x0A); delay(10); //ROM & CGRAM selection (ROM = 10)(OPR = 10)
command(0x79); delay(10); //OLED COMMAND SET enabled (SD = 1)
command(0xDA); delay(10); //set SEG pins hardware configuration
command(0x10); delay(10); //set SEG pins hardware configuration (disable SEG L/R remap)(alternative SEG pin config)(A5 = 0)(A4 = 1)
command(0xDC); delay(10); //function selection C
command(0x00); delay(10); //internal VSL, GPIO input disable (A7 = 0)(A1 = 0)(A0 = 0)
command(0x81); delay(10); //set contrast control
command(0x7F); delay(10); //contrast set to mid-level (half of 255)
command(0xD9); delay(10); //set phase length
command(0x78); delay(10); //default / POR setting //other examples use 0xF1
command(0xDB); delay(10); //set VCOMH deselect level
command(0x20); delay(10); //default / POR setting
command(0x78); delay(10); //OLED command set disabled (SD = 0)
command(0x28); delay(10); //function set (FUNDAMENTAL COMMAND SET)(RE = 0)(2-line display)
command(0x01); delay(10); //clear display
command(0x80); delay(10); //set DDRAM address to 0x00
command(0x0C); delay(100); //display ON (cursor off)(blink off)
}
void loop()
{
blocks();
delay(400);
output();
delay(400);
}
void output()
{
int i;
command(0x01);
delay(40);
for(i=0;i<20;i++){
data(text1[i]);
}
command(0xA0);
delay(40);
for(i=0;i<20;i++){
data(text2[i]);
}
}
void blocks()
{
int i;
command(0x01);
delay(40);
for(i=0;i<10;i++){
data(0x1F);
}
command(0xA0);
delay(40);
for(i=0;i<10;i++){
data(0x1E);
}
}
void command(unsigned char c)
{
unsigned char i, temp;
temp = 0xF8;
for(i=0;i<8;i++)
{
digitalWrite(SCLK, LOW);
if((temp&0x80)>>7==1)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
temp = temp << 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
if((c&0x01)==1)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
c = c >> 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
digitalWrite(SDIN, LOW);
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
if((c&0x10)==0x10)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
c = c >> 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
digitalWrite(SDIN, LOW);
digitalWrite(SCLK, HIGH);
}
delay(2);
}
void data(unsigned char d)
{
unsigned char i, temp;
temp = 0xFA;
for(i=0;i<8;i++)
{
digitalWrite(SCLK, LOW);
if((temp&0x80)>>7==1)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
temp = temp << 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
if((d&0x01)==1)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
d = d >> 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
digitalWrite(SDIN, LOW);
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
if((d&0x10)==0x10)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
d = d >> 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
digitalWrite(SDIN, LOW);
digitalWrite(SCLK, HIGH);
}
delay(2);
}
-
Hi Chad,
We are currently reviewing your code. Could you please confirm that BS0,BS1,BS2 are all connected to GND since you are interfacing in SPI?
0 -
Thank you - I have verified with a multimeter that BS0, BS1, BS2 (pins 17-19) are GND. Unused pins 4-6 and 10-14 are also GND per the datasheet.
The 5V supply was checked for voltage level and noise with an oscilloscope, no issues. Pin 9 (SDO) is not connected to anything. At power-up, RESET is asserted (low) for 160 milliseconds before going high with the current code.
I will get 1-2 more displays ordered, just in case there is something wrong with this particular unit.
Edit: forgot to add - 5V being applied to pins 2 and 3.
0 -
Hi Chad,
Thank you for confirming those pins for me. Could you please try the following initialization code?
command(0x2A); //function set (extended command set)
command(0x71); //function selection A
data(0x5C); // Set 5V on REGVDD
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
data(0x40); //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
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
delay(5);
command(0x80); //set DDRAM address to 0x00
command(0x0C); //display ON
delay(10); //delay0 -
I have pasted in your initialization code after commenting out the original (and also verified the copy/paste didn't miss anything). The display output has not changed from my earlier photos, with the exception of text moving from right to left instead of left to right (i.e. direction of address auto-incrementing).
This direction is easily changed with the "//COM SEG direction" command (RE =1), by using 0x07 versus 0x06 - so this is one of the commands that has the expected result. Note that characters are still mirrored.
Another display is expected here by end of week, so I will test that right away to see if it behaves differently. Thank you!
0 -
Hi Chad,
Thank you for trying that. After looking at your code closer it looks like there might be an issue on the command and data functions. Could you try the following functions instead. i have bold the 2 changes.
void command(unsigned char c)
{
unsigned char i, temp;
temp = 0xF8;
for(i=0;i<8;i++)
{
digitalWrite(SCLK, LOW);
if((temp&0x80)>>7==1)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
temp = temp << 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
if((c&0x01)==1)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
c = c >> 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
digitalWrite(SDIN, LOW);
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
if((c&0x01)==0x01)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
c = c >> 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
digitalWrite(SDIN, LOW);
digitalWrite(SCLK, HIGH);
}
delay(2);
}void data(unsigned char d)
{
unsigned char i, temp;
temp = 0xFA;
for(i=0;i<8;i++)
{
digitalWrite(SCLK, LOW);
if((temp&0x80)>>7==1)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
temp = temp << 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
if((d&0x01)==1)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
d = d >> 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
digitalWrite(SDIN, LOW);
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
if((d&0x01)==0x01)
{
digitalWrite(SDIN, HIGH);
}
else
{
digitalWrite(SDIN, LOW);
}
d = d >> 1;
digitalWrite(SCLK, HIGH);
}
for(i=0;i<4;i++)
{
digitalWrite(SCLK, LOW);
digitalWrite(SDIN, LOW);
digitalWrite(SCLK, HIGH);
}
delay(2);
}0 -
Much better, thank you!
I blindly copied that bug from the example code (link below) and failed to trace it out fully. This is what happens when a hardware engineer writes code.
0 -
Hi Chad,
I am glad you were able to get it working. Please let us know if you have any other questions
0
Please sign in to leave a comment.
Comments
7 comments