Wireless Music Playing Christmas Present - NOTHING WORKS

Hello all. I really want this present to do what I envisioned, it’s crunch time, and I’m getting stressed out.

Goal:
Detect if any of 8 contacts are open, indicating an open box. Send the value of which box is open over an NRF24L01 transceiver.
Receive that value at the receiver end, and use that to play an audio file using the TMRpcm library.

What works:
Detecting which contact is open

What doesn’t work:
Sending or receiving the value wirelessly. I don’t know where the problem is (TX or RX), but I’m not getting the data at the receiver.
Initializing the SD Card for the TMRpcm library. (Prints “SD Fail” when initializing)

The SD card is a 16gb (SDHC) formatted to FAT32.

Anyone see any glaring issues in my code?

Transmitter (Present):

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

const byte Box[] = {2, 3, 4, 5, 6, 7, 8, A0};  //Pin 2 = Bottom, Pin A0 = Lid, Pin 3,4, 5, 6, 9, and 10 correspond to Boxes 1-6

bool CurrentReading[8];
bool PreviousReading[8];
int Signal;

RF24 radio(9, 10); // CE, CSN
const byte address[6] = {"00001"};

/*
  Pin 9  - CE  
  Pin 10 - CSN 
  Pin 11 - MOSI
  Pin 12 - MISO
  Pin 13 - SCK
*/


void setup(){
  Serial.begin(9600);
  
  radio.begin();
  radio.openWritingPipe(address);     // 00001
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();

  for(int i=0; i<=7; i++){
    pinMode(Box[i], INPUT_PULLUP);
  }
}


void loop(){
  for(int i=0; i<=7; i++){
    CurrentReading[i] = digitalRead(Box[i]);
    if(CurrentReading[i] == HIGH && PreviousReading[i] == LOW){
      Signal = i+1;
    }
    PreviousReading[i] = CurrentReading[i];
  }

  Serial.print("Signal: ");
  Serial.println(Signal);

  radio.write(&Signal, sizeof(Signal));
  Serial.println("Data Sent");
  
  delay(6);
  Signal = 0;
}

Receiver (Speaker):

#include <SD.h>
#include <TMRpcm.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define SD_ChipSelectPin 4

RF24 radio(9, 10);  // CE, CSN
const byte address[6] = "00001";

int Signal = 0;  //Starts with the Signal variable set to 0
int LastPlayed;

TMRpcm tmrpcm;
#define DISABLE_SPEAKER2  //Disables default second speaker pin for compatibility with other libs. (pin 10 on Uno)

/*
 Arduino - Devices
 
  Pin 4  - CS   (SD)
  Pin 9  - CE   (NRF24L01)
  Pin 10 - CSN  (NRF24L01)
  Pin 11 - MOSI (SD + NRF24L01)
  Pin 12 - MISO (SD + NRF24L01)
  Pin 13 - SCK  (SD + NRF24L01)

  Pin 5 - Speaker Positive / Mono Headphone Positive
*/


void setup(){
  tmrpcm.speakerPin = 5;
  
  Serial.begin(9600);
  
  if (!SD.begin(SD_ChipSelectPin)) {
    Serial.println("SD fail");
    return;
  }
  
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  
  tmrpcm.setVolume(6);  
}

void loop(){
   if (radio.available()) {
    radio.read(&Signal, sizeof(Signal));  //Read data from NRF24L01
  }
  
  Serial.print("Signal = ");
  Serial.println(Signal);
  
  if(Signal != 0){
   if(Signal != LastPlayed){  
    switch(Signal){
      case(1): 
        tmrpcm.play("Red Pill Blue Pill.wav");  //Play red pill blue pill
        break;
      case(2): 
        tmrpcm.play("Nyan Cat.wav");       //
        break;
      case(3): 
        tmrpcm.play("Derp Song.wav");      //
        break;
      case(4): 
        tmrpcm.play("Harlem Shake.wav");   //
        break;
      case(5): 
        tmrpcm.play("Rick Roll.wav");      //
        break;
      case(6): 
        tmrpcm.play("Troll Song.wav");     //
        break;
      case(7): 
        tmrpcm.play("Russian Song.wav");   //
        break;
      case(8): 
        tmrpcm.play("Far Away.wav");       //Play "Far Away"
        break;
    }
   }
   Signal = LastPlayed;
  }
  delay(4);
}

