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


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...

N'hésitez pas à ajouter un commentaire ici :

Pseudo : Les commentaires font l'objet d'une modération à priori.
Question mathématique :
Click to reload image
=
cliquez sur l'image pour un faire autre calcul.
COMMENTAIRES


883