IoT33 Bluetooth no data exchange when using serialcomm and BlueTooth

I have interconnected an Arduino IoT33 with an ESP32 through serial comm so WiFi link with a remote repository is independent of a data collection of several sensors attached to an IoT33.
I have been able to connect my SmartPhone BlueTooth to the Arduino IoT33 central and have exchanged data through the comm port of both the IoT33 and the ESP32

However, when trying to exchange both data sets, i.e. through the serial commport and the blue tooth, the latter does not send any data out. I am using a WHILE control loop to keep the Blue tooth connected for BlueTooth data exchange and a function to access the commport for data exchange with the ESP32 within the while control loop.

Only the serial comm sends data, but the Blue tooth does not. If the function regarding the serial comm is "commented" only then the Blue Tooth sends data out. In Brief, although the serial comm sends data out and the Blue Tooth has its connection path established, NO DATA is sent out through the IoT33´'s Blue Tooth device.

Does somebody have documentation on the subject or maybe has had a similar issue and was able to sort it out?

Thanks in advance

The while control loop in t he main loop of my sketch, as follows:

while (central.connected())
  {
    long curMillis = millis();
    if (preMillis > curMillis) 
    {
      preMillis = 0; // millis() rollover?
    }
    if (curMillis - preMillis >= 6000)      // check values every 500mS .... Originally was 10 ms (JPV changed it)
      // If the time slot is too short, the APP at the Mobile Phone behaves unstable
    {
      preMillis = curMillis;

      Serial.println("Within the CENTRAL CONNECTED loop");
     
      ReadAllSensors();
      BuildDDBBMessage();
      //ReadWriteSERCOMM2();

      //**** Refreshing Data sent to the Blue Tooth 
                    
                     SGP40_VOC=0;                 // Must delete later, when SGP40 working
                                           
                     String axx="Oct.06.2021 - 12.08.22";                 // Test Purpose Date nd time here, but in String Format
                      
                      //ax=101;                   // Date & Time          // **** Originaly used in the place of axx in the SendDataToApp() FUNCTION
                      
                      ay=float(CO2);              // CO2 [PPM]
                      az=float(SGP40_VOC);        // VOC Index
                      gx=BME280Temperature;       // Temperature [°C]
                      gy=BME280Pressure/100;      // Pressure [hPa]    
                      gz=BME280_RH;               // RH [%]
                      ba=float(CO2);              // Used to present CO2 Level together with Warning Message
                      bap=bapPercentage;          // Hazard Percentage [%]
         
         // ***   END measurements transfered into Main Variables ***
         
         SendDataToApp(axx, ay, az, gx, gy, gz, ay, bap); // Blue Tooth Data refresh function                 
         ReadWriteSERCOMM2();      

        //**** End of Data refresh 
    }   // ***End of IF loop, regarding millis delay
}  // ***End of loop of Central Connected

}
else
{
  // central disconnected:
  digitalWrite(LED_BUILTIN, LOW);
  Serial.print(F("Disconnected from central: "));
  Serial.println(central.address());
  // no central

  ReadAllSensors();
  BuildDDBBMessage();
  ReadWriteSERCOMM2();

}

}

Welcome to the forum.

Please post your complete sketch and use code tags to ensure the source code is in a single box. It should look like this.

// Your example source code

You need three ' at the beginning and end in the edit window? When you click on this icon </> you get.

```
type or paste code here
```

Something I noted in your code. You are using long data type and worry about roll over of millis(). There is no need for that when you use unsigned long / uint32_t data type and math. The millis() function returns unsigned long and unsigned long math handles the overflow correctly.

Regarding BLE, BLE peripherals do not send out data. BLE peripherals update their characteristics. If the characteristic has notification enabled and a connected central has subscribed to the notification it will be notified. Then the central device can automatically read the characteristic, but it can chose not to do that.

Hi Klaus_K, thanks for your comments - My full sketch, down below. Regarding the millis(), understood and THX for the advice.

With respect of my expression "data sent out from the blue tooth ... " or similar, I was referring to the data passed through the function in my sketch<< SendDataToApp(axx, ay, az, gx, gy, gz, ay, bap); >> .

The issue with the sketch is that whenever serial comm function is used within the BlueTooth while control loop, no refresh is received at the App on my smrtphone (I am using LightBlue App); however, if the serial comm function is commented (not included within the loop), the App in the smartphone refreshes the data whatsoever !

I have used the following reference for most of my IoT33 code =>

Beginning Arduino
Nano 33 IoT
Step-By-Step Internet of Things
Projects
Agus Kurniawan

ISBN-13 (pbk): 978-1-4842-6445-4 ISBN-13 (electronic): 978-1-4842-6446-1
https://doi.org/10.1007/978-1-4842-6446-1


// Libraries
#include <ArduinoBLE.h> // Arduino BLE library
#include <Wire.h> // Needed for MUX & CSS811 CO2 Sensor & BME280 Sensor
#include "RTClib.h" // Needed for RTC
#include <Arduino.h> // Needed for UART
#include "wiring_private.h" // Included toreassign GPIO pins UART
#include <SPI.h> // Needed for CSS811 CO2 Sensor
#include <sSense-CCS811.h> // Needed for CSS811 CO2 Sensor
#include <BME280I2C.h> // Needed for BME280 Sensor
#include "sgp40_voc_index.h" // Include Sensirion SGP40 Library


//+++++++++++++++++  Include Class BLEStringCharacteristic ++++++++++++++++++++++++++