You need to get each piece of the project working separately before putting everything together.

Start with the simple stuff. After the radio is set up, trying calling ‘isChipConnected()’ – check out the source code in RF24.h and RF24.cpp to see how it works. That function returns a ‘bool’ telling you whether or not your processor can communicate with the radio over the SPI bus.

Also, check out this Tutorial.

Likely a conflict with sharing the SPI bus between the radio and SD card would be my guess? Looks like you're trying to init the SD card before ever talking to the radio, so unless the radio card is doing something naughty with the SPI bus before you talk to it the first time, you may try to init them both, maybe the radio first?

err what gfvalo said :slight_smile:

I don't have a direct answer that's very helpful, but sometimes spit-balling helps.

Regards and happy holidays

Excellent, with everyone's help, I'm getting somewhere! I used the "Simple NRF24L01" tutorial gfvalvo posted, and have been able to successfully get the transmitter and receiver working (with the audio playing code commented out on the receiver side).

Last step, getting the SD card to initialize properly. Even with all of the wireless code removed and the transceiver disconnected, it still fails.

NOOB thought that I just had... Are the labels for MOSI and MISO on an SD card breakout for that device, or is that where you hook them to the host? As in does MISO on the SD breakout go to Arduino MOSI?

The module that I’m using everything is hooked straight over, miso to miso - mosi to mosi - in reality it would be mosi to miso and miso to mosi or whatever, they tried to make it simple on the modules that I use so that you just run the lines labeled name to labeled name. If that makes any sense. But you can just switch the lines around without hurting anything, just to see. ALSO - another thought, my boards have a 3.3V regulator on board, so you have to power them from +5V at least. I couldn’t get mine to work until I did that! I was using an ESP32 board and used its 3v3 output at first and it wouldn’t work until I went to the raw line in...

Yes, all good points. I did try flipping them around, turns out it was wired correctly and in my case MOSI goes to MOSI, MISO to MISO. The problem with my SD card was the formatting. It turns out when people say use the “official formatter” they mean there is a formatter published by the SD Association.
Link: https://www.sdcard.org/downloads/formatter_4/

Between that and switching to the “SdFat” library, I was able to get the SD card to initialize successfully.

Now, go figure, yet another problem.
Right now, when the player tries to play the audio, it just pops and crackles. There is no determinable audio within the pops and crackles, just a constant buzz and I assume the pops are the audio peaks in the files.

Truly at a loss here, I might have to start playing with the pcmconfig file.

Well, I’m going backwards. I removed all of the wireless code from the speaker side, and only left the audio playing portions. When it was all there, the SD card initializes fine. With just the audio code, the SD card fails to initialize.

Full Code:

#include <SdFat.h>
SdFat sd;
#include <TMRpcm.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define SD_ChipSelectPin 4

RF24 radio(7, 8);  // CE, CSN
const byte address[5] = {'R','x','A','A','A'};

int Signal = 0;  //Starts with the Signal variable set to 0
int LastPlayed = 0;

TMRpcm tmrpcm;
#define DISABLE_SPEAKER2  //Disables default second speaker pin for compatibility with other libs. (pin 10 on Uno)

/*
 Arduino - Devices
 
  Pin 4  - CS   (SD)
  Pin 7  - CE   (NRF24L01)
  Pin 8  - CSN  (NRF24L01)
  Pin 11 - MOSI (SD + NRF24L01)
  Pin 12 - MISO (SD + NRF24L01)
  Pin 13 - SCK  (SD + NRF24L01)

  Pin 9 - Speaker Positive / Mono Headphone Positive
*/


