Arduino Micro and NHD27OLED display

I'm trying to get an NHD OLED display (specficially the NHD-2.7-12864UMY3) working with an Arduino micro and am having difficulties. I know others have been able to get this display working with other Arduino models. I'll get right to it - here's the schematic:

I have everything wired up on a breadboard (except the switches, LM34, and voltage divider going to A0), but the display won't turn on. I've checked all the appropriate voltages and everything looks good.

Any ideas? I've checked and triple checked the Micro documentation and the OLED display documentation and I can't see what I'm missing on the electrical side. I've tried leaving the RST line on the display open, tied to +3.3V, and set up as shown in the schematic. I've even put a 'scope on all the pins and everything appears as it should with nice clean DC +3.3V on the power pin and I can see data on the data pin.

For reference, here's the code loaded on the Micro for testing. I'm sure I've screwed up something here, too, but I don't think that would keep the OLED display from turning on.

#include <SPI.h>
#include <U8glib.h>

// This sketch is for an Arduino Micro based voltmeter and thermometer using an LM34
// connected to a NHD-2.7-12864UMY3 OLED 128x64 display.

// Setup the display driver
// U8GLIB_NHD27OLED_GR u8g(10, 9);   // U8GLIB_NHD27OLED_GR(cs, a0 [, reset]) 
// U8GLIB_NHD27OLED_GR u8g(13, 11, 10, 9);   // U8GLIB_NHD27OLED_GR(sck, mosi, cs, a0 [, reset]) 
// U8GLIB_NHD27OLED_2X_GR u8g(13, 11, 10, 9);   // U8GLIB_NHD27OLED_2X_GR(sck, mosi, cs, a0 [, reset])

// Arduino Micro Serial1 pins are different
// U8GLIB_NHD27OLED_2X_GR u8g(15, 16, 17, 9);   // U8GLIB_NHD27OLED_GR(sck, mosi, cs, a0 [, reset])
U8GLIB_NHD27OLED_2X_GR u8g(17, 9);   // U8GLIB_NHD27OLED_GR(cs, a0 [, reset])

int cnt = 0; // For testing

// SetContrast() stuff
int ContUpState = 0;
int ContDnState = 0;
int ContrastValue = 255; // Start the display at maximum contrast
const int ContrastMin = 50; // Minimum contrast we want to use - 0 is actual HW minimum
const int ContrastMax = 255; // Maximum contrast
const int ContrastStep = 5; // How much to change contrast with each push of the button
unsigned char ContUpPin = 4; // Push button to turn contrast up
unsigned char ContDnPin = 5; // Push button to turn contrast down

// DisplayVoltage() stuff
const int VM_NUM_SAMPLES = 10; // Number of readings to take to average out later
int VMsum = 0; // sum of samples taken
int VMsample_count = 0; // current sample number
unsigned char VMpin = A0; // Use pin A0 for input from 12V after voltage divider - don't exceed 5V actual
float VMvoltage = 0.00; // calculated voltage
float VMout = 0.00; // Voltage output
int VoltWidth = 0; // Width of the voltage reading in pixels
int VoltSpace = 0;

// DisplayTemp() stuff
unsigned char TempPin = A1; // Use pin A1 for input from LM34
int TempWidth = 0; // Width of the temperature reading in pixels
int TempSpace = 0;

void setup() {

  Serial1.begin(9600); // Arduino Micro uses Serial1 for hardware serial

  // Assign Pins
  pinMode(4, INPUT_PULLUP); // Push button to turn contrast up
  digitalWrite(4, HIGH);  // Turn on internal Pull-Up Resistor
  pinMode(5, INPUT_PULLUP); // Push button to turn contrast down
  digitalWrite(5, HIGH);  // Turn on internal Pull-Up Resistor
  pinMode(9, OUTPUT); // Data out to OLED display - SPI2_SI on NHD display
  pinMode(10, OUTPUT); // CS out to display
  // A0 - Input for DisplayVoltage()
  // A1 - Input for DisplayTemp()

  // Testing stuff
  u8g.begin();
  u8g.setContrast(255);
  u8g.setColorIndex(1);
  delay(5000);
  u8g.setColorIndex(0);
  delay(5000);
  u8g.setContrast(127);
  u8g.setColorIndex(1);
  delay(5000);
  u8g.setColorIndex(0);
  delay(5000);
  u8g.setContrast(255);
}

void DisplayVoltage() {
  // take a number of analog samples and add them up
  while (VMsample_count < VM_NUM_SAMPLES) {
    VMsum += analogRead(VMpin); // Read the voltage and add it to the previous readings
    VMsample_count++; // Increment the counter
    delay(10);
  }
  // Calculate the voltage
  // Use 5.0 for a 5.0V ADC reference voltage
  // 5.015V is the calibrated reference voltage
  VMvoltage = ((float)VMsum / (float)VM_NUM_SAMPLES * 5.015) / 1024.0;
  // Send voltage for display 
  // Voltage multiplied by 11 when using voltage divider that
  // divides by 11. 11.132 is the calibrated voltage divide
  // value
  VMout = VMvoltage * 11.132;

  VoltWidth = u8g.getStrWidth("VMout"); // How wide is the voltage reading in pixels
  VoltSpace = VoltWidth + 5; 
  u8g.setFontPosTop(); // Set 0,0 at upper left
  u8g.setFont(u8g_font_9x15Br); // Set the font - 9X15 bold
  u8g.setPrintPos(0, 30); // Start in the upper left corner
  u8g.print(VMout); // Print the voltage
  u8g.setFont(u8g_font_9x15r); // Set the font - 9x15 regular
  u8g.setPrintPos(VoltSpace, 30); // Set the position for the next line
  u8g.print("V"); // Print V next to the voltage reading

  // Reset the counter variables
  VMsample_count = 0; 
  VMsum = 0;
}

void DisplayTemp() {
  int rawvoltage = analogRead(TempPin); // Read the volage from the LM34 - 1.000V = 100 deg F
  float millivolts = (rawvoltage/1024.0) * 5000;
  float DegF = millivolts/10;

  TempWidth = u8g.getStrWidth("DegF"); // How wide is the temperature reading in pixels
  TempSpace = TempWidth + 5; 
  u8g.setFontPosTop(); // Set 0,0 at upper left
  u8g.setFont(u8g_font_9x15Br); // Set the font
  u8g.setPrintPos(63, 30); // Set the print position for the reading
  u8g.print(DegF); // Print the temperature
  u8g.setFont(u8g_font_9x15r); // Set the font 
  u8g.setPrintPos(TempSpace, 30); // Set the print position for the next line
  u8g.print("F"); // Print F next to the temp reading

  delay(1000); // wait 1 sec between updates
}

void SetContrast() {
  // Read the state of the contrast buttons
  ContUpState = digitalRead(ContUpPin);
  ContDnState = digitalRead(ContDnPin);

  // Check if one of the contrast buttons is pressed.
  // If it is, the button state is LOW
  if (ContUpState == LOW) { // Contrast up button is pushed
    if (ContrastValue >= ContrastMin) { // Check to make sure is not all the way down already
      ContrastValue == ContrastValue + ContrastStep; // Adjust the contrast up by one step
      u8g.setContrast(ContrastValue); // Send the new contrast value to the display
    }
  } 
  if (ContDnState == LOW) { // Contrast down button is pushed
    if (ContrastValue <= ContrastMax) { // Check to make sure is not all the way up already
      ContrastValue == ContrastValue - ContrastStep; // Adjust the contrast down by one step
      u8g.setContrast(ContrastValue); // Send the new contrast value to the display
    }
  }
}

// Testing only
void draw() {

  // graphic commands to redraw the complete screen should be placed here  
  u8g.setFont(u8g_font_6x12r);
  u8g.drawStr( 0, 15, "6X12r");
  // u8g.setFont(u8g_font_6x12Br);
  // u8g.drawStr( 63, 15, "6X12Br");
  u8g.setFont(u8g_font_9x15r);
  u8g.drawStr( 0, 30, "9X15r");
  u8g.setFont(u8g_font_9x15Br);
  u8g.drawStr( 63, 30, "9X15Br");
  u8g.setFont(u8g_font_9x18r);
  u8g.drawStr( 0, 50, "9X18r");
  u8g.setFont(u8g_font_9x18Br);
  u8g.drawStr( 63, 50, "9X18Br");
  u8g.setFont(u8g_font_10x20r);
  u8g.drawStr( 0, 63, "10X20r");
  //  u8g.setFont(u8g_font_10x20Br);
  //  u8g.drawStr( 63, 63, "10X20Br");
}

void loop()  {
  // picture loop
  u8g.firstPage();  
  do {
    draw(); // Testing only
  } 
  while( u8g.nextPage() );

  // rebuild the picture after some delay
  delay(1000);

  SetContrast();  // Screen Contrast Adjustment via push buttons

  //DisplayVoltage(); // Display vehicle voltage

  //DisplayTemp(); // Display ambient temperature
}

Anyone? Any ideas are appreciated.

Thanks!

Hi

There are some open questions, which makes it hard to verify your schematic. Is pin 17 or the Micro identical to the slave select?
Are the BSx lines set correctly (should be 4 wire SPI).
In principle it is also more reliable to start with the SW SPI constructor first:
U8GLIB_NHD27OLED_GR u8g(sck, mosi, cs, dc); // U8GLIB_NHD27OLED_GR(sck, mosi, cs, a0 [, reset])

Oliver

olikraus:
There are some open questions, which makes it hard to verify your schematic. Is pin 17 or the Micro identical to the slave select?

I'm not sure what you are asking here. Could you clarify? I used https://github.com/arduino/Arduino/blob/master/hardware/arduino/variants/micro/pins_arduino.h to identify the pins on the micro.

Are the BSx lines set correctly (should be 4 wire SPI).

Per the manufacturer's schematic, I believe so.

In principle it is also more reliable to start with the SW SPI constructor first:
U8GLIB_NHD27OLED_GR u8g(sck, mosi, cs, dc); // U8GLIB_NHD27OLED_GR(sck, mosi, cs, a0 [, reset])

Thanks, I'll try that!

Just an update that I got this resolved. To use this display on an Arduino Micro, the appropriate setting is:

U8GLIB_NHD27OLED_GR u8g(15, 16, 17, 9);   // U8GLIB_NHD27OLED_GR(sck, mosi, cs, a0 [, reset])

I haven't tried hardware SPI yet, but I don't have any reason to believe it won't work.

Thanks for reporting. Good to see that SW SPI is working.

Oliver

And I confirmed today that HW SPI works as well.