/* Arduino IDE - uncomment your watch */
//#define LILYGO_WATCH_2019_WITH_TOUCH
//#define LILYGO_WATCH_2019_NO_TOUCH
//#define LILYGO_WATCH_BLOCK
//#define LILYGO_WATCH_2020_V1
/* PlatformIO -> Select your watch in platformio.ini file */
#include
#include
#include "esp_sleep.h"
/**************************/
/* Static variables */
/**************************/
TTGOClass *watch = nullptr;
BMA *sensor;
AXP20X_Class *power;
TFT_eSPI *tft = nullptr;
bool KeyPressed = false;
bool lenergy = false;
int awake = 0;
int seconde = 0;
int timeleft = 0;
static bool irq_axp202 = false;
static bool irq_bma = false;
static bool return_to_deepsleep = false;
#define DEFAULT_SCREEN_TIMEOUT 5*1000
#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 30 /* Time ESP32 will go to sleep (in seconds) */
/**************************/
/* STATIC PROTOTYPES */
/**************************/
void buildTFTPage(int timeleft);
void goToDeepSleep();
void resetChrono();
int get_wakeup_reason();
/**************************/
/* Switch On/Off power */
/**************************/
void low_energy()
{
if ( watch->bl->isOn()) {
if ( return_to_deepsleep ) {
goToDeepSleep();
} else {
// Si le rétro-éclairage est actif >> passe en mode light sleep. Le Core de l'ESP32 reste actif
Serial.println("BL is ON >> activate light sleep");
watch->closeBL();
watch->bma->enableStepCountInterrupt(false);
watch->displaySleep();
lenergy = true;
// Diminue la fréquence du CPU à 10MHz pour réduire la consommation
setCpuFrequencyMhz(10);
Serial.println("ENTER IN LIGHT SLEEP MODE");
delay(50);
// Réveil avec le bouton principal
gpio_wakeup_enable ((gpio_num_t)AXP202_INT, GPIO_INTR_LOW_LEVEL);
// Réveil avec l'accéléromètre
gpio_wakeup_enable ((gpio_num_t)BMA423_INT1, GPIO_INTR_LOW_LEVEL);
// Active le réveille depuis le GPIO
esp_sleep_enable_gpio_wakeup();
// Met en veille légère. Le Core du CPU continue de fonctionner
esp_light_sleep_start();
}
} else {
// The backlight is off
// Le rétro-éclairage est éteint
lenergy = false;
setCpuFrequencyMhz(160);
resetChrono();
Serial.println("Wake-up ESP32 and accessories");
watch->displayWakeup();
watch->openBL();
watch->rtc->syncToSystem();
delay(100);
}
}
void setup() {
Serial.begin(115200);
// Retourne en sommeil profond si le réveil a été causé par le timer
if ( get_wakeup_reason() == 4 ) return_to_deepsleep = true;
watch = TTGOClass::getWatch();
// Initialize the hardware
watch->begin();
power = watch->power;
// Turn on the backlight | Allume le rétro-éclairage
watch->openBL();
// T-Watch with user button only
watch->button->setClickHandler(goToDeepSleep);
// Turn on the IRQ used
watch->power->adc1Enable(AXP202_BATT_VOL_ADC1 | AXP202_BATT_CUR_ADC1 | AXP202_VBUS_VOL_ADC1 | AXP202_VBUS_CUR_ADC1, AXP202_ON);
watch->power->enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_CHARGING_FINISHED_IRQ, AXP202_ON);
watch->power->clearIRQ();
// Turn off unused power
watch->power->setPowerOutPut(AXP202_EXTEN, AXP202_OFF);
watch->power->setPowerOutPut(AXP202_DCDC2, AXP202_OFF);
watch->power->setPowerOutPut(AXP202_LDO3, AXP202_OFF);
watch->power->setPowerOutPut(AXP202_LDO4, AXP202_OFF);
//Connection interrupted to the specified pin
pinMode(BMA423_INT1, INPUT);
attachInterrupt(BMA423_INT1, [] {
irq_bma = true;
}, RISING);
sensor = watch->bma;
// Paramètre de l'accéléromètre BMA423 (optionnel)
Acfg cfg;
cfg.odr = BMA4_OUTPUT_DATA_RATE_100HZ;
cfg.range = BMA4_ACCEL_RANGE_4G;
cfg.bandwidth = BMA4_ACCEL_NORMAL_AVG4;
cfg.perf_mode = BMA4_CONTINUOUS_MODE;
sensor->accelConfig(cfg);
// Active le BMA 423
sensor->enableAccel();
// Active la fonction de réveil du BMA423
sensor->enableFeature(BMA423_WAKEUP, true);
// Envoi un signal sur la broche 39 de l'ESP32 dès qu'un mouvement est détecté
sensor->enableWakeupInterrupt();
// Interruption qui permet de mettre en veille légère ou réveiller l'écran
pinMode(AXP202_INT, INPUT);
attachInterrupt(AXP202_INT, [] {
irq_axp202 = true;
}, FALLING);
watch->power->enableIRQ(AXP202_PEK_SHORTPRESS_IRQ | AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_CHARGING_IRQ, true);
watch->power->clearIRQ();
// Démarre le chronomètre pour la mise en veille automatique
awake = millis();
resetChrono();
// Build landing page
//créé la page principale
buildTFTPage(timeleft);
}
void loop() {
int16_t x, y;
bool rlst;
if ( watch->getTouch(x,y) ) {
while (watch->getTouch(x, y) ) {}
// Relance le chrono lorsque l'utilisateur touche l'écran
awake = millis();
}
// Lorsqu'on dépasse le temps d'inactivité >> met en veille l'écran et les périphériques de la montre
if ( millis() - awake > DEFAULT_SCREEN_TIMEOUT) {
if ( !lenergy) {
awake = millis();
low_energy();
}
}
if ( millis() - seconde >= 1000 ) {
if ( !lenergy) {
seconde = millis();
timeleft --;
buildTFTPage(timeleft);
}
}
// L'utilisateur vient d'appuyer sur le bouton principal
if (irq_axp202) {
Serial.println("irq detected");
irq_axp202 = false;
watch->power->readIRQ();
if ( watch->power->isPEKShortPressIRQ() ) {
Serial.println("Power button pressed >> wakeup / switch on light sleep");
low_energy();
}
watch->power->clearIRQ();
}
// L'utilisateur vient de tapoter l'écran
if ( irq_bma ) {
Serial.println("irq_bma detectee");
irq_bma = false;
resetChrono();
Serial.println("Power button pressed >> wakeup / switch on light sleep");
do {
rlst = watch->bma->readInterrupt();
} while (!rlst);
low_energy();
}
// On vérifie à chaque passage dans la bouche l'état du bouton utilisateur
watch->button->loop();
}
// Reset du chronomètre pour la mise en veille automatique de l'écran (mode light sleep)
void resetChrono()
{
seconde = millis();
awake = millis();
timeleft = DEFAULT_SCREEN_TIMEOUT / 1000;
buildTFTPage(timeleft);
}
void buildTFTPage(int timeleft){
TFT_eSPI *tft = watch->tft;
tft->fillScreen(TFT_BLACK);
tft->setTextSize(2);
tft->setTextColor(TFT_WHITE);
tft->drawString("T-Watch Sleep Demo", 0,0);
tft->drawFastHLine(0,20,240,TFT_WHITE);
tft->drawString("Light sleep in", 10,60);
char buf[20];
tft->setTextSize(4);
sprintf(buf, "%u s", timeleft);
tft->drawString(buf, 50,100);
}
// Permet d'activer le mode deep sleep et le timer pour un éveil périodique (enregistreur de données par exemple)
void goToDeepSleep()
{
Serial.println("Go To Deep Sleep Mode");
// Set screen and touch to sleep mode
watch->displaySleep();
/*
When using T - Watch2020V1, you can directly call power->powerOff(),
if you use the 2019 version of TWatch, choose to turn off
according to the power you need to turn off
*/
#ifdef LILYGO_WATCH_2020_V1
watch->powerOff();
// LDO2 is used to power the display, and LDO2 can be turned off if needed
// power->setPowerOutPut(AXP202_LDO2, false);
#else
power->setPowerOutPut(AXP202_LDO3, false);
power->setPowerOutPut(AXP202_LDO4, false);
power->setPowerOutPut(AXP202_LDO2, false);
// The following power channels are not used
power->setPowerOutPut(AXP202_EXTEN, false);
power->setPowerOutPut(AXP202_DCDC2, false);
#endif
esp_sleep_enable_ext0_wakeup((gpio_num_t)AXP202_INT, LOW);
// Activate Timer Wakeup. Usefull for a GPS trcker for example
// Active le réveil automatique. Utile pour un tracker GPS
esp_sleep_enable_timer_wakeup(uS_TO_S_FACTOR * TIME_TO_SLEEP);
esp_deep_sleep_start();
}
// Indique la raison du réveil de l'ESP32
int get_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case 1 : Serial.printf("Wakeup caused by external signal using RTC_IO %u \n", wakeup_reason); break;
case 2 : Serial.printf("Wakeup caused by external signal using RTC_CNTL %u \n", wakeup_reason); break;
case 3 : Serial.printf("Wakeup caused by touchpad %u \n", wakeup_reason); break;
case 4 : Serial.printf("Wakeup caused by timer %u \n", wakeup_reason); break;
case 5 : Serial.printf("Wakeup caused by ULP program %u \n", wakeup_reason); break;
default : Serial.printf("Wakeup was not caused by deep sleep %u \n", wakeup_reason); break;
}
return wakeup_reason;
}
[env:ttgo-t-watch]
platform = espressif32
board = ttgo-t-watch
framework = arduino
build_flags =
-D LILYGO_WATCH_2019_WITH_TOUCH=1
;-D LILYGO_WATCH_2019_NO_TOUCH=1
;-D LILYGO_WATCH_BLOCK=1
;-D LILYGO_WATCH_2020_V1=1
;-D LILYGO_WATCH_LVGL=1
; Important, activate LVGL support
;-D LILYGO_WATCH_LVGL=1
lib_deps =
TTGO TWatch Library
upload_speed = 2000000
monitor_speed = 115200