How to broadcast data from one IoT to another IoT or BLE Sense via bluetooth

crispywisp:
I just thought the BLE has a “running” time, because when I connect to it with my phone, I could see the time gets updated every second - honest I don’t know why the time is updated when I view it on the phone.

That is the mbedOS clock. The mbedOS makers want mbedOS to be the Linux of microcontrollers. So, they added some standard OS features. We might as well use it.

crispywisp:
, because the time doesn’t update on it’s own when I unplug the IoT.

It does. There are two times. One is the mbedOS clock and one is the time written to the BLE currentTime characteristic. It is only updated when a central is connected. I rewrote the BLE_Time where you might see this more clearly.

crispywisp:
I finally got the codes incorporated in my other Arduino that needs time updates. It works flawless. Thank you!

Well done. You are welcome.

crispywisp:
But lastly, some questions again regarding the BLE sketch. I hope you don’t mind.

I do not.

crispywisp:

  1. Why is it that you separated the BLE.begin(); from the loop? Why you didn’t include them together?
    1b. What’s the difference between BLE.begin() from

The begin function only needs to be called once.

crispywisp:
2. Can you please breakdown how the following works and what do they do?
a. void updateTimeData()
b. void setupTime(void) → I don’t understand this too. void setuptime(void)?? I mean too voids? this is the first time I saw this structure.
c. void setCurrentTime(date_time_t dateTime); → I just didn’t know you can add something in the parenthesis too.

updateTimeData → It reads the clock and writes the current time to the data structure we use to update the BLE internal data.
setupTime → just set the mbedOS clock to January 1st 00:00:00
setCurrentTime → set the mbedOS clock using a date_time_t type

crispywisp:
3. Why is it that when I call printDateTime( date_time_t dateTime ), it wouldn’t work? Like…

date_time_t is a type like int, float, bool. That is why I used the _t naming convention at the end of the name.
When you call a function, you do not need specify the type. The compiler gets the type from the variable and compares it to the definition. If they do not match and it cannot be type casted you get an error.

void loop() {
  printDateTime( dateTime );
}

Have a look at the updated BLE_Time example. This now allows to add code to the loop function. It also now prints the time and the BLE time in the main loop. You can see that the BLE time is only updated when a central is connected, while the mbedOS time is updated continuously.

BLE_Time_v2.ino (8.39 KB)

I added a DST time change in the Central. I hope this will work next month.

void updateBLETimeData() {
  #define SECONDS_PER_HOUR (60 * 60)
  struct tm * getTime;
  time_t seconds = timeEpoch;

  seconds = seconds + (TIME_ZONE * SECONDS_PER_HOUR) + (DAYLIGHT_SAVING_TIME * SECONDS_PER_HOUR);
  getTime = localtime(&seconds);
  date_time_t dateTime = { getTime->tm_year + 1900,
                           getTime->tm_mon + 1,
                           getTime->tm_mday,
                           getTime->tm_hour,
                           getTime->tm_min,
                           getTime->tm_sec
                         };

  currentTimeData.currentTime.exactTime256.dayDateTime.dateTime = dateTime;
  currentTimeData.currentTime.exactTime256.dayDateTime.dayOfWeek.dayOfWeek = getTime->tm_wday + 1;
  currentTimeData.currentTime.exactTime256.fractions256 = 0;
  currentTimeData.currentTime.adjustReason = 0; //0 - Manual Time Update.

  if ((getTime->tm_mon + 1) >= 3 && (getTime->tm_mon + 1) <= 11) {
    if (startupDST == 0) {
      DAYLIGHT_SAVING_TIME = -6;
      startupDST = 1;
    }
  } else if ((getTime->tm_mon + 1) <= 2 && (getTime->tm_mon + 1) == 12) {
    if (startupDST == 0) {
      DAYLIGHT_SAVING_TIME = -5;
      startupDST = 1;
    }
  }

  if ((getTime->tm_mon + 1) == 11) {  //DST OFF.
    if ((getTime->tm_wday + 1) == 1) {
      if ((getTime->tm_hour) == 1){
        if (DSTstatus == 0) {
            DSTstatus = 1;
            DAYLIGHT_SAVING_TIME = -5;
        }
      }
    }
  } else if ((getTime->tm_mon + 1) == 3) {  //DST ON.
    if ((getTime->tm_wday + 1) == 1) {
      if ((getTime->tm_hour) == 2){
        if (DSTstatus == 1) {
          DSTstatus = 0;
          DAYLIGHT_SAVING_TIME = -6;         
        }
      }
    }
  }
}

