Notifications
Clear all

Connecting multiple SPI Devices (nRF24L01 and 1.5in color OLED)

23 Posts
4 Users
10 Likes
1,541 Views
Leonardo1123
(@leonardo1123)
Trusted Member
Joined: 2 years ago
Posts: 56
Topic starter  

So I separately got my wireless transceiver and OLED working, but I realized when I tried interacting with my OLED I could do so before instantiating my transceiver, but not after. Since they're both SPI, and I'm not super knowledgeable about SPI, I'm sure there's some black magic going on I'm not aware of and need to be to move forward.

Here's my code, it shows what pins I'm using for what. I assumed I had to digitalWrite the Tranceiver's CSN to HIGH before interacting with the display by setting its CS to LOW, and then vice versa after, but had no luck. 

What am I missing?

Thanks for any and all help!


#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
#include <SPI.h>
#include "printf.h"
#include "RF24.h"

#define JX A0
#define JY A1

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 128 // Change this to 96 for 1.27" OLED.

// You can use any (4 or) 5 pins
#define SCLK_PIN 13
#define MOSI_PIN 11
#define DC_PIN 6
#define CS_PIN 7
#define RST_PIN 5

// Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF

RF24 radio(8, 10);
Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, CS_PIN, DC_PIN, MOSI_PIN, SCLK_PIN, RST_PIN);

uint8_t address[][6] = {"1Node", "2Node"};
bool radioNumber = 1;
bool role = true;

uint8_t oldJoystick[2];
uint8_t joystick[2];
uint8_t dist[7];

void sendData() {
// This device is a TX node
radio.stopListening();

bool report = radio.write(&joystick, sizeof(joystick));

if (report) {
Serial.print(F("Transmission successful! Sent: "));
Serial.print("X: ");
Serial.print(joystick[0]);
Serial.print(", Y: ");
Serial.println(joystick[1]);
} else {
Serial.println(F("Transmission failed or timed out"));
}
}

void getData() {
// This device is a RX node

radio.startListening();
uint8_t pipe;
if (radio.available(&pipe)) {
uint8_t bytes = radio.getPayloadSize();
radio.read(&dist, bytes);
Serial.print(F("Received "));
Serial.print(bytes);
Serial.print(F(" bytes on pipe "));
Serial.println(pipe);
}
}

void setup() {
Serial.begin(115200);
tft.begin();
tft.fillRect(0, 0, 128, 128, BLACK); // This works
tft.drawCircle(64, 64, 8, WHITE); // This too

radio.begin();
radio.setPALevel(RF24_PA_LOW);
radio.setPayloadSize(sizeof(dist));
radio.openWritingPipe(address[radioNumber]);
radio.openReadingPipe(1, address[!radioNumber]);
} // setup

void loop() {
joystick[0] = map(analogRead(JX), 0, 1023, 0, 255);
joystick[1] = map(analogRead(JY), 0, 1023, 0, 255);

if ((oldJoystick[0] != joystick[0] or oldJoystick[1] != joystick[1]) and abs(joystick[1] - 128) > 2) {
sendData();
oldJoystick[0] = joystick[0];
oldJoystick[1] = joystick[1];
} else {
getData();
} // role


tft.fillRect(0, 0, 128, 128, BLACK); // This doesn't work
tft.drawCircle(64, 64, 8, WHITE); // nor this
} // loop

Fortune Favors the Bold


   
Quote
Topic Tags
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 

@leonardo1123

Assuming you're setting each device LOW and HIGH accordingly somewhere as you noted, and your pin configuration is correct...

"// This doesn't work" or "// nor this"

...is not very helpful 🙂

I can only guess and say that you're writing to the display at warp speed inside the loop, not giving it enough time to operate correctly.


   
Leonardo1123 reacted
ReplyQuote
Leonardo1123
(@leonardo1123)
Trusted Member
Joined: 2 years ago
Posts: 56
Topic starter  

@frogandtoad you're right, I apologize, let me be more specific!

My wiring for the nRF24L01 is as follows (using the commonly used adapter):

  • CE to 8
  • CSN to 10
  • CLK to 13
  • MOSI to 11
  • MISO to 12
  • IRQ not connected

My wiring for the 1.5in color OLED is as follows:

  • DIN to 11, assuming it's MOSI
  • CLK to 13
  • CS to 7, assuming it's equivalent to CSN
  • DC to 6, not totally sure what it's for
  • RST to 5

