Hello,
Je vais tenter de t'aider. Poste ton dernier code stp.
Une question: quelle est la borne supérieure pour le bargraph ? Car il faut pouvoir le normer, or 147%, c'est assez particuler.
On écrit "J'ai tort" ; "tord" est la conjugaison du verbre "tordre" à la 3ème personne de l'indicatif présent
Salut edgarjacobs
merci par avance pour le coup de main
voici le code :
à la ligne 418
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419 // E_V20240611a // /************************************************************ ESP32 WROOM LOW POWER DEVKIT uPesy ------------------ |1 32| GPIO23 T_IRQ GPIO36 |2 31| GPIO22 T_OUT GPIO39 |3 30| GPIO1 GPIO34 |4 29| GPIO3 NC |5 28| GPIO21 LED T_DIN GPIO32 |6 27| GPIO19 T_CS GPI033 |7 26| GPIO18 T_CLK GPIO25 |8 25| GPIO5 GPIO26 |9 24| GPIO17 GPIO27 |10 23| GPIO16 SDO(MISO) SCK GPIO14 |11 22| GPIO4 TTP223 RESET GPIO12 |12 21| GPIO0 SDI(MOSI) GPIO13 |13 20| GPIO2 D/C |14 19| GPIO15 CS |15 18| 3V3 VCC GND |16 |----| 17| GND \-------| |---/ |----| **************************************************************/ #include <SPIFFS.h> #include <SPI.h> #include <TFT_eSPI.h> #include <XPT2046_Touchscreen.h> // https : //github. com/PaulStoffregen/XPT2046_Touchscreen #include <esp_now.h> #include <WiFi.h> #include <EEPROM.h> TFT_eSPI tft = TFT_eSPI(); // Touchscreen pins #define XPT2046_IRQ 36 // T_IRQ #define XPT2046_MOSI 32 // T_DIN #define XPT2046_MISO 39 // T_OUT #define XPT2046_CLK 25 // T_CLK #define XPT2046_CS 33 // T_CS #define FM9 &FreeMono9pt7b #define DELTA 32 // Bargraff #define BACKCOLOR 0x18E3 //#define BARCOLOR 0x0620 #define BARCOLOR 0x03EF #define SCALECOLOR 0xFFFF // Interruption TPP223 const gpio_num_t vbatPin = GPIO_NUM_35; SPIClass touchscreenSPI = SPIClass(VSPI); XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ); #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 #define FONT_SIZE 2 // definition des boutons #define BUTTON_WIDTH 80 #define BUTTON_HEIGHT 60 #define BUTTON_MARGIN 10 // Structure pour représenter un bouton ************* struct Button { int value; int x, y; bool state; }; RTC_DATA_ATTR int bootCount = 0; RTC_DATA_ATTR Button buttons[9]; // 9 boutons //RTC_DATA_ATTR float vBat = 0; RTC_DATA_ATTR int progress = 0; float vBat = 0; /*****************************************************************/ /*Imprimer les informations de l'écran tactile concernant X, Y et la pression (Z) sur le moniteur série*/ void printTouchToSerial(int touchX, int touchY, int touchZ) { Serial.print("X = "); Serial.print(touchX); Serial.print(" | Y = "); Serial.print(touchY); Serial.print(" | Pression = "); Serial.print(touchZ); Serial.println(); } /*****************************************************************/ /*** Structure Fichier Config.txt ********************************/ const size_t tailleMaxNom = 16; // y compris le caractère nul final struct ClientPC { char nom[tailleMaxNom]; // le nom du client PC uint8_t adresse[6]; // les 6 octets de son adresse }; const size_t nbMaxClients = 20; // nombre maximum de clients ClientPC clients[nbMaxClients]; size_t nbClientsPC = 0; // le nombre de clients lu dans le fichier de config /*****************************************************************/ // ***** Structure du récepteur ************************************* struct struct_message { char a[32]; // ex PC1 bool b; // Etat = 0 ou 1 }; // Créer une struct_message appelée myData struct_message myData; //........... Etat enoi ******************************************** esp_now_peer_info_t peerInfo; void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { Serial.print("\r\nÉtat de l'envoi du dernier paquet:\t"); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Succès" : "Échec"); } //********************************************************************* // Init ESP Now with fallback void InitESPNow() { WiFi.disconnect(); if (esp_now_init() == ESP_OK) { Serial.println("ESPNow Init Succès"); } else { Serial.println("Échec de l'initialisation de ESPNow"); // Retry InitESPNow, add a counte and then restart? // InitESPNow(); // or Simply Restart ESP.restart(); } } unsigned long currentTime=0; unsigned long previousTime=0; int touchX, touchY, touchZ , i; int LastPercent = 0; int valeurBrute ; int vBatOld = 0 ; int k; //************************************************ // SETUP //************************************************ void setup() { Serial.begin(115200); pinMode(35, INPUT); Calcul_vBat(); //Incrémente le numéro de démarrage et l'imprime à chaque redémarrage ++bootCount; Serial.println("Boot number: " + String(bootCount)); // Lire le fichier Config.txt if (!SPIFFS.begin(true)) { Serial.println("Une erreur s'est produite lors du montage de SPIFFS"); return; } File fichierConfig = SPIFFS.open("/config.txt", FILE_READ); if (!fichierConfig) { Serial.println("Impossible d'ouvrir le fichier en lecture"); return; } char bufferLigne[100]; // Buffer pour stocker chaque ligne char format[64]; // pour bâtir dynamiquement le format en tenant compte de la longueur max du nom (reco de Kernighan et Pike dans "The Practice of Programming") snprintf(format, sizeof format, "%%%ds %%hhx %%hhx %%hhx %%hhx %%hhx %%hhx", tailleMaxNom - 1); // lire une chaine de taille max tailleMaxNom - 1 suivie de 6 octets en hexa nbClientsPC = 0; while (fichierConfig.available() && nbClientsPC < nbMaxClients) { // tant qu'on peut lire quelque chose et qu'on a de la place pour stocker memset(bufferLigne, '\0', sizeof bufferLigne); // Effacer le buffer fichierConfig.readBytesUntil('\n', bufferLigne, sizeof bufferLigne); // Lire la ligne dans le buffer memset(clients[nbClientsPC].nom, '\0', sizeof clients[nbClientsPC].nom); // on efface le nom pour être tranquille int nbChampsLus = sscanf(bufferLigne, format, clients[nbClientsPC].nom, &clients[nbClientsPC].adresse[0], &clients[nbClientsPC].adresse[1], &clients[nbClientsPC].adresse[2], &clients[nbClientsPC].adresse[3], &clients[nbClientsPC].adresse[4], &clients[nbClientsPC].adresse[5]); if (nbChampsLus == 7) { // la lecture des 7 champs (le nom et 8 octets sous forme hexadécimale) s'est bien passée nbClientsPC++; } else { // on arrête de lire là break; } } fichierConfig.close(); // Affichage des adresses lues depuis le fichier for (size_t i = 0; i < nbClientsPC; i++) { Serial.printf("%3zu %-*s : ", i + 1, tailleMaxNom - 1, clients[i].nom); // l'index sur 3 caractères, le nom sur tailleMaxNom - 1 cadrée à gauche for (int j = 0; j < 6; j++) Serial.printf("0x%02X ", clients[i].adresse[j]); Serial.println(); } // Set device as a Wi-Fi Station WiFi.mode(WIFI_STA); // Init ESP-NOW InitESPNow(); if (esp_now_init() != ESP_OK) { Serial.println("Erreur d'initialisation de l'ESP-NOW"); } esp_now_register_send_cb(OnDataSent); for (size_t i = 0; i < nbClientsPC; i++) { // Enregistrer les devices peerInfo.channel = 0; peerInfo.encrypt = false; memcpy(peerInfo.peer_addr, clients[i].adresse, 6); if (esp_now_add_peer(&peerInfo) != ESP_OK) { Serial.printf("Échec de l'ajout de %s\n", clients[i].nom); return; } } // Démarrer le SPI pour l'écran tactile et initialiser l'écran tactile touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS); touchscreen.begin(touchscreenSPI); touchscreen.setRotation(3); tft.init(); tft.setRotation(1); tft.fillScreen(TFT_BLACK); // Graph Batterie Affich_vBat(); // Afficage du niveau Batterie // Initialisation des positions des boutons int buttonX = 20; int buttonY = 20; for ( int i = 0; i < 9; ++i) { buttons[i].x = buttonX; buttons[i].y = buttonY; buttons[i].value=i; // Affichage des boutons drawButton(&buttons[i]); buttonX += BUTTON_WIDTH + BUTTON_MARGIN; if (buttonX + BUTTON_WIDTH > tft.width()) { buttonX = 20; buttonY += BUTTON_HEIGHT + BUTTON_MARGIN; } } //Imprimer la raison du réveil de l'ESP32 //print_wakeup_reason(); esp_sleep_enable_ext0_wakeup(GPIO_NUM_4,1); //1 = High, 0 = Low } //************************************************ // LOOP //************************************************ void loop() { currentTime=millis(); // Vérifie si l'écran tactile a été touché et imprime les informations X, Y et la pression (Z) sur l'écran TFT et le moniteur série. if (touchscreen.tirqTouched() && touchscreen.touched()) { previousTime=currentTime; // Obtenir des points pour l'écran tactile TS_Point p = touchscreen.getPoint(); // Calibrer les points de l'écran tactile avec la fonction de carte à la bonne largeur et à la bonne hauteur touchX = map(p.x, 200, 3700, 1, SCREEN_WIDTH); touchY = map(p.y, 240, 3800, 1, SCREEN_HEIGHT); touchZ = p.z; printTouchToSerial(touchX, touchY, touchZ); for (int i = 0; i < 9; ++i) { if (touchX >= buttons[i].x && touchX <= buttons[i].x + BUTTON_WIDTH && touchY >= buttons[i].y && touchY <= buttons[i].y + BUTTON_HEIGHT) { // Si un bouton est touché, inverse son état et met à jour l'affichage Serial.println(); if( i < 8 ) { buttons[i].state = !buttons[i].state; drawButton(&buttons[i]); /*******************************************************/ if (buttons[i].state == 1) { Serial.print("Btn "); Serial.print(i + 1); Serial.println(" enfoncé"); snprintf(myData.a, sizeof myData.a, "PC%02d=> ON", i + 1); myData.b = true; esp_err_t result = esp_now_send(clients[i].adresse, (uint8_t *)&myData, sizeof(myData)); if (result == ESP_OK) { Serial.print("PC"); Serial.print(i + 1); Serial.println(" Envoyé avec succès"); //etat[i] = 1; } else { Serial.print("Erreur d'envoi des données PC"); Serial.print(i + 1); } } /*******************************************************/ if (buttons[i].state == 0) { Serial.print("Btn "); Serial.print(i + 1); Serial.println(" relaché"); snprintf(myData.a, sizeof myData.a, "PC%02d=> OFF", i + 1); myData.b = false; esp_err_t result = esp_now_send(clients[i].adresse, (uint8_t *)&myData, sizeof(myData)); if (result == ESP_OK) { Serial.print("PC"); Serial.print(i + 1); Serial.println(" Envoyé avec succès"); //etat[i] = 0; } else { Serial.print("Erreur d'envoi des données PC"); Serial.print(i + 1); } } } if (i ==8) { i = 0; for (i = 0; i < 8; ++i) { Serial.println(); if (buttons[i].state == 1) { buttons[i].state = 0; drawButton(&buttons[i]); Serial.print("Btn "); Serial.print(i + 1); Serial.println(" relaché"); snprintf(myData.a, sizeof myData.a, "PC%02d=> OFF", i + 1); myData.b = false; esp_err_t result = esp_now_send(clients[i].adresse, (uint8_t *)&myData, sizeof(myData)); if (result == ESP_OK) { Serial.print("PC"); Serial.print(i + 1); Serial.println(" Envoyé avec succès"); //etat[i] = 0; } else { Serial.print("Erreur d'envoi des données PC"); Serial.print(i + 1); } } } } } //break; delay(200); } } if((currentTime-previousTime)>10000){ //Go to sleep now Serial.println("Je vais m'endormir maintenant"); delay(1000); esp_deep_sleep_start(); } } void drawButton(struct Button *btn) { tft.setTextFont(2); tft.setTextSize(3); tft.setCursor(btn->x+30, btn->y+7); if(btn->value!=8) { uint16_t color = btn->state ? TFT_RED : TFT_GREEN; tft.fillRoundRect(btn->x, btn->y, BUTTON_WIDTH, BUTTON_HEIGHT, 10, color); tft.drawRoundRect(btn->x, btn->y, BUTTON_WIDTH, BUTTON_HEIGHT, 10, TFT_YELLOW); tft.drawCircle(btn->x+40, btn->y+30,28,TFT_BLACK); tft.setTextColor(TFT_BLACK, color); tft.print(btn->value+1); } else { tft.fillRoundRect(btn->x, btn->y, BUTTON_WIDTH, BUTTON_HEIGHT, 10, TFT_CYAN); tft.drawRoundRect(btn->x, btn->y, BUTTON_WIDTH, BUTTON_HEIGHT, 10, TFT_YELLOW); tft.setTextColor(TFT_BLACK, TFT_CYAN); tft.print("#"); } } /*******************************************************/ void print_wakeup_reason(){ esp_sleep_wakeup_cause_t wakeup_reason; wakeup_reason = esp_sleep_get_wakeup_cause(); switch(wakeup_reason) { case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Réveil causé par un signal externe utilisant RTC_IO"); break; case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Réveil provoqué par un signal externe utilisant RTC_CNTL"); break; case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Réveil provoqué par la minuterie"); break; case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break; case ESP_SLEEP_WAKEUP_ULP : Serial.println("Réveil causé par le programme ULP"); break; default : Serial.printf("Le réveil n'a pas été causé par un sommeil profond : %d\n",wakeup_reason); break; } } /*******************************************************/ void Calcul_vBat() { for(int cmpt = 8; cmpt > 0; --cmpt) { vBatOld = valeurBrute; // vBatOld peut (doit ?) être une variable locale valeurBrute = analogRead(vbatPin); delay(100); if((abs(valeurBrute-vBatOld) <= DELTA)&& (cmpt > 3)) break; } vBat = 1.40*(valeurBrute/4095.0)*3.3; // carte uPesy Vbat Brute = 3804 pour 100% progress = ((vBat-3.2)*100); } /*******************************************************/ void Affich_vBat() { // Niveau batterie ************************************************ Serial.print(" Valeur Brute = "); Serial.println(valeurBrute); Serial.print(" Vbat = "); Serial.print(vBat,2);Serial.println(" Volts"); Serial.print(" % = "); Serial.println(progress); tft.setCursor(290,1); tft.setTextFont(1); tft.setTextSize(1); tft.setTextColor(TFT_YELLOW, TFT_BLACK); tft.print(progress);tft.println("%"); tft.drawRoundRect(300, 20, 10, 200,10,TFT_YELLOW); }
j'ai dessiné un rectangle à partir du pixel 300,20 sur une longueur ( vers le bas !) de 200 et largeur de 10
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 tft.drawRoundRect(300, 20, 10, 200,10,TFT_YELLOW);
ce bargraph doit pouvoir afficher 0-100% de la variable (progress)
je vais donc tronquer cette mesure à 100% max
en effet avec la particularité de cette carte, la valeur indique 141% lorsque je suis alimenté via l'USB
Re,-
Dans un premier temps, ne sachant pas tester et n'ayant pas l'habitude des rectangles à coins arrondis, j'ai écrit un code qui utilise un rectangle classique (*). Mais il est probable, s'il fonctionne, qu'il fonctionnera également avec des coins arrondis (je te conseille des arrondis de 5 pas plus, la largeur du rectangle étant de 10). Teste et dis-moi ce que ça donne. Change évidement les couleurs à ta meilleure convenance.
(*) et pour ma facilité de visualisation de la chose.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 void DisplayBarGraph(void); void Affich_vBat(void) { Serial.print(" Valeur Brute = "); Serial.println(valeurBrute); Serial.print(" Vbat = "); Serial.print(vBat,2);Serial.println(" Volts"); Serial.print(" % = "); Serial.println(progress); DisplayBarGraph(); } #define BAR_BACKGROUND_COLOR 0xabcd #define BAR_FOREGROUND_COLOR 0xdcba void DisplayBarGraph(void) { tft.setCursor(290,1); tft.setTextFont(1); tft.setTextSize(1); tft.setTextColor(TFT_YELLOW, TFT_BLACK); tft.print(progress); tft.println("%"); tft.drawRect(300, 20, 10, 200, TFT_YELLOW); tft.fillRect(300, 20, 10, 200, BAR_BACKGROUND_COLOR); int h=200*(progress/100.); // 100% pour le maximum int y_bar=20+200-h; tft.fillRect(300, y_bar, 10, h, BAR_FOREGROUND_COLOR); }
On écrit "J'ai tort" ; "tord" est la conjugaison du verbre "tordre" à la 3ème personne de l'indicatif présent
Salut edgarjacobs
Un grand merci pour le coup de main qui a l'air de fonctionner super
j'ai fait 2 supports distincts
Image 1 : upessy ESP32 WROOM LOW POWER DEVKIT + TFT 2.8" ( avec tes couleurs bargraph )
Image 2 : ESP32-2432S028R ( avec mes couleurs bargraph )
bien cordialement
pascal
Hello Cobra38,
Content que ça fonctionne.
Pour les couleurs, je n'avais pas la moindre idée de ce que ça allait donner avec celles que j'avais mises dans les #define. Il fallait simplement qu'elles soient différentes.
J'ai repensé au problème du 143% qui serait le maximum. Et la solution est très simple:Il suffit de changer la valeur de MAXPC en 143. si 143% de charge correspond à "full charged".
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #define BAR_BACKGROUND_COLOR 0xabcd #define BAR_FOREGROUND_COLOR 0xdcba #define MAXPC 100. // ne pas oublier le point décimal ! void DisplayBarGraph(void) { tft.setCursor(290,1); tft.setTextFont(1); tft.setTextSize(1); tft.setTextColor(TFT_YELLOW, TFT_BLACK); tft.print(100*(int)(progress/MAXPC)); // <----------- tft.println("%"); tft.drawRoundRect(300, 20, 10, 200, 5, TFT_YELLOW); tft.fillRoundRect(300, 20, 10, 200, 5, BAR_BACKGROUND_COLOR); int h=200*(progress/MAXPC); // <----------- int y=20+200-h; tft.fillRect(300, y, 10, h, BAR_FOREGROUND_COLOR); }
On écrit "J'ai tort" ; "tord" est la conjugaison du verbre "tordre" à la 3ème personne de l'indicatif présent
Salut edgarjacobs
sauf que çà ne semble pas fonctionner comme espérerJ'ai repensé au problème du 143% qui serait le maximum. Et la solution est très simple:
en effet si je fais çà :
j'ai en branchant la carte via l'USB
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #define MAXPC 100. // ne pas oublier le point décimal ! /*******************************************************/ void DisplayBarGraph(void) { tft.setCursor(295,1); tft.setTextFont(1); tft.setTextSize(1); tft.setTextColor(TFT_YELLOW, TFT_BLACK); //tft.print(progress); tft.println("%"); tft.print(100*(int)(progress/MAXPC)); tft.println("%"); tft.drawRoundRect(300, 20, 10, 200,5,TFT_YELLOW); tft.fillRoundRect(300, 20, 10, 200,5,BAR_BACKGROUND_COLOR); int h=200*((int)(progress/MAXPC)); // <----------- // 100% pour le maximum //int h=200*(progress/100.); int y_bar=20+200-h; tft.fillRoundRect(300, y_bar, 10, h,5, BAR_FOREGROUND_COLOR); tft.drawRoundRect(300, 20, 10, 200,5,TFT_YELLOW); }
valeur en % sur écran = 100%
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 13:57:37.693 -> Valeur Brute = 4095 13:57:37.693 -> Vbat = 4.52 Volts // mais valeur de tension lue à la batterie 4,10v 13:57:37.693 -> % = 132
si je débranche l'USB => Batterie
valeur en % sur écran = 0%
/****************************************
Si je programme ceci
Alors :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 /*******************************************************/ void DisplayBarGraph(void) { tft.setCursor(295,1); tft.setTextFont(1); tft.setTextSize(1); tft.setTextColor(TFT_YELLOW, TFT_BLACK); tft.print(progress); tft.println("%"); //tft.print(100*(int)(progress/MAXPC)); tft.println("%"); tft.drawRoundRect(300, 20, 10, 200,5,TFT_YELLOW); tft.fillRoundRect(300, 20, 10, 200,5,BAR_BACKGROUND_COLOR); //int h=200*((int)(progress/MAXPC)); // <----------- // 100% pour le maximum int h=200*(progress/100.); int y_bar=20+200-h; tft.fillRoundRect(300, y_bar, 10, h,5, BAR_FOREGROUND_COLOR); tft.drawRoundRect(300, 20, 10, 200,5,TFT_YELLOW); }
j'ai avec USB = 132% et le bargraph idem
et sans USB , je lis 79% et le bargraph idem
pourquoi 79% alors la logique voudrait que je lise 90% (4,10v sur un voltmètre ) çà je n'ai pas trouvé (?)
EDIT : après plusieurs investigations , il se trouve que j'ai deux valeurs de mesure de batterie
L'une en veille qui donne à mon sens la vraie tension batterie = 4,10v (Voltmètre) , celle qui sert de référence à la charge
L'autre au moment du réveil qui tombe à 3,66v lorsque l'affichage est actif
L'idéal serait donc de mettre au réveil la valeur de 4,10v pour l'afficher ensuite sur le bargraph
J'ai lu en diagonale.
Je ne comprends pas pourquoi tu as 4.1v en sommeil et 3.66v en fonctionnement. Cela fait un sacré voltage drop.
Le mieux c'est que 100% = 100% de la charge maximal de la batterie.
Salut _Froggy_
Tout d'abord ces mesures sont faites en // de la batterie au voltmètreJe ne comprends pas pourquoi tu as 4.1v en sommeil et 3.66v en fonctionnement. Cela fait un sacré voltage drop.
1) Lorsque l'ESP32 est "Deep Sleep" et qu'il est branché avec l'USB => je mesure 4,18v ( tension de charge max de l'accu)
2) Si je débranche l'USB mais je reste en "Deep Sleep" => je mesure 4,10v (?)
3) Si je réveille l'ESP32 ( avec la touche) mais sans USB => je mesure à une tension de 3,66v mini qui dure environ 5s ( le temps programmé )
Pour afficher le bargraph , je dois donc réveiller l'ESP32 ce qui logique et affiche env 70% sans USB
tandis qu'avec l'USB raccordé => j'affiche au bargraph 132% (4,52v)
La vraie mesure de la batterie devrait être en toute logique 4,10v soit 97% mais il est clair je ne pourrais jamais l'afficher
il faudrait que je puisse sauvegarder la tension batterie juste avant d'afficher le bargraph à l'écran
or je n'ai pas réussi et j'ai du au final supprimer l'affichage du bargrah
Hey !
Le module que tu as, c'est un module tout en un ? Batterie + ESP + ecran ? Ou tu as batterie sur la carte ESP32 et l'écran est sur la breadboard alimenté directement sur le Vcc/Gnd de la carte ?
Pour avoir la tension de la batterie, il faudrait la mesurer avant le réveil de l'écran, sauf que la valeur sera fausse si avec l'écran allumé tu perds quasiment 1v. J'avais testé Vmin pour qu'un ESP fonctionne et de mémoire c'est <2v. Mettons 2v, si tu perds 1v à l'allumage, ton écran ne s'allumera plus (2.7v d'après la doc du XPT2046) mais ton ESP sera toujours fonctionnel avec une batterie à 50% de charge.
A mon sens, il faudrait revoir le montage, avec une telle chute de tension, j'ai peur que ton montage ne tienne pas dans la durée.
Par ailleurs, j'ai regardé ton code et tu ne calcules v_bat que dans ton setup(), donc uniquement au démarrage de l'ESP. Il devrait se trouver dans la loop() en première instruction, puisqu'au réveil l'ESP va relancer la loop().
Globalement, et en lisant en diagonal, pour un fonctionnement sur batterie, il faut ultra optimisé la consommation. Je n'ai plus utilisé d'ESP depuis un certain temps et pas en ultra low consommation, néanmoins il faudrait désactiver l'AGC (ou les AGC) et réactiver si besoin, le WiFi (et le réactiver que si besoin), mettre la clock du CPU au plus bas (non visible dans le code), etc etc
Salut _Froggy_
le montage que j'ai fait , est le suivantLe module que tu as, c'est un module tout en un ? Batterie + ESP + ecran ? Ou tu as batterie sur la carte ESP32 et l'écran est sur la breadboard alimenté directement sur le Vcc/Gnd de la carte ?
uPesy ESP32 WROOM LOW POWER DEVKIT + Ecran TFT 2.8" + TTP223 ( réveil) , la batterie 3.7V 2000mAh est branchée directement sur la carte , elle intègre le chargeur
La consommation en Deep Sleep est d'env 15 µA , je n'ai pas pu le mesurer mais ce qui est certains c'est que j'ai alimenté le module durant des jours sans allumer l'écran, au final je n'avais perdu que 0,01 v sur la batterie
(j'ai par ailleurs un autre montage avec le même µC aussi en "Deep Sleep" qui lui est actif depuis + 6 mois et il est encore à 70% de batterie)
Donc je peux légitiment penser que le constructeur a raison ...
oui , effectivement , je n'y ai pas penséPar ailleurs, j'ai regardé ton code et tu ne calcules v_bat que dans ton setup(), donc uniquement au démarrage de l'ESP. Il devrait se trouver dans la loop() en première instruction, puisqu'au réveil l'ESP va relancer la loop().
peut-être qu'en le mettant dans la boucle LOOP je pourrais l'activer que lorsque je réveille l'ESP32 à voir donc ..
Le constructeur m'indique ceci en mode Deep Sleep , l'ensemble de l'ESP32 semble donc bien éteint à l'exception bien sûr de la surveillance des GPIO et la memoire pour garder les informations essentiellesGlobalement, et en lisant en diagonal, pour un fonctionnement sur batterie, il faut ultra optimisé la consommation. Je n'ai plus utilisé d'ESP depuis un certain temps et pas en ultra low consommation, néanmoins il faudrait désactiver l'AGC (ou les AGC) et réactiver si besoin, le WiFi (et le réactiver que si besoin), mettre la clock du CPU au plus bas (non visible dans le code), etc etc
le but étant d'allumer 8 lampes à distance , j'utilise ESPNow qui ne fait pas d'appel au WiFi de façon traditionnel
Si tu souhaites d'autres infos , dis le moi ..
L'écran TFT est directement alimenté par Vcc de la carte ESP ? Le régulateur de la carte ESP est donné pour > 500mA, donc si ta batterie est bien du 4.2v 2000mAh, tu ne devrais pas avoir de chute de tension.
Au niveau de la consommation, je parlais surtout quand le module fonctionne. Si cela reste allumer 5s, par exemple tu n'as besoin de l'ADC que lors du calcul de VBAT. Tu peux integrer la remise en route de l'ADC dans ta fonction et l'eteindre après avoir relevé la valeur.
Pour v_bat, dans ta version actuelle, il te donne la valeur au moment du démarrage de l'ESP puis ne change jamais. Donc si tu le branches en USB + batterie pour charger, que tu débranches l'USB, l'ESP ne redémarre pas. Donc la valeur correspond à celle au démarrage en USB ou lors de la dernière modification du programme (donc en USB).
Bonjour,
Lorsque l'USB est branché, la batterie est en charge. La tension à ses bornes n'est donc pas représentative de l'état de charge.
Sur beaucoup d'appareils, le mode en charge est représenté par un éclair et l'état de charge - s'il est indiqué - se fait pendant une brève interruption de la charge pour éviter de confondre charge et chargeur. Mais, même dans ce cas là, la mesure est approximative (température de batterie supérieure à la normale, condensateurs de filtrage chargés à bloc etc.).
La solution la plus simple serait donc de ne pas faire de mesure si la batterie est en charge (i.e. branchée en USB). En effet, faire une mesure supposerait alors un circuit (simple mais supplémentaire) qui coupe le 5 V de l'USB, attend quelques dizaines de ms, fait la mesure et rétablit l'alimentation.
Par ailleurs, les mesures de tension à vide, ou quasiment à vide, ne représentent pas la charge. C'est pourquoi on ne peut savoir l'état de charge d'une pile (ou d'un accu) avec un multimètre en V= car sa résistance d'entrée est tellement forte qu'une pile en fin de vie montrera fièrement ses 1.5V, mais s'effondrera lamentablement si elle doit débiter dans, par exemple, 100k (15 uA quand même ).
Aussi la mesure du multimètre en veille profonde n'apporte aucune information sur la charge de la batterie. Sauf si la valeur mesurée reste très faible : il est temps de changer de batterie
Salutations
Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)
Bonjour à tous ,
Merci encore de vous pencher sur mon petit problème qui, semble-t-il, dépasse mes compétences en matière de batterie
c'est mon gros point noir au milieu de beaucoup d'autres j'avoue
j'ai donc pris l'option à regret de ne pas afficher vbat car non significatif de l'état de la batterie
j'avais pensé aussi à un moyen externe à savoir un élément comme par ex :
https://fr.aliexpress.com/item/10050...Cquery_from%3A
mais trop encombrant au final
je vous mets une photo du proto fini mais je dois encore faire les 7 modules externes
Si vous avez d'autres suggestions , je suis preneur
merci encore
pascal
Le problème à mon sens n'est pas l'affichage ou le calcul de vbat mais le montage électronique. Si tu mesures 3.66v en fonctionnement, il y a un problème de montage (ou la batterie est un fake et tu n'a pas les mAh annoncé, ce qui dans le cas d'aliexpress/amazon est un classique), c'est pour cela qu'il serait intéressant que tu montres le montage électronique. Sur le papier, tu devrais avoir minimum 4v en fonctionnement.
Bonjour Froggy,
En pratique, de 3.6V à 3.7V sont des valeurs typiques de fonctionnement des batteries au lithium.
Les valeurs supérieures résultent, soit de la mesure d'une batterie en charge (la tension d'un chargeur doit nécessairement être supérieure à celle nominale de la batterie), soit une mesure sans débit (par exemple avec un multimètre moderne comme déjà expliqué).
Par ailleurs, il semble y avoir une confusion entre tension et capacité. Deux bonnes batteries de capacités différentes peuvent avoir la même tension nominale (qui n'est liée qu'à la valeur du couple électrolytique). Bien sûr la plus faible s'essoufflera avant l'autre.
Salut
Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)
Je suis d'accord, pour moi il faudrait le montage avec les références. J'ai souvenir avoir vu un projet avec une batterie de 4v
Bonjour _Froggy_,
A partir du schéma de la carte, on trouve le modèle et donc la doc du constructeur uPesy :
"Via une batterie externe ( ) : On connecte une batterie Lithium-ion/LiPo de 3.7V sur le connecteur JST PH 2.0. Si l’on branche l’USB en même temps, la carte recharge la batterie. Ce mode d’alimentation est optimisé pour la consommation de courant : la consommation sera < 15µA en Deep Sleep."
Le sujet de l'instabilité des mesures de tensions avaient déjà été rencontrées sur cette carte et reconnue par la société. Elle est bien due à un pont diviseur présentant une trop forte impédance équivalente. Pour moi, la solution à tenter serait de mettre en parallèle du condensateur de 100 nF un autre condensateur de 1 uF et d'espacer les mesures d'au moins 800 ms (il faut que la capacité équivalent de 1.1 µF atteigne sa tension nominale). Cela permet d'avoir une impédance dynamique beaucoup plus faible pendant la mesure. C'est contraignant mais avec un peu de chances, une seule mesure suffirait.
Salut
Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager