Hello everyone!
For a project for school, I'm checking temperature, TVOC, humidity and location using sensors. These variables get converted to std::string and send using ble. This worked perfectly.
Now I first save the variables using SPIFFS. Then I connect to my phone. At this point my "machine" should stop measuring and start reading in the file, line after line. Each line should be sent separately. However, I don't receive any data on my phone.
-> Is it known that SPIFFS and BLE don't work together?
-> How do I make sure I read a line, send it, and then do the same for the next line?
I look forward to hear from someone.
Welcome to the forum
Please post your sketch, using code tags when you do
Here's the code's summary:
if(beurt == 1)
{
Message = String(beurt).c_str() + std::string(",") + String(temp).c_str() + std::string(",") + String(druk).c_str() + std::string(",") + String(vocht).c_str();
appendStringToSPIFFS(filename, Message);
beurt = 2;
}
else if(beurt == 2)
{
Message = String(beurt).c_str() + std::string(",") + String(CO2).c_str() + std::string(",") + String(TVOC).c_str();
appendStringToSPIFFS(filename, Message);
beurt = 3;
}
else if(beurt == 3)
{
Message = String(beurt).c_str() + std::string(",") + String(latitude_decimal).c_str() + std::string(",") + String(NorS).c_str() + std::string(",") + String(longitude_decimal).c_str() + std::string(",") + String(EorW).c_str();
appendStringToSPIFFS(filename, Message);
beurt = 1;
}
else if(beurt == 4)
{
beurt = 3;
}
// opslaan
//appendStringToSPIFFS(filename, Message);
// notify changed value
if (deviceConnected)
{
beurt = 0;
std::string dataRead = readStringFromSPIFFS(filename);
pCharacteristic->setValue(dataRead);
pCharacteristic->notify();
value++;
delay(1000);
}
// disconnecting
if (!deviceConnected && oldDeviceConnected)
{
delay(500); // give the bluetooth stack the chance to get things ready
beurt = 1;
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
and here are the voids for SPIFFS:
void appendStringToSPIFFS(String filename, std::string data)
{
File file = SPIFFS.open(filename, "a");
if (!file)
{
Serial.println("Failed to open file for appending");
return;
}
//file.println(data);
if (file.println(data.c_str()))
{
Serial.println("Data was appended");
}
else
{
Serial.println("Append failed");
}
file.close();
}
std::string readStringFromSPIFFS(String filename)
{
File file = SPIFFS.open(filename, "r");
if (!file)
{
Serial.println("Failed to open file for reading");
return "";
}
std::string data;
char c;
while(file.available())
{
c = file.read();
if(c == '\n')
{
break;
}
}
file.close();
Serial.println("has been read");
return data;
}
Each sensor has it's own turn to work (called "beurt" in the code). When connected via BLE, beurt becomes 0, which makes sure the sensors won't measure anything, while things are getting send.
It would be better if you posted your full sketch so that your problem can be seen in context
Unless there's something else you haven't posted, this code will not work: as it's written, oldDeviceConnected
never gets updated if it is false. The proper way to apply that pattern is to update the previous state, at every cycle, outside all conditions.
Not sure it is the bug you are experiencing, but surely will help 
First of all, I am sorry if the code is unclear.
/*
***How to connect***
*5V -> NEO-6M's VCC
*3.3V -> andere VCC
*16 -> NEO-6M's TX
*17 -> NEO-6M's RX
*21 -> SDA
*22 -> SCL
*GND -> GND & WAK
*/
// SPIFFS
#include <FS.h>;
#include <SPIFFS.h>;
// sensoren
unsigned long tijdstip;
#include <string>
int beurt;
String uitvoer;
String temp;
String druk;
String vocht;
String CO2;
String TVOC;
// CJMCU-811
#include <Adafruit_CCS811.h>
Adafruit_CCS811 ccs;
// BMP/BMP280
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define SEALEVELPRESSURE_HPA (1013.25)
bool status;
Adafruit_BME280 bme;
// NEO-6M
#include <HardwareSerial.h>
String latitude;
String NorS; // north or south
String longitude;
String EorW; // east or west
String foutmelding; // string for errors
float lat_degrees;
float lat_minutes;
float lon_degrees;
float lon_minutes;
float latitude_decimal;
float longitude_decimal;
HardwareSerial gpsSerial(2);
// Bluetooth communication
std::string Message;
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint32_t value = 0;
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
String dataToWrite;
String filename = "/data.txt";
void setup()
{
// put your setup code here, to run once:
// BLE
Serial.begin(115200);
gpsSerial.begin(9600, SERIAL_8N1, 16, 17); // Begin seriële communicatie met de GPS-module
// Create the BLE Device
BLEDevice::init("bikelogger");
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// Create a BLE Descriptor
pCharacteristic->addDescriptor(new BLE2902());
// Start the service
pService->start();
// Start advertising
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
BLEDevice::startAdvertising();
Serial.println("Waiting a client connection to notify...");
// sensoren
Serial.begin(115200);
Wire.begin();
Serial.println("Opstarten . . .");
tijdstip = millis();
//ss.begin(115200);
status = bme.begin(0x76);
if (!status)
{
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
if(!ccs.begin() == true)
{
Serial.println("Failed to start sensor! Please check your wiring.");
while(1);
}
beurt = 1;
// Initialize SPIFFS
if (!SPIFFS.begin(true))
{
Serial.println("An error occurred while mounting SPIFFS.");
return;
}
Serial.println("SPIFFS mounted successfully.");
Serial.println("temp,druk,vocht,CO2,TVOC");
}
void writeStringToSPIFFS(String filename, std::string data)
{
File file = SPIFFS.open(filename, "w");
if (!file)
{
Serial.println("Failed to open file for writing");
return;
}
if (file.print(data.c_str()))
{
Serial.println("File was written");
}
else
{
Serial.println("Write failed");
}
file.close();
}
void appendStringToSPIFFS(String filename, std::string data)
{
File file = SPIFFS.open(filename, "a");
if (!file)
{
Serial.println("Failed to open file for appending");
return;
}
//file.println(data);
if (file.println(data.c_str()))
{
Serial.println("Data was appended");
}
else
{
Serial.println("Append failed");
}
file.close();
}
std::string readStringFromSPIFFS(String filename)
{
File file = SPIFFS.open(filename, "r");
if (!file)
{
Serial.println("Failed to open file for reading");
return "";
}
std::string data;
char c;
while(file.available())
{
c = file.read();
if(c == '\n')
{
break;
}
}
file.close();
Serial.println("has been read");
return data;
}
void loop()
{
if(beurt == 1) // BME280
{
temp = bme.readTemperature();
druk = bme.readPressure() / 100.0F;
vocht = bme.readHumidity();
}
else if(beurt == 2) // CJMCU-811
{
if(ccs.available() == true)
{
float temp = ccs.calculateTemperature();
if(ccs.readData())
{
CO2 = ccs.geteCO2();
TVOC = ccs.getTVOC();
Serial.println(uitvoer);
}
else
{
while(1);
}
}
}
else if(beurt == 3) // NEO-6M
{
if (gpsSerial.available())
{ // Check if sensor is ready
String gpsData = gpsSerial.readStringUntil('\n');
// Check if the message starts with "$GPGGA"
if (gpsData.startsWith("$GPGGA"))
{
// Split string at each comma
int index = 0;
String data[15]; // there are 15 fields in a $GPGGA message
while (gpsData.length() > 0)
{
int commaIndex = gpsData.indexOf(',');
if (commaIndex > 0)
{
data[index] = gpsData.substring(0, commaIndex);
gpsData = gpsData.substring(commaIndex + 1);
}
else
{
data[index] = gpsData; // Last field
gpsData = "";
}
index++;
}
latitude = data[2];
NorS = data[3]; // north or south
longitude = data[4];
EorW = data[5]; // east or west
foutmelding = data[6];
// Convert to decimal
lat_degrees = latitude.substring(0, 2).toFloat();
lat_minutes = latitude.substring(2).toFloat();
lon_degrees = longitude.substring(0, 3).toFloat();
lon_minutes = longitude.substring(3).toFloat();
// Combine degrees and minutes
latitude_decimal = lat_degrees + (lat_minutes / 60.0);
longitude_decimal = lon_degrees + (lon_minutes / 60.0);
tijdstip = millis();
}
}
else if(millis() - tijdstip < 10000)
{
beurt = 4;
}
else
{
//Serial.println("request timed out");
}
}
if(beurt == 1)
{
Message = String(beurt).c_str() + std::string(",") + String(temp).c_str() + std::string(",") + String(druk).c_str() + std::string(",") + String(vocht).c_str();
appendStringToSPIFFS(filename, Message);
beurt = 2;
}
else if(beurt == 2)
{
Message = String(beurt).c_str() + std::string(",") + String(CO2).c_str() + std::string(",") + String(TVOC).c_str();
appendStringToSPIFFS(filename, Message);
beurt = 3;
}
else if(beurt == 3)
{
Message = String(beurt).c_str() + std::string(",") + String(latitude_decimal).c_str() + std::string(",") + String(NorS).c_str() + std::string(",") + String(longitude_decimal).c_str() + std::string(",") + String(EorW).c_str();
appendStringToSPIFFS(filename, Message);
beurt = 1;
}
else if(beurt == 4)
{
beurt = 3;
}
// saving
//appendStringToSPIFFS(filename, Message);
//THIS IS CURRENTLY DONE IN THE PREVIOUS IF ELSE BECAUSE OF DEBUGGING
// notify changed value
if (deviceConnected)
{
beurt = 0;
std::string dataRead = readStringFromSPIFFS(filename);
pCharacteristic->setValue(dataRead);
pCharacteristic->notify();
value++;
delay(1000);
}
// disconnecting
if (!deviceConnected && oldDeviceConnected)
{
delay(500); // give the bluetooth stack the chance to get things ready
beurt = 1;
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected)
{
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}
I hope my code isn't too disorganized.
Hello.
I meanwhile did find out that the problem happens in this method;
std::string readStringFromSPIFFS(String filename)
{
File file = SPIFFS.open(filename, "r");
if (!file)
{
Serial.println("Failed to open file for reading");
return "";
}
std::string data;
char c;
while(file.available())
{
c = file.read();
if(c == '\n')
{
break;
}
}
file.close();
Serial.println("has been read");
return data;
}
It returns data, but If I check it by printing it in Serial monitor, it just prints an empty line.
Why does this happen?
Thanks for clearing it up for me!
In this function you define data
, then you read the file one char at a time into c
until you find a newline or EOF, then you return data
- which is just sitting there waiting for some love. I think you're just missing an "add this c
to data
" bit 
Ah, yes, thank you!
This will help me for sure! I will test this out right away.
Once again thank you very much
1 Like
This was the solution. I thank you for your time.
1 Like