stevie135s
Published © GPL3+

TTGO T4 BLE Clock Project

The original TTGO T4 Clock project but enhanced to set the DS3231 RTC over Bluetooth (BLE).

BeginnerWork in progress1 hour152
TTGO T4 BLE Clock Project

Things used in this project

Hardware components

LILYGO TTGO T4
×1
DS3231 RTC
×1

Story

Read more

Custom parts and enclosures

Android apk

Install to an android phone

Schematics

Circuit for the DS3231 RTC

The I2C port is connected to the RTC

Code

TTGO T4 BLE Code v2

Arduino
Update 2 : Avoids crashing on countdown print
/*  *********************************************************************************
 * * The original TTGO T4 Clock Program, enhanced to be set over Bluetooth LE      *
 * * During the first 30 seconds after switch on, the TTGO T4 will look for a BLE  *
 * * Bluetooth connection from the Android phone app to set the time on the DS3231.*
 * * After which it will go into display mode.                                     *
   *********************************************************************************
 */

#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>
#include <DS3231.h>
#include <Wire.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID        "fe45c941-9b87-4ef1-ac31-990dd686f813"
#define CHARACTERISTIC_UUID "ebc2e890-8ad5-4d51-a4a1-0e60efc9df4a"

String BT_IN;
char inString[13];
byte Sec = 1;
byte Min = 38;
byte Hr = 12;
byte Weekday = 1;
byte Months;
byte DAY = 1;
byte date;
byte L_Weekday = 1;
byte Year;
String L_Sec = "01";
String L_Min = "38";
String L_Hr = "12";
byte L_Month = 1;
String L_DAY = "01";
char T_emp  = 247;
String T_emp2 = String(T_emp) + "c";
byte Temp = 23;
String L_Temp = "23";
bool h12Flag,pmFlag;
bool century = false;
String Dow []= {"0","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday" };
int Spc []= {0,92,79,53,66,92,66,92};
String MONTH []= {"0"," JANUARY","FEBRUARY","  MARCH","  APRIL","   MAY","  JUNE","  JULY"," AUGUST","SEPTEMBER"," OCTOBER","NOVEMBER","DECEMBER" };
byte CountDown;
bool deviceConnected = false;

BLEServer *pServer;
BLEService *pService;
BLECharacteristic *pCharacteristic;

TFT_eSPI tft = TFT_eSPI();
DS3231 rtc;

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
      CountDown = 1;
    }
};

void setup() {

  Wire.begin();
  rtc.setClockMode(false);  // Run Once to set 12 true 24hr false
  tft.init();
  tft.setRotation(1);

  BLEDevice::init("T4_Set_Time");
  pServer = BLEDevice::createServer();
  pService = pServer->createService(SERVICE_UUID);
  pServer->setCallbacks(new MyServerCallbacks());
  pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );
  pCharacteristic->setValue("");
  pService->start();
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();

  tft.fillScreen(TFT_BLACK);  
  Get_Time(); // Call routine to set over BLE
  tft.fillScreen(TFT_BLACK);
  tft.drawRect(0,0,319,239,TFT_RED);
  tft.drawLine(0,100,319,100,TFT_RED);
  tft.drawLine(0,160,319,160,TFT_RED);
  tft.drawLine(160,160,160,239,TFT_RED);
  tft.drawLine(160,200,339,200,TFT_RED);
  tft.setTextColor(TFT_RED,TFT_BLACK);
  tft.drawString("23",40,175,2);// Temperature
  tft.drawString(T_emp2,92,175,1);
  tft.setTextColor(TFT_YELLOW,TFT_BLACK);
  tft.drawString("12:38",50,16,4); // Inititial Time
  tft.setTextColor(TFT_WHITE,TFT_BLACK);
  tft.drawString("00",250,16,2);   // Initial Seconds
  tft.setTextColor(TFT_GREEN,TFT_BLACK);
  tft.drawString("Monday",92,104,2); // Initial Day
  tft.setTextColor(TFT_WHITE,TFT_BLACK);
  tft.drawString(MONTH [1],161,169,1);// Month
  tft.setTextColor(TFT_YELLOW,TFT_BLACK);
  tft.drawString("01",221,207,1);   // Initial Date
 

}

