Storing data in SD card from Bluetooth Device (Multiple Devices to Arduino)

Hi everyone,

I am working on a part of a project in which I have to store data within a SD card from a bluetooth device. The bluetooth module (nRF8001 Adafruit) and the SD Card are both connected to an Arduino UNO (I have used the Mega also) through the SPI interface.

I know I have to enable and disable the CS or SS (chip select) of each device in order to independently communicate with the master (Arduino).

The issue is that I am trying to add to the original code (Bluetooth code from the Adafruit) the part that theoretically allows to write on the SD card. However, I am not succeding.

I downloaded an app from the Adafruit website to communicate between my phone and the serial monitor of the Arduino. So when I type something on the phone I can see it on the serial monitor and vice versa.

So I would like to able to write on the SD card at the same time that when I send something from the phone to the serial monitor. So far I would like to do that just creating the file on the SD card and write on it the same stuff that are shown on the serial monitor.

The code is as follows:

// This version uses the internal data queing so you can treat it like Serial (kinda)!

#include <SD.h>
#include <SPI.h>
#include "Adafruit_BLE_UART.h"

byte address=0x00;
File myFile;
char c;


// Connect CLK/MISO/MOSI to hardware SPI
// e.g. On UNO & compatible: CLK = 13, MISO = 12, MOSI = 11
#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RDY 2     // This should be an interrupt pin, on Uno thats #2 or #3
#define ADAFRUITBLE_RST 9

Adafruit_BLE_UART BTLEserial = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
/**************************************************************************/
/*!
    Configure the Arduino and start advertising with the radio
*/
/**************************************************************************/
void setup(void)
{ 

  pinMode(4, OUTPUT); //Digital SS Pin SD Card 
  pinMode(10, OUTPUT); //Digital SS Pin bluetooth
    
  Serial.begin(9600);
  while(!Serial); // Leonardo/Micro should wait for serial init
  Serial.println(F("Adafruit Bluefruit Low Energy nRF8001 Print echo demo"));

  // BTLEserial.setDeviceName("NEWNAME"); /* 7 characters max! */

  BTLEserial.begin();


 while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only

  if (!SD.begin(4)) {
     Serial.println("initialization failed!");
    return;
  }
 }
}

/**************************************************************************/
/*!
    Constantly checks for new events on the nRF8001
*/
/**************************************************************************/
aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;

void loop()
{
  // Tell the nRF8001 to do whatever it should be working on.
  BTLEserial.pollACI();

  // Ask what is our current status
  aci_evt_opcode_t status = BTLEserial.getState();
  // If the status changed....
  if (status != laststatus) {
    // print it out!
    if (status == ACI_EVT_DEVICE_STARTED) {
        Serial.println(F("* Advertising started"));
    }
    if (status == ACI_EVT_CONNECTED) {
        Serial.println(F("* Connected!"));
    }
    if (status == ACI_EVT_DISCONNECTED) {
        Serial.println(F("* Disconnected or advertising timed out"));
    }
    // OK set the last status change to this one
    laststatus = status;
  }

  if (status == ACI_EVT_CONNECTED) {
    // Lets see if there's any data for us!
    if (BTLEserial.available()) {
      Serial.print("* "); Serial.print(BTLEserial.available()); Serial.println(F(" bytes available from BTLE"));
    }
    // OK while we still have something to read, get a character and print it out
    while (BTLEserial.available()) {
      char c = BTLEserial.read();
      Serial.print(c);

    activationbt(c);
    activationsd(c);
    sdcard(c);
      
    }
  }
}

char activationbt(char value)
//Send value from the Bluetooth module to SPI interface 
{
digitalWrite(10, LOW); //It activates the Bluetooth module
SPI.transfer(address);
SPI.transfer(value);
digitalWrite(10, HIGH);
}


char activationsd(char value)
//Send value from the SPI interface to SD Card 
{
digitalWrite(4, LOW);
SPI.transfer(address);
SPI.transfer(value);
digitalWrite(4, HIGH);
}


char sdcard(char value)
{

myFile = SD.open("sdcard.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {  
    myFile.println(value);
    Serial.println(value);
    // close the file:
    myFile.close();
    Serial.println("done.");
  }else {
    // if the file didn't open, print an error:
    Serial.println("error opening sdcard.txt");
  }

}

I was wondering if someone might take a look at the code and help me out.

Any ideas?

Thank you in advance for your help.

Regards.

What does your code actually do and how is that different from what you want?

Are you using the SD module from Adafruit or one from a different vendor?

One problem with some SD modules (non Adafruitt) is that they use a level shifter to shift the 3.3V levels to 5V for 5V Arduino boards. The level shifter does not properly release the MISO line so those modules do not "play nice" with the SPI bus. The Adafruit module has the MISO line that bypasses the level shifter and should work fine on the SPI bus.

Hi,

First of all, thank you for your reply.

The code sends and receives data from a phone to the serial monitor of the Arduino and vice versa. That is, everything typing (letters, numbers, sentences, and so on) on the Adafruit App gets to the serial monitor. When typing anything on the serial monitor it shows on the Adafruit App on the phone.

It is like if two people texting each through an app. One gets on the phone what the other one is typing and vice versa.

Here. the bluetooth module receives the information from the phone and shows it on the serial monitor. And it does the same from the Arduino to the phone.

The SD card module is from Adafruit also. It is exactly a MicroSD card and based on its datasheet it needs 5V to work.

Any thoughts?

Thank you again for your help guys.

In the current code you are reading one character at a time, Serial printing the character, opening the file, saving the character to SD and closing the file. That is not very efficient.

Better would be to set up your app and the BT sending routine to always add a newline at the end of each text packet. In serial monitor, enable sending a line feed in the line endings box. So from serial monitor, you send "HI there" The Arduino serial port gets "Hi there\n". Same with BT messages send from an Arduino. Use the println() method to send the data. The println() method ends messages with '\n'.

Now you can read in and output complete strings instead of character by character. Example #2 of the serial input basics tutorial shows how to read a string from the serial port that ends with a line feed ('\n').

Now you can open the file and write the strings to it as they come in or are sent. You will have to modify your sdcard() function to accept a string as a parameter and use the print() method instead of write.

The activationbt(c) and activationsd(); functions are not useful. You should not have to mess with chip selects as the libraries take care or that when you use the write() or print() methods. You do not need to use the SPI bus to send data out from the BLE module, that is what print() and write() do for you.

To write data out using the BLE module use:

BTLEserial,print("some text");
// or
BTLEserial.println("some text");
// or
BTLEserial.write(array, array_size);

This Adafruit page has more information on the library functions,

Hello,

The first thing, my apologies for getting back you late. Secondly, thank you so much for your feedbacks. I really appreciate them.

No doubts I am going to follow your explanations and test it out today in the lab. And obviously, I will let you know anything.

Sorry if I ask too much but I have another doubt.

Both devices (the bluetooth module and the SD Card) are connected to the SPI bus or interface. My question is if there will not be some kind of conflict when trying to use both devices. I mean, what I understood after reading about how to connect multiple SPI devices to an Arduino is that the bus is simultaneouly shared by both devices and a selection of one of the devices has to be done (by the Chip Selection Pin) in order to avoid conflicts between them.

For this reason in the code, I used the SPI library and played around with the CS pin because what I had understood is that a previous selection of each device should be done to communicate the master with each slave.

Am I wrong?

And again, thank you sou much for your help.

Regards.