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
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.
@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
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.
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
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.
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.
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.
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:
In fact, some of the example even look familiar 🙂
Cheers.
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
nRF24L01 Arduino UNO
--------------------
VCC 3.3V
GND GND
SCK --> D13
MISO --> D12
MOSI --> D11
CSN D7
CE D8Also, 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);
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...
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
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 );
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
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.