Code conflict between two libraries (Adafruit_SSD1306 and RF24)

In the same hardware configuration i have an oled screen and a RF radio, those work with the Adafruit library Adafruit_SSD1306 GitHub - adafruit/Adafruit_SSD1306: Arduino library for SSD1306 monochrome 128x64 and 128x32 OLEDs and the RF24 library GitHub - maniacbug/RF24: Arduino driver for nRF24L01.

Separately those two works ok, if I load just the code for the oled screen testing it works, if i load the code just for the rf modem testing it works, but if I initialize the RF modem and then the oled screen, just the modem starts and the screen remains black, no compiler errors.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

//RF DEFINITIONS
RF24 radio(9,10);
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
bool done = false;
char data_in[9];

//OLED DEFINITIONS
#define OLED_DC 6
#define OLED_CS 7
#define OLED_CLK 13
#define OLED_MOSI 11
#define OLED_RESET 8
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
#define LOGO16_GLCD_HEIGHT 16 
#define LOGO16_GLCD_WIDTH  16 


void setup () {
  Serial.begin(57600);
  printf_begin();
  
  //Radio config
  radio.begin();
  delay(1000);
  /*radio.setDataRate(RF24_250KBPS);
  radio.setChannel(1);
  radio.setRetries(15,15);
  radio.printDetails();
  radio.openReadingPipe(1,pipes[0]);
  radio.startListening();
  */
  
  //OLED CONFIG
  display.begin(SSD1306_SWITCHCAPVCC);

If I comment the line radio.begin the screen works, so im 100% sure there is a conflict between those two libraries, i checked the radio begin function but i dont see anything that could cause the problem:

void RF24::begin(void)
{
  // Initialize pins
  pinMode(ce_pin,OUTPUT);
  pinMode(csn_pin,OUTPUT);

  // Initialize SPI bus
  SPI.begin();

  ce(LOW);
  csn(HIGH);

  // Must allow the radio time to settle else configuration bits will not necessarily stick.
  // This is actually only required following power up but some settling time also appears to
  // be required after resets too. For full coverage, we'll always assume the worst.
  // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped.
  // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure.
  // WARNING: Delay is based on P-variant whereby non-P *may* require different timing.
  delay( 5 ) ;

  // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
  // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
  // sizes must never be used. See documentation for a more complete explanation.
  write_register(SETUP_RETR,(B0101 << ARD) | (B1111 << ARC));

  // Restore our default PA level
  setPALevel( RF24_PA_MAX ) ;

  // Determine if this is a p or non-p RF24 module and then
  // reset our data rate back to default value. This works
  // because a non-P variant won't allow the data rate to
  // be set to 250Kbps.
  if( setDataRate( RF24_250KBPS ) )
  {
    p_variant = true ;
  }
  
  // Then set the data rate to the slowest (and most reliable) speed supported by all
  // hardware.
  setDataRate( RF24_1MBPS ) ;

  // Initialize CRC and request 2-byte (16bit) CRC
  setCRCLength( RF24_CRC_16 ) ;
  
  // Disable dynamic payloads, to match dynamic_payloads_enabled setting
  write_register(DYNPD,0);

  // Reset current status
  // Notice reset and flush is the last thing we do
  write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );

  // Set up default configuration.  Callers can always change it later.
  // This channel should be universally safe and not bleed over into adjacent
  // spectrum.
  setChannel(76);

  // Flush buffers
  flush_rx();
  flush_tx();
}

What do you think?

I think all two module use SPI comunication. In RF24::begin you show a SPI.begin command and LCD you declare to use OLED_MOSI and MISO/MOSI are pin used for SPI comunication.

So I think you need to understand how to use multiple devices using SPI: http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Independent_slave_SPI_configuration

How have you connected the devices to the Arduino?

I know very well how SPI works, as I said the hardware works ok, the connections are right and the CS uses of course two different output pins.

RF for the rf modem and S for the screen connections

Stupid question, but if you invert in setup() the begin of RF24 and begin of LCD, now work lcd and not the RF24 ?

nid69ita: Stupid question, but if you invert in setup() the begin of RF24 and begin of LCD, now work lcd and not the RF24 ?

Already tried, the oled screen starts but when the RF config comes, the oled screen freezes, its like the signals from one peripheral are getting mixed with the other one, but im pretty sure the connections are correct...

Sorry, I’m not an expert using SPI.
But when signals are on cables, the device that need receive must be enabled using his CS pin, but the others devices need that their CS pins are disabled.

Maybe RF24 or both library keep his CS enabled ?

nid69ita: Maybe RF24 or both library keep his CS enabled ?

Thats actually a very good observation, i suppose they dont let the CS always on, will be very stupid, im gonna check it with my tester any way

they are always on :astonished:

It have to be something that im doing wrong, is not normal that i have to modify two libraries that use SPI just to make them work together

domingosl: they are always on :astonished:

:grin: :grin: :grin:

I think it's strange for an Adafruits library. Usually they are made in a very good way and thinked for any circumstance. For RF24 I think who create the library do test only with one SPI component.

P.S. sorry for my English.

Hi, any progress? I'm currently fighting with the same problem, so I'm really curious about any solution.

I have a the same problem…

The screen not work…

I used a Arduino Nano