#ifndef _BLE_STRING_CHARACTERISTIC_H_
#define _BLE_STRING_CHARACTERISTIC_H_

#include <Arduino.h>

#include "BLECharacteristic.h"

class BLEStringCharacteristic : public BLECharacteristic
{
  public:
    BLEStringCharacteristic(const char* uuid, unsigned char properties, int valueSize);

    int writeValue(const String& value);
    int setValue(const String& value) { return writeValue(value); }
    String value(void);

  private:
};

#endif



//+++++++++++++++++  END of Include Class BLEStringCharacteristic ++++++++++++++++++++++++++



RTC_DS3231 rtc;
BME280I2C bme;         // Default : forced mode, standby time = 1000 ms

//--------------------------------------------------------------------------------------------------------------------------------------
//  Peripheral ID
//--------------------------------------------------------------------------------------------------------------------------------------
String PeripheralID = "LUFTBM-0001"; // This ID must be changed before compiling so scketch upload includes the PeripheralID
# define BlueToothID "LUFTBM-0003"

//--------------------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------------------
//  Sensor-Device addressing {sensor_0(RTC), sensor_1(BME280) ... sensor_6(SGP40), sensor_7(CO2)} -- NDIR CO2 sensor works through UART
//--------------------------------------------------------------------------------------------------------------------------------------
bool EnableDeviceI2C[8] = {true, true, false, false, false, false, true, true};
bool EnableDeviceUART[3] = {true, false, false};
String DeviceID[11] = {"RTC - DS3231", "TPH - BME280", "", "", "",  "",  "VOC Index; T & H - SGP40", "CO2 - CCS811", "CO2 - MH-Z19C", "",  "",};
//--------------------------------------------------------------------------------------------------------------------------------------

//--- RTC Variables --------------------------------------------------------------------------------------------------------------------
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// -------------------------------------------------------------------------------------------------------------------------------------

// --- Varibles FAN CONTROL  -----------------------------------------------------------------------------------------------------------
const int FanControlPin = 9;   // Naming FAN CONTROL OUTPUT pin
// -------------------------------------------------------------------------------------------------------------------------------------

