Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] NRF24L01+ fails when using with MicroSD card. #692

Closed
rbp9802 opened this issue Nov 29, 2020 · 13 comments
Closed

[Question] NRF24L01+ fails when using with MicroSD card. #692

rbp9802 opened this issue Nov 29, 2020 · 13 comments
Labels

Comments

@rbp9802
Copy link

rbp9802 commented Nov 29, 2020

Sorry to ask here. This is not a library issue.

Hi, im trying to log and send aceleration data using NRF24L01+ (3.3v) and MicroSD (5V) modules. They are both working correctly separately but when i try both at the same time, NRF24L01+ fails.

i tried 2k ohm resistor in MISO line (see https://forum.arduino.cc/index.php?topic=507086.0) without success.

Also saw https://forum.mysensors.org/topic/6724/solved-nodemcu-esp8266-and-spi-with-nrf24l01-sd-card-module-sanity-errors/3 but i'm not sure if it applies to my problem. As this implies breaking the moduleI, befor i would like to know if ther are any other solutions. In my cases NRF24L01+ can be configured while not having MISO conected (obiously logging fails for this).

if it helps, her is my code:

#include "Arduino.h"
#include "Wire.h"
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
#include "SdFat.h"
SdFat SD;
const int CS_SD = 10;
const int CS_RF = 8;
const int CE_RF = 7;
File DataFile;
  
RF24 radio(CE_RF, CS_RF); // CE, CSN

typedef struct{
  const int8_t ID = 1;
  int16_t AY;       // Y Acceleration
  int16_t AZ;       // Z Acceleration
  unsigned long t1; // time in microseconds
  }
myData;
myData data;

unsigned long t2;

void setup(){
  Wire.begin();
  Serial.begin(115200);
  printf_begin();
  Serial.print("Initializing SD card:   ");
  if(!SD.begin(CS_SD)){
    Serial.println("SD Fail");}
  else{Serial.println("SD OK");}
  
  RadioSetUp();

  data.t1 = micros();
  }

void loop(){
  t2 = micros();
  if (t2 - data.t1 > 9990) {       //100Hz reading - logging - sending
    Read();

    DataFile = SD.open("data.txt", FILE_WRITE);
    if (DataFile) {
      DataFile.print(data.ID);DataFile.print("\t");
      DataFile.print(data.t1);DataFile.print("\t");
      DataFile.print(data.AY);DataFile.print("\t");
      DataFile.println(data.AZ);
      DataFile.close();
      SerialPrint();}
      
    else {Serial.println("SD Error");}

    Send();
    }
  }

void RadioSetUp(){
  const uint64_t pipes[2] = { 0xE8E8F0F0E1LL, 0xE0F0E0F0E1LL };
  radio.begin();
  radio.setPALevel(RF24_PA_HIGH);
  radio.setChannel(0x76);
  radio.openWritingPipe(pipes[1]);
  radio.openReadingPipe(1, pipes[0]);
  radio.enableDynamicPayloads();
  radio.setPayloadSize(32);
  radio.setCRCLength(RF24_CRC_8);
  radio.setDataRate(RF24_250KBPS);
  radio.setAutoAck(1);
  radio.setRetries(1, 15);
  radio.powerUp();
  radio.stopListening();
  radio.printDetails();
  }

void Read(){
  data.t1 = micros();
  data.AY = yRead();
  data.AZ = zRead();
  }

void SerialPrint(){
  Serial.print(data.AY);Serial.print("\t");Serial.println(data.AZ);}

void Send(){
  if (radio.write(&data, sizeof(data))){
    SerialPrint();
    }
  }
@2bndy5
Copy link
Member

2bndy5 commented Nov 30, 2020

It is important to manage the Chip Select pins properly when using 1 SPI bus for multiple SPI slave devices (in your case the SD card module and the nRF24 module are SPI slave devices).

My first guess is the Chip Select pins aren't being managed properly. Looks like the fix in the link you posted bypassed the problem by disabling the level shifting chip on the SD card module via connecting the level shifting chip's Enable pin to the SD card module's CS pin. I would need to see the schematic for the level shifting chip and how it is soldiered into the SD card module's PCB to fully endorse this fix.

What MCU are you using?

Why are you using I2C? #include "Wire.h" is for I2C & the code you posted doesn't use it for either SD card or nRF24 modules. I haven't looked at the Wire.h file, but the I2C library might be messing with the SPI bus pins depending on the MCU board you are using (you didn't mention what MCU you're working with).

@rbp9802
Copy link
Author

rbp9802 commented Nov 30, 2020

Hi, thanks for your reply. I'm using Arduino nano, CS pins are correct. NRF24 works correctly with accelerometer LIS2DW12 which also use SPI. NRF24 stop working when i connect MISO pin of Micro SD Adapter to the arduino.

I'm using I2C to call ADS1115 in data.AY = yRead(); and data.AZ = zRead(); which i didn't include in the post.

Nano ADS1115 ADXL335 NRF24 Micro SD LIS2DW12
5V VCC     VCC  
3V3   VCC VCC   VCC
GND GND GND GND GND GND
A4 SCL       SCL*not used here
A5 SDA       SDA*not used here
--- A0 X      
 --- A1 Y      
---   A2 Z    
GND A3        
GND ADDR        
D13     SCK SCK SPC (SCL)
D12     MISO MISO SDO
D11     MOSI MOSI SDI (SDA)
D10     CS  
D9         CS
D8     CSN    
D7     CE    

@2bndy5
Copy link
Member

2bndy5 commented Nov 30, 2020

Thanks for specifying the MCU.

NRF24 stop working when i connect MISO pin of Micro SD Adapter to the arduino.

  1. This probably has something to do with the level shifting chip on the SD card module (assuming you're using one mentioned in the blog post you linked to).
  2. SD cards use the SPI bus a little differently than any other SPI slave device. The differences depend on the type of SD card that you're using (I'm not too personally familiar with these differences).

Conclusion

Look into the specs for your SD card and the datasheet for the level shifting chip on the SD card reader module. Prepare for a new level of confusion because the specs/datasheet for these devices will likely not share the same terminology.

I'm starting to think that tying the level shifting chip's CE pin to the SD card module's CS pin might be the only fix. Your concern before making that hardware modification is a good habit. Since there doesn't seem to be a problem on the RF24 side of the application, I probably won't be of much more help to you. Feel free to keep posting progress/questions on this thread.

@rbp9802
Copy link
Author

rbp9802 commented Dec 15, 2020

Hi Brendan, I solved it by setting a dedicated SPI bus for de SD module using https://github.com/greiman/SdFat library. I followed the "SoftwareSPI.ino" example https://github.com/greiman/SdFat/tree/master/examples/SoftwareSpi.

You have to change SdFatConfig.h file of the library. In line 112 change #define SPI_DRIVER_SELECT 0 to #define SPI_DRIVER_SELECT 2

Here is my new code:

#include "SdFat.h"
//new SPI pins
const uint8_t SD_CS_PIN     = 2;
const uint8_t SOFT_MOSI_PIN = 3;
const uint8_t SOFT_MISO_PIN = 4;
const uint8_t SOFT_SCK_PIN  = 5;

SoftSpiDriver<SOFT_MISO_PIN, SOFT_MOSI_PIN, SOFT_SCK_PIN> softSpi;
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(0), &softSpi)
SdFat sd;
File file;

