Introduction: Lilygo T-Watch 2020 Arduino Framework
Lilygo has put out a new version of it's development platform TWatch. It is the T-Watch 2020. It is based on an ESP32 chip with a touch screen, accelerometer, real time clock, power controller, and more. For people who have been waiting for a commercial grade watch that can be programmed, this is a dream come true. It is available at Tindie.com.
https://www.tindie.com/products/ttgo/lilygor-ttgo-...
I was super excited so I ordered one as soon as they became available. When I received it, I got it to work with the Arduino IDE. But as I started to look at the sample code, I realized I needed some documentation to help me get started. As I searched, I didn't find much. The best sample app to show some of the functions of the watch is the SimpleWatch app in the LVGL section. Looking at the code, it is anything but simple. It is heavy in C++ and object oriented architecture and it runs under the RTOS (real-time operating system). If you are not familiar with these, they can be daunting.
So, not being an expert programmer, I set out to create a simple Arduino C-based framework for the watch that will get you up and running and able to add your own apps really easily.
The first thing to know about the watch (and this took me a while to figure out) is that there is no user accessible button. The button on the side of the watch turns the watch on and off.
Hold it for 2 seconds to power on the watch and 6 seconds to turn it off.
From the AXP202 Datasheet:
Power Enable Key (PEK)
The Power Enable/ Sleep/Wakeup Key can be connected between PWRON pin and GND of AXP202. AXP202 can automatically identify the “Long-press” and “Short-press” and then correspond respectively.
It looks like the power button is directly connected to the AXP202 and not the ESP32.
This turns out to be pretty useful. The AXP202 datasheet has pretty good information on this chip and you can do a little reverse engineering using it and the TWatch axp202 library. When the watch is shut down, it looks like it secures power to most of the hardware which does a pretty good job of reducing power. I have had the watch sitting on the counter for two days without operating and it only lost about 15% power. This prevented me from having to worry a lot about getting the watch into low power mode. I just turn it off when I am not using it.
Again, from the datasheet:
Power Off
When you push-and-hold PEK longer than IRQLEVEL, HOST can write “1” into“REG32H [7]” to inform AXP202 to shutdown, which can disable all power output except LDO1.
When you view the library, the functionint AXP20X_Class::shutdown() manipulates this bit 7 so just call the shutdown function and it will have the same effect as long pressing the button.
There is an IRQ input from the AXP202 to the ESP32 (AXP202_INT). There are a bunch of interrupts generated from the AXP202. If you need to use the button, you can poll the shortpress interrupt as follows:
ttgo->power->readIRQ(); // This reads the interupts<br> if (ttgo->power->isPEKShortPressIRQ()) { // This will be true if the button was short pressed ttgo->tft->println("Press"); ttgo->power->clearIRQ(); // Clear the interrupts so you can receive some more } else { ttgo->tft->println("OPEN"); }
See the example code in Examples->TTGO Watch Library->Basic Unit->AXP20X_IRQ.
Since most interaction happens on the touch screen, you may want to look into the LVGL framework. This allows you to make standard GUI elements (buttons, lists, etc) and respond to touches. You could probably use the accelerometer also as a gesture input.
Supplies
1) T-Watch 2020
2) Arduino IDE
Step 1: The Framework
My code is borrowed heavily from the example code written by Lewis He.
The framework is set up to display the time. Every second the screen will update and flash the colon. This is a good visual that the watch is not hung up.
When you touch the screen, you will see the Menu. Touching up and down will allow you to cycle through menu items. When the desired item is displayed in the center, click the center to launch it.
Pretty straight forward, and that is the point.
The video shows the basic function and a couple of simple apps I included to let you see how to access the accelerometer, battery monitor, touch screen, and more.
Step 2: Get Your Watch Connected
The new Arduino method of loading libraries and boards makes this pretty straight forward.
If you don't already have the ESP32 board library loaded, in the File menu, select Preferences.
In the section Additional Boards Manager URLs, click the box on the right of the text block. This will bring up a box that has all of your current URLs for boards you are using. Add the following to the list:
https://dl.espressif.com/dl/package_esp32_index.json
Click OK until you are out of the Preferences menu.
Then go into Tools->Board->Boards Manager
Search for esp32 and install the latest version.
To load the library, go to the GitHub site, download the repository in zip format, and then import it into Arduino using the Library import ZIP function.
https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Libr...
Plug in your watch, start Arduino IDE, Select the watch on the Board section, open a sample application in the TTGO section of Examples (try SimpleWatch in the LVGD section), compile and download. Hopefully all went well and your watch is ready to be programmed.
Step 3: Load the Framework and Add Your App
Download the Arduino Framework code in the individual INO files in this Instructable (sorry, I could not get the zip file to be accepted by Instrucables). Place them all into a folder in your Arduino sketch folder (Name the folder something you will remember). Open it in the IDE (may have to restart the IDE).
You will see that there are a bunch of separate tabs to the program. The Main tab is labeled TWatch_Framework_0. It is where the setup() and loop() subroutines are. The other important tab is the Menu tab.
If you have verified you can download the examples to your watch, you should now be able to download this to your watch.
To add your own app to this watch do the following:
1) In the Menu tab you will see the code:
const int maxApp = 6; // number of apps String appName[maxApp] = {"Clock", "Jupiter", "Accel", "Battery", "Touch", "Set Time"}; // app names
Increment the constant maxApp by 1. This is the total number of apps.
Append the name of your app to the appName string array. It can be inserted anywhere. But be advised, the menu function returns the number of the selected app. It has to match the switch-case to select the correct app.
2) In the Main tab, add a call to your app as a case in the switch statement in the main loop().
switch (modeMenu()) { // Call modeMenu. The return is the desired app number case 0: // Zero is the clock, just exit the switch break; case 1: jSats(); break; case 2: appAccel(); break; case 3: appBattery(); break; case 4: appTouch(); break; case 5: appSetTime(); break; }
3) Add a tab, and write your code as a subroutine or function that is called from the case statement. See the appTouch tab as an example.
That is it. With the tabs I have already, you should be able to quickly code a new app that can be called from the menu. Take a look at the methods I use to exit apps. You want to make sure that the user is not pressing the touch screen when the app exits or you will immediately go back to the menu instead of the time display.
I so hope this helps. I saw a lot of people initially complaining about the lack of documentation and support. But this is a great product that will give you your own programmable watch with lots and lots of geek cred.
Just show people at a party the current orientation of Jupter's moons and you'll see.
******* Right now, Instructables will not upload the zipped code file. I uploaded the individual tabs. **********
******* Download them all, place them in a directory in the Arduino sketch folder and open the Framework ino file ****
Step 4: Some Helpful Apps
As I come up with apps for my watch, I'll post useful ones here:
This app sets the watch time from the internet. Just add your WiFi credentials.
#include <WiFi.h> #include "time.h" void appWiFiTime() { // WiFi settings ******* Use your network values ********** const char* ssid = "put your ssid here"; const char* password = "put your passcode here"; const char* ntpServer = "pool.ntp.org"; const long gmtOffset_sec = -18000; const int daylightOffset_sec = 3600; WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) {} configTime(-18000, 3600 , "pool.ntp.org", "time.nis.gov"); delay(3000); struct tm timeinfo; if (!getLocalTime(&timeinfo)) { ttgo->tft->drawString("Failed", 5, 30, 1); } else { ttgo->tft->setCursor(0, 130); ttgo->tft->print(&timeinfo, "%A, %B %d %Y\n%H:%M:%S"); ttgo->rtc->setDateTime(timeinfo.tm_year, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); } delay(5000); WiFi.disconnect(true); WiFi.mode(WIFI_OFF); ttgo->tft->fillScreen(TFT_BLACK); }
I set up a call to give a quick motor vibration. Make sure you setup the motor pin in your setup() routine to be an OUTPUT (pinMode(4, OUTPUT); )
void quickBuzz() { digitalWrite(4, HIGH); delay(200); digitalWrite(4, LOW); }
Here is the code to retrieve the current Bitcoin price from the server. Again, I am not an expert programmer so you will see there is little error checking and waiting for conformation, but this works on my watch so it must be close. Remember to put in your own wifi credentials.
#include <ArduinoJson.h> #include <WiFi.h> #include <WiFiClientSecure.h>
void appBitcoin() { // WiFi settings const char* ssid = "ssid"; const char* password = "passcode"; // API server const char* host = "api.coindesk.com"; int16_t x, y; ttgo->tft->fillScreen(TFT_PURPLE); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) {} while (ttgo->getTouch(x, y)) {} WiFiClient client; const int httpPort = 80; client.connect(host, httpPort); // We now create a URI for the request String url = "/v1/bpi/currentprice.json"; // This will send the request to the server client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); delay(100); // Read all the lines of the reply from server and print them to Serial String answer; while (!client.available()) {} while (client.available()) { String line = client.readStringUntil('\r'); answer += line; } client.stop(); // Convert to JSON String jsonAnswer; int jsonIndex; for (int i = 0; i < answer.length(); i++) { if (answer[i] == '{') { jsonIndex = i; break; } } // Get JSON data jsonAnswer = answer.substring(jsonIndex); jsonAnswer.trim(); // Get rate as float int rateIndex = jsonAnswer.indexOf("rate_float"); String priceString = jsonAnswer.substring(rateIndex + 12, rateIndex + 19); priceString.trim(); float price = priceString.toFloat(); ttgo->tft->setTextSize(2); ttgo->tft->setTextColor(TFT_GREEN); ttgo->tft->setCursor(40, 90); ttgo->tft->println("Bitcoin Price"); ttgo->tft->setCursor(70, 130); ttgo->tft->println(priceString); client.stop(); WiFi.disconnect(true); WiFi.mode(WIFI_OFF); while (!ttgo->getTouch(x, y)) {} // wait until you touching while (ttgo->getTouch(x, y)) {} ttgo->tft->fillScreen(TFT_BLACK); }
This app returns the analog value proportional to the AXP202 temperature. It is a raw value and the data sheet I saw didn't have any discussion on the conversion to actual temperature so you will have to calibrate it yourself. My value is about 170 when the watch has been off for a while and I just turn it on and 190 when it has been running for a while.
void appTemp() {<br> int16_t x, y; while (ttgo->getTouch(x, y)) { } while (!ttgo->getTouch(x, y)) { // Wait for press float temp = ttgo->power->getTemp(); ttgo->tft->fillScreen(TFT_BLACK); ttgo->tft->setTextColor(TFT_YELLOW, TFT_BLACK); ttgo->tft->setCursor(40, 100); ttgo->tft->print("Temp: "); ttgo->tft->print(temp); delay(300); } while (ttgo->getTouch(x, y)) {} // wait until you stop touching ttgo->tft->fillScreen(TFT_BLACK); }
Step 5: A STTNG-like Drop-in Replacement for DisplayTime()
I wrote a replacement function for the displayTime() subroutine to mimic a ST-like screen display. The easy way would have been to use a bitmap image and overwrite the text. But, I just created it with display paint commands. If you use the above files, this would just replace the displayTime() tab. Here is the code:
// An advanced Time Display // This is a drop-in replacement for the displayTime() // In the original Instructable. s such, it redraws GUI // every minute so you will see a little flicker. void displayTime(boolean fullUpdate) { ttgo->power->adc1Enable(AXP202_VBUS_VOL_ADC1 | AXP202_VBUS_CUR_ADC1 | AXP202_BATT_CUR_ADC1 | AXP202_BATT_VOL_ADC1, true); // Get the current data RTC_Date tnow = ttgo->rtc->getDateTime(); hh = tnow.hour; mm = tnow.minute; ss = tnow.second; dday = tnow.day; mmonth = tnow.month; yyear = tnow.year; ttgo->tft->setTextSize(1); if (fullUpdate) { //Draw the back graphics - Top of display ttgo->tft->fillScreen(TFT_BLACK); ttgo->tft->fillRoundRect(0, 0, 239, 120, 40, TFT_PURPLE); ttgo->tft->fillRoundRect(40, 20, 196, 80, 20, TFT_BLACK); ttgo->tft->fillRect(80, 20, 159, 80, TFT_BLACK); ttgo->tft->fillRect(170, 0, 45, 20, TFT_BLACK); ttgo->tft->fillRect(110, 0, 4, 20, TFT_BLACK); ttgo->tft->fillRect(0, 45, 50, 7, TFT_BLACK); ttgo->tft->fillRect(0, 70, 50, 7, TFT_BLACK); ttgo->tft->fillRect(215, 0, 24, 20, TFT_DARKCYAN); //Draw the back graphics - Bottom of display ttgo->tft->fillRoundRect(0, 130, 239, 109, 40, TFT_MAROON); ttgo->tft->fillRoundRect(40, 150, 199, 88, 20, TFT_BLACK); ttgo->tft->fillRect(0, 179, 50, 10, TFT_BLACK); ttgo->tft->fillRect(100, 160, 40, 10, TFT_YELLOW); ttgo->tft->fillRect(140, 160, 40, 10, TFT_DARKGREEN); ttgo->tft->fillRect(180, 160, 40, 10, TFT_RED); ttgo->tft->setTextColor(TFT_WHITE, TFT_BLACK); ttgo->tft->drawString("Temp", 66, 158, 2); ttgo->tft->fillRoundRect(119, 210, 120, 29, 15, TFT_DARKCYAN); // Display Temp Marker - you may need to adjust the x value based on your normal ADC results float temp = ttgo->power->getTemp(); ttgo->tft->fillRoundRect(int(temp) - 20, 170, 10, 20, 5, TFT_WHITE); // Display Time // Font 7 is a 7-seg display but only contains // characters [space] 0 1 2 3 4 5 6 7 8 9 0 : . ttgo->tft->setTextColor(0xFBE0, TFT_BLACK); int xpos = 55; if (hh < 10) xpos += ttgo->tft->drawChar('0', xpos, 35, 7); xpos += ttgo->tft->drawNumber(hh, xpos, 35, 7); xpos += 3; xpos += ttgo->tft->drawChar(':', xpos, 35, 7); if (mm < 10) xpos += ttgo->tft->drawChar('0', xpos, 35, 7); ttgo->tft->drawNumber(mm, xpos, 35, 7); // Display Battery Level ttgo->tft->setTextSize(1); ttgo->tft->setTextColor(TFT_YELLOW); ttgo->tft->drawString("Power", 124, 2, 2); ttgo->tft->setTextColor(TFT_GREEN); int per = ttgo->power->getBattPercentage(); per = ttgo->power->getBattPercentage(); ttgo->tft->drawString(String(per) + "%", 179, 2, 2); ttgo->tft->setTextColor(TFT_GREENYELLOW); ttgo->tft->drawString(String(dday), 50, 188, 6); // Turn off the battery adc ttgo->power->adc1Enable(AXP202_VBUS_VOL_ADC1 | AXP202_VBUS_CUR_ADC1 | AXP202_BATT_CUR_ADC1 | AXP202_BATT_VOL_ADC1, false); // Draw Month String mStr; switch (mmonth) { case 1: mStr = "Jan"; break; case 2: mStr = "Feb"; break; case 3: mStr = "Mar"; break; case 4: mStr = "Apr"; break; case 5: mStr = "May"; break; case 6: mStr = "Jun"; break; case 7: mStr = "Jul"; break; case 8: mStr = "Aug"; break; case 9: mStr = "Sep"; break; case 10: mStr = "Oct"; break; case 11: mStr = "Nov"; break; case 12: mStr = "Dec"; break; } ttgo->tft->setTextColor(TFT_WHITE); ttgo->tft->drawString(mStr, 9, 194, 2); } // Build a bargraph every 10 seconds int secmod = ss % 10; if (secmod) { // Show growing bar every 10 seconds ttgo->tft->fillRect(126 + secmod * 10, 215, 6, 15, TFT_ORANGE); } else { ttgo->tft->fillRoundRect(119, 210, 120, 29, 15, TFT_DARKCYAN); } }
91 Comments
Question 7 months ago
Hi, would this work also on the Lilygo Paul 3d open smartwatch? The round one I mean. Because I am finding very hard to retrieve tools to write arduino code for it. Thanks!
9 months ago on Step 5
Hi, this is really very impressive. Please advice me where to add my "void setup()" contents of my .ino file in your Framework arrangement.
Reply 9 months ago
I don't know if I understand your question. The framework includes setup code in the main file. If there is anything additional you need to add, you can add it to the existing setup procedure.
Reply 9 months ago
Thank you for your reply. This is my App's "setup" code and it has to be run only once when my App starts.
My doubt is: How can I add this with the Framework's setup itself, if it is so, will it not work (or disturb) with all the Apps in the Framework's menu? Please advise.
void setup() {
/************* Already Exists *******************************/
//Serial.begin(115200);
//ttgo = TTGOClass::getWatch();
//ttgo->begin();
//ttgo->openBL();
/************************************************************/
/*************************** WiFi Connection Code ************************************/
// Connect to WiFi access point.
Serial.println(); Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: "); Serial.println(WiFi.localIP());
// Blynk.begin(auth, ssid, pass);
ttgo->lvgl_begin();
lv_obj_t *label;
/* Create a Title */
lv_obj_t * title = lv_label_create(lv_scr_act(), NULL);
lv_label_set_text(title, "MQTT Home Automation");
lv_obj_align(title, NULL, LV_ALIGN_IN_TOP_LEFT, 30, 0);
lv_obj_t *btn1 = lv_btn_create(lv_scr_act(), NULL);
lv_obj_set_event_cb(btn1, event_handler1);
lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, -80, -80);
lv_btn_set_checkable(btn1, true);
lv_btn_toggle(btn1);
lv_btn_set_fit2(btn1, LV_FIT_NONE, LV_FIT_TIGHT);
label = lv_label_create(btn1, NULL);
lv_label_set_text(label, "Relay1");
lv_obj_t *btn2 = lv_btn_create(lv_scr_act(), NULL);
lv_obj_set_event_cb(btn2, event_handler2);
lv_obj_align(btn2, NULL, LV_ALIGN_CENTER, 80 , -80);
lv_btn_set_checkable(btn2, true);
lv_btn_toggle(btn2);
lv_btn_set_fit2(btn2, LV_FIT_NONE, LV_FIT_TIGHT);
label = lv_label_create(btn2, NULL);
lv_label_set_text(label, "Relay2");
lv_obj_t *btn3 = lv_btn_create(lv_scr_act(), NULL);
lv_obj_set_event_cb(btn3, event_handler3);
lv_obj_align(btn3, NULL, LV_ALIGN_CENTER, -80, -30);
lv_btn_set_checkable(btn3, true);
lv_btn_toggle(btn3);
lv_btn_set_fit2(btn3, LV_FIT_NONE, LV_FIT_TIGHT);
label = lv_label_create(btn3, NULL);
lv_label_set_text(label, "Relay3");
lv_obj_t *btn4 = lv_btn_create(lv_scr_act(), NULL);
lv_obj_set_event_cb(btn4, event_handler4);
lv_obj_align(btn4, NULL, LV_ALIGN_CENTER, 80, -30);
lv_btn_set_checkable(btn4, true);
lv_btn_toggle(btn4);
lv_btn_set_fit2(btn4, LV_FIT_NONE, LV_FIT_TIGHT);
label = lv_label_create(btn4, NULL);
lv_label_set_text(label, "Relay4");
lv_ex_slider_2();
lv_ex_bar_1();
lv_ex_bar_2();
// Setup MQTT subscription for onoff feed.
mqtt.subscribe(&temperature);
mqtt.subscribe(&humidity);
}
Reply 9 months ago
Got it. Yes, this would interfere with the framework. But it looks like you could create a new app, and place your code in it to run this mqtt code when selected from the main menu.
Reply 9 months ago
Thank you, this is exactly what I am trying to do. I am a hardware guy and newbie to software. Please help me how to create an Arduino sketch shown here into an App that can run inside your Framework.
Reply 9 months ago
I am not familiar with using MQTT. If you follow the steps on the Instructable, in step 3, I show you how to add an app. Increase the number of apps by one, add your title to the list, in the case statement, add a reference to your subroutine (you could call it mqtt()) and then add a tab in the Arduino IDE, type in void mqtt(){ and then add the code you want to run (everything after the setup(){). Since the display is already setup, you don't need the line ttgo->lvgl_begin(); . I can't be much more help than that as I am not sure is any of your code will interfere with the rest of the framework, but I don't think it will.
9 months ago on Step 5
Hi, this is really very impressive. Please advice me where to add my "void setup()" contents of my .ino file in your Framework arrangement.
Tip 1 year ago
short write :
String days[]={"AHAD", "SENIN", "SELASA", "RABU", "KAMIS", "JUM'AT", "SABTU"};
char pasar[][7] ={"WAGE", "KLIWON", "LEGI", "PAHING", "PON"};
char Sasi[][4] = { "JAN", "FEB", "MAR", "APR", "MEI", "JUN", "JUL", "AGS", "SEP", "OKT", "NOV", "DES" };
#define cetak ttgo->tft->drawString
#define tengah ttgo->tft->drawCentreString
#define garis ttgo->tft->drawLine
#define lingkaran ttgo->tft->drawCircle
#define lingkaranIsi ttgo->tft->fillCircle
#define kotak ttgo->tft->drawRect
#define kotakIsi ttgo->tft->fillRect
#define kotakr ttgo->tft->drawRoundRect
#define tmerah ttgo->tft->setTextColor(TFT_RED, TFT_BLACK)
#define thijau ttgo->tft->setTextColor(TFT_GREEN, TFT_BLACK)
#define tbiru ttgo->tft->setTextColor(TFT_BLUE, TFT_BLACK)
#define tungu ttgo->tft->setTextColor(TFT_MAGENTA, TFT_BLACK)
#define tkuning ttgo->tft->setTextColor(TFT_YELLOW, TFT_BLACK)
#define tcyan ttgo->tft->setTextColor(TFT_CYAN, TFT_BLACK)
#define tputih ttgo->tft->setTextColor(TFT_WHITE, TFT_BLACK)
#define hitam 0x0000
#define biru 0x001F
#define merah 0xF800
#define hijau 0x07E0
#define cyan 0x07FF
#define ungu 0xF81F
#define kuning 0xFFE0
#define putih 0xFFFF
#define grey 0x8410
displayTime :
#include
byte xcolon = 0; // location of the colon
//void displayTime(boolean fullUpdate) {
void displayTime() {
byte xpos = 40; // Stating position for the display
byte ypos = 90;
// Get the current data
RTC_Date tnow = ttgo->rtc->getDateTime();
hh = tnow.hour;
mm = tnow.minute;
ss = tnow.second;
dday = tnow.day;
mmonth = tnow.month;
yyear = tnow.year;
ttgo->tft->setTextSize(1);
static long lsRn;
long Tmr = millis();
char jams[3];
char mens[3];
char dets[3];
char jamu[10];
char tgl1[3];
char tgl2[3];
char tgl3[5];
char tanggalan[15];
char tanggale[15];
char din[10];
char pasare[8];
sprintf(jams, "%02d", hh);
sprintf(mens, "%02d", mm);
sprintf(dets, "%02d", ss);
sprintf(jamu, "%02d:%02d:%02d",hh,mm,ss);
sprintf(tgl1,"%02d", dday);
sprintf(tgl2,"%02d", mmonth);
sprintf(tgl3,"%04d", yyear);
// sprintf(din,"%s",days[dino-48]);
sprintf(tanggalan, "%02d-%02d-%04d", dday, mmonth,yyear);
sprintf(tanggale, "%02d %s %04d", dday, Sasi[mmonth],yyear);
int x = 0;
kotakr(25,80,190,80,10,hijau);
lingkaran(120,121,119,putih);
tkuning;
cetak(jams,x+30,95,7);
cetak(mens,x+110,95,7);
tputih;
cetak(dets,x+180,120,4);
if (Tmr - lsRn < 500){
tputih;
cetak(":",x+100,95,7);
}else{
cetak(";",x+100,95,7);
}
if (Tmr - lsRn > 1000) lsRn = Tmr;
tcyan; tengah(tanggalan,120,175,4);
tputih; tengah("Teknik Otomasi Industri",120,50,2);
// if (fullUpdate) {
// char jame[10];
// char tgl[12];
//
// sprintf(jame,"%02d:%02d:%02d",hh,mm,ss);
// sprintf(tgl,"%02d-%02d-%04d",dday,mmonth,yyear);
//
//
// ttgo->tft->setTextColor(0x39C4, TFT_BLACK);
// ttgo->tft->drawCentreString(jame,120,80,7);
//
//
// ttgo->tft->setTextSize(3);
// // ttgo->tft->setCursor( 10, 210);
// ttgo->tft->setTextColor(0xFfff, TFT_BLACK);
// ttgo->tft->drawCentreString(tgl,120,200,1);
//
// Font 7 is a 7-seg display but only contains
// characters [space] 0 1 2 3 4 5 6 7 8 9 0 : .
// ttgo->tft->setTextColor(0x39C4, TFT_BLACK); // Set desired color
// ttgo->tft->drawString("88:88", xpos, ypos, 7);
// ttgo->tft->setTextColor(0xFBE0, TFT_BLACK); // Orange
//
// if (hh < 10) xpos += ttgo->tft->drawChar('0', xpos, ypos, 7);
// xpos += ttgo->tft->drawNumber(hh, xpos, ypos, 7);
// xcolon = xpos + 3;
// xpos += ttgo->tft->drawChar(':', xcolon, ypos, 7);
// if (mm < 10) xpos += ttgo->tft->drawChar('0', xpos, ypos, 7);
// ttgo->tft->drawNumber(mm, xpos, ypos, 7);
// }
// if (ss % 2) { // Toggle the colon every second
// ttgo->tft->setTextColor(0x39C4, TFT_BLACK);
// xpos += ttgo->tft->drawChar(':', xcolon, ypos, 7);
// ttgo->tft->setTextColor(0xFBE0, TFT_BLACK);
// } else {
// ttgo->tft->drawChar(':', xcolon, ypos, 7);
// }
// ttgo->tft->setTextSize(3);
// ttgo->tft->setCursor( 10, 210);
// ttgo->tft->setTextColor(0xFfff, TFT_BLACK);
// ttgo->tft->print(mmonth);
// ttgo->tft->print("/");
// ttgo->tft->print(dday);
// ttgo->tft->print("/");
// ttgo->tft->print(yyear);
}
1 year ago on Step 5
Coreect Menu
// Set the time - no error checking, you might want to add it
void appSetTime() {
// Get the current info
RTC_Date tnow = ttgo->rtc->getDateTime();
hh = tnow.hour;
mm = tnow.minute;
ss = tnow.second;
dday = tnow.day;
mmonth = tnow.month;
yyear = tnow.year;
//Set up the interface buttons
ttgo->tft->fillScreen(TFT_BLACK);
ttgo->tft->fillRect(0, 35, 80, 50, TFT_BLUE);
ttgo->tft->fillRect(161, 35, 78, 50, TFT_BLUE);
ttgo->tft->fillRect(81, 85, 80, 50, TFT_BLUE);
ttgo->tft->fillRect(0, 135, 80, 50, TFT_BLUE);
ttgo->tft->fillRect(161, 135, 78, 50, TFT_BLUE);
ttgo->tft->fillRect(0, 185, 80, 50, TFT_RED);
ttgo->tft->setTextColor(TFT_GREEN);
ttgo->tft->drawNumber(1, 30, 40, 2);
ttgo->tft->drawNumber(2, 110, 40, 2);
ttgo->tft->drawNumber(3, 190, 40, 2);
ttgo->tft->drawNumber(4, 30, 90, 2);
ttgo->tft->drawNumber(5, 110, 90, 2);
ttgo->tft->drawNumber(6, 190, 90, 2);
ttgo->tft->drawNumber(7, 30, 140, 2);
ttgo->tft->drawNumber(8, 110, 140, 2);
ttgo->tft->drawNumber(9, 190, 140, 2);
ttgo->tft->drawNumber(0, 30, 190, 2);
// ttgo->tft->fillRoundRect(120, 200, 119, 39, 6, TFT_WHITE);
ttgo->tft->fillRect(81, 185, 158, 50, TFT_WHITE);
ttgo->tft->setTextSize(2);
ttgo->tft->setCursor(0, 0);
ttgo->tft->setCursor(155, 210);
ttgo->tft->setTextColor(TFT_BLACK);
ttgo->tft->print("SAVE");
ttgo->tft->setTextColor(TFT_WHITE);
int wl = 0; // Track the current number selected
byte curnum = 1; // Track which digit we are on
prtTime(curnum); // Display the time for the current digit
while (wl != 13) {
wl = getTnum();
if (wl != -1) {
switch (curnum) {
case 1:
hh = wl * 10 + hh % 10;
break;
case 2:
hh = int(hh / 10) * 10 + wl;
break;
case 3:
mm = wl * 10 + mm % 10;
break;
case 4:
mm = int(mm / 10) * 10 + wl;
break;
case 5:
break;
}
while (getTnum() != -1) {}
curnum += 1;
if (curnum > 5) curnum = 1;
prtTime(curnum);
}
}
while (getTnum() != -1) {}
if(wl == 13){
ttgo->rtc->setDateTime(yyear, mmonth, dday, hh, mm, 0);
}
ttgo->tft->fillScreen(TFT_BLACK);
}
// prtTime will display the current selected time and highlight
// the current digit to be updated in yellow
void prtTime(byte digit) {
ttgo->tft->fillRect(0, 0, 100, 34, TFT_BLACK);
if (digit == 1) ttgo->tft->setTextColor(TFT_RED);
else ttgo->tft->setTextColor(TFT_WHITE);
ttgo->tft->drawNumber(int(hh / 10), 5, 5, 2);
if (digit == 2) ttgo->tft->setTextColor(TFT_RED);
else ttgo->tft->setTextColor(TFT_WHITE);
ttgo->tft->drawNumber(hh % 10, 25, 5, 2);
ttgo->tft->setTextColor(TFT_WHITE);
ttgo->tft->drawString(":", 45, 5, 2);
if (digit == 3) ttgo->tft->setTextColor(TFT_RED);
else ttgo->tft->setTextColor(TFT_WHITE);
ttgo->tft->drawNumber(int(mm / 10), 65 , 5, 2);
if (digit == 4) ttgo->tft->setTextColor(TFT_RED);
else ttgo->tft->setTextColor(TFT_WHITE);
ttgo->tft->drawNumber(mm % 10, 85, 5, 2);
}
// getTnum takes care of translating where we pressed into
// a number that was pressed. Returns -1 for no press
// and 13 for DONE
int getTnum() {
int16_t x, y;
if (!ttgo->getTouch(x, y)) return - 1;
if (y < 85) {
if (x < 80) return 1;
else if (x > 160) return 3;
else return 2;
}
else if (y < 135) {
if (x < 80) return 4;
else if (x > 160) return 6;
else return 5;
}
else if (y < 185) {
if (x < 80) return 7;
else if (x > 160) return 9;
else return 8;
}
else if (x < 80) return 0;
else return 13;
}
1 year ago
ttgo = TTGOClass::getWatch(); -> ttgo = TTGOClass::getWatch();
TFT_BLACK -> Use of undeclared identifier 'TFT_BLACK'clang(undeclared_var_use)
TFT_YELLOW -> Use of undeclared identifier 'TFT_YELLOW'clang(undeclared_var_use)
i think I'm missing something, and this is strange because the errors are on AppAccel and appBattery all the others .ino files can find this variables. I just started with Arduino so apologies for the question maybe is really straight forward to fix. Many thanks for the help.
UPDATE: Fix it! i was missing the config.h file!
Question 2 years ago
Hi Dan,
I am a few weeks ago very interested in buying this Lilygo T-Watch, or the WS2812 RGB module for an application in which I only intend to use with the Accelerometer, Bluetooth, Wiff or GPS to light up some led strips. WS2812 RGB on the following page promote the module.
The supplier's website https://t-watch.readthedocs.io/zh_CN/latest/introduction/index.html
I would like to know your opinion of how reliable is the Accelerometer. From what I see in your video I would personally remove many functions, which do not appeal to me for my application. And how much more features would it have and what would I lose?
Thank you very much.
Helbert Ramirez.
Reply 2 years ago
The accelerometer is a BMA423. You can download the specs from the internet. It is a pretty standard accelerometer with some special features like step detection and detection of single and double taps. The response is nice too. I am not sure what you mean by "how much more features would it have and what would I lose?" If you look at the framework, you can get rid of anything you don't want and add any features that you program in.
Reply 2 years ago
ok gracias por su respuesta revisare detalladamente el marco
2 years ago
In active mode, the watch consumes about 90mAh.
I do not use Wi-Fi, everything works well this way.
bool irq = false;
void loop() {
low_energy();
>>>>>>>>>>>>
ttgo->power->readIRQ(); // Reading the state of the power controller
if (ttgo->power->isPEKShortPressIRQ()) { // if the button is pressed
ttgo->power->clearIRQ();
while (irq){
// Serial.println("SLEEEP MODE");
if (ttgo->bl->isOn()) { // If ** backlight is on **
ttgo->closeBL(); // turn off the screen backlight
ttgo->stopLvglTick(); // stop working with BMA423
ttgo->bma->enableStepCountInterrupt(false);
ttgo->displaySleep(); // turn off the Display
WiFi.mode(WIFI_OFF); // turn off WiFi
rtc_clk_cpu_freq_set(RTC_CPU_FREQ_2M); // set the clock mode
setCpuFrequencyMhz(10); // We set the clock frequency of the processor 10 MHz
gpio_wakeup_enable ((gpio_num_t)AXP202_INT, GPIO_INTR_LOW_LEVEL);
gpio_wakeup_enable ((gpio_num_t)BMA423_INT1, GPIO_INTR_HIGH_LEVEL);
esp_sleep_enable_gpio_wakeup ();
esp_light_sleep_start();
}
ttgo->power->readIRQ();
if (ttgo->power->isPEKShortPressIRQ()) {
irq = false;
setCpuFrequencyMhz(80); // Set the clock frequency of the processor to 80 MHz
displayTime(true);
ttgo->power->clearIRQ();
ttgo->startLvglTick();
ttgo->displayWakeup();
ttgo->rtc->syncToSystem();
ttgo->openBL();
ttgo->bma->enableStepCountInterrupt();
}
}
}
}
Question 2 years ago
Download the Arduino Framework code in the individual INO files in this Instructable (sorry, I could not get the zip file to be accepted by Instrucables). Place them all into a folder in your Arduino sketch folder (Name the folder something you will remember). Open it in the IDE (may have to restart the IDE).
You will see that there are a bunch of separate tabs to the program.
I got a problem...
The " Bunch of seperate tabs to the program" are not showing for me..
I can open only the single .ino's and for every other .Ino I open it will open a whole new IDE widow
things I tried;
installed all updates to all the files
Added all seperate .Ino files into a .zip in the hope it would then open all the tabs (it didn' t, doesnt even find the zipped file)
upon opening the single .Ino's, the message ".ino needs it's own map, want to create it?"
created all maps and it still doesn' t work
I must admit this is all pretty new stuff for me, but I did manage to install the latest TTGO T watch library and updated my watch (so it's only showing the button and toggle button now)
I'm sure it's a minor thing, but it is beyond me...
All help is much appreciated!
Answer 2 years ago
I created a folder named "TWatch_framework_0".
Then all 9 files were copied to this folder. Using Arduino IDE I opened a file named TWatch_framework_0.ino and all 9 files were available for use. Of course, I did this by accident, since I am using the ESP32 for the first time and, in general, a beginner in this business.
Reply 2 years ago
The most probable is that you don't have all the files in the same directory. Make sure you put all of them in one directory and then open the main file and the others should load as tabs.
If that doesn't work, load the main one in the Arduino IDE, click on the drop down box in the upper right of the IDE and select "Add Tab". Then copy and paste one of the files into it. Repeat that for the others.
Answer 2 years ago
Anybody please answer my question??
2 years ago
Hello in step 4 wifi time how do i set that up? I'm still having problem with the manual time select. Everytime i try to set it for 7:23 for am it goes to 17:23.