void setup(){
  Serial.begin(115200);
 
  tmrpcm.speakerPin = 9;
 
  if (!sd.begin(SD_ChipSelectPin, SPI_FULL_SPEED)){
    Serial.println("SD Failed");
    return;   
  }
  else Serial.println("SD OK"); 
  
  tmrpcm.setVolume(6);  

  delay(100);

  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.openReadingPipe(1, address);
  radio.startListening();

  bool result = radio.isChipConnected ();
  Serial.println (result);  
}

void loop(){
   if (radio.available()) {
    radio.read(&Signal, sizeof(Signal));  //Read data from NRF24L01
    Serial.print("Signal = ");
    Serial.println(Signal);  
  }
  
  if(Signal != 0){
   if(Signal != LastPlayed){  
    switch(Signal){
      case(1): 
        tmrpcm.play("Red Pill Blue Pill.wav");  //Play red pill blue pill
        break;
      case(2): 
        tmrpcm.play("Nyan Cat.wav");       //
        break;
      case(3): 
        tmrpcm.play("Derp Song.wav");      //
        break;
      case(4): 
        tmrpcm.play("Harlem Shake.wav");   //
        break;
      case(5): 
        tmrpcm.play("Rick Roll.wav");      //
        break;
      case(6): 
        tmrpcm.play("Troll Song.wav");     //
        break;
      case(7): 
        tmrpcm.play("Russian Song.wav");   //
        break;
      case(8): 
        tmrpcm.play("Far Away.wav");       //Play "Far Away"
        break;
    }
   LastPlayed = Signal;
   }
  }
}

Audio Only:

#include <SdFat.h>
SdFat sd;
#include <TMRpcm.h>
#include <SPI.h>

#define SD_ChipSelectPin 4

TMRpcm tmrpcm;
#define DISABLE_SPEAKER2  //Disables default second speaker pin for compatibility with other libs. (pin 10 on Uno)

/*
 Arduino - Devices
 
  Pin 4  - CS   (SD)
  Pin 7  - CE   (NRF24L01)
  Pin 8  - CSN  (NRF24L01)
  Pin 11 - MOSI (SD + NRF24L01)
  Pin 12 - MISO (SD + NRF24L01)
  Pin 13 - SCK  (SD + NRF24L01)

  Pin 9 - Speaker Positive / Mono Headphone Positive
*/


void setup(){
  Serial.begin(115200);
 
  tmrpcm.speakerPin = 9;
 
  if (!sd.begin(SD_ChipSelectPin, SPI_FULL_SPEED)){
    Serial.println("SD Failed");
    return;   
  }
  else Serial.println("SD OK"); 
  
  tmrpcm.setVolume(6);  
}

void loop(){ 
        tmrpcm.play("Red Pill Blue Pill.wav");  //Play red pill blue pill
        tmrpcm.play("Nyan Cat.wav");       //
        tmrpcm.play("Derp Song.wav");      //
        tmrpcm.play("Harlem Shake.wav");   //
        tmrpcm.play("Rick Roll.wav");      //
        tmrpcm.play("Troll Song.wav");     //
        tmrpcm.play("Russian Song.wav");   //
        tmrpcm.play("Far Away.wav");       //Play "Far Away"
}

I'm using SdFat as well for my project and had to slow the bus down to 1MHz - sometimes it would initialize, but the data would be corrupt. Now at 1MHz and it seems to work well for writing to the card and reading the data back, but it's a .txt file in my case.

For reading PCM/WAV files I would imagine you would want to be able read rather quickly, or as slow as your audio tracks would allow for without failing or playing weird. Obeying nyquist and such.

Also taking a look at TMRpcm, you do have to use lower sample rate files and you can't play back tracks that were recorded in stereo via mono-mode:

"WAV files, 8-bit, 8-32khz Sample Rate, mono"

I assume you handled your audio tracks in something like audacity to drop the sample rate and to get them in mono?

Somewhere in here: Advanced Features · TMRh20/TMRpcm Wiki · GitHub - it mentions pops and clicks being a fact of life. Sounds like maybe DC offset issues or a track that doesn't start on the zero crossing to me, like between tracks? Maybe not so much to do with normal playback.