Montre T-Watch 2020 v1

Application pratique : LISTE DE COURSES. Et en plus elle donne l'heure !

1 Présentation

La montre TTGO modèle T-Watch du fabricant Lilygo est totalement programmable. Elle est basée sur un ESP32 avec un affichage couleur 240 x 240, et batterie Li-Ion de 320mAh.

De nombreux programmes d'exemples sont disponibles sur Github.
Toutefois je voulais une chose bien précise : afficher la liste des courses à faire dans les magasins, sans devoir tenir le smartphone d'une main ce qui est fort peu pratique (mais que je faisait jusqu'à présent).


2 Principe : les deux listes

Deux listes sont enregistrées dans la montre :
  • la liste de tous les articles couramment achetés (image ci-contre)
  • la liste des articles à acheter (image ci-dessus)
Bien entendu la liste de tous les articles couramment achetés ne comprend pas seulement 11 articles, enfin en ce qui me concerne... deux boutons (flèches haut et bas) permettent de naviguer dans la liste. Eh oui, l'écran est tactile (capacitif , très agréable et précis, digne d'un smartphone).

Le curseur (flèche sur le bord de gauche) se déplace de haut en bas en caressant l'écran du bout du doigt. C'est très pratique.

3 L'utilisation

Le principe d'utilisation est le suivant : le bouton (!) fait basculer l'article pointé par le curseur d'une liste à l'autre.

Quant au contenu de la liste principale de tous les articles couramment achetés, il est simplement écrit en clair dans le fichier "data_perso2.c". Ci-contre un extrait.

4 L'écran de selection de mode de fonctionnement

On y accède par un appui bref sur le bouton (mécanique) situé sur le coté droit de la montre.

Cet écran comporte 5 boutons virtuels sensitifs :
  • [W] pour enregistrer les données en EEPROM (en fait en mémoire flash comme il se doit sur les ESP32)
  • [R] pour lire ces données (état des deux listes)
  • [Montre] pour afficher l'heure (si, si !)
  • [R] pour afficher l'heure en donnant la possibilité de modifier les minutes
  • [Liste] pour revenir à la liste de courses

5 Un montre qui donne l'heure

Il est très facile de programmer un affichage analogique (avec des aiguilles et même une trotteuse), j'ajouterai ça plus tard.

6 Le règlage de minutes :

En fait l'heure se programme dans le code source avant de compiler et de programmer la montre. Le règlage des minutes est un plus. On pourra aussi ajouter les fonctions suivantes :
  • règlage des heures (heure d'hiver - heure d'été)
  • mise à l'heure par bluetooth


je sais faire tout ça, à suivre donc...

7 Le code source du programme :