In the setup section include this

if (!sd.begin(SD_CONFIG)) {
    sd.initErrorHalt();
  }

In the loop section nothing changes

    file = sd.open("file.txt", FILE_WRITE);
    if (file) {
      file.println("print done.");
      file.close();

Thank you fo your support.

@2bndy5
Copy link
Member

2bndy5 commented Dec 15, 2020

Well done!! If you are able to, you should copy this successful solution to that mysensor forum you linked to in the OP.

Its probably a good tactic (in this particular scenario) to use the bitbanged SPI (AKA SoftSPI or SoftwareSPI) for the SD card since those things aren't exactly used for their "fast" I/O transfer speed. As for the nRF24, SPI timing is rather detrimental.

Thank you for posting back (not many people do). Again, good job!

@2bndy5 2bndy5 closed this as completed Dec 15, 2020
@rbp9802
Copy link
Author

rbp9802 commented Dec 16, 2020

Thanks Brendan! I tested velocities over Hardware SPI and SoftSPI. Hardware SPI can write data up to 168Hz while Software SPI up to 54Hz, arround 3 time slower. I wonder if there is a way to use SoftSPI on NRF24L01 modules that can read/write data over 100Hz.

@2bndy5
Copy link
Member

2bndy5 commented Dec 16, 2020

Well there is a bit in the RF24 docs about using SoftSPI, but it would be slower...

I wouldn't recommend it because wireless throughput it often the "tighter" bottleneck in most projects. But you are free to experiment. As always, feel free to post your findings here!

@2bndy5
Copy link
Member

2bndy5 commented May 9, 2021

Now that I think about it, this RF24 library has introduced (since this issue was closed) a new feature to allow using secondary (or non-primary) hardware-driven SPI buses. But that still depends on if your MCU board has more than 1 SPI bus exposed.

@rbp9802
Copy link
Author

rbp9802 commented May 15, 2021

I've actually read that specifying SPI bus was an issue when using Raspberry Pi Pico. These does not include SoftSPI on Arduino Nano?

@2bndy5
Copy link
Member

2bndy5 commented May 15, 2021

specifying SPI bus was an issue when using Raspberry Pi Pico.

I need more details to confirm this. Where did you find that info?

The SoftSPI implementation likely won't work with the RP2040 because it wasn't written for that architecture. SoftSPI should work on AVR architecture (like Arduino nano) as long as the pins specified aren't the same pins used for hardware-driven SPI.

@rbp9802
Copy link
Author

rbp9802 commented May 16, 2021

Where did you find that info?

Read that from you, sorry. The RP2040 exposes multiple hardware SPI buses, so we may have to chew on that a bit.

@2bndy5
Copy link
Member

2bndy5 commented May 16, 2021

oh. 😆 That shouldn't be a problem anymore; consider it chewed and digested. I'm now a bit more familiar with the PicoSDK now than when I originally made that comment. Actually, I was able to apply the overloaded-begin() feature (which provides an OOP approach to specifying a different SPI bus) towards the RP2040. I've outlined as much in the rp2xxx branch's how-to docs about using the PicoSDK.

@jvi326
Copy link

jvi326 commented Jul 5, 2024

A way to fix it is making some changes to the board. You need to get rid of a resistor, cut some connection and wire from MISO pin to pin 7 DO of the SD adapter directly. It wasn't my idea but I followed the following tutorials which I give all the credit to:

https://www.youtube.com/watch?v=_Q2pBEgoMN0&t=548s
https://www.youtube.com/watch?v=iqqFn2jn3p8
https://easyeda.com/modules/SD-card-module-schematic_88def62da2c043ee96033c31134c0a25

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants