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


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

Me contacter à propos de cet article :

Pseudo : Les messages envoyés font l'objet d'une modération à priori.
Question mathématique :
Click to reload image
=
cliquez sur l'image pour un faire autre calcul.
Réponses à certaines de vos questions...


239