CODE SOURCE en C++
  1. /*
  2. pour montre TTGO T-Watch v1
  3.  
  4. par Silicium628
  5.  
  6. à voir aussi -> https://projetsdiy.fr/ttgo-t-watch-debuter-librairie-esp32-tft_espi/
  7. */
  8.  
  9. #define version1 "2.0"
  10.  
  11.  
  12. #include "config.h"
  13. #include "Free_Fonts.h"
  14. #include <EEPROM.h>
  15. #define EEPROM_SIZE 100
  16.  
  17. #include "data_perso2.c"
  18. #include "Listeuse.h"
  19.  
  20. bool irq = false;
  21.  
  22. char buf[128];
  23. bool rtcIrq = false;
  24.  
  25. TTGOClass *ttgo;
  26.  
  27. TFT_eSPI * tft;
  28.  
  29. AXP20X_Class *power;
  30.  
  31. BOUTON bouton1;
  32. BOUTON bouton2;
  33. BOUTON bouton3;
  34. BOUTON bouton4;
  35. BOUTON bouton5;
  36. BOUTON bouton6;
  37. BOUTON bouton7;
  38. BOUTON bouton8;
  39. BOUTON bouton9;
  40. BOUTON bouton10;
  41. BOUTON bouton11;
  42. BOUTON bouton12;
  43. BOUTON bouton13;
  44. BOUTON bouton14;
  45. BOUTON bouton15;
  46.  
  47.  
  48. /***************************************************************************************
  49. ** Section 6: Colour enumeration
  50. ***************************************************************************************/
  51. // Default color definitions
  52. /**
  53. #define TFT_BLACK 0x0000 // 0, 0, 0
  54. #define TFT_NAVY 0x000F // 0, 0, 128
  55. #define TFT_DARKGREEN 0x03E0 // 0, 128, 0
  56. #define TFT_DARKCYAN 0x03EF // 0, 128, 128
  57. #define TFT_MAROON 0x7800 // 128, 0, 0
  58. #define TFT_PURPLE 0x780F // 128, 0, 128
  59. #define TFT_OLIVE 0x7BE0 // 128, 128, 0
  60. #define TFT_LIGHTGREY 0xD69A // 211, 211, 211
  61. #define TFT_DARKGREY 0x7BEF // 128, 128, 128
  62. #define TFT_BLUE 0x001F // 0, 0, 255
  63. #define TFT_GREEN 0x07E0 // 0, 255, 0
  64. #define TFT_CYAN 0x07FF // 0, 255, 255
  65. #define TFT_RED 0xF800 // 255, 0, 0
  66. #define TFT_MAGENTA 0xF81F // 255, 0, 255
  67. #define TFT_YELLOW 0xFFE0 // 255, 255, 0
  68. #define TFT_WHITE 0xFFFF // 255, 255, 255
  69. #define TFT_ORANGE 0xFDA0 // 255, 180, 0
  70. #define TFT_GREENYELLOW 0xB7E0 // 180, 255, 0
  71. #define TFT_PINK 0xFE19 // 255, 192, 203 //Lighter pink, was 0xFC9F
  72. #define TFT_BROWN 0x9A60 // 150, 75, 0
  73. #define TFT_GOLD 0xFEA0 // 255, 215, 0
  74. #define TFT_SILVER 0xC618 // 192, 192, 192
  75. #define TFT_SKYBLUE 0x867D // 135, 206, 235
  76. #define TFT_VIOLET 0x915C // 180, 46, 226
  77. **/
  78.  
  79. bool KeyPressed = false;
  80. bool lenergy = false;
  81. static bool irq_axp202 = false;
  82. static bool return_to_deepsleep = true;
  83. #define TIME_TO_SLEEP 30
  84.  
  85.  
  86. uint8_t secondes;
  87. uint8_t heures;
  88. uint8_t minutes;
  89.  
  90. uint8_t etats[nb_elements]; // nb_elements est défini dans le fichier data_perso2.c
  91.  
  92. uint8_t lst_num_affi[11]; // liste des numéros des strings actuellement affichés
  93. uint16_t num_ligne_pointee;
  94. uint8_t top_lst=0;
  95. uint8_t lst_a_afficher=1; // =0 ou 1 (2 listes)
  96. uint8_t choix_ok =0;
  97. uint8_t mode=0;
  98. uint8_t reg_heure=0;
  99.  
  100. int16_t x_1, y_1;
  101. int16_t x_2, y_2;
  102. uint16_t memo_y_2=0;
  103.  
  104.  
  105. void init_boutons()
  106. {
  107.  
  108. // sur la partie listeuse
  109.  
  110. if(lst_a_afficher == 0)
  111. {
  112. bouton1.init(199,0, 40,40, "fleche_droite", TFT_BROWN);
  113. }
  114. else
  115. {
  116. bouton1.init(199,0, 40,40, "fleche_gauche", TFT_CYAN);
  117. }
  118.  
  119.  
  120. bouton1.dessine(0);
  121.  
  122. String s2;
  123. if(lst_a_afficher == 0) {s2="x";} else {s2="!";}
  124. bouton2.init(199,65, 40,40, s2, TFT_GREEN);
  125. bouton2.dessine(0);
  126.  
  127. bouton3.init(199,140, 40,20, "fleche_haut", TFT_WHITE);
  128. bouton3.dessine(0);
  129.  
  130. bouton4.init(199,200, 40,20, "fleche_bas", TFT_WHITE);
  131. bouton4.dessine(0);
  132.  
  133. // sur la page de choix
  134.  
  135. bouton5.init(120,0, 40,40, "W", TFT_RED);
  136.  
  137. bouton6.init(180,0, 40,40, "R", TFT_GREEN);
  138.  
  139. bouton7.init(5,80, 100,40, "Montre", TFT_WHITE);
  140.  
  141. bouton8.init(5,130, 100,40, "Liste", TFT_WHITE);
  142.  
  143. bouton9.init(150,190, 40,40, "+", TFT_WHITE); // bouton "inc minutes"
  144. bouton10.init(80,190, 40,40, "-", TFT_WHITE); // bouton "dec minutes"
  145.  
  146. bouton11.init(120,80, 110,40, "Reg h,m", TFT_WHITE); // bouton accès règlage minutes
  147.  
  148. bouton12.init(120,130, 110,40, "Batt", TFT_WHITE);
  149.  
  150. bouton13.init(130,200, 100,40, "retour", TFT_WHITE);
  151.  
  152. bouton14.init(150,40, 40,40, "+", TFT_WHITE); // bouton "inc heures"
  153. bouton15.init(80,40, 40,40, "-", TFT_WHITE); // bouton "dec heures"
  154. }
  155.  
  156.  
  157. uint16_t nb_elmt_liste_en_cours()
  158. {
  159. uint16_t nb1=0;
  160. for(int n=0; n<nb_elements; n++)
  161. {
  162. if (etats[n] == lst_a_afficher) {nb1++;}
  163. }
  164. return(nb1);
  165. }
  166.  
  167.  
  168.  
  169. void affiche_data()
  170. {
  171. if (mode==0)
  172. {
  173. String s1;
  174. tft->setFreeFont(FF18);
  175. tft->fillScreen(TFT_BLACK);
  176.  
  177. if(lst_a_afficher==0) {tft->setTextColor(TFT_CYAN, TFT_BLACK);} else {tft->setTextColor(TFT_BROWN, TFT_BLACK);}
  178.  
  179. for(uint16_t i=0; i<11; i++) {lst_num_affi[i]=255;} // RAZ liste
  180.  
  181.  
  182. int16_t dy=22;
  183.  
  184. // n'affiche que les lignes de la liste choisie (parmi 2 listes)
  185. uint16_t y=0;
  186.  
  187. uint8_t i=top_lst;
  188. uint8_t n=0;
  189. while((i<nb_elements) && (n<11))
  190. {
  191. if (etats[i] == lst_a_afficher)
  192. {
  193. uint16_t num1;
  194. num1 =top_lst + n;
  195. //num1 ++; // pour afficher à partir de 1 au lieu de 0...
  196. s1 =(String)num1;
  197. tft->setFreeFont(FF1);
  198. tft->setTextColor(TFT_SILVER, TFT_BLACK);
  199. tft->drawString(s1, 0, y+2, GFXFF); // affiche les numéros à gauche du texte
  200.  
  201.  
  202. String el1 = elements[i];
  203. tft->setFreeFont(FF18);
  204. if(lst_a_afficher==0) {tft->setTextColor(TFT_CYAN, TFT_BLACK);} else {tft->setTextColor(TFT_BROWN, TFT_BLACK);}
  205. tft->drawString(el1, 34, y, GFXFF);
  206. y+=dy;
  207. lst_num_affi[n]=i;
  208. n++;
  209. }
  210. i++;
  211. }
  212.  
  213. tft->setFreeFont(FF1);
  214. init_boutons();
  215.  
  216. uint16_t nb_el1;
  217.  
  218. nb_el1= nb_elmt_liste_en_cours();
  219. s1 =(String)nb_el1;
  220. tft->setTextColor(TFT_WHITE, TFT_BLUE);
  221. tft->setTextFont(2); // très petits caractères
  222. tft->drawString(s1, 220, 225, GFXFF); // affiche le nombre en bas à droite
  223. }
  224. }
  225.  
  226.  
  227.  
  228. void affiche_batterie()
  229. {
  230.  
  231.  
  232. tft->fillScreen(TFT_BLACK);
  233. uint8_t fin_bcl=0;
  234. while (fin_bcl == 0)
  235. {
  236. //tft->fillScreen(TFT_BLACK);
  237. tft->fillRect(0, 0, 230, 150, TFT_BLACK);
  238. tft->setTextColor(TFT_CYAN, TFT_BLACK);
  239. tft->setFreeFont(FF1);
  240.  
  241. bouton13.dessine(0);
  242.  
  243. tft->setTextColor(TFT_CYAN, TFT_BLACK);
  244. tft->setFreeFont(FF1);
  245.  
  246.  
  247. tft->setCursor(0, 10);
  248.  
  249. tft->print("VBUS ETAT: ");
  250.  
  251. if (power->isVBUSPlug())
  252. {
  253. tft->setTextColor(TFT_GREEN, TFT_BLACK);
  254. tft->println("CONNECT");
  255.  
  256. tft->setTextColor(TFT_YELLOW, TFT_BLACK);
  257. tft->print("VBUS V : ");
  258. tft->print(power->getVbusVoltage());
  259. tft->println(" mV");
  260.  
  261. tft->setTextColor(TFT_BLUE, TFT_BLACK);
  262. tft->print("VBUS I: ");
  263. tft->print(power->getVbusCurrent());
  264. tft->println(" mA");
  265. }
  266. else
  267. {
  268. tft->setTextColor(TFT_RED, TFT_BLACK);
  269. tft->println("DISCONNECT");
  270. tft->setTextColor(TFT_GREEN, TFT_BLACK);
  271. }
  272.  
  273. tft->println();
  274. tft->setTextColor(TFT_CYAN, TFT_BLACK);
  275. tft->print("BATT Li-Ion : ");
  276. // You can use isBatteryConnect() to check whether the battery is connected properly
  277. if (power->isBatteryConnect())
  278. {
  279. tft->setTextColor(TFT_GREEN, TFT_BLACK);
  280. tft->println("CONNECT");
  281.  
  282. tft->setTextColor(TFT_YELLOW, TFT_BLACK);
  283. float V=power->getBattVoltage();
  284. V /=1000;
  285. tft->print(V);
  286.  
  287. tft->println(" V");
  288.  
  289. // To display the charging status, you must first discharge the battery,
  290. // and it is impossible to read the full charge when it is fully charged
  291. if (power->isChargeing())
  292. {
  293. tft->setTextColor(TFT_BLUE, TFT_BLACK);
  294. tft->print("Charge : ");
  295. tft->print(power->getBattChargeCurrent());
  296. tft->println(" mA");
  297. }
  298. else
  299. {
  300. // Show current consumption
  301. tft->setTextColor(TFT_WHITE, TFT_BLACK);
  302. tft->print("Decharge : ");
  303. tft->print(power->getBattDischargeCurrent());
  304. tft->println(" mA");
  305.  
  306. tft->print(power->getBattPercentage());
  307. tft->println(" %");
  308.  
  309. }
  310. }
  311. else
  312. {
  313. tft->setTextColor(TFT_RED, TFT_BLACK);
  314. tft->println("DISCONNECT");
  315. tft->setTextColor(TFT_GREEN, TFT_BLACK);
  316. }
  317.  
  318. for(int n=0; n<10; n++) // pour obtenir un temps de réaction très bref en gardant une tempo de 1s
  319. {
  320.  
  321. if (ttgo->getTouch(x_1, y_1))
  322. {
  323. fin_bcl=1;
  324. affi_choix();
  325. mode=1;
  326. }
  327. delay(100);
  328. }
  329.  
  330.  
  331. }
  332.  
  333. }
  334.  
  335.  
  336.  
  337. void affi_choix()
  338. {
  339.  
  340. tft->fillScreen(TFT_BLACK);
  341.  
  342. tft->setTextColor(TFT_CYAN, TFT_BLACK);
  343. tft->setFreeFont(FF18);
  344.  
  345. tft->drawString("Eeprom :", 10, 5, GFXFF);
  346.  
  347. tft->drawLine(0, 45, 239, 45, TFT_WHITE);
  348.  
  349. //tft->drawString("Fonction :", 10, 55, GFXFF);
  350.  
  351. bouton5.dessine(0);
  352. bouton6.dessine(0);
  353. bouton7.dessine(0);
  354. bouton8.dessine(0);
  355. bouton11.dessine(0);
  356. bouton12.dessine(0);
  357. }
  358.  
  359.  
  360.  
  361.  
  362. void setup()
  363. {
  364. //Serial.begin(115200);
  365. //Serial.println("setup()");
  366.  
  367. EEPROM.begin(EEPROM_SIZE); // en mémoire flash
  368.  
  369. ttgo = TTGOClass::getWatch();
  370. ttgo->begin();
  371.  
  372. power = ttgo->power;
  373.  
  374. ttgo->openBL(); // allume le rétroéclairage
  375. ttgo->bl->adjust(150); //Lower the brightness
  376.  
  377. tft = ttgo->tft;
  378.  
  379. tft->fillScreen(TFT_BLACK);
  380.  
  381. ttgo->rtc->disableAlarm();
  382. // ttgo->rtc->setDateTime(2021, 03, 12, 17, 21, 30); // commenter cette ligne sauf pour remettre à l'heure
  383.  
  384. for(int n =0; n<nb_elements; n++)
  385. {
  386. etats[n]= 1;
  387. }
  388.  
  389. uint16_t dy=22;
  390. uint16_t decal=0;
  391.  
  392. // for(int decal =0; decal<nb_elements; decal++)
  393. {
  394. uint16_t y=0;
  395. tft->fillScreen(TFT_BLACK);
  396.  
  397. affiche_data();
  398.  
  399. delay(100);
  400. }
  401.  
  402. init_boutons();
  403.  
  404. uint8_t v1 = EEPROM.read(0);
  405. String s1;
  406. s1 =(String)v1;
  407. tft->setFreeFont(FF1);
  408. tft->setTextColor(TFT_SILVER, TFT_BLACK);
  409. tft->drawString(s1, 150, 70, GFXFF);
  410.  
  411. pinMode(AXP202_INT, INPUT_PULLUP);
  412. attachInterrupt(AXP202_INT, []
  413. {
  414. irq = true;
  415. }, FALLING);
  416.  
  417. //!Clear IRQ unprocessed first
  418.  
  419. power->enableIRQ(AXP202_PEK_SHORTPRESS_IRQ | AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_CHARGING_IRQ, true);
  420. // ADC monitoring must be enabled to use the AXP202 monitoring function
  421. power->adc1Enable(AXP202_VBUS_VOL_ADC1 | AXP202_VBUS_CUR_ADC1 | AXP202_BATT_CUR_ADC1 | AXP202_BATT_VOL_ADC1, true);
  422.  
  423. power->clearIRQ();
  424.  
  425. read_eeprom();
  426. mode=0;
  427. lst_a_afficher=0;
  428.  
  429. //affi_choix();
  430. //affiche_data();
  431.  
  432. affiche_heure();
  433.  
  434. }
  435.  
  436.  
  437.  
  438. void trace_curseur_triangulaire(uint16_t x, uint16_t y, uint32_t couleur)
  439. {
  440. tft->fillTriangle (x, y-12, x, y+6, x+10, y-2, couleur);
  441. }
  442.  
  443.  
  444.  
  445. void affi_string(String s, uint16_t x, uint16_t y)
  446. {
  447. tft->setFreeFont(FF1);
  448. tft->setTextColor(TFT_WHITE, TFT_BLACK);
  449. tft->drawString(" ", x, y, GFXFF);
  450. tft->drawString(s, x, y, GFXFF);
  451. }
  452.  
  453.  
  454.  
  455. void affi_int(uint16_t k, uint16_t x, uint16_t y)
  456. {
  457. String s1 =(String)k;
  458. tft->setFreeFont(FF1);
  459. tft->setTextColor(TFT_WHITE, TFT_BLACK);
  460. tft->drawString(" ", x, y, GFXFF);
  461. tft->drawString(s1, x, y, GFXFF);
  462. }
  463.  
  464.  
  465.  
  466. void affi_message(String m1)
  467. {
  468. tft->setTextColor(TFT_WHITE, TFT_BLUE);
  469. tft->setFreeFont(FF18);
  470. ttgo->tft->drawString(m1, 25, 100);
  471. delay(1000);
  472. affiche_data();
  473. }
  474.  
  475.  
  476. void record_etat()
  477. {
  478. if (nb_elements > 100) {return;}
  479. int adresse =0;
  480. uint8_t nbe = nb_elements;
  481. for(int n=0; n<nb_elements; n++)
  482. {
  483. EEPROM.write(adresse, etats[n]);
  484. EEPROM.commit();
  485. delay(5);
  486. adresse ++;
  487. }
  488. }
  489.  
  490.  
  491. void read_eeprom()
  492. {
  493. int adresse =0;
  494. for(int n=0; n<nb_elements; n++)
  495. {
  496. uint8_t v;
  497. v = EEPROM.read(adresse);
  498. //Serial.print(n); Serial.print(": "); Serial.println(v);
  499. etats[n]=v;
  500. adresse ++;
  501. }
  502. }
  503.  
  504.  
  505.  
  506. void inc_heures()
  507. {
  508. RTC_Date dt1 = ttgo->rtc->getDateTime();
  509.  
  510. if (dt1.hour<23) {dt1.hour++;}
  511. ttgo->rtc->setDateTime(dt1);
  512. }
  513.  
  514.  
  515. void dec_heures()
  516. {
  517. RTC_Date dt1 = ttgo->rtc->getDateTime();
  518.  
  519. if (dt1.hour>0) {dt1.hour--;}
  520. ttgo->rtc->setDateTime(dt1);
  521. }
  522.  
  523.  
  524.  
  525. void inc_minutes()
  526. {
  527. RTC_Date dt1 = ttgo->rtc->getDateTime();
  528.  
  529. if (dt1.minute<59) {dt1.minute++;}
  530. else
  531. {
  532. dt1.hour++;
  533. dt1.minute=0;
  534. }
  535.  
  536. ttgo->rtc->setDateTime(dt1);
  537. }
  538.  
  539.  
  540. void dec_minutes()
  541. {
  542. RTC_Date dt1 = ttgo->rtc->getDateTime();
  543.  
  544. if (dt1.minute>0) {dt1.minute--;}
  545. else
  546. {
  547. dt1.hour--;
  548. dt1.minute=59;
  549. }
  550.  
  551. ttgo->rtc->setDateTime(dt1);
  552. }
  553.  
  554.  
  555.  
  556.  
  557.  
  558. void affiche_heure()
  559. {
  560. uint32_t d2;
  561. String s1, s2;
  562.  
  563. tft->fillScreen(TFT_BLACK);
  564.  
  565. if (reg_heure==1)
  566. {
  567. tft->fillScreen(TFT_BLACK);
  568.  
  569. tft->setTextColor(TFT_CYAN, TFT_BLACK);
  570. tft->setFreeFont(FF18);
  571. tft->drawString("h:", 10, 50, GFXFF);
  572.  
  573. bouton14.dessine(0);
  574. bouton15.dessine(0);
  575.  
  576. tft->setTextColor(TFT_CYAN, TFT_BLACK);
  577. tft->setFreeFont(FF18);
  578. tft->drawString("mn :", 10, 200, GFXFF);
  579.  
  580. bouton9.dessine(0);
  581. bouton10.dessine(0);
  582.  
  583. bouton14.dessine(0);
  584. bouton15.dessine(0);
  585. }
  586.  
  587. //ttgo->tft->setTextColor(TFT_YELLOW, TFT_BLACK);
  588.  
  589. uint8_t stop=0;
  590. while(stop==0)
  591. {
  592.  
  593. ttgo->tft->setTextColor(TFT_YELLOW, TFT_BLACK);
  594. RTC_Date dt1 = ttgo->rtc->getDateTime();
  595. heures = dt1.hour;
  596. s1="";
  597. if (heures<10) {s1 +="0";}
  598. s1+= String(heures);
  599. s1+=":";
  600.  
  601. minutes = dt1.minute;
  602. if (minutes<10) {s1 +="0";}
  603. s1 += String (minutes);
  604. s1+=" ";
  605.  
  606. tft->setFreeFont(FM24);
  607. ttgo->tft->drawString(s1, 40, 100);
  608.  
  609.  
  610. secondes = dt1.second;
  611. s2 = String (secondes);
  612. s2+=" ";
  613.  
  614. tft->setFreeFont(FM12);
  615. ttgo->tft->setTextColor(TFT_BLUE, TFT_BLACK);
  616. ttgo->tft->drawString(s2, 40, 150);
  617.  
  618. if (irq)
  619. {
  620. ttgo->power->readIRQ();
  621. if (ttgo->power->isPEKShortPressIRQ())
  622. {
  623. ttgo->power->clearIRQ();
  624. stop=1;
  625. }
  626. //irq = false;
  627. }
  628.  
  629. if (reg_heure==1)
  630. {
  631. if (ttgo->getTouch(x_1, y_1))
  632. {
  633. if (detect_btn(&bouton9)) { inc_minutes(); }
  634. if (detect_btn(&bouton10)) { dec_minutes(); }
  635. if (detect_btn(&bouton14)) { inc_heures(); }
  636. if (detect_btn(&bouton15)) { dec_heures(); }
  637.  
  638. }
  639. }
  640. if (stop ==0) {delay(500);}
  641. }
  642.  
  643. reg_heure=0;
  644. mode=1;
  645. affi_choix();
  646.  
  647. }
  648.  
  649.  
  650. int detect_btn(BOUTON *bouton_i)
  651. {
  652. // calcul de la distance^2 du point cliqué / centre du bouton; rappel : sq = fonction "carré de"
  653. // d²=dx²+dy²
  654. // inutile d'en prendre la racine carrée, on peut utiliser la valeur d² directement
  655. uint32_t d2;
  656.  
  657. uint16_t milieu_x = bouton_i->x0 + bouton_i->dx/2;
  658. d2= sq(x_1 - milieu_x) + sq(y_1 - bouton_i->y0);
  659.  
  660. if (d2 < 2000)
  661. {
  662. bouton_i->dessine(1);
  663. delay (200);
  664. bouton_i->dessine(0);
  665. return(1);
  666. }
  667. else
  668. {
  669. return(0);
  670. }
  671.  
  672. }
  673.  
  674.  
  675. void loop()
  676. {
  677. uint32_t d2;
  678.  
  679.  
  680. if (irq)
  681. {
  682. irq = false;
  683. power->readIRQ();
  684.  
  685. //if (power->isVbusPlugInIRQ()) {affi_message("Power Plug In"); }
  686. //if (power->isVbusRemoveIRQ()) {affi_message("Power Remove"); }
  687.  
  688. if (power->isPEKShortPressIRQ())
  689. {
  690. affi_choix();
  691. mode=1;
  692. }
  693. power->clearIRQ();
  694. }
  695.  
  696.  
  697. if (ttgo->getTouch(x_1, y_1))
  698. {
  699. if(mode==0) // mode "normal"
  700. {
  701. if (x_1<160) // gestion du curseur à gauche
  702. {
  703. num_ligne_pointee = y_1/22;
  704.  
  705. /** affi_int(num_ligne_pointee, 120, 0); // pour test -> [0..10] **/
  706.  
  707. x_2=20;
  708. y_2=22*(y_1/22)+12;
  709.  
  710. uint8_t num_el = lst_num_affi[num_ligne_pointee];
  711.  
  712. if(((y_2 != memo_y_2) && (num_el != 255))|| (num_ligne_pointee==0) ) // la valeur 255 est inscrite au delà de la fin des éléments présents . cf: affiche_data()
  713. {
  714. /**
  715. affi_int(num_el, 120, 20); // pour test
  716. String s1 = elements[num_el];
  717. affi_string(s1 ,120,40); // pour test
  718. **/
  719. trace_curseur_triangulaire(x_2, memo_y_2, TFT_BLACK); //efface le précédent
  720. trace_curseur_triangulaire(x_2, y_2, TFT_YELLOW); //trace le curseur triangulaire jaune
  721. memo_y_2 = y_2;
  722. bouton2.couleur=TFT_GREEN;
  723. bouton2.dessine(0);
  724. choix_ok=1;
  725. }
  726. }
  727. else // gestion des boutons à droite
  728. {
  729. if (detect_btn(&bouton1))
  730. {
  731. lst_a_afficher=1-lst_a_afficher;
  732. top_lst=0;
  733. affiche_data();
  734. }
  735. if (detect_btn(&bouton2))
  736. {
  737. if (choix_ok==1)
  738. {
  739. uint8_t n_el = lst_num_affi[num_ligne_pointee];
  740. etats[n_el]=1-etats[n_el];
  741. affiche_data();
  742. bouton2.couleur=TFT_DARKGREY;
  743. bouton2.dessine(0);
  744. choix_ok=0;
  745. }
  746. }
  747. if (detect_btn(&bouton3))
  748. {
  749. top_lst=0;
  750. affiche_data();
  751. }
  752. if (detect_btn(&bouton4))
  753. {
  754. uint16_t nb_max = nb_elmt_liste_en_cours();
  755. //if (top_lst < (nb_max-11))
  756.  
  757. top_lst=lst_num_affi[10]; // on part du dernier élément de l'affichage en cours
  758. //{top_lst+=11;} //attention à cette valeur : elle doit correspondre au nb de lignes affichées
  759. affiche_data();
  760. }
  761.  
  762. }
  763. }
  764. else if(mode==1) // ecran de choix avec 5 boutons
  765. {
  766. if (detect_btn(&bouton5))
  767. {
  768. record_etat();
  769. }
  770.  
  771. if (detect_btn(&bouton6))
  772. {
  773. read_eeprom();
  774. mode=0;
  775. lst_a_afficher=0;
  776. affiche_data();
  777. }
  778.  
  779. if (detect_btn(&bouton7))
  780. {
  781. affiche_heure();
  782. x_1=0;
  783. y_1=0;
  784. }
  785.  
  786. if (detect_btn(&bouton8))
  787. {
  788. x_1=0;
  789. y_1=0;
  790. mode=0;
  791. affiche_data();
  792. }
  793.  
  794. if (detect_btn(&bouton11))
  795. {
  796. reg_heure=1;
  797. affiche_heure();
  798. }
  799.  
  800. if (detect_btn(&bouton12))
  801. {
  802. affiche_batterie();
  803. }
  804. }
  805. }
  806.  
  807. delay(5);
  808. }
  809.  
  810. /** ***********************************************************************************
  811. CLASS BOUTON // affiche un bouton cliquable
  812. ***************************************************************************************/
  813.  
  814.  
  815.  
  816. // Constructeur
  817. BOUTON::BOUTON()
  818. {
  819.  
  820. }
  821.  
  822.  
  823. void BOUTON::init(uint16_t x_i, uint16_t y_i, uint16_t dx_i, uint16_t dy_i, String s_i, uint32_t couleur_i)
  824. {
  825. x0 = x_i;
  826. y0 = y_i;
  827. dx = dx_i;
  828. dy = dy_i;
  829. s = s_i;
  830. couleur =couleur_i;
  831. }
  832.  
  833.  
  834.  
  835.  
  836. void BOUTON::dessine(uint8_t fill_i)
  837. {
  838. if(fill_i==1)
  839. {
  840. tft->fillRoundRect(x0, y0, dx, dy, 5, couleur);
  841.  
  842. }
  843. else
  844. {
  845. tft->fillRoundRect(x0, y0, dx, dy, 5, TFT_BLACK); // "éteint" le bouton
  846. tft->drawRoundRect(x0, y0, dx, dy, 5, couleur); // retrace le pourtour
  847. //
  848.  
  849. if (s=="fleche_haut") {tft->fillTriangle (x0+12, y0+15, x0+30, y0+15, x0+20, y0+5, couleur);}
  850. else if (s=="fleche_bas") {tft->fillTriangle (x0+12, y0+5, x0+30, y0+5, x0+20, y0+15, couleur);}
  851. else if (s=="fleche_droite") {tft->fillTriangle (x0+15, y0+8, x0+15, y0+26, x0+25, y0+18, couleur);}
  852. else if (s=="fleche_gauche") {tft->fillTriangle (x0+25, y0+8, x0+25, y0+26, x0+15, y0+18, couleur);}
  853.  
  854. else
  855. {
  856. tft->setFreeFont(FF18);
  857. tft->setTextColor(TFT_WHITE, TFT_BLACK);
  858. tft->drawString(s, x0+11, y0+10);
  859. }
  860.  
  861. }
  862.  
  863. }
  864.  
  865.  
  866.  