Any solutions ?

#include <SPI.h>
#include <Wire.h>

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_MOSI 11
#define OLED_CLK 13
#define OLED_DC 7
#define OLED_CS 8
#define OLED_RESET 6
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

//GND: power ground
//VCC: 3.3v or 5.0V power supply
//D0: ClK
//D1: MOSI data
//RST: Reset
//DC: Data/Command
//CS: Chip select Port

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#include “nRF24L01.h”
#include “RF24.h”

#include “printf.h”

#include “DHT.h”
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

//#include <LiquidCrystal.h>
//LiquidCrystal lcd(3, 4, 5, 6, 7, 8);

//RF24 radio(9,10);//CE and CSN

byte addresses[6] = {“1Node”,“2Node”};

void setup(){

Serial.begin(57600);

printf_begin();
dht.begin();

//lcd.begin(16,2);

display.begin(SSD1306_SWITCHCAPVCC);
display.clearDisplay();

/*
radio.begin(); // Start up the radio
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.setRetries(15,15); // Max delay between retries & number of retries
radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(1,addresses[1]);
radio.stopListening();
radio.printDetails();
*/

}

void loop(void){

int h = dht.readHumidity();
int t = dht.readTemperature();

//delay(2000);

//lcd.setCursor(0,0);

//lcd.print("Temp: ");
//lcd.print(t);
//lcd.print(“C”);

//lcd.setCursor(0,1);
//lcd.print(“Humidite: “);
//lcd.print(h);
//lcd.print(”%”);

//radio.write(&t, sizeof(int));

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("Temperature: ");
display.print(t);
display.print(“C”);
display.display();

}

SendTemp.ino (1.19 KB)

I was able to get this working with the Adafruit_ssd1306syp library. When I downloaded the example files from the manufacture of the OLED, there was 2 examples using I2C. One was using the Adafruit_SSD1306 library and another was using the Adafruit_ssd1306syp library. You can find the sources here:

The folder has a bunch of files including the datasheet.

Here is my code with RF24

#include <Adafruit_ssd1306syp.h>
#define SDA_PIN A4
#define SCL_PIN A5


#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
Adafruit_ssd1306syp display(SDA_PIN,SCL_PIN);

RF24 radio(9,10);

// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
int ct = 0; // count for number of lines to display
//
// Role management
//
// Set up role.  This sketch uses the same software for all the nodes
// in this system.  Doing so greatly simplifies testing.  
//

// The various roles supported by this sketch
typedef enum { role_ping_out = 1, role_pong_back } role_e;

// The debug-friendly names of those roles
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};

// The role of the current running sketch
role_e role = role_pong_back;

static const char rf24_model_e_str_0[] PROGMEM = "nRF24L01";
static const char rf24_model_e_str_1[] PROGMEM = "nRF24L01+";

static const char * const rf24_model_e_str_P[] PROGMEM = {
  rf24_model_e_str_0,
  rf24_model_e_str_1,
};

void setup()
{
  delay(1000);
  display.initialize();
   Serial.begin(57600);
  printf_begin();
  printf("\n\rRF24/examples/GettingStarted/\n\r");
  printf("ROLE: %s\n\r",role_friendly_name[role]);
  printf("*** PRESS 'T' to begin transmitting to the other node\n\r");
  //
  // Setup and configure rf radio
  //

  radio.begin();
 

  // optionally, increase the delay between retries & # of retries
  radio.setRetries(15,15);

  // optionally, reduce the payload size.  seems to
  // improve reliability
  radio.setPayloadSize(8);

  //
  // Open pipes to other nodes for communication
  //

  // This simple sketch opens two pipes for these two nodes to communicate
  // back and forth.
  // Open 'our' pipe for writing
  // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)

  if ( role == role_ping_out )
  {
    radio.openWritingPipe(pipes[0]);
    radio.openReadingPipe(1,pipes[1]);
  }
  else
  {
    radio.openWritingPipe(pipes[1]);
    radio.openReadingPipe(1,pipes[0]);
  }

  //
  // Start listening
  //

  radio.startListening();

  //
  // Dump the configuration of the rf unit for debugging
  //

  radio.printDetails();
  
  display.clear();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  //display.println(RX_ADDR_P0,2);
  
  uint8_t ty = pgm_read_word(&rf24_model_e_str_P[radio.isPVariant()]);
  if(ty == 108){
    display.println("nRF24L01+ Connected");
    
  }else{
    display.println("No radio found!");
  }
    
  display.update();
  delay(4000);
  display.clear();
  
}


void loop()
{
  display.clear();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("working..");
  display.update();
  delay(2000);
  display.clear();
}

Hi Domingosl,

It is 7.5 years later and I am running into exactly the same problems. I have a NRF24L01+ used by Mysensors and the SSD1306 with the Adafruit Library, both operating on SPI. Individually they work perfectly but I am not able to get them working together. Tried both HW and SW SPI, changed SPI speeds etc… no effect. I was wondering: did you ever get the two working on SPI together?

I saw that somebody reported a solution but that one was using I2C for the OLED. That is in the end my backup strategy but I firtst I want to understand why it doesn’t work on SPI (although this should be possible according to the specs).

Thanks a lot for sharing your experience on this subject!

Kind regards, Armand