// --- Varibles UART  ------------------------------------------------------------------------------------------------------------------
// Serial COMM 1 for communication with NDIR
byte outByte[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
byte inputData[9];
int bufferLength = 9;
int CO2, CO2_Test;
int CalFlag = 0;

// Serial COMM 1 for 33IoT link to ESP32
String MessageOut, I_MessageOut;
String Scontador;
String CentinelIoT33 = "RQ";
int contador;

// Serial COMM for 33IoT for Pin reassignment
Uart mySerial (&sercom0, 5, 6, SERCOM_RX_PAD_1, UART_TX_PAD_0);

// ---END Vaiables COMMPORT ------------------------------------------------------------------------------------------------------------

// -------------------------------------------------------------------------------------------------------------------------------------
//     Variables BlueTooth
// -------------------------------------------------------------------------------------------------------------------------------------
static float ax, ay, az, gx, gy, gz, ba, bap, bapPercentage;
String S_ax;

float BME280Temperature, BME280Pressure, BME280_RH, SGP40_Temperature, SGP40_Pressure;
int NDIR_PPM, SGP40_VOC;

int PPM_ALARM_Base = 1100; // Reference level for ALARM warning

// --- END Variables BlueTooth --------------------------------------------------------------------------------------------------------

// -------------------------------------------------------------------------------------------------------------------------------------
//     Variables DataMessage
// -------------------------------------------------------------------------------------------------------------------------------------
String MessageString;                                                              // Message Builder

String sep = "|";                                                                  // Message Fileds Separator

String S_BME280Temperature, S_BME280Pressure, S_BME280_RH, S_SGP40_Temperature;    // BME280  (TPH Sensor)
String S_SGP40_Pressure, S_SGP40_VOC;                                              // SGP40   (Air Quality Sensor)
String S_NDIR_PPM;                                                                 // MHC19-C (CO2 Sensor)
String S_year, S_month, S_day, S_dayOfTheWeek, S_hour, S_minute, S_second;         // RTC (Real Time CLock)
// --- END Variables DataMessage --------------------------------------------------------------------------------------------------------

//=====================================================================================================================================
//         BlueTooth CONFIGURATION
//=====================================================================================================================================

// UUid for Service
const char* UUID_serv = "84582cd0-3df0-4e73-9496-29010d7445dd";

// UUids for RTC(ax) - NDIR CO2 PPM(ay) - SGP40 VOC_Index(az) -

//const char* UUID_ax   = "84582cd1-3df0-4e73-9496-29010d7445dd";
const char* UUID_ax   = "84582cd1-3df0-4e73-9496-29010d7445dd";

const char* UUID_ay   = "84582cd2-3df0-4e73-9496-29010d7445dd";
const char* UUID_az   = "84582cd3-3df0-4e73-9496-29010d7445dd";

// UUids for BME280 Temperature(gx)-Pressure(gy)-RH(gz)
const char* UUID_gx   = "84582cd4-3df0-4e73-9496-29010d7445dd";
const char* UUID_gy   = "84582cd5-3df0-4e73-9496-29010d7445dd";
const char* UUID_gz   = "84582cd6-3df0-4e73-9496-29010d7445dd";

// UUid for Alarm_Status(bap) & Device_Status(Ba)
const char* UUID_bap  = "84582cd7-3df0-4e73-9496-29010d7445dd";
const char* UUID_ba   = "84582cd8-3df0-4e73-9496-29010d7445dd";

// BLE Service
BLEService myService(UUID_serv);

// BLE Characteristics
//BLEFloatCharacteristic  chAX(UUID_ax,  BLERead|BLENotify);

BLEStringCharacteristic chAX(UUID_ax,  BLERead | BLENotify, 15);

BLEFloatCharacteristic  chAY(UUID_ay,  BLERead | BLENotify);
BLEFloatCharacteristic  chAZ(UUID_az,  BLERead | BLENotify);
BLEFloatCharacteristic  chGX(UUID_gx,  BLERead | BLENotify);
BLEFloatCharacteristic  chGY(UUID_gy,  BLERead | BLENotify);
BLEFloatCharacteristic  chGZ(UUID_gz,  BLERead | BLENotify);
BLEFloatCharacteristic chBAP(UUID_bap, BLERead | BLENotify);
BLEFloatCharacteristic  chBA(UUID_ba,  BLERead | BLENotify);

//====== END BlueTooth CONFIGURATION ===================================================================================================


//------ Function => Retrieve Data from all sensors ----------------------------------------------------------------------------------------

void ReadAllSensors()
{

  //----- Readings of all all sensors & RTC attached to the TCA9548A Multiplexer ----------------------------------------------------------
  if (EnableDeviceI2C[0] == true) //RTC
  {
    TCA9548A(0);
    Serial.print("I2C MUX Address [0] ");
    Serial.print(DeviceID[0]);
    Serial.print(" ");

    DateTime now = rtc.now();

    Serial.print("Current Date & Time: ");
    Serial.print(now.year(), DEC);
    S_year = String(now.year());
    Serial.print('/');
    Serial.print(now.month(), DEC);
    S_month = String(now.month());
    Serial.print('/');
    Serial.print(now.day(), DEC);
    S_day = String(now.day());
    Serial.print(" (");
    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    S_dayOfTheWeek = String(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(now.hour(), DEC);
    S_hour = String(now.hour());
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    S_minute = String(now.minute());
    Serial.print(':');
    Serial.print(now.second(), DEC);
    S_second = String(now.second());
    Serial.println();
    Serial.println("-------------------------------------------------------------------------------------------------------------------------------------------------");

    delay(2000);
  }
  else
  {
    Serial.print("I2C MUX Address [0] ");
    Serial.print(DeviceID[0]);
    Serial.println("    - D I S A B L E D ");
    delay (500);
  }

  if (EnableDeviceI2C[1] == true)  // BME280
  {
    Serial.print("I2C MUX Address [1] ");
    Serial.print(DeviceID[1]);
    Serial.print(" ");

    TCA9548A(1);
    printBME280Data(&Serial);
    Serial.println("-------------------------------------------------------------------------------------------------------------------------------------------------");

    delay(2000);

  }
  else
  {
    Serial.print("I2C MUX Address [1] ");
    Serial.print(DeviceID[1]);
    Serial.println("    - D I S A B L E D ");
    delay (500);
  }

  /*
     if (EnableDeviceI2C[2] == true)
     {
       Serial.print("I2C MUX Address [2] ");
       Serial.print(DeviceID[2]);
     }
     else
     {
       Serial.print("I2C MUX Address [2] ");
       Serial.print(DeviceID[2]);
       Serial.println("    - D I S A B L E D ");
     }

     if (EnableDeviceI2C[3] == true)
     {
       Serial.print("I2C MUX Address [3] ");
       Serial.print(DeviceID[3]);
       DebugPort.println("-------------------------------------------------------------------------------------------------------------------------------------------------");

       delay(1000);
     }
     else
     {
       Serial.print("I2C MUX Address [3] ");
       Serial.print(DeviceID[3]);
       Serial.println("    - D I S A B L E D ");
     }

     if (EnableDeviceI2C[4] == true)
     {
       Serial.print("I2C MUX Address [4] ");
       Serial.print(DeviceID[4]);
       DebugPort.println("-------------------------------------------------------------------------------------------------------------------------------------------------");

       delay(1000);
     }
     else
     {
       Serial.print("I2C MUX Address [4] ");
       Serial.print(DeviceID[4]);
       Serial.println("    - D I S A B L E D ");
     }

     if (EnableDeviceI2C[5] == true)
     {
       Serial.print("I2C MUX Address [5] ");
       Serial.print(DeviceID[5]);
       DebugPort.println("-------------------------------------------------------------------------------------------------------------------------------------------------");

       delay(1000);
     }
     else
     {
       Serial.print("I2C MUX Address [5] ");
       Serial.print(DeviceID[5]);
       Serial.println("    - D I S A B L E D ");
     }
  */

  // Next section - Disconnected until SGP40 is read withput crashing with TCA9548A MULTIPLEXER
  /*
  if (EnableDeviceI2C[6] == true)  // SGP40
  {
    Serial.print("I2C MUX Address [6] ");
    Serial.print(DeviceID[6]);
    Serial.println(" ");

    TCA9548A(6); // MUX Port access N(6)

    int16_t err;
    int32_t voc_index;
    int32_t temperature_celsius;
    int32_t relative_humidity_percent;
    err = sensirion_measure_voc_index_with_rh_t(&voc_index, &relative_humidity_percent, &temperature_celsius );
    if (err == STATUS_OK)
    {
      Serial.print("VOCindex:");
      Serial.print(voc_index);
      Serial.print("\t");
      Serial.print("Humidity[%RH]:");
      Serial.print(relative_humidity_percent * 0.001f);
      Serial.print("\t");
      Serial.print("Temperature[degC]:");
      Serial.println(temperature_celsius * 0.001f);
      Serial.println("-------------------------------------------------------------------------------------------------------------------------------------------------");

    }
    else
    {
      Serial.print("error reading signal: ");
      Serial.println(err);
    }

    sensirion_sleep_usec(1000000); // wait one second /
  }
  else
  {
    Serial.print("I2C MUX Address [6] ");
    Serial.print(DeviceID[6]);
    Serial.println("    - D I S A B L E D ");
  }

*/

  /*
    if (EnableDeviceI2C[7] == true)  // CSS811 CO2 sensor
    {
      Serial.print("I2C MUX Address [7] ");
      Serial.print(DeviceID[7]);

      TCA9548A(7);

      ssenseCCS811.setEnvironmentalData((float)(21.102), (float)(57.73));  // replace with temperature and humidity values from HDC2010 sensor

      if (ssenseCCS811.checkDataAndUpdate())
      {
        DebugPort.print("CO2 ");
        DebugPort.print(ssenseCCS811.getCO2());
        DebugPort.print("[PPM] tVOC ");
        DebugPort.print(ssenseCCS811.gettVOC());
        DebugPort.print(" millis ");
        DebugPort.print(millis());
        DebugPort.print("[millis]");
        DebugPort.println();
      }
      else if (ssenseCCS811.checkForError())
      {
        ssenseCCS811.printError();
      }

      Serial.println("-------------------------------------------------------------------------------------------------------------------------------------------------");

      delay(2000);
    }
    else
    {
      Serial.print("I2C MUX Address [7] ");
      Serial.print(DeviceID[7]);
      Serial.println("    - D I S A B L E D ");
      DebugPort.println("-------------------------------------------------------------------------------------------------------------------------------------------------");

      delay(2000);
    }

  */

  if (EnableDeviceUART[0] == true)  // NDIR CO2 Sensor
  {
    Serial.print("UART Address    [0] ");
    Serial.print(DeviceID[8]);
    Serial.print(" ");

    for (int x = 0; x <= 8; x++)
    {
      Serial1.write(outByte[x]);
    }

    for (int z = 0; z <= 8; z++)
    {
      inputData[z] = Serial1.read();
    }

    CO2 = ( (inputData[2] * 256) + inputData[3] );

    // aqui insertar calibracion

    if (CalFlag > 4)
    {
      Serial.print("CO2 Concentration: ");
      Serial.print(CO2);
      Serial.println(" [PPM]");
      Serial.println("-------------------------------------------------------------------------------------------------------------------------------------------------");

      delay(1000);
    }
    else
    {
      Serial.println("Initialising NDIR CO2 sensor ...");
      Serial.println("-------------------------------------------------------------------------------------------------------------------------------------------------");
      CalFlag = CalFlag + 1;
    }



  }
  else
  {
    Serial.print("UART Address [0] ");
    Serial.print(DeviceID[8]);
    Serial.println("    - D I S A B L E D ");
  }

  //Serial.println("-----------------------------------------------------------------------------------------------------------------------------------------------------------------");


}
//-----------------------------------------------------------------------------------------------------------------------------------------



//------ Function => BlueTooth Data TX for Data Refresh loop ----------------------------------------------------------------------------------------

void SendDataToApp(String ax1, float ay1, float az1, float gx1, float gy1, float gz1, float ba1, float bap1)
{
  String ax;
  static float ay, az, gx, gy, gz, ba, bap;

  ax = ax1;
  ay = ay1;
  az = az1;
  gx = gx1;
  gy = gy1;
  gz = gz1;
  ba = ba1;
  bap = bap1;

  //RTC - CO2 PPm - VOC Index
  chAX.writeValue(ax);
  chAY.writeValue(ay);
  chAZ.writeValue(az);

  //BME280 : Temperature/Pressure/RH
  chGX.writeValue(gx);
  chGY.writeValue(gy);
  chGZ.writeValue(gz);

  // send Alarm Status
  chBA.writeValue(ba);

  // send Device status
  chBAP.writeValue(bap); // ALARM Percentage [%]

}

//----- END Function => Blue Tooth Data TX for Data Refresh loop ----------------------------------------------------------------------------------

//======================================================================================================================================
//I2C Mutiplexing setup using TCA9548A MUX
//======================================================================================================================================
void TCA9548A(uint8_t I2C_bus)
{
  Wire.beginTransmission(0x70);
  Wire.write(1 << I2C_bus);
  Wire.endTransmission();
}
//======================================================================================================================================

//===== BME280 Readings Function =======================================================================================================

void printBME280Data
(
  Stream* client
)
{
  float temp(NAN), hum(NAN), pres(NAN);

  BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
  BME280::PresUnit presUnit(BME280::PresUnit_Pa);

  bme.read(pres, temp, hum, tempUnit, presUnit);

  client->print("Temp: ");
  client->print(temp);
  client->print("°" + String(tempUnit == BME280::TempUnit_Celsius ? 'C' : 'F'));
  client->print("\t\tHumidity: ");
  client->print(hum);
  client->print("% RH");
  client->print("\t\tPressure: ");
  client->print(pres);
  client->println(" Pa");

  BME280Temperature = float(temp);
  BME280Pressure = float(pres);
  BME280_RH = float(hum);

}
//===== END BME280 Readings Function ===================================================================================================

// ===== Build message for the DataBase ===================================================================================================
void BuildDDBBMessage()
{
  S_NDIR_PPM = String(CO2);
  S_BME280Temperature = String(BME280Temperature);
  S_BME280Pressure = String(BME280Pressure);
  S_BME280_RH = String(BME280_RH);
  S_SGP40_Temperature = String(SGP40_Temperature);
  S_SGP40_Pressure = String(SGP40_Pressure);
  S_SGP40_VOC = String(SGP40_VOC);

  // RTC variables => (S_year,S_month,S_day,S_dayOfTheWeek,S_hour,S_minute,S_second)
  // are loaded within the RTC function, for RTC variable are MAIN programe variables (Global within this same sketch)

  MessageString = "MHD" + sep + S_year + sep +  S_month + sep +  S_day + sep +  S_dayOfTheWeek + sep +  S_hour + sep + S_minute + sep + S_second + sep + S_NDIR_PPM + sep + S_BME280Temperature + sep + S_BME280Pressure + sep + S_BME280_RH + sep + S_SGP40_Temperature + sep +  S_SGP40_Pressure + sep +  S_SGP40_VOC + sep + "END";

}
// ===== END Build message to send to the DataBase ================================================================================================

// ===== Communication protocl for COMMPORT N2 ======

void HandShakeIoT33()
{
  String PRQ33 = "";
  String RQ = "RQ";
  bool Protocol33OK = false;



  // ***** Flushing the commport buffer **************
  if (mySerial.available())         // clears out any junk
  {
    do {
      byte junk = mySerial.read();
    }
    while (mySerial.available() > 0);
  }
  //********************************************************************************


  Serial.println("System Start");
  delay(2000);

  int z = 0; // Consider deleting - JPV
  while (!Protocol33OK)
  {
    z = ++z;
    mySerial.println(RQ + '\n');
    Serial.println(String(z) + " | HandShaking in Progress .. Sending " + RQ + " - Waiting for ACK");
    delay(500);

    if (mySerial.available())
    {
      PRQ33 = ""; // consider deleting - JPV **************************

      PRQ33 = mySerial.readStringUntil('\n');
    }
    Serial.print(" PRQ33 ");  // consider delete JPV **************************
    Serial.println(PRQ33);    // consider delete JPV **************************
    if (PRQ33 == "ACK")
    {
      Protocol33OK = true;
      Serial.println("Running & Engaged to ESP32");
    }
    else
    {
      delay(500);
    }
  }

  Serial.println("Engaged to ESP32");
}

// Attach the interrupt handler to the SERCOM
void SERCOM0_Handler()
{
  mySerial.IrqHandler();
}

//==========================================================

//===== Read and write to serial COMM N2 ===================
void ReadWriteSERCOMM2()
{
  // Do something with mySerial...

  contador = contador + 1;
  Scontador = String(contador);

  //************Consider reviewing ... Here we are posting real data to the ESP32 // I_MessageOut is a fix String for test purposes only!  *****
  //MessageOut=I_MessageOut+" | "+Scontador;
  MessageOut = MessageString + " || " + Scontador;
  //************Consider reviewing******************

  Serial.println(MessageOut);
  delay(200);

  mySerial.println(MessageOut + '\n');

  Serial.println("Centinel .. " + CentinelIoT33);
  mySerial.println(CentinelIoT33 + '\n');

  Serial.println("------------------------------------------------------------");
  delay(2000);

  // *************************** ATTENTION !
  // Consider deleting the contador variable and reset to contador=0 loop
  if (contador == 25000)
  {
    contador = 0;
  }
  // ***************************
}
//==========================================================

void setup()
{




  // ----- Serial COMM N2 Setup ----------------------------------------------------------------------------------------------------------

  // Reassign pins 5 and 6 to SERCOM alt
  pinPeripheral(5, PIO_SERCOM_ALT);
  pinPeripheral(6, PIO_SERCOM_ALT);

  // Start my new hardware serial
  mySerial.begin(9600);

  // delete this next sentence --- JPV
  //I_MessageOut="MHD|Anillo la Cumbre 1265|LBM-00003|Tag1|00:00:00:00:00:00|2021|5|17|Monday|22|5|16|0|23.58|913.12|35.29|0.00|0.00|0|EOM";

  Serial.println("Initialising 33IoT");
  delay(3000);
  HandShakeIoT33();

  // -------------------------------------------------------------------------------------------------------------------------------------

  // ----- BlueTooth SetUp ---------------------------------------------------------------------------------------------------------------
  // Variables initialisation
  //ax1=("02.05.2021/22.24.17");

  ax = 0; // Date & Time
  ay = 0; // CO2 [PPM]
  az = 0; // VOC Index
  gx = 0; // Temperature [°C]
  gy = 0; // Pressure [hPa]
  gz = 0; // RH [%]
  ba = 0; // Used to present CO2 Level together with Warning Message
  bap = 0; // Hazard Percentage [%]

  //**********************************
  /*
    Serial.begin(115200);
    uint32_t t=millis();
    while (!Serial) // wait 5 seconds for serial connection
      {
      if ((millis()-t) > 5000) break;
      }
  */

  //**********************************


  bool err = false;
  pinMode(LED_BUILTIN, OUTPUT); // onboard led
  digitalWrite(LED_BUILTIN, LOW); // led off

  // init BLE
  if (!BLE.begin())
  {
    Serial.println("BLE: failed");
    err = true;
  }
  Serial.println("BLE: ok");

  // error: flash led forever
  if (err)
  {
    Serial.println("Init error. System halted");
    while (1)
    {
      digitalWrite(LED_BUILTIN, HIGH); // led on
      delay(500);
      digitalWrite(LED_BUILTIN, LOW); // led off
      delay(500);
    }
  }

  // BLE service
  // correct sequence:
  // set BLE name > advertised service > add characteristics > add service > set initial values > advertise

  // Set BLE name
  //BLE.setLocalName("LuftBM");
  BLE.setLocalName(BlueToothID);
  BLE.setDeviceName("Arduino"); // Arduino is the default value on this module

  // Set advertised Service
  BLE.setAdvertisedService(myService);

  // Add characteristics to the Service
  myService.addCharacteristic(chAX);
  myService.addCharacteristic(chAY);
  myService.addCharacteristic(chAZ);
  myService.addCharacteristic(chGX);
  myService.addCharacteristic(chGY);
  myService.addCharacteristic(chGZ);
  myService.addCharacteristic(chBAP);
  myService.addCharacteristic(chBA);

  // add service to BLE
  BLE.addService(myService);

  // characteristics initial values
  chAX.writeValue("0");
  chAY.writeValue(0);
  chAZ.writeValue(0);
  chGX.writeValue(0);
  chGY.writeValue(0);
  chGZ.writeValue(0);
  chBAP.writeValue(0);
  chBA.writeValue(0);

  // start advertising
  BLE.advertise();
  Serial.println("Advertising started");

  // ----- END BlueTooth SetUp -----------------------------------------------------------------------------------------------------------

  // ------ Initialise FAN digital pin ---------------------------------------------------------------------------------------------------

  //while (!Serial); //while the serial stream is not open, do nothing - This is to enable printing one time at the beginning of the Serial Monitor:

  pinMode(7, OUTPUT);
  pinMode(FanControlPin, OUTPUT);
  delay(1000);
  Serial.println("Starting the Exhaust Fan");
  digitalWrite(7, HIGH);
  delay(2000);
  Serial.println("   (1) FAN Acknowledgement Request");
  delay(1000);
  delay(1000);
  Serial.println("   (2) Request Acknowledged!");
  digitalWrite(7, LOW);
  delay(1000);
  digitalWrite(FanControlPin, HIGH);   // Turn ON the FAN (HIGH is the voltage level to the Gate of the MOSFET DRIVER)
  Serial.println("   (3) Activating FAN");
  delay(2000);
  Serial.println("Fan Running");
  //---------------------------------------------------------------------------------------------------------------------------------------

  /*
    Serial.println("-------------------------------------------------------------------------------------------------------------------------------------------------");
    Serial.println("                                                LuftBioMonitor - Peripheral Configuration Check");
    Serial.println("-------------------------------------------------------------------------------------------------------------------------------------------------");
    Serial.println("");

    for (int x = 0; x <= 7; x++)
    {
      if (EnableDeviceI2C[x] == true)
      {
        Serial.print("I2C MUX Address [x] ");
        Serial.print(DeviceID[x]);
        Serial.println(" ... ENABLED ");
        //delay (500);
      }
      else
      {
        Serial.print("I2C MUX Address [x] ");
        Serial.print(DeviceID[x]);
        Serial.println("    - D I S A B L E D ");
        //delay (500);
      }
    }

    for (int y = 0; y <= 2; y++)
    {
      if (EnableDeviceUART[y] == true)
      {
        Serial.print("UART Address    [2] ");
        Serial.print(DeviceID[8 + y]);
        Serial.println("... ENABLED ");
      }
      else
      {
        Serial.print("UART Address    [2] ");
        Serial.print(DeviceID[8 + y]);
        Serial.println("    - D I S A B L E D ");
      }
    }

  */

  //=======================================================================================================================================
  //Start I2C channel for TCA9548A MUX
  //=======================================================================================================================================
  Wire.begin();  // I2C start
  TCA9548A(0);   // RTC Device Address at the TCA9548A MUX
  TCA9548A(1);   // BME280 THP Sensor Device Address at the TCA9548A MUX
  TCA9548A(6);   // SGP40 THP Sensor Device Address at the TCA9548A MUX

  //========================================================================================================================================

  Serial.println("=================================================================================================================================================");
  delay(1000);

  // *** Void_Setup RTC
  //================================================
  //Start I2C channel for TCA9548A MUX
  //================================================
  Wire.begin();  // I2C start
  TCA9548A(0);   // RTC Device Addres at the TCA9548A MUX
  //================================================

  Serial.begin(9600);
  delay(500); // wait for console opening

  // In case time set lost, force time set through the following command... Only one time
  // Function structure => ***** DateTime(year, month, day, hour, min, sec))*****
  //rtc.adjust(DateTime(2021, 3, 1, 10, 30, 0));

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");

    // Comment out below lines once you set the date & time.
    // Following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

    // Following line sets the RTC with an explicit date & time
    // for example to set January 27 2017 at 12:56 you would call:
    //rtc.adjust(DateTime(2021, 3, 1, 10, 30, 0));
  }
  //----- END Void_Setup RTC --------------------------------------------------------------------------------------------------------------

  //----- Void_Setup BME280 ---------------------------------------------------------------------------------------------------------------

  Wire.begin();
  TCA9548A(1);

  while (!bme.begin())
  {
    Serial.println("Could not find BME280 sensor!");
    delay(1000);
  }

  // bme.chipID(); // Deprecated. See chipModel().
  switch (bme.chipModel())
  {
    case BME280::ChipModel_BME280:
      Serial.print(""); //"Found BME280 sensor! Success."
      break;
    case BME280::ChipModel_BMP280:
      Serial.println("Found BMP280 sensor! No Humidity available.");
      break;
    default:
      Serial.println("Found UNKNOWN sensor! Error!");
  }

  // ----- END Void_Setup BME280 ----------------------------------------------------------------------------------------------------------

  // ----- Void_Setup SGP40 ---------------------------------------------------------------------------------------------------------------

  /*
    Wire.begin();
    TCA9548A(6);

    //    int16_t err;
    //     Serial.begin(115200);  // start serial for output

    // wait for serial connection from PC
    // comment the following line if you'd like the output
    // without waiting for the interface being ready
             //while(!Serial);

    // Initialize I2C bus, SHT, SGP and VOC Engine

             while ((err = sensirion_init_sensors()))
             {
               Serial.print("initialization failed: ");
               Serial.println(err);
               sensirion_sleep_usec(1000000); // wait one second /
             }

    Serial.println("initialization successful");

  */

  //----- END Void_Setup SGP40 -------------------------------------------------------------------------------------------------------------

  //----- Void_Setup UART ------------------------------------------------------------------------------------------------------------------
  Serial1.begin(9600, SERIAL_8N1);   // Tx - Rx Port Setup & Initialisation (Pins 1 and 2 Arduino Nano 33IoT)

  //----- END Void_Setup UART (Down Below) -------------------------------------------------------------------------------------------------
}


void loop()
{

  static long preMillis = 0;

  // listen for BLE centrals devices
  BLEDevice central = BLE.central();


  // central device connected?
  if (central)
  {
    digitalWrite(LED_BUILTIN, HIGH);           // turn on the onboard led
    Serial.print("Connected to central: ");
    Serial.println(central.address());         // central device MAC address

    // while central is connected to BlueTooth requester
    while (central.connected())
    {

      long curMillis = millis();

      if (preMillis > curMillis) 
      {
        preMillis = 0; // millis() rollover?
      }

      if (curMillis - preMillis >= 6000)      // check values every 500mS .... Originally was 10 ms (JPV changed it)
        // If the time slot is too short, the APP at the Mobile Phone behaves unstable
      {
        preMillis = curMillis;

        Serial.println("Within the CENTRAL CONNECTED loop");
       
        ReadAllSensors();
        BuildDDBBMessage();
        //ReadWriteSERCOMM2();

        //**** Refreshing Data sent to the Blue Tooth *******************************************************************
                      
                       SGP40_VOC=0;                 // Must delete later, when SGP40 working
                                             
                       String axx="Oct.06.2021 - 12.08.22";                 // Test Purpose Date and time here, but in String Format
                        
                        //ax=101;                   // Date & Time          // **** Originaly used in the place of axx in the SendDataToApp() FUNCTION
                        
                        ay=float(CO2);              // CO2 [PPM]
                        az=float(SGP40_VOC);        // VOC Index
                        gx=BME280Temperature;       // Temperature [°C]
                        gy=BME280Pressure/100;      // Pressure [hPa]    
                        gz=BME280_RH;               // RH [%]
                        ba=float(CO2);              // Used to present CO2 Level together with Warning Message
                        bap=bapPercentage;          // Hazard Percentage [%]
           
           // ***   END measurements transfered into Main Variables ***
           
           SendDataToApp(axx, ay, az, gx, gy, gz, ay, bap); // Blue Tooth Data refresh function        
           
           ReadWriteSERCOMM2();
      
          //**** End of Data refresh ********************************************************************************************
          //*********************************************************************************************************************
     
      }   // End of IF loop, regarding millis delay 

    }  // End of loop of Central Connected

  }
  else
  {
    // central disconnected:
    digitalWrite(LED_BUILTIN, LOW);
    Serial.print(F("Disconnected from central: "));
    Serial.println(central.address());
    // no central

    ReadAllSensors();
    BuildDDBBMessage();
    ReadWriteSERCOMM2();

  }

  //----- MAIN END down Below --------------------------------------------------------------------------------------------------------------
}

The first thing I noted in your sketch is the use of delay(). This is not a good idea in general and especially when using communication stacks.
You are using the millis() function in other parts of your code, so you know how to control timing without the use of delay(). I recommend you write all your code using the millis technique. This way you can extend your code without breaking what you already have.

The else statement in line 976 is wrong. The code needs to be after the while loop. That is when the device gets disconnected.

An even better option is to use handlers to handle the BLE connections. Have a look at the example I posed in reply #2 in the following forum thread.

https://forum.arduino.cc/t/bluetooth-communications/902610/2

The example also does not use any while and therefore allows the loop function to work continuously.

Your code seems to be coming from many different places and experience levels. I would recommend to:

  • Try Tools -> AutoFormat in the IDE to get consistent indentation and code formatting. You can choose your own code style changing the formatter.conf file on your computer. The following page describes all the options:
    http://astyle.sourceforge.net/astyle.html
  • use the Arduino naming convention
    -- ALL_CAPITALS_WITH_UNDERSCORE for constants e.g., UUID_SERVICE
    -- camelCase for variables and functions e.g., readAllSensors
  • chose variables names that are easy to understand after not reading your code for a while
    -- mySerial - I do not like this mySomething stuff on microcontrollers looks like PC example programs and does not tell me what it is used for
    -- ax1, ay1 used once in a function. I would use names that tell me what is expected here. And variables that have similar names should probably be of the same type.

Regarding your BLE characteristics. Float is not a good type for public interfaces. There are different specifications for floating-point formats. The BLE SIG has used fixed point values with exponents for some defined services to show how this can be done better. This is also shown in my example and links to some further documents. This allows centrals and peripherals with different floating-point formats to work together without complicated float-to-float conversions.

1 Like

Many thanks, Klaus_K, for your advice and support - Will work on the adjustments you have suggested.

Hi Klaus, I worked on the subject during the weekend and sorted out the issue. I fixed the editing style comments, changed some variables to leave them FRIENDLY-DEFINED to somebody else. I decided to keep, though, the Blue Tooth configurations, but change the variable types as you suggested.

Regarding the BlueTooth "CENTRAL" control loop, the else position was not wrong, but the main control loop was incomplete. However, it was a brilliant HINT to discover the issue . Many thanks for this clue. Accordingly, I added a time control loop, within the else, running at a shorter refresh time (5.5 [sec]) than the BlueTooth refresh Loop (6 [sec]). I included, out of the Blue Tooth "CENTRAL" loop, ReadWriteSERCOMM2() data refresh function, so whenever a Bluetooth is not connected, the ReadWriteSERCOMM2() data refresh function keeps running indefinitely -- together with other 2 functions << ReadAllSensors() and BuildDDBBMessage() >> related to ReadWriteSERCOMM2() data refresh function --

In Brief, the control logic (GENERIC PSEUDOLANGUAGE APPROACH) is as follows:

Main Loop

      While CENTRAL Loop
           If ()  (6 seconds loop)
                 refresh loop for the BlueTooth Data // Uses Millis() Technique
           ElseIf (5.5 seconds loop)
                 refresh loop for the SERCOMM2 Data // Uses Millis() Technique
           EndIf  
      End while CENTRAL Loop

      refresh SERCOMM2 Data // Running indefinitely

End Main Loop

The final main code segment of the sketch is the following:

void loop()
{
  static long preMillis = 0;

  // listen for BLE centrals devices
  BLEDevice central = BLE.central();

  // central device connected?
  if (central)
  {
    digitalWrite(LED_BUILTIN, HIGH);           // turn on the onboard yellow led
    Serial.print("Connected to central: ");
    Serial.println(central.address());         // central device MAC address

    // while central is connected to BlueTooth requester
    while (central.connected())
    {
      long curMillis = millis(); if (preMillis > curMillis) {
        preMillis = 0;
      }

      if (curMillis - preMillis >= BT_REFRESH_GAP)  // check values every 6[s] - If the time slot is too short, the APP on the Mobile Phone behaves unstable, whatsoever!
      {
        preMillis = curMillis;
        Serial.println("Within the CENTRAL CONNECTED loop");

        ReadAllSensors();

        //**** Refreshing Data to the Blue Tooth *******************************************************************
        //**********************************************************************************************************
        SGP40_VOC = 0;                            // Must delete later, when SGP40 working
        ax = 1;                               // Date & Time **** Originaly used in the place of axx in the  () FUNCTION

        String axx = String(ax);     // Test Purpose Date and time here, but in String Format

        // ***   Sensors measurements transfered into Main Variables ***
        ay = float(CO2);                           // CO2 [PPM]
        az = float(SGP40_VOC);                    // VOC Index
        gx = BME280Temperature;                   // Temperature [°C]
        gy = BME280Pressure / 100;                // Pressure [hPa]
        gz = BME280_RH;                           // RH [%]
        ba = float(CO2);                          // Used to present CO2 Level together with Warning Message
        bapPercentage = (ba / PPM_ALARM_LEVEL) * 100;
        bap = bapPercentage;                      // Hazard Percentage [%]
        // ***   END of measurements transfered into Main Variables ***

        SendDataToApp(axx, ay, az, gx, gy, gz, ay, bap); // Blue Tooth Data refresh function

        //**** End of BlueTooth Data refresh ************************************************************************
        //**********************************************************************************************************

      } // End of IF loop, regarding millis delay fot BlueTooth refresh
      else
      {
        if ((curMillis - preMillis) > COMM2_REFRESH_GAP) // Serialcomm2 refresh, out of the CENTRAL CONNECTED loop and with a shorter refresh time, to AVOID crashing with the Blue Tooth refresh action
        {
          ReadAllSensors();
          BuildDDBBMessage();
          ReadWriteSERCOMM2();
        }
      }    // End of else of the IF loop, regarding millis delay fot BlueTooth refresh. Within the else, a shorter time loop refresh is set for the serialcomm2, that otherwise crashes with the BlueTooth refresh loop

    }  // End of loop of Central Connected (Engaged!)

  }  // End of the BlueTooth available

  // actions when central disconnected
  digitalWrite(LED_BUILTIN, LOW);
  Serial.print(F("Disconnected from central: "));
  Serial.println(central.address());
  // no central

  // Next 3 functions: sending out data to serialcomm2 by default, i.e. outside of the BlueTooth refresh loop
  ReadAllSensors();
  BuildDDBBMessage();
  ReadWriteSERCOMM2();

  //----- MAIN END --------------------------------------------------------------------------------------------------------------
}

Now I am working on the improvement of the definition of the variables for the Blue Tooth services and adding a Millis() technique delay for smoother working of the ReadWriteSERCOMM2(), at the very end of the sketch.

Thanks for your advice and support. Hope it may be useful to anybody else with similar issues.
JPV