(I'd post a picture, but the wiring is not clean. I've double-checked it, but I'm working with half my cables up in a cabin for a few days away.)

Below is some abbreviated code that shows the issue with less baggage. The expected result is nothing on the screen but a medium-sized green circle, instead all that is displayed is the small white circle. 


#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
#include <SPI.h>
#include "printf.h"
#include "RF24.h"

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 128

#define SCLK_PIN 13 // These definitions are for the OLED
#define MOSI_PIN 11
#define DC_PIN 6
#define CS_PIN 7
#define RST_PIN 5

#define BLACK 0x0000
#define GREEN 0x07E0
#define WHITE 0xFFFF

RF24 radio(8, 10);
Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, CS_PIN, DC_PIN, MOSI_PIN, SCLK_PIN, RST_PIN);

void setup() {
Serial.begin(115200);
tft.begin();
tft.fillRect(0, 0, 128, 128, BLACK);
tft.drawCircle(64, 64, 8, WHITE);

radio.begin();
} // setup

void loop() {
digitalWrite(10, HIGH);
digitalWrite(7, LOW);
tft.fillRect(0, 0, 128, 128, BLACK);
tft.drawCircle(64, 64, 8, WHITE);
digitalWrite(7, HIGH);
digitalWrite(10, LOW);
} // loop


Fortune Favors the Bold


   
ReplyQuote
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 

@leonardo1123

Posted by: @leonardo1123

Below is some abbreviated code that shows the issue with less baggage. The expected result is nothing on the screen but a medium-sized green circle, instead all that is displayed is the small white circle. 

Not sure what you mean - It looks like it's doing what you asked for?

In your code you only specify WHITE, with a radius of 8 which IS small?

Also, try fill instead:

    tft.fillCircle(x, y, radius, color);

...and a small delay.


   
Leonardo1123 reacted
ReplyQuote
Leonardo1123
(@leonardo1123)
Trusted Member
Joined: 2 years ago
Posts: 56
Topic starter  

I'm so sorry, I meant to have changed that circle in the loop to green. The tft code in loop does not seem to be executing, or, more specifically, it doesn't seem able to communicate with the display after calling radio.begin().

Below is the adjusted code that displays a white filled circle instead of a green filled circle. 


#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
#include <SPI.h>
#include "printf.h"
#include "RF24.h"

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 128

#define SCLK_PIN 13
#define MOSI_PIN 11
#define DC_PIN 6
#define CS_PIN 7
#define RST_PIN 5

#define BLACK 0x0000
#define GREEN 0x07E0
#define WHITE 0xFFFF

RF24 radio(8, 10);
Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, CS_PIN, DC_PIN, MOSI_PIN, SCLK_PIN, RST_PIN);

void setup() {
Serial.begin(115200);
tft.begin();
tft.fillRect(0, 0, 128, 128, BLACK);
tft.fillCircle(64, 64, 8, WHITE);

radio.begin();
} // setup

void loop() {
digitalWrite(10, HIGH);
digitalWrite(7, LOW);
tft.fillRect(0, 0, 128, 128, BLACK);
tft.fillCircle(64, 64, 16, GREEN);
delay(1000);
digitalWrite(7, HIGH);
digitalWrite(10, LOW);
} // loop

Fortune Favors the Bold


   
ReplyQuote
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 

@leonardo1123

OK... I would check your pins... aside from other pins, the nrf24l01 requires pins 11 and 13 too, but you're using them for the display, so there appears to be a possible conflict there.

I don't have the time now, but I'll see if I can get an example for you to look at later.

Cheers.


   
Leonardo1123 reacted
ReplyQuote
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 

@leonardo1123

Posted by: @frogandtoad

OK... I would check your pins... aside from other pins, the nrf24l01 requires pins 11 and 13 too, but you're using them for the display, so there appears to be a possible conflict there.

I don't have the time now, but I'll see if I can get an example for you to look at later.

Sorry, but I wasn't able to dig out my nrf24l01 today, but in either case, here is the pin configuration (specifically for the highlighted entries), you need to use for an Uno:

nRF24L01 Arduino UNO
--------------------
VCC 3.3V
GND GND
SCK --> D13
MISO --> D12
MOSI --> D11
CSN D7
CE D8

Also, I got confused before... I believe the display pins for SCK, MISO and MOSI should also be tied together, to be a part of the same SPI bus.

Try that and see how you go.

Cheers.


   
Leonardo1123 reacted
ReplyQuote
noweare
(@noweare)
Estimable Member
Joined: 3 years ago
Posts: 115
 

 

I don't know if it has anything to do with your problem. But just checking the library

radio.available() takes no arguments and you have address of pipe as an 
argument radio.available(&pipe)

EDIT:
I just looked at some of the examples and that function does accept argument in some of the
examples. There is another function of the same name that does take an argument.

   
Leonardo1123 reacted
ReplyQuote
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 
Posted by: @noweare

 

I don't know if it has anything to do with your problem. But just checking the library

radio.available() takes no arguments and you have address of pipe as an 
argument radio.available(&pipe)

EDIT:
I just looked at some of the examples and that function does accept argument in some of the
examples. There is another function of the same name that does take an argument.

As I noted earlier, the NRF24L01 has many member functions, and to program this device properly, it's always a good idea to refer to the reference:

    Class Reference - nRF24L01

In fact, some of the example even look familiar 🙂

Cheers.


   
Leonardo1123 and noweare reacted
ReplyQuote
magicChristian
(@magicchristian)
Active Member
Joined: 2 years ago
Posts: 10
 

@leonardo1123

I have used SPI several times but I did not go through all the Messages allready  written:

At SPI you need a seperate CS  for every device on the same bus! Normally the CS is active Low and it is called Chip select. This means only the selected device is listening and can also answere.

There are different Modes according to the polarity of Clock signal and signifcant edges of Clock at MOSI and MISO


   
Leonardo1123 reacted
ReplyQuote
Leonardo1123
(@leonardo1123)
Trusted Member
Joined: 2 years ago
Posts: 56
Topic starter  
Posted by: @frogandtoad
nRF24L01 Arduino UNO
--------------------
VCC 3.3V
GND GND
SCK --> D13
MISO --> D12
MOSI --> D11
CSN D7
CE D8

Also, I got confused before... I believe the display pins for SCK, MISO and MOSI should also be tied together, to be a part of the same SPI bus.

Try that and see how you go.

Cheers.

Alright, so I disconnected everything but my joystick and I'm starting again. The only difference between what you have above and what I'm doing is the rf24 library has this:

RF24 radio(7, 8); // using pin 7 for the CE pin, and pin 8 for the CSN pin

which is backward from what you have listed. 

I'm jumpered pins 13, 12, and 11 to my breadboard to use them for both SPI devices.

My nRF24L01 matches your pinout, except for the 7,8 reversal. 

For my OLED I have:

  • "DIN" going to the jumpered MOSI (assuming DIN is MOSI)
  • CLK going to the jumpered CLK
  • CS to 5 (assuming CS is CSN)
  • DC going to 4 (not sure what it does)
  • RST going to 3

Here's a picture of the OLED in case that helps, and also a quote from the ADAfruit display library that may shed light on the SPI issue (I've been using the top method):

// Option 1: use any pins but a little slower
Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, CS_PIN, DC_PIN, MOSI_PIN, SCLK_PIN, RST_PIN);

// Option 2: must use the hardware SPI pins
// (for UNO thats sclk = 13 and sid = 11) and pin 10 must be
// an output. This is much faster - also required if you want
// to use the microSD card (see the image drawing example)
//Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, CS_PIN, DC_PIN, RST_PIN);

IMG 3537

Are there any other pins I'm supposed to have tied together? Is there any other code I'm supposed to be running? I have a fair amount of experience with I2C, but this is my first time trying to get two SPI devices working...

Posted by: @magicchristian

@leonardo1123

I have used SPI several times but I did not go through all the Messages allready  written:

At SPI you need a seperate CS  for every device on the same bus! Normally the CS is active Low and it is called Chip select. This means only the selected device is listening and can also answere.

There are different Modes according to the polarity of Clock signal and signifcant edges of Clock at MOSI and MISO

I think my main issue is being confused by my OLED pinout, and the fact that on both devices there's more than just CLK, MOSI, MISO, and CSN. What's CE then? DIN? CS? DC? I may just have to go back and watch Bill's videos on displays...

Here's my updated code to reflect suggestions.


#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
#include <SPI.h>
#include "printf.h"
#include "RF24.h"

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 128

#define SCLK_PIN 13
#define MOSI_PIN 11
#define DC_PIN 4
#define CS_PIN 5
#define RST_PIN 3

