power issue with RF24

Hi everyone!

I am having difficulty powering a project of mine. I am using an Arduino Uno with a RF24 module, a Micro-SD module and hall effect sensor. When I only conect the RF24 module the messages I transmit are received just fine but as soon as I plug in the SD module the wireless communication doesn't work no more.

The Rf24 is powered by the 3.3V output of the Arduino, everything else by its 5V output. My question is, if you think that I can get by with using a capacitor on the RF24. I have 2.2, 4.7 and 100 uf capacitors at hand.

Or do I need a seperate power source? If so could you recommend a way to power my project? It is build in to a 1:10 RC car which gives me access to 7.2 and 6V.

Thanks for your help (=

It could also be a pin conflict. Post your code.

The SD card needs a good bit of current and the RF24 needs a large current when Xmitting, you may need a >= 1 Amp, 3.3V PS.
https://www.digikey.com/product-detail/en/murata-power-solutions-inc/OKI-78SR-3.3-1.5-W36-C/811-2195-5-ND/2259780

6v6gt:
It could also be a pin conflict. Post your code.

Sure but I split my code in multiple tabs and it is not very well programmed...
I wanted to try powering the SD with a battery. But I was shocked when I saw that the power led of the Arduino was lighting up when I connected the SD module to the battery. Apparently the Arduino receives power via the SPI interface. Is this normal? Do I have to worry about that?

Main tab

//VWA - combined car v1 MAIN
#include <SPI.h>
#include <SD.h>
#include <Servo.h>
#include "RF24.h"
#include <Wire.h>

// Variables for main program
byte state = 0; //variable for saving the state of operation
#define LED_PIN 5

// Variables for PWM control
#define RECEIVER_PIN 3 // Read PWM signal from here
#define ESC_PWM_PIN 4  // Create PWM signal on this pin to control ESC
volatile unsigned long pulseStartTime;
volatile int receiverPulse;
Servo ESC1;
//--------------------

// Variables for data logging
#define SD_CS 7
String filename_bare = "VWAlog";
String filename = "";
File logFile;
//--------------------

// Variables for wireless communication
#define RF24_CE  8
#define RF24_CSN 9
RF24 myRadio(RF24_CE, RF24_CSN);
byte addresses[][6] = {"1Node"};

struct MSG_info_start {
  char description[28];
  byte targetSpeed;
  bool start; 
};
MSG_info_start my_received_info_start_MSG;

bool brakingMSG = false;
//--------------------

// Variables for PID control
#define CIRCUMFERENCE 0.21 //in meter   //should be changed
#define TARGET_SPEED 25                 //has to be changed
#define coeffP 0.05
#define coeffI 0
#define coeffD 0.75

float targetSpeed = 25;
volatile unsigned long lastTimeHallInt;
volatile float pidOutput = 12;
volatile float rpm;
float errorIntegral = 0;
float previousError = 0;
float measuredSpeed = 0;
//--------------------

void setup() {
  initBasics();
  initRadio();
  led_test();

  Serial.println("Setup abgeschlossen.");
}

void loop() {
  switch (state) { //depending on the state the system is in do the appropriate thing
    case (0): //idle: passthrough of RC singal; check for message with settings and start signal
      receiveSettingStruct();
      if (my_received_info_start_MSG.start) {
        my_received_info_start_MSG.start = false;
        state = 1;
        digitalWrite(LED_PIN, HIGH);
      }
      
      logFile.close();
      logFile = SD.open(filename, FILE_WRITE);
      ESC1.writeMicroseconds(receiverPulse); // pass the received PWM signal to the ESC
      break;
    case (1): //accelerationInit: create file on SD and attachInterrupt; set state to 2
      Serial.println("Started!!!");
      createFile_w_header();
      state = 2;
      break;
    case (2): //acceleration: accelerate; check if there is an input from RC transmitter; if so state -> 0; also check for braking signal
    show_state_w_LED();
      Serial.println("Reaching and maintaining speed!");
      listenForBraking();
      if (brakingMSG) {
        brakingMSG = false;
        state = 3;
        break;
      }
      /*if (abs(receiverPulse - 1500) > 50){
        Serial.println("Run was interrupted by user via RC transmitter.");
        state = 0;
        logFile.close();
      }*/
      break;
    case (3): //braking: detachInterrupt; start logging of Gyro & Accelerometer; Brake; check if a ~ 0 for 3s; if so state -> 4
      Serial.println("Braking!");
      delay(1500);
      state = 4;
      break;
    case (4): //transmit Data; then state -> 0
      Serial.println("Transmit Data back to station!");
      delay(500);
      state = 0;
      logFile.close();
      break;
    default:  // should never get here; state -> 0
      state = 0;
  }
}

init tab

void initBasics() {
  my_received_info_start_MSG.start = false;
  Serial.begin(9600);
  while (!Serial);
  Wire.begin();
  if (!SD.begin(SD_CS))
    Serial.println("Unable to initialize SD!");
  pinMode(LED_PIN, OUTPUT);
}

void led_test() {
  for(int i=0; i<3; i++) { 
    digitalWrite(LED_PIN, HIGH);
    delay(200);
    digitalWrite(LED_PIN, LOW);
    delay(200);
  }
}

wireless tab

void receiveSettingStruct() {
  if(myRadio.available()) {
    myRadio.read(&my_received_info_start_MSG, sizeof(my_received_info_start_MSG));

    Serial.println("Startsignal über wirelessverbindung erhalten!");
    Serial.print("Beschreibung:\t\t");
    Serial.println(my_received_info_start_MSG.description);
    Serial.print("Targetspeed:\t\t");
    Serial.println(my_received_info_start_MSG.targetSpeed);
    Serial.print("Startbefehl:\t\t");
    Serial.println(my_received_info_start_MSG.start);
    Serial.println();
  }
}

void listenForBraking() {
  if (myRadio.available()) { // Check for incoming data from transmitter
    while (myRadio.available())  // While there is data ready
      myRadio.read( &brakingMSG, sizeof(brakingMSG) ); // Get the data payload (You must have defined that already!)

    Serial.print("Braking MSG erhalten: ");
    Serial.println(brakingMSG);
  }
}

void initRadio() {
  myRadio.begin();
  myRadio.setChannel(108);
  myRadio.setPALevel(RF24_PA_MIN);

  myRadio.openReadingPipe(1, addresses[0]);
  myRadio.startListening();
}

sd tab

void getSDfileName() {
  int i = 1;
  while (SD.exists(filename_bare + i + ".txt"))
    i++;

  filename = filename_bare + i + ".txt";
}

void createFile_w_header() {
  getSDfileName();
  
  logFile = SD.open(filename, FILE_WRITE);
  logFile.print("Description: ");
  logFile.println(my_received_info_start_MSG.description);
  logFile.print("Targetspeed: ");
  logFile.println(my_received_info_start_MSG.targetSpeed);
  logFile.print("Start: ");
  logFile.println(my_received_info_start_MSG.start);
}

You must never back-power a board like this - all signal lines must be at ground potential if the supply is absent,
otherwise current flows through the protection diodes on the signal pins and can burn them out. The datasheet
specifically warns that no pin should be at or greater than +0.5V higher than Vcc. Make sure all
supplies come up together, ie derive your 3.3V from the 5V rail directly.

You need a good solid 3.3V supply for an SDcard, not the built-in 3.3V regulator on the Uno for instance,
which is tiny. An SDcard is power hungry because its a massive flash chip and associated processor (which
is way more powerful that your basic Arduino and requires way more power).

Ever noticed how hot SDcards get? That's because they eat power.

MarkT:
You must never back-power a board like this - all signal lines must be at ground potential if the supply is absent,
otherwise current flows through the protection diodes on the signal pins and can burn them out. The datasheet
specifically warns that no pin should be at or greater than +0.5V higher than Vcc. Make sure all
supplies come up together, ie derive your 3.3V from the 5V rail directly.

You need a good solid 3.3V supply for an SDcard, not the built-in 3.3V regulator on the Uno for instance,
which is tiny. An SDcard is power hungry because its a massive flash chip and associated processor (which
is way more powerful that your basic Arduino and requires way more power).

Ever noticed how hot SDcards get? That's because they eat power.

Ok but as long as I power up the arduino first with a delay() in the setup function and then power the sd externally everything should be fine, right?

The sd module has a voltage regulator which accepts 5v. Sorry I should have mentioned this. I am currently running the RF24 from the 3.3v output of the arduino and the sd module over an external battery. Grounds are connected. However, it stil doesn't work.

I think

6v6gt:
It could also be a pin conflict. Post your code.

was maybe correct. There seems to be a conflict on the SPI bus or something. Any suggestions on how to solve this?

I experimented some more. The rf24 works as long as I don't connect the MSIO pin of the SD module. I don't even initialize the SD but just pull its CS high with a digital write. It seems that the SD module messes with the MISO line regardless of it not being selected by the CS. And it really is just the MISO line. I tried to disconnect the SCK and MOSI lines with the MISO connected but the RF24 still does not work.

Any idea how to solve this? I am really at a loss here...

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom.. :slight_smile:

MarkGoingToSpace:
I am currently running the RF24 from the 3.3v output of the arduino and the sd module over an external battery.

I see ...... so the above is different from what you had before, right?

MarkGoingToSpace:
The Rf24 is powered by the 3.3V output of the Arduino, everything else by its 5V output.

Southpark:
I see ...... so the above is different from what you had before, right?

Yes, I wanted to test whether the RF24 wasn't working due to power issues. As it turned out this wasn't the case since even with the load of the SD module removed it didn't work.

I found a thread about the same problem: Trouble getting two SPI devices working at the same time (nRF24L01 and SD card) - Project Guidance - Arduino Forum

It seems that the SD module is poorly designed and blocks the SPI communication:

johnwasser:
Apparently it's like the SparkFun one that has the level shifter driving MISO (Master In/Slave Out) all the time, even when that slave is not selected. That makes it impossible for your other slaves to drive the bus when they are selected.
Bad design, unless you are only using one SPI device. :frowning:

I will work around the problem by sending the data to the other arduino and saving it with a processing programm rather than saving it on a SD.

But I want to thank you all for your help!
Have a nice day (=
Mark