8 Quelques précisions :

Voici quelques infos à propos du fonctionnement de ce programme et de la montre en général :

  1. La liste complète de tous articles se trouve placée en mémoire flash (celle-là même qui héberge l'exécutable du programme) lors de la programmation. Le statut de chaque article, qui détermine s'il sera affiché en liste des produit à acheter ou en liste potentielle est, lui, placé dans un tableau en RAM. C'est à dire perdu lors de l'arrêt complet de la montre. J'ai donc ajouté une fonction qui enregistre ce tableau en mémoire EEPROM (qui sur les ESP32 n'est autre qu'une partie de la mémoire flash accessible en lecture-écriture par le programme). Cet enregistrement du tableau s'effectue manuellement par appui sur un bouton comme vu plus haut.

  2. Lorsque l'écran est allumé et que le programme tourne, la consommation électrique est d'environ 100mA, ce qui est normal pour ces composants, mais compte tenu de la capacité réduite de la batterie Li-Ion (380mAh) ne permet qu'une autonomie de moins de 4 heures, et en réalité bien moins encore. D'ou l'intérêt de la mise en veille.

  3. La mise en veille s'effectue par un appui (très long, ~10s) sur le bouton mécanique placé sur le côté droit de la montre. La consommation descend à moins de 1mA, cette fois.

  4. Lors de la mise en veille, les données de la RAM ne sont pas conservées. D'où la nécessité de l'enregistrement en EEPROM

  5. Lors de la mise en veille, l'horloge RTC interne continue à fonctionner, l'heure reste exacte. Ouf ! Et même si on retire la batterie (en fait il y a une micro-batterie qui continue à alimenter le circuit RTC (PCF8563).

  6. Cette montre est géniale.

  7. Le système de fermeture du bracelet est merdique grave.

9 Documents

10 -

Liens...

3937