Hello again Klaus,

I have a minor problem. I'm trying to minimize power consumption with the project I'm working on.

Here's what I've done so far:

void timeCheck() {
  static long previousMillis = 0;
  #define TIME_UPDATE_INTERVAL 1000

  //Listen for BLE peripherals to connect.
  BLEDevice central = BLE.central();
  if (central) {
    Serial.print("Connected to central: ");
    Serial.println(central.address());

    while (central.connected()) {
      if (currentTimeCharacteristic.written()) {
        currentTimeCharacteristic.readValue(currentTimeData.bytes, sizeof currentTimeData.bytes);
        setCurrentTime(currentTimeData.currentTime.exactTime256.dayDateTime.dateTime);
        Serial.println("Current Time written.");
      }

      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > TIME_UPDATE_INTERVAL) {
        previousMillis = currentMillis;

        updateTimeData();

        printDateTime(currentTimeData.currentTime.exactTime256.dayDateTime.dateTime);
        Serial.print("Central RSSI: ");
        Serial.println(central.rssi());
 
        if (central.rssi() != 0) {
          //digitalWrite(RSSI_LED_PIN, LOW);
          currentTimeCharacteristic.writeValue(currentTimeData.bytes, sizeof currentTimeData.bytes);
        //} else {
        //  digitalWrite(RSSI_LED_PIN, HIGH);
        }
      }
    }
    BLE.end();
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
  }
}

What I'm trying to do is to call timeCheck(); on a specific time, like 2:00am, turn off the BLE. And turn it on again the next day at 2:00am and sync the time. But the time sync only works once when I add the BLE.end(); at the end of timeCheck();
I don't understand why it's like that. How can I turn off the BLE after sync, and turn it on again before sync?
Thanks.

When you call BLE.end() you need to call BLE.begin() to start the BLE module again.

I tried playing around with the BLE.begin() and BLE.end(), but I can't get the time syncing again after calling BLE.end();

Can you help me figure out where to add the BLE.begin() to get it working again?

Here is the test BLE, I added it in the loop.

void loop()
{
  static long previousMillis = 0;
  #define TIME_UPDATE_INTERVAL 1000

  // listen for BLE peripherals to connect:
  BLEDevice central = BLE.central();
  if ( central )
  {
    Serial.print( "Connected to central: " );
    Serial.println( central.address() );

    while ( central.connected() )
    {

      if( currentTimeCharacteristic.written() )
      {
        currentTimeCharacteristic.readValue( currentTimeData.bytes, sizeof currentTimeData.bytes );
        setCurrentTime( currentTimeData.currentTime.exactTime256.dayDateTime.dateTime );
        Serial.println( "Current Time written." );
      }


      unsigned long currentMillis = millis();
      if( currentMillis - previousMillis > TIME_UPDATE_INTERVAL )
      {
        previousMillis = currentMillis;

        updateTimeData();

        printDateTime( currentTimeData.currentTime.exactTime256.dayDateTime.dateTime );
        Serial.print( "Central RSSI: " );
        Serial.println( central.rssi() );

        if( central.rssi() != 0 )
        {
          digitalWrite( RSSI_LED_PIN, LOW );

          currentTimeCharacteristic.writeValue( currentTimeData.bytes, sizeof currentTimeData.bytes );
        }
        else
        {
          digitalWrite( RSSI_LED_PIN, HIGH );
        }
      }    
    }
    BLE.end();

      BLE.begin();
      setupBleMode();
      Serial.println("BLE Run.");
    
    Serial.print( "Disconnected from central: " );
    Serial.println( central.address() );
  }
}

When I try to call BLE.end() and then call BLE.begin(), the bluetooth seems running, but it's not advertising. And I think that's why it's not syncing with the IoT.

Here's a much better example with the IF statements I'm working on.