#define BLACK 0x0000
#define GREEN 0x07E0
#define WHITE 0xFFFF

RF24 radio(7, 8);
Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, CS_PIN, DC_PIN, MOSI_PIN, SCLK_PIN, RST_PIN);

void setup() { Serial.begin(115200);
tft.begin();
tft.fillRect(0, 0, 128, 128, BLACK);
tft.fillCircle(64, 64, 8, WHITE);

radio.begin();
} // setup

void loop() {
delay(1000);
digitalWrite(8, HIGH);
digitalWrite(5, LOW);
tft.fillRect(0, 0, 128, 128, BLACK);
tft.fillCircle(64, 64, 16, GREEN);
digitalWrite(5, HIGH);
digitalWrite(8, LOW);
} // loop

Fortune Favors the Bold


   
ReplyQuote
noweare
(@noweare)
Estimable Member
Joined: 3 years ago
Posts: 115
 

I don't see any pin conficts but I haven't dived too deep.

One of the adafruit examples that uses <SPI.h> uses a different constructor than what your using.

It uses:

Adafruit_SSD1351 tft =Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, OLED_pin_cs_ss, OLED_pin_dc_rs, OLED_pin_res_rst );


   
ReplyQuote
magicChristian
(@magicchristian)
Active Member
Joined: 2 years ago
Posts: 10
 

This time Iwent through all the old messages, but I looked for the display descripton too and here is a link to:

https://www.robotshop.com/media/files/pdf2/1.5inch_oled_module_user_manual_en.pdf

You have to choose  SPI or IIC  Communication by a solder bridge  BS to GND

and the Pin  DC   means   Data / Commands,  should be done by Library

 

 

 


   
ReplyQuote
noweare
(@noweare)
Estimable Member
Joined: 3 years ago
Posts: 115
 

I think he can talk to the display until he initializes the radio then he can't. I thought it

was some sort of conflict. It is hard to troubleshoot things remotely without the hardware.


   
ReplyQuote
frogandtoad
(@frogandtoad)
Noble Member
Joined: 4 years ago
Posts: 1506
 

@leonardo1123

I managed to dig some parts out to test this for myself.  Although this is a very simple example, the following worked perfectly for me - Note that I did not have to set anything HIGH or LOW:

-- transmitter --

#include <RF24.h>
#define CE_PIN 9
#define CSN_PIN 10

const uint64_t pipe = 0x2A;
 
RF24 radio(CE_PIN, CSN_PIN);

char data[] = "Hello World!";
 
void setup()
 {
  Serial.begin(57600);
 
  radio.begin();
  radio.openWritingPipe(pipe);
 }
 
void loop()
 {
  radio.write(data, sizeof(data));
  
  delay(1000);
 }

-- receiver --

#include <SPI.h>
#include <TFT.h>  // Arduino LCD library

#include <RF24.h>
// Pin definitions and hookup for nRF24L01
//    SCK  - was tied to pin 13
//    MISO - was tied to pin 12
//    MOSI - was tied to pin 11
#define CE_PIN 9
#define CSN_PIN 10

// Pin definitions and hookup for 128x128 TFT display
//    CLK (Clock signal) - was tied to pin 13
//    SDI (Data signal)  - was tied to pin 11
#define cs   7
#define dc   3
#define rst  8

TFT TFTscreen = TFT(cs, dc, rst);

const uint64_t pipe = 0x2A;

RF24 radio(CE_PIN, CSN_PIN);

char data[50] = {0};

void setup()
 {
  Serial.begin(57600);

  TFTscreen.begin();
  TFTscreen.background(0, 0, 0);
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.setTextSize(1);
  TFTscreen.fillCircle(64, 64, 30, ST7735_BLUE);

  radio.begin();
  radio.openReadingPipe(1, pipe);
  radio.startListening();
 }

void loop()
 {
  if(radio.available()) {
      radio.read(&data, sizeof(data));
      Serial.println(data);
   }
 }

It continues to display a blue circle in the centre of the display, whilst continually printing "Hello World" at the receiver end serial monitor.  Note that the pin and hookup configuration was also the same on the transmitter for the nRF24L01.

If this doesn't work for you, I'm not sure what else I can suggest.  Either way, the wiring I stated previously, I believe must be on 11, 12 and 13 for the nRF24L01 to even have a chance, so make sure to get that right for the Uno - Others have different pins.

Hope this help's.

Cheers.


   
ReplyQuote
Page 1 / 2