Control the TV ! A surprising function for the TTGO watch 2020.
Fortunately all of the hard work has been done and libraries are well known. As always thanks to the inspiration and developers.
https://github.com/Arduino-IRremote/Arduino-IRremote
Here are some tips for getting the Watch going.
First step is to get the codes you are going to need.
I lashed up a sensor to an old ESP8266. This allowed getting the codes from the old remote control output to Serial Monitor.

Simple code to read IR signals from the old remote.
#include <IRremoteESP8266.h>
#include <IRrecv.h> // Needed if you want to receive IR commands.
int RECV_PIN = D4; //an IR detector connected to D4
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(115200);
irrecv.enableIRIn(); // Start the receiver
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results, HEX);
irrecv.resume(); // Receive the next value
}
delay(100);
}
Once the required codes are noted, they can be used by the watch.
The example shows controlling an LG TV.
#define LILYGO_WATCH_2020_V1 // Using T-Watch2020
#define LILYGO_WATCH_LVGL
//#define LILYGO_WATCH_HAS_MOTOR
#include <LilyGoWatch.h>
#include <IRremote.h>
IRsend irsend(TWATCH_2020_IR_PIN);
//#include "watchdef.h"
#include <soc/rtc.h>
bool exitMenu = false;
long unsigned int irCode;
TTGOClass *ttgo; //Main watch class, used to access all watch features
void setup() {
Serial.begin(115200); //
Serial.println("Starting.");
ttgo = TTGOClass::getWatch();
ttgo->begin();
ttgo->openBL();
ttgo->tft->fillScreen(TFT_BLACK);
ttgo->tft->setTextColor(TFT_YELLOW); // Note: the new fonts do not draw the background colour
//Initialize lvgl
ttgo->lvgl_begin();
ttgo->rtc->check();
ttgo->rtc->syncToSystem();
ttgo->tft->setTextSize(2);
ttgo->tft->setCursor(10, 42);
ttgo->tft->print("IR Remote");
delay(500);
ttgo->tft->fillScreen(TFT_BLACK);
// Setup the Menu
for (int m = 1;m <= 8; m++) {
drawMenuItem(m,TFT_BLUE);}
}
void loop() {
int16_t x, y, tx, ty;
boolean exitMenu = false; // used to stay in the menu until user selects app
while (!exitMenu) {
while (!ttgo->getTouch(x, y)) {}
if (ttgo->getTouch(x, y)) {
int cmdReceived = Serial.read();
Serial.print(x);
Serial.print ("-");
Serial.println(y);
if (x > 0 && x < 120 && y > 0 && y < 60) { //Button 1 OFF/ON
Serial.println("Pressed 1 - ON/OFF");
drawMenuItem(1,TFT_GREEN);
irsend.sendNEC(0x20DF10EF, 32);
delay(500);
drawMenuItem(1,TFT_BLUE);
}
if (x > 120 && x < 240 && y > 0 && y < 60) { //Button 2
Serial.println("Pressed 2 - OK");
drawMenuItem(2,TFT_GREEN);
irsend.sendNEC(0x20DF22DD, 32);
delay(500);
drawMenuItem(2,TFT_BLUE);
}
if (x > 0 && x < 120 && y > 60 && y < 120) { //Button 3
Serial.println("Pressed 3 - Vol UP");
drawMenuItem(3,TFT_GREEN);
irsend.sendNEC(0x20DF40BF, 32);
delay(500);
drawMenuItem(3,TFT_BLUE);
}
if (x > 120 && x < 240 && y > 60 && y < 120) { //Button 4
Serial.println("Pressed 4 - Ch UP");
drawMenuItem(4,TFT_GREEN);
irsend.sendNEC(0x20DF00FF, 32);
delay(500);
drawMenuItem(4,TFT_BLUE);
}
if (x > 0 && x < 120 && y > 120 && y < 180) { //Button 5
Serial.println("Pressed 5 - Vol DOWN");
drawMenuItem(5,TFT_GREEN);
irsend.sendNEC(0x20DFC03F, 32);
delay(500);
drawMenuItem(5,TFT_BLUE);
}
if (x > 120 && x < 240 && y > 120 && y < 180) { //Button 6
Serial.println("Pressed 6 - Ch DOWN");
drawMenuItem(6,TFT_GREEN);
irsend.sendNEC(0x20DF807F, 32);
delay(500);
drawMenuItem(6,TFT_BLUE);
}
if (x > 0 && x < 120 && y > 180 && y < 240) { //Button 7
Serial.println("Pressed 7");
drawMenuItem(7,TFT_GREEN);
// irsend.sendNEC(0x20DF807F, 32);
delay(500);
drawMenuItem(7,TFT_BLUE);
}
if (x > 120 && x < 240 && y > 180 && y < 240) { //Button 8
Serial.println("Pressed 8");
drawMenuItem(8,TFT_GREEN);
// irsend.sendNEC(0x20DF807F, 32);
delay(500);
drawMenuItem(8,TFT_BLUE);
}
// exitMenu = true;
// irsend.enableIROut(38);
delay(500);
//drawMenu();
}
}
Serial.println("end Loop");
}
void drawMenuItem(int button,uint16_t bgcolour) { /// Eight button menu 1
ttgo->tft->setTextColor(TFT_YELLOW);
ttgo->tft->setTextSize(2);
switch (button) {
case 1:
ttgo->tft->drawRoundRect(0, 0, 119, 59, 6, bgcolour); //Button 1
ttgo->tft->setCursor(10, 22);
ttgo->tft->print("ON/OFF");
break;
case 2:
ttgo->tft->drawRoundRect(120, 0, 119, 59, 6, bgcolour); // Button 2
ttgo->tft->setCursor(130, 22);
ttgo->tft->print("OK");
break;
case 3:
ttgo->tft->drawRoundRect(0, 60, 119, 59, 6, bgcolour);
ttgo->tft->setCursor(10, 82);
ttgo->tft->print("Vol UP");
break;
case 4:
ttgo->tft->drawRoundRect(120, 60, 119, 59, 6, bgcolour);
ttgo->tft->setCursor(130, 82);
ttgo->tft->print("Ch UP");
break;
case 5:
ttgo->tft->drawRoundRect(0, 120, 119, 59, 6, bgcolour);
ttgo->tft->setCursor(10, 142);
ttgo->tft->print("Vol DN");
break;
case 6:
ttgo->tft->drawRoundRect(120, 120, 119, 59, 6, bgcolour);
ttgo->tft->setCursor(130, 142);
ttgo->tft->print("Ch DN");
break;
case 7:
ttgo->tft->drawRoundRect(0, 180, 119, 59, 6, bgcolour);
ttgo->tft->setCursor(10, 202);
ttgo->tft->print("");
break;
case 8:
ttgo->tft->drawRoundRect(120, 180, 119, 59, 6, bgcolour);
ttgo->tft->setCursor(130, 202);
ttgo->tft->print("");
break;
}
}
Note that the IR sender of the TTGO watch is on the front… inconvenient since my hand is in the way. I got around this by programming a 1000ms delay between the button press on the watch screen and sending the IR codes. This gives a moment to point the watch face at the TV !