void loop() {
  Sec = rtc.getSecond();     // Get the seconds
  if(L_Sec.toInt() != Sec) {
    tft.setTextColor(TFT_BLACK,TFT_BLACK);
    tft.drawString(L_Sec,250,16,2);
    L_Sec = "0" + String(Sec);
    L_Sec = L_Sec.substring(L_Sec.length()-2);
    tft.setTextColor(TFT_WHITE,TFT_BLACK);
    tft.drawString(L_Sec,250,16,2);
      }
      Min = rtc.getMinute();  // Get the minutes
      if (L_Min.toInt() != Min) {
        tft.setTextColor(TFT_BLACK,TFT_BLACK);
        tft.drawString(L_Min,155,16,4);
        L_Min = "0" + String(Min);
        L_Min = L_Min.substring(L_Min.length()-2);
        tft.setTextColor(TFT_YELLOW,TFT_BLACK);
        tft.drawString(L_Min,155,16,4);
      }
      Hr = rtc.getHour(h12Flag,pmFlag); //Get the hours
      if (L_Hr.toInt() != Hr) {
        tft.setTextColor(TFT_BLACK,TFT_BLACK);
        tft.drawString(L_Hr,50,16,4);
        L_Hr = "0" + String(Hr);
        L_Hr = L_Hr.substring(L_Hr.length()-2);
        tft.setTextColor(TFT_YELLOW,TFT_BLACK);
        tft.drawString(L_Hr,50,16,4);
      }
      Weekday = rtc.getDoW();   // Get the Day of the week
      if (L_Weekday != Weekday) {
        tft.setTextColor(TFT_BLACK,TFT_BLACK);
        tft.drawString(Dow[L_Weekday],Spc[L_Weekday],104,2);
        tft.setTextColor(TFT_GREEN,TFT_BLACK);
        tft.drawString(Dow[Weekday],Spc[Weekday],104,2);
        L_Weekday = Weekday;
      }
      Temp = rtc.getTemperature();    // Get the temperature
      if (L_Temp.toInt() != Temp) {
        tft.setTextColor(TFT_BLACK,TFT_BLACK);
        tft.drawString(L_Temp,40,175,2);
        L_Temp = "0" + String(Temp);
        L_Temp = L_Temp.substring(L_Temp.length()-2);
        tft.setTextColor(TFT_BLUE,TFT_BLACK);
        tft.drawString(L_Temp,40,175,2);
      }
      Months = rtc.getMonth(century);   // Get the Month
      if (L_Month != Months) {
        tft.setTextColor(TFT_BLACK,TFT_BLACK);
        tft.drawString(MONTH[L_Month],161,169,1);
        L_Month = Months;
        tft.setTextColor(TFT_WHITE,TFT_BLACK);
        tft.drawString(MONTH[L_Month],161,169,1);
      }
      DAY = rtc.getDate();          // Get the date
      if (L_DAY.toInt() != DAY) {
        tft.setTextColor(TFT_BLACK,TFT_BLACK);
        tft.drawString(L_DAY,221,207,1);
        L_DAY = "0" + String(DAY);
        L_DAY = L_DAY.substring(L_DAY.length()-2);
        tft.setTextColor(TFT_YELLOW,TFT_BLACK);
        tft.drawString(L_DAY,221,207,1);
      }
}

void Get_Time() {
    CountDown = 30; // Seconds taken to set the time 
    tft.setTextColor(TFT_WHITE,TFT_BLACK);
    tft.setTextSize(2);
    tft.drawString("Waiting For Bluetooth",16,104,2);
    tft.setTextSize(3);
    tft.drawString(String(CountDown),40,16,4);
    while (CountDown) {
    while(deviceConnected) {
      if(CountDown) {
        tft.setTextColor(TFT_BLACK,TFT_BLACK);
        tft.drawString(String(CountDown),40,16,4);
        CountDown = 0;
        tft.setTextSize(2);
        tft.drawString("Waiting For Bluetooth",16,104,2);            
        tft.setTextColor(TFT_GREEN,TFT_BLACK);
        tft.drawString("BLUETOOOTH CONNECTED",4,104,2);
        tft.setTextSize(3); 
      }
    BT_IN = pCharacteristic->getValue();
    if (BT_IN.length() == 15) {
    pCharacteristic->setValue("");
    inString[0]= BT_IN[0];  //Y
    inString[1]= BT_IN[1];  //Y
    inString[2]= BT_IN[2];  //M
    inString[3]= BT_IN[3];  //M
    inString[4]= BT_IN[4];  //D
    inString[5]= BT_IN[5];  //D
    inString[6]= BT_IN[6];  //w
    inString[7]= BT_IN[7];  //H
    inString[8]= BT_IN[8];  //H
    inString[9]= BT_IN[9];  //M
    inString[10]= BT_IN[10];//M
    inString[11]= BT_IN[11];//S
    inString[12]= BT_IN[12];//S

    Year = (((inString[0] -48)*10)+(inString[1] -48)); 
    // now month
    Months = (((inString[2] -48)*10)+(inString[3] -48));
    // now date
    date = (((inString[4] -48)*10)+(inString[5] -48));
    // now Day of Week
    Weekday = (inString[6] -48);
    // now hour
    Hr = (((inString[7] -48)*10)+(inString[8] -48));
    // now minute
    Min = (((inString[9] -48)*10)+(inString[10] -48));
    // now second
    Sec = (((inString[11] -48)*10)+(inString[12] -48));

    rtc.setClockMode(false);// set to 24h 
    rtc.setYear(Year);
    rtc.setMonth(Months);
    rtc.setDate(date);
    rtc.setDoW(Weekday);
    rtc.setHour(Hr);
    rtc.setMinute(Min);
    rtc.setSecond(Sec);
    rtc.turnOffAlarm(1);
    rtc.turnOffAlarm(2);
    delay(600);
    BLEDevice:: deinit(true);
    delay(600);             // Allow RTC registers to set before any read occurs
    return; 
       }
    }  
        delay (1000) ;
            tft.setTextColor(TFT_BLACK,TFT_BLACK);
            tft.drawString(String(CountDown),40,16,4);
        CountDown = CountDown - (CountDown > 0);
            tft.setTextColor(TFT_WHITE,TFT_BLACK);
            tft.drawString(String(CountDown),40,16,4);
       }
          BLEDevice:: deinit(true);
          delay(600);
       
    }

    

Credits

stevie135s
28 projects • 12 followers
I've been interested in microprocessors for a long time.

Comments