void loop() {
  DateTime now = rtc.now(); //Get the current time from RTC.

  if (startup == HIGH) {
    //Set Last Time Synced date to current date.
    ltsYear = now.year();
    ltsMonth = now.month();
    ltsDay = now.day();
    ltsHour = now.hour();
    ltsMin = now.minute();
    ltsSec = now.second();
    startup = LOW;
  }

  //Update time on start up.
  if (startupTimeCheck == LOW) {
    timeCheck();
    digitalWrite(BLE_LED_PIN, LOW);
    if (ntpHour != 0) {

      //Time Update Display Message.
      display.clearDisplay();
      display.display();
      display.setTextSize(1);
      display.setTextColor(WHITE, BLACK);
      display.setCursor(30, 12);
      display.println("Syncing Time");
      display.display();
      
      millisNTP = millis();
      if (millisNTP - previousNTP >= 10000) {
        rtc.adjust(DateTime(ntpYear, ntpMonth, ntpDay, ntpHour, ntpMin, ntpSec));
        ntpYear = 0; ntpMonth = 0; ntpDay = 0; ntpHour = 0; ntpMin = 0; ntpSec = 0; //Reset value to zero.
        //Serial.print("value reset to zero.");
        digitalWrite(BLE_LED_PIN, LOW);
        
        ltsYear = now.year();
        ltsMonth = now.month();
        ltsDay = now.day();
        ltsHour = now.hour();
        ltsMin = now.minute();
        ltsSec = now.second();
        startupTimeCheck = HIGH;
        timeSync = HIGH;
        
        BLE.end();
      }
      previousNTP = millisNTP;
        delay(2500);
      display.clearDisplay();
      display.display();
    }
  }

  //Update time every first day of the month, at 9am.
  //if (now.day() == 1) {
  //  if (now.hour() == 9) {
  if (now.hour() == 18){
    if (now.minute() == 38) {
      if (timeUpdate == LOW) {
        
        BLE.begin();
        
        timeCheck();
        digitalWrite(BLE_LED_PIN, HIGH);
        if (ntpHour != 0) {
          
          //Time Update Display Message.
          display.clearDisplay();
          display.display();
          display.setTextSize(1);
          display.setTextColor(WHITE, BLACK);
          display.setCursor(30, 12);
          display.println("Syncing Time");
          display.display();
          
          millisNTP = millis();
          if (millisNTP - previousNTP > 10000) {
            rtc.adjust(DateTime(ntpYear, ntpMonth, ntpDay, ntpHour, ntpMin, ntpSec));
            ntpYear = 0; ntpMonth = 0; ntpDay = 0; ntpHour = 0; ntpMin = 0; ntpSec = 0; //Reset value to zero.
            //Serial.print("value reset to zero.");
            digitalWrite(BLE_LED_PIN, LOW);

            ltsYear = now.year();
            ltsMonth = now.month();
            ltsDay = now.day();
            ltsHour = now.hour();
            ltsMin = now.minute();
            ltsSec = now.second();
            startupTimeCheck = HIGH;
            timeSync = HIGH;
            timeUpdate = HIGH;
          }
          previousNTP = millisNTP;
            delay(2500);
          display.clearDisplay();
          display.display();
        }
      }
    }
  }

In reply #24.

BLE.begin();
setupBleMode();

This does not work. You can not call BLE.begin twice. It is already called in setupBleMode.

Can you post a complete sketch? Reading bits of this code does not work in my brain. :slight_smile:

Did you have a look at the second BLE Time example? That state machine could easily be adapted to have a wait state where BLE is disabled and a condition that would disable BLE.

Are you worried about power on both sides? BLE has been designed for small batteries. What power sources do you have?

I haven’t checked the codes in the second example, but I am looking at it now. I’ll check it out.

Anyway, I attached the sketch. I didn’t copy all, but only the necessary ones because it’s to long to paste the entire sketch. I hope the example is clear.

the timeCheck() is basically the loop() in the first example you sent me before.

Yes. Actually the project I’m working on is powered by battery. I noticed a significant increase in power consumption with the BLE. I read that low power kicks in automatically with the BLE Arduino, but I don’t know why the consumption is high. That’s why I’m thinking of shutting off the BLE after syncing the time from the IoT.

For the IoT, it’s powered by USB. So I’m not really worried about it. Only the BLE ones.

test_BLE_time_with_scheduled_sync.ino (9.36 KB)