I have had some hangups trying to use multiple sparkfun micro led displays. using each display individually works fine, but when I go to use each display at the same time to display different data, only one display initiates and displays the logo and that is it. Using the SPI communication protocol, each display is connected to the shared SPI pins and connected to seperate CS,RST, and D/C pins. This is utilizing an arduino 2040 Connect. Should I be starting up the displays in a specific way…
Hi Shawn (@sfoyee ),
Can you share your code? How are you creating, beginning and updating the OLED instances? Individually, or as an array?
Best wishes,
Paul
The code is below, I believe that the problem may be with the sparkfun commands setting the CS pins. I measured it with a meter and when the code should be driving the CS pin low for the second display it does not and both pins remain high. I have gone through a couple different iterations of the code to manually drive the pins but have been unsuccesful. Thank you for the help.
#include <SPI.h>
#include <Wire.h>
#include <SFE_MicroOLED.h>
#include <Adafruit_MPL3115A2.h>
Adafruit_MPL3115A2 baro;
// Display 1 (Speed) pins
#define RST1 8
#define DC1 9
#define CS1 7
// Display 2 (Altitude) pins
#define RST2 15
#define DC2 14
#define CS2 16
MicroOLED oledSpeed(RST1, DC1, CS1);
MicroOLED oledAlt(RST2, DC2, CS2);
unsigned long prevSpeedUpdate = 0;
unsigned long prevAltUpdate = 0;
const unsigned long speedInterval = 400;
const unsigned long altInterval = 750;
float kmh = 0.0;
float altitude = 0;
void safeBegin(MicroOLED &display, uint8_t csPin) {
digitalWrite(CS1, HIGH);
digitalWrite(CS2, HIGH);
digitalWrite(csPin, LOW);
delay(10);
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
display.begin();
SPI.endTransaction();
digitalWrite(csPin, HIGH);
delay(10);
}
void setup() {
Wire.begin();
pinMode(CS1, OUTPUT);
pinMode(CS2, OUTPUT);
digitalWrite(CS1, HIGH);
digitalWrite(CS2, HIGH);
SPI.begin();
// Safe display init
safeBegin(oledSpeed, CS1);
safeBegin(oledAlt, CS2);
oledSpeed.flipVertical(true);
oledSpeed.contrast(255);
digitalWrite(CS2, HIGH); // Ensure other CS is high
digitalWrite(CS1, LOW);
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
oledSpeed.clear(ALL);
oledSpeed.display();
SPI.endTransaction();
digitalWrite(CS1, HIGH);
oledAlt.flipVertical(true);
oledAlt.contrast(255);
digitalWrite(CS1, HIGH); // Ensure other CS is high
digitalWrite(CS2, LOW);
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
oledAlt.clear(ALL);
oledAlt.display();
SPI.endTransaction();
digitalWrite(CS2, HIGH);
if (!baro.begin()) {
digitalWrite(CS1, HIGH);
digitalWrite(CS2, LOW);
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
oledAlt.setCursor(0, 0);
oledAlt.print(“Altimeter Err”);
oledAlt.display();
SPI.endTransaction();
digitalWrite(CS2, HIGH);
while (1);
}
}
void loop() {
unsigned long currentTime = millis();
bool updateSpeed = false;
bool updateAlt = false;
if (currentTime - prevSpeedUpdate >= speedInterval) {
kmh += 1.3;
if (kmh >= 160.0) kmh = 0.0;
prevSpeedUpdate = currentTime;
updateSpeed = true;
}
if (currentTime - prevAltUpdate >= altInterval) {
altitude = baro.getAltitude() * 3.28084;
prevAltUpdate = currentTime;
updateAlt = true;
}
if (updateSpeed) {
float mph = kmh * 0.621371;
digitalWrite(CS2, HIGH); // disable other display
digitalWrite(CS1, LOW); // enable current display
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
oledSpeed.clear(PAGE);
oledSpeed.setFontType(2);
oledSpeed.setCursor(0, 0);
oledSpeed.print(mph, 1);
oledSpeed.setFontType(0);
oledSpeed.setCursor(45, 10);
oledSpeed.print("mph");
oledSpeed.display();
SPI.endTransaction();
digitalWrite(CS1, HIGH);
}
if (updateAlt) {
digitalWrite(CS1, HIGH); // disable other display
digitalWrite(CS2, LOW); // enable current display
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
oledAlt.clear(PAGE);
if (altitude >= 10000) oledAlt.setFontType(1);
else oledAlt.setFontType(2);
oledAlt.setCursor(0, 0);
oledAlt.print((int)altitude);
oledAlt.setFontType(0);
oledAlt.setCursor(45, 10);
oledAlt.print(“ft”);
oledAlt.display();
SPI.endTransaction();
digitalWrite(CS2, HIGH);
}
}
Thanks Shawn,
Just a quick reply (it’s late here)… Some comments that may help:
The way you’re wrapping (e.g.) display.begin()
inside an SPI Transaction is very unusual. I’ve never seen that before and may be the cause of your issues? Please comment all the additional beginTransaction
and endTransaction
.
You shouldn’t need to set the CS pin low manually. I recommend letting the library MicroOLED instance look after that. It will pull it low when needed. It will only pull it low momentarily; you will be able to catch it with a logic analyzer, but a multimeter is likely to be too slow.
Try and keep your code as close to the Library example as possible.
I hope this helps,
Paul
Thank you, I have have gone back to the drawing board and just modified the hello example from the library. I modified it to display the splash page on display 1 for 3 seconds then turn off for one second and repeat that a second time before trying to initialize the second display. I have included a significant wait before initializing the second display to avoid any timing issues but the second display never seems to initialize. I have pasted the updated code below, thank you for the help:
/******************************************************************************
MicroOLED_Hello.ino
SFE_MicroOLED Hello World Demo
Jim Lindblom @ SparkFun Electronics
Original Creation Date: October 26, 2014
This sketch lights up a familiar pattern on the MicroOLED
Breakout. It’s a great way to prove you’ve connected everything
correctly and that your display is in working order.
Hardware Connections:
We’ll be using the SPI interface on the MicroOLED, though it
also supports I2C (and a really messy parallel). If you want
to swap in I2C, read through the comments to find out how.
MicroOLED ------------- Arduino
GND ------------------- GND
VDD ------------------- 3.3V (VCC)
D1/MOSI ----------------- D11 (don't change)
D0/SCK ------------------ D13 (don't change)
D2
D/C ------------------- D8 (can be any digital pin)
RST ------------------- D9 (can be any digital pin)
CS ------------------- D10 (can be any digital pin)
Development environment specifics:
IDE: Arduino 1.0.5
Hardware Platform: MicroOLED Breakout
Arduino Pro 3.3V/8MHz
Note: The display on the MicroOLED is a 1.8V-3.3V device only.
Don’t try to connect a 5V Arduino directly to it! Use level
shifters in between the data signals if you have to resort to
a 5V board.
This code is beerware; if you see me (or any other SparkFun
employee) at the local, and you’ve found our code helpful,
please buy us a round!
Distributed as-is; no warranty is given.
*******************************************************************************/
#include <Wire.h> // Include Wire if you’re using I2C
#include <SPI.h> // Include SPI if you’re using SPI
#include <SFE_MicroOLED.h> // Include the SFE_MicroOLED library
//////////////////////////
// MicroOLED Definition //
//////////////////////////
#define PIN_RESET 8 // Connect RST to pin 9 (req. for SPI and I2C)
#define PIN_DC 9 // Connect DC to pin 8 (required for SPI)
#define PIN_CS 7 // Connect CS to pin 10 (required for SPI)
#define DC_JUMPER 0 // Set to either 0 (default) or 1 based on jumper, matching the value of the DC Jumper
// Also connect pin 13 to SCK and pin 11 to MOSI
#define PIN_RESET2 15 // Connect RST to pin 9 (req. for SPI and I2C)
#define PIN_DC2 14 // Connect DC to pin 8 (required for SPI)
#define PIN_CS2 16 // Connect CS to pin 10 (required for SPI)
#define DC_JUMPER2 0 // Set to either 0 (default) or 1 based on jumper, matching the value of the DC Jumper
// Also connect pin 13 to SCK and pin 11 to MOSI
//////////////////////////////////
// MicroOLED Object Declaration //
//////////////////////////////////
// Declare a MicroOLED object. The parameters include:
// 1 - Reset pin: Any digital pin
// 2 - D/C pin: Any digital pin (SPI mode only)
// 3 - CS pin: Any digital pin (SPI mode only, 10 recommended)
MicroOLED oled(PIN_RESET, PIN_DC, PIN_CS); //Example SPI declaration, comment out if using I2C
MicroOLED oled2(PIN_RESET2, PIN_DC2, PIN_CS2);
//MicroOLED oled(PIN_RESET, DC_JUMPER); //Example I2C declaration, uncomment if using I2C
// I2C is great, but will result in a much slower update rate. The
// slower framerate may be a worthwhile tradeoff, if you need more
// pins, though.
void setup()
{
delay(100);
//Wire.begin(); //set up I2C bus, uncomment if you are using I2C
// These three lines of code are all you need to initialize the
// OLED and print the splash screen.
// Before you can start using the OLED, call begin() to init
// all of the pins and configure the OLED.
oled.begin();
// clear(ALL) will clear out the OLED’s graphic memory.
// clear(PAGE) will clear the Arduino’s display buffer.
oled.clear(ALL); // Clear the display’s memory (gets rid of artifacts)
// To actually draw anything on the display, you must call the
// display() function.
oled.display();
delay (3000);
oled.command(DISPLAYOFF); // Turns display off (sleep)
delay (1000);
oled.command(DISPLAYON);
delay (3000);
oled.command(DISPLAYOFF); // Turns display off (sleep)
delay (1000);
oled2.begin();
oled2.clear(ALL);
oled2.display();
}
void loop()
{
}
Thank you Shawn (@sfoyee ),
I’m seeing the same issue. I’m using two 0.96" OLEDs and an ESP32 Thing Plus C, but the issue is the same: the first OLED displays correctly, the second is blank.
I’ve had a quick look through the library and I can’t see anything obvious. I’ll have to dig in further with a logic analyzer when time permits.
I have opened an issue for this on GitHub - link below. I’ll track it there.
Best wishes,
Paul
Hi Shawn (@sfoyee ),
Adafruit have an SSD1306 library which may help. Their SPI driver allows you to define the OLED width and height, so it should work OK with our 64x48 displays. I honestly don’t know if it supports multiple SPI displays, but it may be a faster solution for you than waiting for us to fix our library. I see that it has an option for software (bit-bang) SPI, so it’s likely to work just fine:
Adafruit_SSD1306(uint8_t w, uint8_t h, int8_t mosi_pin, int8_t sclk_pin,
int8_t dc_pin, int8_t rst_pin, int8_t cs_pin);
I hope this helps,
Paul
Thank you Paul, I will keep an eye out if you are able to find anything. Just another note, I went back to square one and tried using only one display and utilized different pins just to make sure there wasn’t anything on my end. When going to just run the demo_V13 code I noticed that the display would not show anything. I uploaded the hello and draw bitmap image examples and both displayed fine. Just an FYI, but utilizing a simple hello world code for the SSD1306 library seems to be working on one display for now. Again appreciate teh help. Let me know if you need any more information.
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 64 // SparkFun MicroOLED is 64x48
#define SCREEN_HEIGHT 48
// SPI pins
#define OLED_CS 7
#define OLED_DC 9
#define OLED_RESET 8
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
&SPI, OLED_DC, OLED_RESET, OLED_CS);
void setup() {
Serial.begin(9600);
// Wait for Serial Monitor
while (!Serial) { }
// Initialize display
if (!display.begin(SSD1306_SWITCHCAPVCC)) {
Serial.println(F(“SSD1306 allocation failed”));
for (;;); // Don’t proceed, loop forever
}
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 0); // Top-left corner
display.println(F(“Hello, world!”));
display.display();
}
void loop() {
// Nothing here
}