Station météo avec un arduino mega2560

Avec affichage TFT 320x480 et enregistrement sur SDcard

1 Présentation

J'avais récupéré un capteur de température & humidité externe (transmettant par radio sur 433MHz) ainsi que son petit récepteur associé provenant d'un modèle du commerce. J'ai alors décidé de créer cette station météo, dont voici les principales caractéristiques :
  • réalisation autour d'une carte Arduino mega2560
  • Affichage sur écran TFT 320x480
  • heure
  • température intérieure
  • température extérieure
  • taux d'humidité
  • pression atmosphérique
  • Tracé des courbes en temps réel
  • Enregistrement des mesures sur carte mémoire micro SDcard
  • Envoie des infos en temps réel par la liaison USB (à capter avec le terminal série tel que CuteCom sous Linux)
  • Fonction de capture d'écran et enregistrement de l'image obtenue sur la SDcard (utilisable pour d'autres projets le cas échéant...)
Un switch câble directement sur l'afficheur après coupure d'une piste permet d'éteindre l'écran TFT durant la nuit.

Cela existe déjà tout fait ? Sans doute mais cette réalisation est totalement décrite, y compris le code source du programme. Le matériel est modulable. Et puis le tout est compris dans un très petit volume, facile à caser n'importe où dans la maison ou sur le bureau.

Remarque : Cette réalisation date de 2020. J'ai fait mieux depuis : une station météo basée sur un ESP32.

2 Le schema

3 Vue de dessous

Sous la carte Arduino mega2560 se trouve une fine plaque en plastique sur laquelle sont fixés les différents capteurs. Tous ces capteurs sont reliés électriquement par des connecteurs, ce qui rend possible le démontage très simplement. On remarquera que j'ai utilisé du fil de câblage trop gros : ça fait moche ! Je vais tout recâbler avec du fil à wrapper !

4 Programme source en C++

CODE SOURCE en C++
  1.  
  2. /***********************************************************************************
  3.  Mega2560
  4.  
  5. use the BREAKOUT BOARD only and use these 8bit data lines to the LCD,
  6. pin usage:
  7.   LCD_CS LCD_CD LCD_WR LCD_RD LCD_RST SD_SS SD_DI SD_DO SD_SCK
  8.   Arduino Uno A3 A2 A1 A0 A4 10 11 12 13
  9. Arduino Mega2560 A3 A2 A1 A0 A4 10 11 12 13
  10.  
  11.   LCD_D0 LCD_D1 LCD_D2 LCD_D3 LCD_D4 LCD_D5 LCD_D6 LCD_D7
  12.   Arduino Uno 8 9 2 3 4 5 6 7
  13. Arduino Mega2560 8 9 2 3 4 5 6 7
  14.  
  15. **********************************************************************************/
  16. // Donc toutes les I/O logiques de l'UNO sont prises -> on utilisera un Mega2560
  17.  
  18. /**
  19. RAPPEL ATmega 2560 :
  20. – 256KBytes of In-System Self-Programmable Flash
  21. – 4Kbytes EEPROM
  22. – 8Kbytes Internal SRAM
  23. **/
  24.  
  25.  
  26. #include "Arduino.h"
  27. #include <stdint.h>
  28. #include "Station_meteo.h"
  29.  
  30.  
  31. /** STATION METEO **/
  32.  
  33. #define version "16.4"
  34.  
  35.  
  36. #define portPIN_switch0 PINL
  37. #define pin_switch0 0b00000100
  38.  
  39. int sram;
  40. uint32_t bmp_offset = 0;
  41. uint16_t s_width = TFT480.Get_Display_Width();
  42. uint16_t s_heigh = TFT480.Get_Display_Height();
  43.  
  44. #define NOIR 0x0000
  45. #define ROUGE 0xF800
  46. #define ORANGE 0xFBC0
  47. #define JAUNE 0xFFE0
  48. #define JAUNE_PALE 0xF7F4
  49. #define VERT 0x07E0
  50. #define CYAN 0x07FF
  51. #define BLEU_CLAIR 0x455F
  52. #define BLEU 0x001F
  53. #define MAGENTA 0xF81F
  54. #define VIOLET 0x781A
  55. #define GRIS_TRES_CLAIR 0xDEFB
  56. #define GRIS_CLAIR 0xA534
  57. #define GRIS 0x8410
  58. #define GRIS_FONCE 0x5ACB
  59. #define BLANC 0xFFFF
  60.  
  61.  
  62. Etiq3 Etiq_1;
  63. Etiq3 Etiq_2;
  64. //Etiq3 Etiq_3;
  65. Etiq3 Etiq_4;
  66. Etiq3 Etiq_5;
  67. //Etiq3 Etiq_6;
  68.  
  69. //LED Led1;
  70. LED Led2;
  71. //LED Led3;
  72. //LED Led4;
  73.  
  74. Scope Scope_1;
  75.  
  76.  
  77. uint16_t aff_y;
  78.  
  79. /**--------------------------------------------------------
  80. déclarations RECEPTION & DECODAGE SONDE EXTERNE
  81. --------------------------------------------------------**/
  82.  
  83. /**
  84. Rappels :
  85. Scope_1.dx = 450
  86. lst_records[500]
  87. **/
  88.  
  89. record_meteo lst_records[460]; // voir la définition de la struct 'record_meteo' dans le .h
  90. uint16_t n_record=0;
  91. uint16_t n_record_max=450;
  92.  
  93.  
  94. const int INPUT_PIN = 22;
  95. uint8_t SDcardOk=0;
  96. byte etat = 0;
  97. byte memo_etat;
  98. uint32_t memo_micros1 = 0;
  99. uint32_t memo_micros2 = 0;
  100. uint32_t temps_ecoule;
  101. uint32_t pulseWidth;
  102. uint16_t i_buff;
  103. uint16_t TT1;
  104.  
  105. uint16_t nb_acqui433=0;
  106. uint16_t nb_wr_SD=0;
  107. uint8_t todo_init_record=0;
  108. uint8_t todo_wr_scope_on_sd=0;
  109.  
  110.  
  111. uint16_t annee_actuelle;
  112. uint8_t mois_actuel;
  113. uint8_t jour_actuel;
  114. uint8_t jour_de_la_semaine; // 0=dimanche
  115. uint8_t heure_actuelle;
  116. uint8_t minute_actuelle;
  117. uint8_t seconde_actuelle;
  118. float age_Lune;
  119.  
  120. //uint8_t premiere_passe;
  121. //uint8_t stable;
  122. float echelle_T=1; // pour l'affichage des températures sur le Scope
  123. float echelle_P=1; // pour l'affichage des pressions sur le Scope
  124.  
  125. int16_t gradu_minT, gradu_maxT;
  126. // int16_t gradu_minP, gradu_maxP;
  127.  
  128. uint8_t num_acquisition;
  129. uint8_t acqui_valide =0;
  130. uint8_t scope_dat_ok =0;
  131. int16_t T_EXT_lue[5]={NOIR,0,0}; // temperature extérieure (la sonde envoie des salves de 5 messages identiques)
  132. uint8_t confiance[5]; //indice de confiance = nb d'occurences identiques pour chaque valeur reçue
  133. int16_t T_EXT_retenue; // après comparaison des 5 valeurs reçues
  134. int16_t Tmin, Tmax;
  135. int16_t Tmoy; // pour 1 enregistrement, moyenne entre le jour et la nuit
  136. int16_t moyenne_T_sur_toutes; // température mohenne sur l'ensemble des enregistrments affichés
  137. uint16_t T_INTE_lue; // temperature intérieure
  138.  
  139. uint16_t Pression_lue;
  140. uint16_t Pmin, Pmax;
  141. uint16_t Pmoy;
  142.  
  143. uint8_t H_in_lue; // humidite
  144. uint8_t memo_H_in;
  145.  
  146. uint8_t H_out_lue; // humidite
  147. uint8_t memo_H_out;
  148.  
  149. // String dataString = "";
  150.  
  151. tmElements_t tm;
  152.  
  153. const int MAX_BUFFER = 120;
  154. String message;
  155.  
  156. char buffer[MAX_BUFFER];
  157. void changed() { }
  158.  
  159. void init_ports()
  160. {
  161. // 0 = entree, 1=sortie ; les 1 sur les pins en entrees activent les R de Pull Up (tirage à VCC)
  162.  
  163. DDRL = 0b11111011;
  164. PORTL = 0b00000100;
  165. }
  166.  
  167.  
  168. /** -------------------------------------------------------
  169.   SD card
  170. -----------------------------------------------------------
  171. ADAPT SD -> mega2560 pins
  172.  
  173. CS -> 53
  174. MISO -> 50
  175. MOSI -> 51
  176. SCK -> 52
  177. **/
  178.  
  179.  
  180. int freeRam()
  181. {
  182. extern int __heap_start, *__brkval;
  183. int v;
  184. return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
  185. }
  186.  
  187.  
  188.  
  189. void Init_SDcard()
  190. {
  191. Serial.print("Init SDcard...");
  192.  
  193. pinMode(53, OUTPUT);
  194. if (!SD.begin(53)) //ici l'appel (et test) de la fonction 'begin' effectue l'initialisation (si possible)
  195. {
  196. Serial.println("init failed ! (pas de SDcard ?)");
  197. // Led3.setCouleur(NOIR);
  198. TFT480.Set_Text_Back_colour(NOIR);
  199. TFT480.Set_Text_colour(VIOLET);
  200. TFT480.Set_Text_Size(2);
  201. TFT480.Print_String("init failed ! (pas de SDcard ?)", 50, 250);
  202. delay(1000);
  203.  
  204. TFT480.Set_Text_Back_colour(NOIR);
  205. TFT480.Set_Text_colour(ORANGE);
  206. TFT480.Set_Text_Size(2);
  207. TFT480.Print_String("demande de RAZ scope.dat", 80, 200);
  208. TFT480.Print_String("elle se fera sur la minute", 70, 230);
  209. todo_init_record =1;
  210. return;
  211. }
  212. else
  213. {
  214. SDcardOk=1;
  215. }
  216. Serial.println("init Ok.");
  217. if (SD.exists("data.txt")) {Serial.println("data.txt existe.");} else { Serial.println("pas de fichier data.txt");}
  218.  
  219. if (SD.exists("scope.dat"))
  220. {
  221. Serial.println("scope.dat existe.");
  222. scope_dat_ok=1;
  223. }
  224. else
  225. {
  226. scope_dat_ok=0;
  227. TFT480.Set_Text_Back_colour(NOIR);
  228. TFT480.Set_Text_colour(ORANGE);
  229. TFT480.Set_Text_Size(1);
  230. TFT480.Print_String("pas de fichier scope.dat, je vais le creer", 10, 260);
  231. Serial.println("pas de fichier scope.dat sur la SDcard, je vais le creer");
  232.  
  233. TFT480.Set_Text_Back_colour(NOIR);
  234. TFT480.Set_Text_colour(ORANGE);
  235. TFT480.Set_Text_Size(2);
  236. TFT480.Print_String("demande de RAZ scope.dat", 80, 200);
  237. TFT480.Print_String("elle se fera sur la minute", 70, 230);
  238. todo_init_record =1;
  239. todo_wr_scope_on_sd=1;
  240. }
  241. }
  242.  
  243.  
  244.  
  245. /** -------------------------------------------------------
  246.   Sensor local BMP280 (Pression & température)
  247. --------------------------------------------------------**/
  248.  
  249.  
  250. Adafruit_BMP280 bmp; // use I2C interface
  251. Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor();
  252. Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor();
  253.  
  254. void init_BMP280()
  255. {
  256. Serial.println(F("BMP280 Sensor event test"));
  257.  
  258. if (!bmp.begin())
  259. {
  260. Serial.println(F("Could not find BMP280 sensor !"));
  261. while (1) delay(10);
  262. }
  263. else {Serial.println(F("BMP280 sensor OK!")); }
  264.  
  265. /* Default settings from datasheet. */
  266. bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
  267. Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
  268. Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
  269. Adafruit_BMP280::FILTER_X16, /* Filtering. */
  270. Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
  271.  
  272. bmp_temp->printSensorDetails();
  273. }
  274.  
  275.  
  276. void acqui_PressionTemperature()
  277. {
  278. Serial.println(" "); Serial.println("acqui_PressionTemperature()");
  279. /**
  280. pression athmosphérique normale au niveau de la mer = 1013 hPa
  281. 0m ->1013 hPa
  282. 1000m-> 899 hPa
  283. -soit 1016-899 = 114 hPa / 1000 m (attention la variation n'est pas linéaire, au dessus de 1000 m, ce n'est plus exact)
  284. -soit 11.4 hPa / 100 m
  285. vu que mon capteur est situé à 100 m d'altitude, je vais rajouter 11.4 hPa à la mesure
  286. afin d'obtenir des valeurs cohérentes par rapport aux information météorologiques
  287. */
  288.  
  289. sensors_event_t temp_event, pressure_event;
  290. bmp_temp->getEvent(&temp_event);
  291. bmp_pressure->getEvent(&pressure_event);
  292.  
  293. Serial.println();
  294.  
  295. Serial.print(F("Temperature IN = "));
  296. T_INTE_lue =(int16_t)(10*temp_event.temperature);
  297.  
  298. T_INTE_lue-=50; //c.a.d 5°C de moins, pour compenser le fait que la sonde interne soit chauffée par sa proximité avec l'afficheur etc...
  299. // une autre solution consisterait à l'aloigner du reste de l'électronique.
  300.  
  301.  
  302. Serial.print(T_INTE_lue);
  303. Serial.println(" *C");
  304.  
  305. Serial.print(F("Pression = "));
  306. float pression_acq = pressure_event.pressure;
  307. pression_acq += 11.4; // mon capteur est situé à 100 m d'altitude, voir commentaire ci-dessus
  308. Pression_lue = (int16_t)pression_acq;
  309. Serial.print(Pression_lue);
  310. Serial.println(" hPa");
  311.  
  312. Serial.println();
  313. }
  314.  
  315. /**--------------------------------------------------------
  316. fonctions AFFICHAGE TFT
  317. --------------------------------------------------------**/
  318.  
  319.  
  320. void clear_screen()
  321. {
  322. TFT480.Fill_Screen(40,40,40);
  323. }
  324.  
  325.  
  326. void dessine_triangles()
  327. {
  328. int i = 0;
  329. uint16_t L, H;
  330. L=TFT480.Get_Display_Width();
  331. H=TFT480.Get_Display_Height();
  332.  
  333. for(i=0; i<H/2; i+=5)
  334. {
  335. TFT480.Set_Draw_color(0,i+64,i+64);
  336. TFT480.Draw_Triangle(L/2-1,H/2-1-i,L/2-1-i,H/2-1+i,L/2-1+i,H/2-1+i);
  337. }
  338. }
  339.  
  340.  
  341. void dessine_degrade(uint16_t x, uint16_t y, uint8_t longueur, uint8_t dy, uint8_t RR1, uint8_t RR2, uint8_t GG1, uint8_t GG2, uint8_t BB1, uint8_t BB2)
  342. {
  343. // dessine un dégr&dé horizontal de couleurs (R1,G1,B1) -> (R2,G2,B2)
  344. uint16_t i;
  345. float R,G,B;
  346.  
  347. if(longueur==0) {return;}
  348.  
  349. i=0;
  350.  
  351. R=RR1;
  352. G=GG1;
  353. B=BB1;
  354.  
  355. while(i<longueur)
  356. {
  357. x++;
  358. R+=(RR2-RR1)/longueur;
  359. G+=(GG2-GG1)/longueur;
  360. B+=(BB2-BB1)/longueur;
  361. TFT480.Set_Draw_color((uint8_t)R,(uint8_t)G,(uint8_t)B);
  362. TFT480.Draw_Line(x, y, x, y+dy);
  363. i++;
  364. }
  365. }
  366.  
  367.  
  368.  
  369.  
  370. void dessine_arc_en_ciel()
  371. {
  372. int16_t i;
  373. float xr,xv,xb;
  374. float r,v,b;
  375. for (i=0; i<63; i++) // 10 * 2 pi radians
  376. {
  377. xr=(i+12)/10.0; r=140.0+120.0*sin(xr)-i; if (r<0) {r=0;} if (r>255) {r=255;}
  378. xv=(i+54)/10.0; v=130.0+150.0*sin(xv); if (v<0) {v=0;} if (v>255) {v=255;};
  379. xb=(i+38)/10.0; b=100.0+150.0*sin(xb); if (b<0) {b=0;} if (b>255) {b=255;};
  380.  
  381. /*
  382. //pour test du déphasage des courbes sinus...
  383. TFT480.Set_Draw_color(255, 255, 255);
  384. TFT480.Draw_Pixel(200+i, 150-(uint8_t)(r/10.0));
  385. TFT480.Draw_Pixel(200+i, 200-(uint8_t)(v/10.0));
  386. TFT480.Draw_Pixel(200+i, 250-(uint8_t)(b/10.0));
  387. */
  388.  
  389. TFT480.Set_Draw_color((uint8_t)r,(uint8_t)v,(uint8_t)b);
  390. TFT480.Draw_Circle_Helper(400, 280, 400-i, 1);
  391. }
  392.  
  393. // while (1) {;}
  394. }
  395.  
  396.  
  397.  
  398.  
  399. void dessine_cercle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t couleur)
  400. {
  401. uint16_t n;
  402. float i;
  403. float x,y;
  404.  
  405. TFT480.Set_Draw_color(couleur);
  406. i=0;
  407. while(i<2*M_PI)
  408. {
  409. x=x0+r*cos(i);
  410. y=y0+r*sin(i);
  411. TFT480.Draw_Pixel(x,y);
  412. i+=0.01; // radians
  413. }
  414. }
  415.  
  416.  
  417.  
  418. void Draw_arc_elliptique(uint16_t x0, uint16_t y0, int16_t dx, int16_t dy, float alpha1, float alpha2, uint16_t couleur) // alpha1 et alpha2 en radians
  419. {
  420. /*
  421. REMARQUES :
  422. -cette fonction permet également de dessiner un arc de cercle (si dx=dy), voire le cercle complet
  423. - dx et dy sont du type int (et pas uint) et peuvent êtres négafifs, ou nuls.
  424. -alpha1 et alpha2 sont les angles (en radians) des azimuts des extrémités de l'arc
  425. */
  426. uint16_t n;
  427. float i;
  428. float x,y;
  429.  
  430. TFT480.Set_Draw_color(couleur);
  431. i=alpha1;
  432. while(i<alpha2)
  433. {
  434. x=x0+dx*cos(i);
  435. y=y0+dy*cos(i+M_PI/2.0);
  436. TFT480.Draw_Pixel(x,y);
  437. i+=0.01; // radians
  438. }
  439. }
  440.  
  441.  
  442. void Fill_croissant_elliptique(uint16_t x0, uint16_t y0, int16_t dx1, int16_t dx2, int16_t dy, float alpha1, float alpha2, uint16_t couleur)
  443. {
  444. // dx1 et dx2 sont les extremums (en pixels) horizontaux d'un croissant vertical
  445.  
  446. if (dx2<dx1) {return;}
  447. int16_t dx;
  448. dx = dx1;
  449. while(dx<dx2)
  450. {
  451. Draw_arc_elliptique(x0, y0, dx, dy, alpha1, alpha2, couleur);
  452. dx++;
  453. }
  454. }
  455.  
  456.  
  457.  
  458. void Dessine_Lune2(uint16_t x0, uint16_t y0, float age)
  459. {
  460. //Remarque : l'age admet des nombres réels (avec décimales)
  461.  
  462. affi_img(y0-24, x0-24, "/bmp/lune5.bmp"); // image 48x48px
  463.  
  464. uint8_t r=22;
  465. int16_t T1, T2; //Terminators gauche et droite, limites entre partie éclairée et partie dans l'ombre
  466.  
  467. if (age<1)
  468. {
  469. TFT480.Set_Draw_color(NOIR);
  470. TFT480.Fill_Rectangle(x0-r, y0-r, x0+r, y0+r); // efface l'image
  471. dessine_cercle(x0, y0, r, GRIS_FONCE); // Nouvelle Lune
  472. }
  473.  
  474. // on procède par masquage (sur l'image bmp affichée) de la partie dans l'ombre
  475.  
  476. if (age <= 15) // premier croissant... pleine
  477. {
  478. T1=-r;
  479. T2=r-2*r*age/15;
  480. }
  481.  
  482. if ((age > 15) && (age <=30)) // pleine... dernier croissant
  483. {
  484. T1=r-2*r*(age-15)/15;
  485. T2=r+1;
  486. }
  487.  
  488. if(((uint8_t)age)==0)
  489. {
  490. dessine_cercle(x0, y0, r, GRIS);
  491. }
  492. else
  493. {
  494. dessine_cercle(x0, y0, r, GRIS_FONCE);
  495. Fill_croissant_elliptique(x0, y0, T1, T2, r, -M_PI/2, M_PI/2, NOIR);
  496. }
  497. }
  498.  
  499.  
  500.  
  501.  
  502. float Decimale(float valeur)
  503. {
  504. float d;
  505. d=valeur-floor(valeur);
  506. return d;
  507. }
  508.  
  509.  
  510. float GetPhase(int Y, int M, int D)
  511. {
  512. // return "age de le Lune" (nombre allant de 0.00 à 29.xx)
  513. float AG, IP;
  514. uint32_t Y2, M2, K1, K2, K3, JD;
  515. Y2=Y-floor((12-M)/10);
  516. M2=M+9;
  517. if (M2>=12) {M2-=12;}
  518. K1= floor(365.25 * (Y2 + 4712));
  519. K2= floor(30.6 * M2+0.5);
  520. K3= floor(floor((Y2/100) + 49)*0.75)-38;
  521. JD= K1+K2+D+59;
  522. if (JD > 2299160) {JD=JD-K3;}
  523. IP= Decimale((JD-2451550.1)/29.53058);
  524. AG= IP*29.53;
  525.  
  526. return AG;
  527. }
  528.  
  529.  
  530.  
  531. void calcul_moyenne_T_sur_toutes()
  532. {
  533. // calcul sur l'ensemble des temperature affichée
  534. uint16_t i;
  535. int32_t sum_T =0;
  536.  
  537. for (i=2; i<= n_record_max ; i++)
  538. {
  539. sum_T += lst_records[i].T;
  540. }
  541. moyenne_T_sur_toutes = sum_T / n_record_max;
  542.  
  543. Serial.print(" moyenne_T_sur_toutes= "); Serial.println(moyenne_T_sur_toutes);
  544.  
  545. }
  546.  
  547.  
  548.  
  549.  
  550. void determine_Tmin_Tmax()
  551. {
  552. uint16_t i;
  553. int16_t t1,t2;
  554. Tmin=500;
  555. Tmax=-500;
  556.  
  557. for (i=2; i<= n_record_max ; i++) // attention départ=2, pas 0 pour éviter de prendre en compte l'acquisition en cours
  558. {
  559. if (lst_records[i].heure != 0xFFFF)
  560. {
  561. t1=lst_records[i].T;
  562. t2=lst_records[i-1].T;
  563. /*
  564. Serial.print(i);
  565. Serial.print(" t1=");
  566. Serial.println(t1);
  567. */
  568. if ((t1 !=0) && (t1 > -250) && (t1 < 480)) // -25°C à +48°C
  569. {
  570. if (t1 < (moyenne_T_sur_toutes + 100) ) // pour éliminer les glitches dans le calcul
  571. {
  572. if (t1 < Tmin) {Tmin= t1;}
  573. if (t1 > Tmax) {Tmax= t1;}
  574. }
  575. }
  576. }
  577. }
  578.  
  579. if ((Tmax - Tmin) < 40) // soit 4°C
  580. {
  581. // dans ce cas on impose des valeurs permettant de calculer une échelle fonctionnelle
  582. //Tmin-=10; // c.à.d -=1°C
  583. //Tmax+=10; // c.à.d +=1°C
  584. }
  585.  
  586. //Tmin=150;
  587. //Tmax=450;
  588.  
  589. Tmoy=(Tmin+Tmax)/2;
  590.  
  591. // TFT480.Set_Text_Back_colour(NOIR);
  592. // TFT480.Set_Text_colour(JAUNE);
  593. // TFT480.Set_Text_Size(1);
  594. // TFT480.Print_Number_Float(Tmax/10, 1, 350, 15, '.', 3, ' ');
  595. // TFT480.Print_Number_Float(Tmin/10, 1, 350, 25, '.', 3, ' ');
  596. /*
  597. TFT480.Print_Number_Int(Tmin,400,5,3,' ',10);
  598. TFT480.Print_Number_Int(Tmax,400,15,3,' ',10);
  599. */
  600. }
  601.  
  602.  
  603.  
  604. void fixe_Tmin_tmax()
  605. {
  606. // pour l'echelle verticale
  607. // en remplacement éventuel de la fonction précédente
  608.  
  609. Tmin=180; // 18°C
  610. Tmax=320; // 32°C
  611.  
  612. Tmoy=(Tmin+Tmax)/2;
  613. }
  614.  
  615.  
  616.  
  617.  
  618.  
  619. void efface_glitch_P()
  620. {
  621. int16_t p0,p1,p2;
  622. uint16_t i,n;
  623.  
  624. for(n=0; n<2; n++)
  625. {
  626. for (i=n_record_max-2; i>1 ; i--)
  627. {
  628. p0=lst_records[i].P;
  629. p1=lst_records[i-1].P;
  630. p2=lst_records[i-2].P;
  631.  
  632. if ((abs(p1-p2)) > 5)
  633. {
  634. lst_records[i-1].P=p0;
  635. lst_records[i-2].P=p0;
  636. i-=2;
  637. }
  638. }
  639. }
  640. }
  641.  
  642.  
  643. void efface_glitch_T()
  644. {
  645. Serial.println("efface_glitch_T()");
  646. int16_t T0,T1,T2;
  647. uint16_t i,n;
  648.  
  649. for(n=0; n<5; n++)
  650. {
  651. for (i=2; i<n_record_max ; i++)
  652. {
  653. T0=lst_records[i].T;
  654. T1=lst_records[i+1].T;
  655. T2=lst_records[i+2].T;
  656.  
  657. if ((abs(T1-T2)) > 30)
  658. {
  659. Serial.print("ici i="); Serial.println(i);
  660. lst_records[i+1].T=T0;
  661. lst_records[i+2].T=T0;
  662. i-=2;
  663. }
  664. }
  665. }
  666. }
  667.  
  668.  
  669.  
  670. void verifie_data_scope()
  671. {
  672. Serial.println(" ");
  673. Serial.println("verifie_data_scope() ");
  674.  
  675. if(! SDcardOk){return;}
  676.  
  677. int16_t T,P,H;
  678. uint16_t heure1, heure2;
  679. uint16_t i;
  680. uint8_t h, mn;
  681. uint8_t compte;
  682.  
  683. for (i=1; i<n_record_max-1; i++)
  684. {
  685. T=lst_records[i].T;
  686. P=lst_records[i].P;
  687. H=lst_records[i].H;
  688. heure1=lst_records[i].heure;
  689. heure2=lst_records[i+1].heure;
  690.  
  691. h= heure1 / 60;
  692. mn = heure1 % 60;
  693.  
  694. Serial.print(i);
  695. Serial.print(" Heure=");
  696. Serial.print(h);
  697. Serial.print(":");
  698. Serial.print(mn);
  699. Serial.print(" T=");
  700. Serial.print(T);
  701. Serial.print(" P=");
  702. Serial.print(P);
  703. Serial.print(" Hum=");
  704. Serial.print(H);
  705. Serial.println(" ");
  706. }
  707. }
  708.  
  709.  
  710.  
  711. void calcul_Gradu_ech_T()
  712. {
  713.  
  714. //calcul de la grd min & grad max
  715. gradu_minT = -10+(Tmin/10)*10; // division entière ce qui donne une valeur arrondie
  716. gradu_maxT = 10+(Tmax/10)*10;
  717. // gradu_maxT+=10;
  718.  
  719. echelle_T =(float) (gradu_maxT - gradu_minT)/(Scope_1.dy);
  720. if (echelle_T==0) {echelle_T=1;} // cas où la température est totalement constante - évite des /0 plus tard
  721.  
  722. /*
  723. TFT480.Set_Text_colour(BLANC);
  724. TFT480.Set_Text_Size(1);
  725. TFT480.Print_Number_Int(gradu_minT,400,30,3,' ',10);
  726. TFT480.Print_Number_Int(gradu_maxT,400,40,3,' ',10);
  727. */
  728. // TFT480.Set_Text_colour(ROUGE[0],ROUGE[1],ROUGE[2]);
  729. // TFT480.Print_Number_Float(echelle_T, 1, 400, 50, '.', 3, ' ');
  730.  
  731. }
  732.  
  733.  
  734. void determine_Pmin_Pmax()
  735. {
  736. uint16_t i, p1;
  737. Pmin=2000;
  738. Pmax=0;
  739. for (i=0; i< n_record_max ; i++) // attention départ=2, pas 0 pour éviter de prendre en copta l'acquisition en cours
  740. {
  741. if (lst_records[i].heure != 0xFFFF)
  742. {
  743. p1=lst_records[i].P;
  744. if (p1 !=0)
  745. {
  746. if ((p1 >800) && (p1 < Pmin)) {Pmin= p1;}
  747. if (p1 > Pmax) {Pmax= p1;}
  748. }
  749. }
  750. }
  751.  
  752. if ((Pmax - Pmin) < 20)
  753. {
  754. // dans ce cas on impose des valeurs permettant de calculer une échelle fonctionnelle
  755. Pmin-=2; // hPa
  756. Pmax+=2;
  757. }
  758.  
  759. Pmoy=(Pmin+Pmax)/2;
  760.  
  761. TFT480.Set_Text_Back_colour(NOIR);
  762. TFT480.Set_Text_colour(VERT);
  763. TFT480.Set_Text_Size(1);
  764.  
  765. // TFT480.Print_Number_Int(Pmax,160,85,3,' ',10);
  766. // TFT480.Print_Number_Int(Pmin,160,95,3,' ',10);
  767.  
  768.  
  769. // TFT480.Set_Text_colour(BLANC);
  770. // TFT480.Print_Number_Int(Pmoy,390,25,3,' ',10);
  771. }
  772.  
  773.  
  774. void calcul_ech_P()
  775. {
  776. echelle_P =(float) (Pmax -Pmin)/(Scope_1.dy-20);
  777. if (echelle_P==0) {echelle_P=1;}
  778.  
  779. // TFT480.Set_Text_colour(ROUGE[0],ROUGE[1],ROUGE[2]);
  780. // TFT480.Print_Number_Float(echelle_P, 3, 390, 35, '.', 3, ' ');
  781. }
  782.  
  783.  
  784. uint16_t nb_acq_heures()
  785. {
  786. uint16_t v1=0;
  787. uint16_t i;
  788.  
  789. for (i=0; i<n_record_max; i++)
  790. {
  791. if (lst_records[i].heure != 0xFFFF) {v1++;}
  792. }
  793. return v1;
  794. }
  795.  
  796.  
  797.  
  798. void affiche_courbeT() // Température extérieure & la graduation temporelle -> sur le scope
  799. {
  800. Serial.println(" "); Serial.println("affiche_courbeT()");
  801. //sram = freeRam(); Serial.print("5-freeRam="); Serial.println(sram);
  802. // Ymax du scope = 142
  803. //142 * 3 = 426 -> 42.6°C max
  804. uint16_t i,j, k1;
  805. uint16_t x, xt;
  806. uint8_t nb_ech=3; // pour le lissage de la courbe
  807. float Ti1, Ti2; // =316 pour 31.6°C
  808. float y1, y2;
  809. uint16_t heure1, heure2;
  810. uint8_t h1, h2, mn1, mn2;
  811. uint8_t RR1, RR2, GG1, GG2, BB1, BB2;
  812.  
  813. x=Scope_1.dx;
  814. for (i=n_record_max-1; i>nb_ech ; i--)
  815. {
  816. heure1=lst_records[i].heure;
  817. heure2=lst_records[i-1].heure;
  818.  
  819. h1= heure1 / 60;
  820. mn1 = heure1 % 60;
  821.  
  822. h2= heure2 / 60;
  823. mn2 = heure2 % 60;
  824.  
  825. Ti1=lst_records[i-1].T;
  826. Ti2=lst_records[i].T;
  827. /*
  828. if ((abs(Ti1 - memo_Ti1)) > 30.0) {Ti1 = memo_Ti1;} // détection valeur impossible, et correction
  829. else (memo_Ti1 = Ti1); // si OK
  830.  
  831. if ((abs(Ti2 - memo_Ti2)) > 30.0) {Ti1 = memo_Ti1;} // détection valeur impossible, et correction
  832. else (memo_Ti2 = Ti2); // si OK
  833. */
  834.  
  835. // if ((heure==0) && (Ti1==0) &&(Ti2==0)) {return;}
  836.  
  837. if ((heure1 != 0xFFFF) && (mn1 % 5) == 0) // l'enregistrement doit être valide et être centré sur les multiples de 5mn
  838. {
  839. //Serial.print("affiche_courbeT() ");
  840. //Serial.print(h); Serial.print(":"); Serial.println(mn);
  841.  
  842.  
  843. if(nb_acq_heures() > nb_ech) // lissage
  844. {
  845. // lissage de la courbe : filtre passe bas par moyenne glissante
  846. Ti1=0; Ti2=0;
  847. for (j=0; j<nb_ech; j++)
  848. {
  849. k1=i-j;
  850. if (k1>1)
  851. {
  852. Ti1 += lst_records[k1-1].T;
  853. Ti2 += lst_records[k1].T;
  854. }
  855. }
  856. Ti1/=nb_ech; Ti2/=nb_ech;
  857. }
  858. else
  859. {
  860. Ti1=lst_records[i-1].T;
  861. Ti2=lst_records[i].T;
  862. }
  863.  
  864.  
  865. y1 = Scope_1.dy/2.0 + (Ti1-Tmoy) / echelle_T;
  866. if (y1>=Scope_1.dy){y1=Scope_1.dy;} // rabote ce qui dépace du cadre
  867. if (y1<0) {y1=0;}
  868.  
  869. y2 = Scope_1.dy/2.0 + (Ti2-Tmoy) / echelle_T;
  870. if (y2>=Scope_1.dy){y2=Scope_1.dy;} // rabote ce qui dépace du cadre
  871. if (y2<0) {y2=0;}
  872.  
  873. if ((y1 >1) && (y2 >1))
  874. {
  875. if (mn1 ==0) // tracé de lignes temporelles verticales toutes les heures 'pile'
  876. {
  877. Scope_1.setCouleurTrace(GRIS_FONCE);
  878. if (h1 == 0) {Scope_1.setCouleurTrace(GRIS_CLAIR);}
  879. if (h1 == 12) {Scope_1.setCouleurTrace(ROUGE);}
  880.  
  881. if (heure1 !=(heure2 + 5) && (heure1 != 0))
  882. {
  883. // signale un manque de data par un tiret violet en bas
  884. Scope_1.Tiret(x, 30, x, Scope_1.dy-2);
  885. Scope_1.setCouleurTrace(VIOLET);
  886. Scope_1.Tiret(x, 20, x, 30);
  887. }
  888. else
  889. {
  890. // mode normal
  891. Scope_1.Tiret(x, 20, x, Scope_1.dy-2);
  892. }
  893.  
  894. if (h1 == 0)
  895. {
  896. TFT480.Set_Text_Size(1);
  897. TFT480.Set_Text_Back_colour(NOIR);
  898. TFT480.Set_Text_colour(BLANC);
  899. TFT480.Print_String("00", x+12, Scope_1.y0+Scope_1.dy/2);
  900.  
  901. affi_img(Scope_1.y0+5, x+8, "/bmp/lune3b.bmp");
  902. }
  903.  
  904. if (h1 == 5)
  905. {
  906. xt=x+15;
  907. // DEGRADE DE COULEUR pour marquer la matinée
  908. // bleu -> jaune
  909. RR1=0; RR2=255;
  910. GG1=0; GG2=255;
  911. BB1=200; BB2=0;
  912. dessine_degrade(xt, Scope_1.y0+15, 60, 4, RR1, RR2, GG1, GG2, BB1, BB2);
  913. }
  914. if (h1 == 12)
  915. {
  916. TFT480.Set_Text_Size(1);
  917. TFT480.Set_Text_Back_colour(NOIR);
  918. TFT480.Set_Text_colour(BLANC);
  919. TFT480.Print_String("12h", x+12, Scope_1.y0+Scope_1.dy/2);
  920.  
  921.  
  922. // ********* DEGRADES DE COULEUR pour marquer la période diurne **************
  923. xt=x+15;
  924. //Serial.print("xt="); Serial.println(xt); // if ((xt+64)< 470)
  925. {
  926. // jaune -> orange
  927. RR1=255; RR2=100;
  928. GG1=255; GG2=60;
  929. BB1=0; BB2=0;
  930. dessine_degrade(xt, Scope_1.y0+15, 80, 4, RR1, RR2, GG1, GG2, BB1, BB2);
  931.  
  932. // bleu -> jaune
  933. RR1=0; RR2=255;
  934. GG1=0; GG2=255;
  935. BB1=200; BB2=0;
  936. dessine_degrade(xt-70, Scope_1.y0+15, 60, 4, RR1, RR2, GG1, GG2, BB1, BB2);
  937.  
  938. }
  939.  
  940. //icone soleil:
  941. affi_img(Scope_1.y0+5, x+7, "/bmp/soleil.bmp");
  942.  
  943. }
  944. }
  945. Scope_1.setCouleurTrace(JAUNE);
  946. Scope_1.Tiret(x-1, (uint16_t)y1, x, (uint16_t)y2); // tracé de la courbe
  947. Scope_1.Tiret(x-1, (uint16_t)y1+1, x, (uint16_t)y2+1); // pour épaissir le trait
  948. }
  949. }
  950. else
  951. { // si enregistrement non valide
  952. //Scope_1.setCouleurTrace(ROUGE);
  953. //Scope_1.Tiret(x-1, 99, x, 101);
  954. }
  955. x--;
  956. }
  957. TFT480.Set_Draw_color(NOIR);
  958. TFT480.Fill_Rectangle(470, 140, 479, 318);
  959.  
  960. }
  961.  
  962.  
  963. void affiche_courbeP() // pression - sur le scope
  964. {
  965. Serial.println(" "); Serial.println("affiche_courbeP()");
  966. /**PNM minimum : 870 hPa, au large des Philippines, près du centre du typhon Tip, le 12 octobre 1979...
  967. Ouragan2 de classe 5 : pression au centre inférieure à 920 hPa
  968. **/
  969. uint8_t lissage;
  970. uint16_t i, j, k1;
  971. uint16_t x;
  972. uint8_t nb_ech=20;
  973. float p1, p2;
  974. float Pi1, Pi2;
  975. /*
  976. Serial.println("affiche_courbeP()");
  977. Serial.print("Pmoy=");
  978. Serial.println(Pmoy);
  979. Serial.print("echelle_P=");
  980. Serial.println(echelle_P);
  981. */
  982.  
  983. Scope_1.setCouleurTrace(VERT);
  984.  
  985. x=Scope_1.dx;
  986.  
  987.  
  988. for (i=n_record_max-1; i>nb_ech ; i--)
  989. {
  990. if (lst_records[i].heure != 0xFFFF)
  991. {
  992. lissage=0;
  993. if ((acqui_valide ==1)||(scope_dat_ok==1)){lissage =1;}
  994.  
  995. if(lissage==1)
  996. {
  997. // lissage de la courbe : filtre passe bas par moyenne glissante
  998. p1=0; p2=0;
  999. for (j=0; j<nb_ech; j++)
  1000. {
  1001. k1=i-j;
  1002. if (k1>1)
  1003. {
  1004. p1 += lst_records[k1-1].P;
  1005. p2 += lst_records[k1].P;
  1006. }
  1007. }
  1008. p1/=nb_ech; p2/=nb_ech;
  1009. }
  1010. else
  1011. {
  1012. p1 = lst_records[i-1].P;
  1013. p2 = lst_records[i].P;
  1014. }
  1015. /*
  1016. Serial.print("p1=");
  1017. Serial.println(p1);
  1018. Serial.print("p2=");
  1019. Serial.println(p2);
  1020. */
  1021.  
  1022. if ((p1>800)&&(p2>800))
  1023. {
  1024. Pi1 = Scope_1.dy/2.0 + (p1-Pmoy) / echelle_P;
  1025. if (Pi1>=Scope_1.dy){Pi1=Scope_1.dy-1;}
  1026. if (Pi1<0) {Pi1=0;}
  1027.  
  1028. Pi2 = Scope_1.dy/2.0 +(p2-Pmoy) / echelle_P;
  1029. if (Pi2>=Scope_1.dy){Pi2=Scope_1.dy-1;}
  1030. if (Pi2<0) {Pi2=0;}
  1031. }
  1032.  
  1033. if ((Pi1 > 0) && (Pi2 > 0))
  1034. {
  1035. Scope_1.Tiret(x-1, (uint16_t)Pi1, x, (uint16_t)Pi2);
  1036. }
  1037. }
  1038. x--;
  1039. }
  1040.  
  1041. }
  1042.  
  1043.  
  1044.  
  1045. void affiche_courbeH() // Humidité - sur le scope
  1046. {
  1047. Serial.println(" "); Serial.println("affiche_courbeH()");
  1048. uint16_t i,j, k1;
  1049. uint8_t nb_ech=20;
  1050. float Hi1, Hi2;
  1051. float h1, h2;
  1052. float ech_Hum;
  1053.  
  1054. ech_Hum = (Scope_1.dy) / 100.0;
  1055.  
  1056. Scope_1.setCouleurTrace(BLEU);
  1057.  
  1058. for (i=n_record_max-1; i>nb_ech ; i--)
  1059. {
  1060.  
  1061. if (lst_records[i].heure != 0xFFFF)
  1062. {
  1063. // lissage de la courbe : filtre passe bas par moyenne glissante
  1064. h1=0; h2=0;
  1065. for (j=0; j<nb_ech; j++)
  1066. {
  1067. k1=i-j;
  1068. if (k1>1)
  1069. {
  1070. h1 += lst_records[k1-1].H;
  1071. h2 += lst_records[k1].H;
  1072. }
  1073. }
  1074. h1/=nb_ech; h2/=nb_ech;
  1075.  
  1076. Hi1=h1 * ech_Hum;
  1077. if (Hi1>=Scope_1.dy){Hi1=Scope_1.dy-1;}
  1078. if (Hi1<1) {Hi1=1;}
  1079.  
  1080. Hi2=h2 * ech_Hum;
  1081. if (Hi2>=Scope_1.dy){Hi2=Scope_1.dy-1;}
  1082. if (Hi2<1) {Hi2=1;}
  1083.  
  1084. uint16_t H1_int, H2_int;
  1085. H1_int = (uint16_t)Hi1;
  1086. H2_int = (uint16_t)Hi2;
  1087.  
  1088. if ((H1_int > 1) && (H2_int > 1) && (abs((H1_int-H2_int)) < 20))
  1089. {
  1090. Scope_1.Tiret(i-1, H1_int, i, H2_int);
  1091. }
  1092. }
  1093. }
  1094.  
  1095. TFT480.Set_Text_colour(BLEU_CLAIR);
  1096. TFT480.Set_Text_Size(1);
  1097. TFT480.Print_String("100%", 390, 150);
  1098. TFT480.Print_String(" 0%", 390, 305);
  1099. }
  1100.  
  1101.  
  1102.  
  1103.  
  1104. void affiche_ligne_ref()
  1105. {
  1106. uint8_t R=300/echelle_T; // 300 -> 30°C
  1107. Scope_1.setCouleurTrace(ROUGE);
  1108. Scope_1.Tiret(0, R, Scope_1.dx, R);
  1109. }
  1110.  
  1111.  
  1112. void affiche_Lune()
  1113. {
  1114. age_Lune = GetPhase(annee_actuelle, mois_actuel, jour_actuel);
  1115.  
  1116. // Affichage de 'l'age' de la Lune [0..29 j]
  1117. TFT480.Set_Text_Size(1);
  1118. uint16_t x0=436;
  1119. uint16_t y0=8;
  1120. TFT480.Set_Text_colour(GRIS);
  1121. TFT480.Print_String(" AGE:", x0, y0) ;
  1122. TFT480.Set_Text_Size(2);
  1123. TFT480.Print_Number_Int(age_Lune,x0,y0+10,3,' ',10);
  1124.  
  1125. TFT480.Set_Text_colour(BLANC);
  1126. switch (((int8_t)age_Lune))
  1127. {
  1128. case 0:
  1129. {
  1130. TFT480.Print_String("NL", x0, y0+27);
  1131. }
  1132. break;
  1133. case 8:
  1134. {
  1135. TFT480.Print_String("PQ", x0, y0+27);
  1136. }
  1137. break;
  1138. case 15:
  1139. {
  1140. TFT480.Print_String("PL", x0, y0+27);
  1141. }
  1142. break;
  1143. case 22:
  1144. {
  1145. TFT480.Print_String("DQ", x0, y0+27);
  1146. }
  1147. break;
  1148. default:
  1149. {
  1150. TFT480.Print_String("--", x0, y0+27);
  1151. }
  1152. break;
  1153. }
  1154.  
  1155. Dessine_Lune2(407, 32, age_Lune);
  1156. }
  1157.  
  1158.  
  1159. void affiche_SCOPE() // vide
  1160. {
  1161. Scope_1.init(18,145, n_record_max,172); // 1px toutes les 5mn; 12px = 1h
  1162. Scope_1.setCouleurCadre(BLANC);
  1163. Scope_1.traceCadre();
  1164. // Scope_1.traceReticule(); // et efface_surface au préalable
  1165. // affiche_ligne_ref();
  1166. }
  1167.  
  1168.  
  1169.  
  1170. void affiche_pannel()
  1171. {
  1172.  
  1173. // dessine_triangles();
  1174.  
  1175. TFT480.Set_Text_Back_colour(NOIR);
  1176. TFT480.Set_Text_colour(BLANC);
  1177. TFT480.Set_Text_Size(1);
  1178. TFT480.Print_String("STATION METEO v:", 250, 0);
  1179. TFT480.Print_String(version, 250 +100, 0);
  1180.  
  1181. uint16_t hauteur = 0;
  1182.  
  1183. hauteur += 6;
  1184.  
  1185. Etiq_1.setCouleurTxt(ORANGE);
  1186. Etiq_1.setCouleurCadre(BLEU_CLAIR);
  1187. Etiq_1.setCouleurNom(BLANC);
  1188. Etiq_1.init(5, hauteur, 180, 60, "IN");
  1189. //RAPPEL : void affiche_float(float valeur, uint8_t nb_chiffres, uint8_t nb_dec, char txt_unite_i[3]);
  1190. Etiq_1.affiche_float(0, 4, 1, " C",0,0);
  1191. TFT480.Set_Draw_color(Etiq_1.couleur_txt);
  1192. TFT480.Draw_Circle(Etiq_1.x0+157, Etiq_1.y0+Etiq_1.dy-24, 3); // affiche le signe "°"
  1193.  
  1194.  
  1195. Etiq_2.setCouleurTxt(JAUNE);
  1196. Etiq_2.setCouleurCadre(BLEU_CLAIR);
  1197. Etiq_2.setCouleurNom(BLANC);
  1198. Etiq_2.init(200, hauteur, 180, 60, "OUT");
  1199. Etiq_2.affiche_float(0, 4, 1, " C",0,0);
  1200. TFT480.Set_Draw_color(Etiq_2.couleur_txt);
  1201. TFT480.Draw_Circle(Etiq_2.x0+157, Etiq_2.y0+Etiq_2.dy-24, 3); // affiche le signe "°"
  1202.  
  1203. hauteur += 65;
  1204.  
  1205. TFT480.Set_Text_colour(BLEU_CLAIR);
  1206. TFT480.Set_Text_Back_colour(NOIR);
  1207. TFT480.Set_Text_Size(1);
  1208. TFT480.Print_String("PRESSION", 60, hauteur);
  1209.  
  1210. TFT480.Set_Text_colour(BLANC);
  1211. TFT480.Set_Text_Back_colour(NOIR);
  1212. TFT480.Set_Text_Size(1);
  1213. TFT480.Print_String("HUMIDITE (%)", 200, hauteur);
  1214.  
  1215. hauteur += 6;
  1216.  
  1217.  
  1218. Etiq_5.setCouleurTxt(VERT);
  1219. Etiq_5.setCouleurCadre(BLEU_CLAIR);
  1220. Etiq_5.setCouleurNom(BLANC);
  1221. Etiq_5.init(5, hauteur, 180, 60, "");
  1222. //rappel affiche_int(uint32_t valeur, uint8_t nb_chiffres, char txt_unite_i[3])
  1223. Etiq_5.affiche_int(0, 4, "hPa",0,0);
  1224.  
  1225.  
  1226. Etiq_4.setCouleurTxt(BLEU);
  1227. Etiq_4.setCouleurCadre(BLEU_CLAIR);
  1228. Etiq_4.setCouleurNom(BLANC);
  1229. Etiq_4.init(200, hauteur, 80, 60, "");
  1230. Etiq_4.affiche_int(0, 2, "%",0,0);
  1231. TFT480.Print_String("%", Etiq_4.x0+60,Etiq_4.y0+35);
  1232.  
  1233.  
  1234. TFT480.Set_Text_Size(1);
  1235. TFT480.Set_Text_colour(BLANC);
  1236.  
  1237. // TFT480.Print_Number_Int(nb_acqui433,330,70,6,' ',10);
  1238. // TFT480.Print_Number_Int(nb_wr_SD,440,70,6,' ',10);
  1239.  
  1240. }
  1241.  
  1242.  
  1243. void affiche_LEDS()
  1244. {
  1245. TFT480.Set_Text_Size(1);
  1246. TFT480.Set_Text_colour(BLANC);
  1247.  
  1248. // TFT480.Print_String("WR SDcard", 300, 70);
  1249. // Led1.init(390,68, 10,10);
  1250. // Led1.setCouleur(NOIR);
  1251.  
  1252. Led2.init(410,60, 10,10);
  1253. TFT480.Print_String("RX", Led2.x0-20, Led2.y0);
  1254.  
  1255. Led2.setCouleur(NOIR);
  1256.  
  1257. // TFT480.Print_String("RAZ data", 300, 96);
  1258. // Led3.init(390,96, 10,10);
  1259. // Led3.setCouleur(NOIR);
  1260.  
  1261. // Led4.init(390,10, 20,20);
  1262. // Led4.setCouleur(NOIR);
  1263.  
  1264. }
  1265.  
  1266.  
  1267.  
  1268.  
  1269. /**--------------------------------------------------------
  1270. fonctions RECEPTION & DECODAGE SONDE EXTERNE 433MHz
  1271. --------------------------------------------------------**/
  1272.  
  1273. void init_lst_records()
  1274. {
  1275.  
  1276. Serial.println(" "); Serial.println("init_lst_records()");
  1277.  
  1278. uint16_t i;
  1279. uint8_t h;
  1280. uint8_t mn;
  1281. uint8_t mn5;
  1282. float Tn,Pn,Hn;
  1283.  
  1284. h= heure_actuelle;
  1285. mn=5*(minute_actuelle/5);
  1286. //mn=5*mn5;
  1287. Serial.print("heure actuelle ponderee="); Serial.print(h); Serial.print(":");Serial.println(mn);
  1288.  
  1289. //on part de l'heure actuelle puis on la décrémente par pas de 5mn
  1290. for (i=n_record_max; i>0 ; i--)
  1291. {
  1292. Serial.print(i); Serial.print(" "); Serial.print(h); Serial.print(":");Serial.println(mn);
  1293.  
  1294. // lst_records[i].T=0;
  1295. // lst_records[i].P=0;
  1296. // lst_records[i].H=0;
  1297.  
  1298. // sinusoiïdes centrées sur la dernière valeur acquise par les capteurs
  1299.  
  1300. Tn = T_EXT_retenue + 10*sin(i/20.0); // sinusoïde (pour affichage echelle consistante)
  1301. Tn = T_EXT_retenue;
  1302.  
  1303. lst_records[n_record_max-i].T= (int16_t)Tn;
  1304.  
  1305.  
  1306. //Pn = Pression_lue + (i/20)*sin(i/27.0); // sinusoïde (pour affichage echelle consistante)
  1307. Pn = Pression_lue;
  1308.  
  1309. lst_records[n_record_max-i].P= (int16_t)Pn;
  1310.  
  1311. //Hn = H_out_lue + (i/10)*sin(i/43.0); // sinusoïde (pour affichage echelle consistante)
  1312. Hn = H_out_lue;
  1313.  
  1314. lst_records[n_record_max-i].H= (uint16_t)Hn;
  1315.  
  1316. //
  1317.  
  1318. if (mn>=5){mn-=5;}
  1319. else
  1320. {
  1321. mn=55;
  1322. if (h>0){h--;} else {h=23;}
  1323. }
  1324. lst_records[i].heure=mn+60*h;
  1325. }
  1326.  
  1327. /**
  1328. for (i=0; i<n_record_max ; i++)
  1329. {
  1330.  
  1331. // sinusoiïdes centrées sur la dernière valeur acquise par les capteurs
  1332. Tn = T_EXT_retenue + 10.0*sin(i/40.0); // sinusoïde (pour affichage echelle consistante)
  1333. lst_records[n_record_max-i].T= (int16_t)Tn;
  1334.  
  1335. Pn = Pression_lue + 5.0*sin(i/40.0); // sinusoïde (pour affichage echelle consistante)
  1336. lst_records[n_record_max-i].P= (int16_t)Pn;
  1337.  
  1338. Hn = H_out_lue + 5.0*sin(i/40.0); // sinusoïde (pour affichage echelle consistante)
  1339. lst_records[n_record_max-i].H= (uint16_t)Hn;
  1340. // ---------------------------------------------------------------------
  1341. }
  1342. **/
  1343.  
  1344. }
  1345.  
  1346.  
  1347.  
  1348.  
  1349. void efface_buffer()
  1350. {
  1351. for(int i=0; i<120; i++)
  1352. {
  1353. buffer[i]=' ';
  1354. }
  1355.  
  1356. }
  1357.  
  1358.  
  1359. void record_enr_actuel()
  1360. {
  1361. Serial.println( "record_enr_actuel()");
  1362. // enregistre les data actuels en fin de liste avant décalage des enregistrements (par la fonction suivante)
  1363. lst_records[n_record_max].T= T_EXT_retenue; // format 325 -> 32.5°C
  1364. lst_records[n_record_max].P= Pression_lue;
  1365. lst_records[n_record_max].H= H_out_lue;
  1366. lst_records[n_record_max].heure= heure_actuelle*60 + minute_actuelle;
  1367. }
  1368.  
  1369.  
  1370.  
  1371. void decale_enregistrements(uint16_t p)
  1372. {
  1373. Serial.println( "decale_enregistrements");
  1374. //décalage vers la gauche depuis la position p
  1375. uint16_t i;
  1376.  
  1377. TFT480.Set_Text_Back_colour(BLANC);
  1378. TFT480.Set_Text_colour(NOIR);
  1379. TFT480.Set_Text_Size(2);
  1380. TFT480.Print_String("<", 440, 170);
  1381.  
  1382. for (i=0; i<p; i++)
  1383. {
  1384. // decalage
  1385. lst_records[i].T=lst_records[i+1].T; // ->remarque : l'enr 'p' est pris par le 'i+1' et est dupliqué vers la gauche
  1386. lst_records[i].P=lst_records[i+1].P;
  1387. lst_records[i].H=lst_records[i+1].H;
  1388. lst_records[i].heure=lst_records[i+1].heure;
  1389. }
  1390. }
  1391.  
  1392.  
  1393.  
  1394. int16_t strbinToInt(String str1, uint8_t nb_bits)
  1395. {
  1396. uint8_t i;
  1397. int16_t result=0;
  1398. bool negatif = false;
  1399. int tableau1[10];
  1400.  
  1401. for (i=0; i<nb_bits; i++) { if(str1[i] == '0') {tableau1[i]=0;} else {tableau1[i]=1;} }
  1402. if (tableau1[0] == 1) {negatif=true;}
  1403. if (negatif) { for (i=0; i<nb_bits; i++) {tableau1[i] = 1-tableau1[i]; } }
  1404. for (i=0; i<nb_bits; i++) { if (tableau1[(nb_bits-1)-i]==1) {result+= 1<<i;} }
  1405. if (negatif) { result+=1; result = -result; }
  1406. return result;
  1407. }
  1408.  
  1409.  
  1410.  
  1411.  
  1412. void calcul_confiance()
  1413. {
  1414. // les 5 valeurs reçues à l'issue d'une salve ne sont pas toujours toutes identiques, dû à des aléas de transmission
  1415. // ici on affecte à chaque valeur le nombre d'occurences (qui va de 1 si valeur "exotique" à 5 si toutes identiques)
  1416. // ces nombres d'occurences sont inscrites dans un tableau semblable à celui des valeurs lues (mêmes indices).
  1417. uint8_t i,j;
  1418. uint16_t Ti;
  1419.  
  1420.  
  1421. for(i=0; i<5; i++) {confiance[i]=0;} //RAZ
  1422.  
  1423. for(i=0; i<5; i++)
  1424. {
  1425. Ti=T_EXT_lue[i];
  1426. for(j=0; j<5; j++)
  1427. {
  1428. if (T_EXT_lue[j] == Ti) {confiance[i]++;}
  1429. }
  1430. }
  1431. }
  1432.  
  1433.  
  1434.  
  1435. uint16_t meilleure_valeur()
  1436. {
  1437. // trouver la valeur ayant obtenu le meilleur score de présence dans la salve (= le plus grand nombre d'occurences)
  1438. // à l'issue de la fonction "calcul_confiance()"
  1439.  
  1440. uint16_t meilleure;
  1441. uint16_t i;
  1442.  
  1443. meilleure = T_EXT_lue[0];
  1444. for(i=0; i<4; i++)
  1445. {
  1446. if (confiance[i+1] > confiance[i]) {meilleure = T_EXT_lue[i+1];}
  1447. }
  1448. return (meilleure);
  1449. }
  1450.  
  1451.  
  1452.  
  1453. void lit_temperature() // de la sonde ext 433MHz
  1454. // source = message
  1455. //(message a été constitué par la fonction "decodeBuffer()")
  1456. // destination -> tableau "T_EXT_lue[5]" des 5 valeurs lues (correspondant à une salve)
  1457. {
  1458.  
  1459. uint8_t p; // position de la séquence de référence fixe
  1460. uint8_t decal;
  1461. uint8_t nbBits;
  1462. int16_t valeur_lue;
  1463. String s1;
  1464.  
  1465. p = message.indexOf("100000",6); // séquence apparemment fixe > à la 6eme position... (
  1466. //le début du message change à chaque changement des piles !)
  1467.  
  1468. nbBits=10; // nb de bits à lire
  1469. decal=6; // décalage depuis la position p (ici les 6 bits de la séquence fixe)
  1470.  
  1471.  
  1472. if (p>0)
  1473. {
  1474. s1=message.substring(p+decal, p+decal+nbBits); // TFT480.Print_String(s1, 100, 100); // en binaire
  1475.  
  1476. //ici, par exemple s1 = "0011111011" -> 251 décimal -> 25.1 °C
  1477. // ou bien s1 = "1111100101" -> TEMPERATURE NEGATIVE "1111100101" -> -27 decimal -> -2.7°C
  1478.  
  1479. //s1 = "1100010110"; //-234 decimal -> -23.4°C POUR TEST valeurs négatives
  1480.  
  1481. valeur_lue=strbinToInt(s1, nbBits);// =316 pour 31.6°C //TFT480.Print_Number_Int(T1,220,100,3,' ',10);
  1482.  
  1483. Serial.print(heure_actuelle); Serial.print(":"); Serial.println(minute_actuelle);
  1484. Serial.print("Temperature EXT= ");
  1485. float temp_f = valeur_lue /10.0;
  1486. Serial.println(temp_f);
  1487.  
  1488. // todo // expérimenter avec des températures négatives (sonde au frigo !!)
  1489.  
  1490. if ((valeur_lue != 0) )
  1491. {
  1492. T_EXT_lue[num_acquisition] = valeur_lue; // on renregistre la nouvelle valeur (parmi 5 qui constituent une salve)
  1493. }
  1494.  
  1495. }
  1496. }
  1497.  
  1498.  
  1499.  
  1500. void lit_humidite()
  1501. {
  1502. // de la sonde ext 433MHz
  1503. uint8_t p; // position de la séquence de référence fixe
  1504. uint8_t decal;
  1505. uint8_t nbBits;
  1506. uint16_t valeur_precedente, valeur_lue;
  1507. String s1;
  1508.  
  1509. p = message.indexOf("100000",6); // séquence apparemment fixe
  1510. nbBits=7; // nb de bits à lire
  1511. decal=6+10+5; // décalage depuis la position p
  1512.  
  1513. if (p>0)
  1514. {
  1515. s1=message.substring(p+decal, p+decal+nbBits);
  1516. memo_H_out = H_out_lue;
  1517. valeur_lue = strbinToInt(s1,nbBits); //TFT480.Print_Number_Int(T1,220,100,3,' ',10);
  1518. valeur_precedente = memo_H_out;
  1519.  
  1520. if ((valeur_lue != 0) && (valeur_lue < 100) ) // 100% max !
  1521. {
  1522. if ( abs(valeur_lue - valeur_precedente) < 10 ) // delta de 10% max
  1523. {
  1524. H_out_lue = valeur_lue; // on renregistre la nouvelle valeur
  1525. }
  1526. else // au delà -> anti-glich
  1527. {
  1528. if ( valeur_lue > valeur_precedente) {H_out_lue = valeur_precedente+5;}
  1529. if ( valeur_lue < valeur_precedente) {H_out_lue = valeur_precedente-5;}
  1530. }
  1531. }
  1532. }
  1533.  
  1534. }
  1535.  
  1536.  
  1537. void decodeBuffer()
  1538. // transcode les 'A' et 'B' et 'C' qui représentent des durées en '0' et '1' -> destination = message
  1539. // pour la suite du traitement voir fonction "lit_temperature()"
  1540. {
  1541.  
  1542. Serial.println(" "); Serial.println("reception signal 433MHz sonde externe :");
  1543. int k;
  1544. char car1;
  1545. char car2;
  1546. k=0;
  1547. while (k<=73)
  1548. {
  1549. car1=buffer[k];
  1550. car2=buffer[k+1];
  1551. if ((car1=='A') &&(car2=='B'))
  1552. {
  1553. message += "0";
  1554. //TFT480.Print_String("0", 4*k, 10*aff_y);
  1555. Serial.print(0);
  1556. }
  1557. else if ((car1=='A') &&(car2=='C'))
  1558. {
  1559. message += "1";
  1560. //TFT480.Print_String("1", 4*k, 10*aff_y);
  1561. Serial.print(1);
  1562. }
  1563. k++;
  1564. }
  1565. Serial.println(' ');
  1566. efface_buffer();
  1567. aff_y++;
  1568. if (aff_y>50) {aff_y = 1;}
  1569.  
  1570. nb_acqui433++;
  1571.  
  1572. TFT480.Set_Text_Size(1);
  1573. TFT480.Set_Text_colour(BLANC);
  1574. TFT480.Print_Number_Int(nb_acqui433, Led2.x0+25, Led2.y0, 6,' ',10);
  1575.  
  1576. Serial.println("-----------------------------------");
  1577. }
  1578.  
  1579. /**
  1580.  
  1581. RESULTS
  1582.  
  1583. 2020-09-07 PM
  1584. ABABACACACACABACACABABABABABABABACACACACACACACACACACACACABABACABACABABACA-␍␊
  1585. 001111011000000011111111111100101001-␍␊
  1586.  
  1587. 2020-09-08 AM
  1588. ABACABACABABABACACABABABABABABABACACACABACACABACACACACACABABACABACACACABA-␍␊
  1589. 010100011000000011101101111100101110-␍␊
  1590.  
  1591. ABACABABABACACABABABABABABABACACACACACACACABACACACACABABACACABABACACA-␍␊
  1592. 0100011000000011111110111100110011-␍␊
  1593.  
  1594. ABACABABABABABABACABABABABABABABACACACACACACABABACACACACABABACABACACABABA-␍␊
  1595. 010000001000000011111100111100101100-␍␊
  1596.  
  1597. ABACABABABACABACACABABABABABABABACACACACABACACACACACACACABABACABACACABACA-␍␊
  1598. 010001011000000011110111111100101101-␍␊
  1599.  
  1600. ABABABACABACACABABABABABABABACACACACABACACABACACACACABABACABACACABACA-␍␊
  1601. 010001011000000011110110111100101101-␍␊
  1602.  
  1603. ABACABABABACABACACABABABABABABABACACACACABACABABACACACACABABACABACACABACA-␍␊
  1604. 010001011000000011110100111100101101-␍␊
  1605.  
  1606.  
  1607.  
  1608. 00111000 100000 0100000111 111100 110011-␍␊
  1609. 01000000 100000 0011111111 111100 110010
  1610. 01000001 100000 0011111110 111100 110001
  1611. 01000001 100000 0100000000 111100 101111-␍␊
  1612. 01000001 100000 0100000000 111100 10111-␍␊
  1613.  
  1614. AVEC temperature variable (R ajustable en // sur la thermistance) :
  1615. 00111101 100000 0011111111 111100 101001-␍␊
  1616.  
  1617. 01001000 100000 0011111011 11110 0101010-␍␊ 251 (sans la R ajustable en //) -> 25,1 °C ?
  1618. 01001000 100000 0100011001 11110 0100110-␍␊ 281 (sans la R mais chauffée avec le doigt) -> 28,1 °C ?
  1619. 01100110 100000 0110101100 11110 0011111-␍␊ 428
  1620. 10101110 100000 0111001100 11110 0100010-␍␊ 460
  1621. 10100101 100000 0111011100 11110 0100001-␍␊ 476
  1622. 10011100 100000 0111101110 11110 0100000-␍␊ 494
  1623. 10001101 100000 1000001110 11110 0011101-␍␊ 526
  1624. 10000100 100000 1000100001 11110 0011100-␍␊ 545
  1625. 01110100 100000 1001001011 11110 0011011-␍␊ 587
  1626. 01100101 100000 1001110111 11110 0011001-␍␊ 631
  1627. 01011000 100000 1010100010 11110 0011011-␍␊ 674
  1628. 01000110 100000 1011000010 11110 0011011-␍␊ 706
  1629. 00011111 100000 1011011010 11110 0011010-␍␊ 730
  1630.  
  1631. 10000001 100000 0010000111 11110 0111101
  1632.  
  1633. 11000101 100000 0000000001 11110 0111100 ␍␊
  1634. 11000101 100000 0000000010 11110 0111100
  1635. 11000101 100011 1111111011 11110 0111100 ␍␊ <- TEMPERATURE NEGATIVE
  1636. 11000101 100011 1111100101 11110 0111100 ␍␊ <- TEMPERATURE NEGATIVE "1111100101" -> -27 decimal -> -2.7°C
  1637. 11000101 100011 1111100011 11110 1000000
  1638. 11000101 100000 0000010101 11110 0111011 ␍␊
  1639. 11000101 100000 0000010101 11110 0111100
  1640.  
  1641.  
  1642.  
  1643. ANALYSE "colonne" 3 (= température):
  1644.  
  1645. 0110101100 = 428
  1646. 0111001100 = 460
  1647. 0111011100 = 476
  1648. 0111101110 = 494
  1649. 1000001110 = 526
  1650. 1000100001 = 545
  1651. 1001001011 = 587
  1652. 1001110111 = 631
  1653. 1010100010 = 674
  1654. 1011000010 = 706
  1655. 1011011010 = 730
  1656.  
  1657.  
  1658.  
  1659. Humidité (colonne 5):
  1660.  
  1661.  
  1662.  
  1663. **/
  1664.  
  1665.  
  1666.  
  1667.  
  1668. /**--------------------------------------------------------
  1669. partie COMMUNE
  1670. --------------------------------------------------------**/
  1671.  
  1672. uint8_t decToBcd( int val )
  1673. {
  1674. return (uint8_t) ((val / 10 * 16) + (val % 10));
  1675. }
  1676.  
  1677.  
  1678. void setDateTime()
  1679. {
  1680. // mise à l'heure exacte
  1681. // cette fonction ne doit être appelée qu'une fois pour mettre l'horloge RTC à l'heure, ou en cas de changement de sa pile
  1682. // il faut la parametrer correctement au préalable en fonction de la date et de l'heure actuelle
  1683.  
  1684. #define DS1307_ADDRESS 0x68
  1685. byte zero = 0x00;
  1686.  
  1687.  
  1688. byte second = 25; //0-59
  1689. byte minute = 54; //0-59
  1690. byte hour = 14; //0-23
  1691. byte weekDay = 5; //1-7
  1692. byte monthDay = 20; //1-31
  1693. byte month = 7; //1-12
  1694. byte year = 23; //0-99
  1695.  
  1696. Wire.beginTransmission(DS1307_ADDRESS);
  1697. Wire.write(zero);
  1698.  
  1699. Wire.write(decToBcd(second));
  1700. Wire.write(decToBcd(minute));
  1701. Wire.write(decToBcd(hour));
  1702. Wire.write(decToBcd(weekDay));
  1703. Wire.write(decToBcd(monthDay));
  1704. Wire.write(decToBcd(month));
  1705. Wire.write(decToBcd(year));
  1706.  
  1707. Wire.write(zero); //start
  1708.  
  1709. Wire.endTransmission();
  1710.  
  1711. }
  1712.  
  1713.  
  1714. double MoonPhase(int Year,int Month,int Day)
  1715. {
  1716. double M;
  1717. int XYear,Century;
  1718. if(Month<=2)
  1719. {
  1720. Year--;
  1721. Month+=12;
  1722. }
  1723. Month-=3;
  1724. XYear=Year % 100;
  1725. Century=(int(Year / 100)*146097) >> 2;
  1726. XYear=(XYear*1461) >> 2;
  1727. M=(floor(((((Month*153)+2)/ 5)+Day)+1721119+XYear+Century)+4.867)/29.53058;
  1728. return fabs(2*(M-floor(M))-1);
  1729. }
  1730.  
  1731.  
  1732.  
  1733.  
  1734.  
  1735. void setup()
  1736. {
  1737. // premiere_passe=1;
  1738. init_ports();
  1739. Serial.begin(115200);
  1740. pinMode(INPUT_PIN, INPUT);
  1741. attachInterrupt((INPUT_PIN), changed, CHANGE);
  1742. Serial.println("Bonjour");
  1743.  
  1744. sram = freeRam(); Serial.print("01-freeRam="); Serial.println(sram); //=1552 sans les fonctions SD, =518 avec
  1745. //RAPPEL: ATmega2560 SRAM = 8KB...
  1746.  
  1747. i_buff=0;
  1748. efface_buffer();
  1749.  
  1750. TFT480.Init_LCD();
  1751. clear_screen();
  1752. delay(100);
  1753. TFT480.Set_Rotation(1);
  1754.  
  1755. Init_SDcard();
  1756.  
  1757. /** pour tests
  1758. uint8_t r=123;
  1759. uint8_t g=228;
  1760. uint8_t b=17;
  1761. uint16_t couleur1;
  1762.  
  1763. couleur1 = TFT480.Color_To_565(r, g, b);
  1764.  
  1765. RGB565_to_888(couleur1, &r, &g, &b);
  1766.  
  1767. Serial.print("r="); Serial.println(r);
  1768. Serial.print("g="); Serial.println(g);
  1769. Serial.print("b="); Serial.println(b);
  1770. **/
  1771.  
  1772.  
  1773. /* TESTS affichage d'images lues sur la SDcard
  1774.  
  1775. affi_img(100, 200, "/bmp/lune5.bmp");
  1776. delay(300);
  1777.  
  1778. affi_img(200,10, "/bmp/skippy.bmp");
  1779. delay(300);
  1780.  
  1781. affi_img(300,50, "/bmp/soleil.bmp");
  1782. delay(300);
  1783.  
  1784. affi_img(0,0, "/bmp/montagne.bmp");
  1785. delay(300);
  1786. */
  1787.  
  1788.  
  1789.  
  1790.  
  1791. sram = freeRam(); Serial.print("ici -> freeRam="); Serial.println(sram); //468
  1792.  
  1793.  
  1794. /* TEST AFFICHAGE DE NOMBREUSES ICONES*/
  1795. /*
  1796. uint16_t x,y;
  1797. x=0;
  1798. y=0;
  1799. for(uint16_t i=0; i<300; i++)
  1800. {
  1801. affi_img(x,y, "/bmp/soleil.bmp"); // ici c'est ok; plus loin dans une fonction, -> crash de stack
  1802. Serial.println(i);
  1803.  
  1804. sram = freeRam(); Serial.print("freeRam="); Serial.println(sram); //410
  1805.  
  1806. x+=20;
  1807. if (x>450){x=0; y+=20;}
  1808. }
  1809. */
  1810. /* ********************************** */
  1811.  
  1812.  
  1813. //dessine_arc_en_ciel();
  1814. //delay(2000);
  1815.  
  1816. /*
  1817. clear_screen();
  1818. */
  1819.  
  1820. aff_y=0;
  1821. T_INTE_lue=0;
  1822. T_EXT_retenue=0;
  1823. Pression_lue=1013; //hPa
  1824. H_in_lue = 50; // 50%
  1825. H_out_lue = 50; // 50%
  1826.  
  1827.  
  1828. affiche_meteo();
  1829. num_acquisition=0;
  1830.  
  1831. affiche_pannel();
  1832. affiche_heure(); //et initialise les variables : annee_actuelle, mois_actuel, jour_actuel, heure_actuelle, minute_actuelle
  1833. affiche_date(); // attention : executer la ligne précedente au moins 1 fois au préalable pour initialiser les variables
  1834. affiche_LEDS();
  1835. affiche_SCOPE();
  1836.  
  1837. TFT480.Set_Text_Back_colour(NOIR);
  1838. TFT480.Set_Text_colour(VIOLET);
  1839. TFT480.Set_Text_Size(2);
  1840. TFT480.Print_String("Initialisations...", 30, 160);
  1841.  
  1842.  
  1843. /**
  1844. Rappels :
  1845. Scope_1.dx = 450
  1846. lst_records[500]
  1847. **/
  1848.  
  1849. TFT480.Set_Text_Back_colour(NOIR);
  1850. TFT480.Set_Text_colour(BLANC);
  1851. TFT480.Set_Text_Size(1);
  1852.  
  1853. init_BMP280();
  1854.  
  1855. // setDateTime(); // à décommenter (une fois, à recommenter ensuite) pour mise à l'heure (paramétrer correctement la fonction au préalable !)
  1856.  
  1857. TT1=0;
  1858. // TT2=50;
  1859. // TT3=0;
  1860. // TT4=0;
  1861.  
  1862. /** --------------------------------------------
  1863. les 3 lignes ci-dessous sont à commenter, sauf pour initaliser éventuellement les enregistrements sur la SDcard, pour test
  1864.  si elles ne sont pas commentées, les enregistrements seront perdus à chaque redémarrage de la carte Arduino **/
  1865.  
  1866. // charge_enregistrements(); // pour afficher rapidement (sans attendre les acquisitions) des sinusoïdes...
  1867. if (0) // =1 à la 1ere utilisation
  1868. {
  1869. init_lst_records();
  1870. trace_sur_Scope();
  1871. write_scope_on_SDcard();
  1872. }
  1873.  
  1874. /** --------------------------------------------**/
  1875.  
  1876.  
  1877. read_scope_on_SDcard();
  1878. trace_sur_Scope();
  1879.  
  1880. // TFT480.Set_Text_Back_colour(NOIR);
  1881. // TFT480.Set_Text_colour(ORANGE[0],ORANGE[1],ORANGE[2]);
  1882. // TFT480.Set_Text_Size(1);
  1883. // TFT480.Print_String("en attente de donnees reçues", 150, 260);
  1884.  
  1885. affiche_Lune();
  1886.  
  1887. sram = freeRam(); Serial.print("02-freeRam="); Serial.println(sram); // 1067
  1888.  
  1889. }
  1890.  
  1891.  
  1892.  
  1893.  
  1894.  
  1895.  
  1896. void trace_sur_Scope() // affiche les courbes
  1897. {
  1898. Serial.println(" "); Serial.println("trace_sur_Scope()");
  1899.  
  1900. verifie_data_scope(); // pour visu sur le port série (USB)
  1901.  
  1902.  
  1903. //efface_glitch_T();
  1904.  
  1905. calcul_moyenne_T_sur_toutes();
  1906. determine_Tmin_Tmax();
  1907. //fixe_Tmin_tmax();
  1908.  
  1909. calcul_Gradu_ech_T();
  1910.  
  1911. efface_glitch_P();
  1912. determine_Pmin_Pmax();
  1913. calcul_ech_P();
  1914.  
  1915. if ((acqui_valide ==1) || (scope_dat_ok==1))
  1916. {
  1917. Scope_1.traceGraduation(); // ce qui efface tout au préalable
  1918. affiche_courbeH();
  1919. affiche_courbeP();
  1920. affiche_courbeT();
  1921. }
  1922. }
  1923.  
  1924.  
  1925. void affiche_meteo()
  1926. {
  1927. // sur l'écran TFT
  1928. Serial.println("affiche_meteo()");
  1929. float T_in_f = T_INTE_lue / 10.0; // float
  1930. Etiq_1.affiche_float(T_in_f, 4, 1, " C", 0, 0);
  1931. TFT480.Set_Draw_color(Etiq_1.couleur_txt);
  1932. TFT480.Draw_Circle(Etiq_1.x0+157, Etiq_1.y0+Etiq_1.dy-24, 3); // affiche le signe "°"
  1933.  
  1934.  
  1935. /**
  1936. // utile lors de la phase de mise au point...
  1937.  
  1938. // Affichage de 5 valeurs reçues, constituant une salve, et de leur indice de confiance
  1939.  
  1940. TFT480.Set_Draw_color(NOIR);
  1941. TFT480.Fill_Rectangle(434, 4, 476, 54); // efface tout pour crééer une "animation" de l'affichage même si valeurs inchangées
  1942.  
  1943. TFT480.Set_Text_Back_colour(NOIR);
  1944.   TFT480.Set_Text_colour(BLANC);
  1945.  
  1946. TFT480.Set_Draw_color(GRIS);
  1947. TFT480.Draw_Fast_VLine(430, 4, 55);
  1948.  
  1949.  
  1950. // Affichage des détails de la salve reçue en petits chiffres, à droite
  1951. TFT480.Set_Text_Size(1);
  1952. uint16_t x0=434;
  1953. uint16_t y0=0;
  1954. y0+= 5; TFT480.Print_Number_Int(T_EXT_lue[0],x0,y0,3,' ',10); TFT480.Print_Number_Int(confiance[0],x0+30,y0,1,' ',10);
  1955. y0+=10; TFT480.Print_Number_Int(T_EXT_lue[1],x0,y0,3,' ',10); TFT480.Print_Number_Int(confiance[1],x0+30,y0,1,' ',10);
  1956. y0+=10; TFT480.Print_Number_Int(T_EXT_lue[2],x0,y0,3,' ',10); TFT480.Print_Number_Int(confiance[2],x0+30,y0,1,' ',10);
  1957. y0+=10; TFT480.Print_Number_Int(T_EXT_lue[3],x0,y0,3,' ',10); TFT480.Print_Number_Int(confiance[3],x0+30,y0,1,' ',10);
  1958. y0+=10; TFT480.Print_Number_Int(T_EXT_lue[4],x0,y0,3,' ',10); TFT480.Print_Number_Int(confiance[4],x0+30,y0,1,' ',10);
  1959.  
  1960. // Affichage en VERT de la valeur retenue
  1961. TFT480.Set_Text_Back_colour(NOIR);
  1962. TFT480.Set_Text_colour(GRIS);
  1963. TFT480.Print_String("ok->", 410,57);
  1964. TFT480.Set_Text_colour(VERT);
  1965. y0+=12; TFT480.Print_Number_Int(meilleure_valeur(),x0,y0,3,' ',10);
  1966.  
  1967. **/
  1968.  
  1969. float T_out_f = T_EXT_retenue / 10.0; // float
  1970. Etiq_2.affiche_float(T_out_f, 4, 1, " C", Tmin/10, Tmax/10);
  1971.  
  1972. TFT480.Set_Draw_color(Etiq_2.couleur_txt);
  1973. TFT480.Draw_Circle(Etiq_2.x0+157, Etiq_2.y0+Etiq_2.dy-24, 3); // affiche le signe "°"
  1974.  
  1975. Etiq_5.affiche_int(Pression_lue, 4, "hPa", Pmin, Pmax);
  1976.  
  1977. // if (stable==1) {Led3.setCouleur(VERT);} else {Led3.setCouleur(ORANGE);}
  1978.  
  1979. Etiq_4.affiche_int(H_out_lue, 2, "", 0, 0);
  1980. TFT480.Set_Text_Size(2);
  1981. TFT480.Print_String("%", Etiq_4.x0+60,Etiq_4.y0+35);
  1982. }
  1983.  
  1984.  
  1985.  
  1986. void analyse_signal_primaire()
  1987. {
  1988.  
  1989. char lettre_i;
  1990. pulseWidth = micros() - memo_micros1; // VOIR la doc micros() -> nb de microsecondes depuis le démarrage de la carte
  1991. memo_micros1 = micros();
  1992.  
  1993. //Serial.print('\n');
  1994. //Serial.print(pulseWidth);
  1995.  
  1996. /**
  1997. Une analyse des signaux fait apparaitre ceci:
  1998. 4 durées caractéristiques 490us ; 95us ; 1940us; 3700us
  1999. - 490us c'est la durée des tops HIGHT (tous identiques)
  2000. - 950ums ; 1940ms ; 3700ms sont les différentes durées à l'état LOW qui séparent les tops ()
  2001.  
  2002. appelons ces durées par une lettre :
  2003. A -> 490us
  2004. B -> 950us
  2005. C -> 1940us
  2006. D -> 3700us
  2007. **/
  2008.  
  2009. if ( (pulseWidth < 460) )
  2010. {
  2011. return;
  2012. }
  2013. if ( (pulseWidth >= 460) && (pulseWidth < 530) )
  2014. {
  2015. //Serial.print('A');
  2016. lettre_i = 'A';
  2017. buffer[i_buff]= lettre_i; //memorisation de la lettre
  2018. i_buff++;
  2019. }
  2020. if ( (pulseWidth >= 910) && (pulseWidth < 1100) )
  2021. {
  2022. //Serial.print('B');
  2023. lettre_i = 'B';
  2024. buffer[i_buff]= lettre_i;
  2025. i_buff++;
  2026. }
  2027. if ( (pulseWidth >= 1900) && (pulseWidth < 1970) )
  2028. {
  2029. //Serial.print('C');
  2030. lettre_i = 'C';
  2031. buffer[i_buff]= lettre_i;
  2032. i_buff++;
  2033. }
  2034. if (pulseWidth >= 3000) // sonne la fin de la séquence...
  2035. {
  2036. if (i_buff>=72)
  2037. {
  2038. Led2.setCouleur(JAUNE);
  2039. Serial.println(' ');
  2040. decodeBuffer();
  2041. Serial.print(" ");
  2042. lit_temperature(); // de la sonde ext 433MHz
  2043. lit_humidite(); // de la sonde ext 433MHz
  2044.  
  2045. message="";
  2046. //memo_micros2 = micros();
  2047. efface_buffer();
  2048.  
  2049. // premiere_passe==0;
  2050.  
  2051. num_acquisition++;
  2052. if (num_acquisition >=5)
  2053. {
  2054. num_acquisition=0;
  2055. acqui_valide =1;
  2056.  
  2057. calcul_confiance();
  2058. T_EXT_retenue = meilleure_valeur();
  2059.  
  2060. //determine_Tmin_Tmax();
  2061. fixe_Tmin_tmax();
  2062.  
  2063. calcul_Gradu_ech_T();
  2064. acqui_PressionTemperature();
  2065. affiche_meteo();
  2066. }
  2067. }
  2068. i_buff=0;
  2069. }
  2070. /**
  2071. résultat :
  2072. AB AC AB AB AC AB AC AC AC AB AB AB AB AB AB AB AC AC AC A
  2073. 0 1 0 0 1 0 1 1 1 0 0 0 0 0 0 0 1 1 1
  2074.  
  2075. Les motifs qui apparaissent sont AB et AC
  2076. Il est vraissemblable que AB code pour 0 et AC pour 1 (ou l'inverse))
  2077. **/
  2078. }
  2079.  
  2080.  
  2081.  
  2082. void calcul_jour_de_la_semaine()
  2083. {
  2084. // d'après l'Algorithme de Mike Keith
  2085. uint16_t d, m, y, z, jds;
  2086.  
  2087. d=jour_actuel;
  2088. m=mois_actuel;
  2089. y=annee_actuelle;
  2090.  
  2091. if (m>=3)
  2092. {
  2093. jds = ( ((23*m)/9) + d + 4 + y + (y/4) - (y/100) + (y/400) - 2 ) % 7;
  2094. }
  2095. else
  2096. {
  2097. z = y-1;
  2098. jds = ( ((23*m)/9) + d + 4 + y + (z/4) - (z/100) + (z/400) ) % 7;
  2099. }
  2100. jour_de_la_semaine = jds;
  2101. }
  2102.  
  2103.  
  2104. String conv_time(uint8_t t)
  2105. {
  2106. String r;
  2107. r=String(t);
  2108. if (t<10) {r="0"+r;}
  2109. return r;
  2110. }
  2111.  
  2112.  
  2113. /*
  2114. RAPPEL :
  2115. tm.Day // uint8_t
  2116. tm.Month
  2117. tmYearToCalendar(tm.Year)
  2118. tm.Hour)
  2119. tm.Minute)
  2120. tm.Second)
  2121. */
  2122.  
  2123.  
  2124.  
  2125.  
  2126. void affiche_heure()
  2127. {
  2128. //Serial.println("affiche_heure()");
  2129.  
  2130. String heure;
  2131. String heure_sec;
  2132.  
  2133. if (RTC.read(tm))
  2134. {
  2135. annee_actuelle = tmYearToCalendar(tm.Year);
  2136. mois_actuel = tm.Month;
  2137. jour_actuel = tm.Day;
  2138. heure_actuelle = tm.Hour;
  2139. minute_actuelle = tm.Minute;
  2140. seconde_actuelle = tm.Second;
  2141. /*
  2142. Serial.print(" annee="); Serial.println(annee_actuelle);
  2143. Serial.print(" mois="); Serial.println(mois_actuel);
  2144. Serial.print(" jour="); Serial.println(jour_actuel);
  2145. Serial.print(" h="); Serial.println(heure_actuelle);
  2146. Serial.print(" mn=");Serial.println(minute_actuelle);
  2147. Serial.println("------");
  2148. */
  2149. heure = conv_time(tm.Hour)+":"+conv_time(tm.Minute);
  2150. heure_sec = heure+":"+conv_time(tm.Second)+" ";
  2151.  
  2152. TFT480.Set_Text_Size(4);
  2153. TFT480.Set_Text_Back_colour(NOIR);
  2154. TFT480.Set_Text_colour(BLANC);
  2155. TFT480.Print_String(heure_sec, 290, 105);
  2156.  
  2157. if (seconde_actuelle == 0){ tt_les_1mn(); }
  2158. if (((minute_actuelle %5) == 0) && (seconde_actuelle == 10)) { tt_les_5mn(); }
  2159. if (((minute_actuelle %30) == 0) && (seconde_actuelle == 20)) { tt_les_30mn();}
  2160. }
  2161. }
  2162.  
  2163.  
  2164. void affiche_date()
  2165. {
  2166. String date;
  2167. date = String(conv_time(jour_actuel))+" ";
  2168.  
  2169. switch (mois_actuel)
  2170. {
  2171. case 1: {date+="JAN"; } break;
  2172. case 2: {date+="FEV"; } break;
  2173. case 3: {date+="MARS";} break;
  2174. case 4: {date+="AVR"; } break;
  2175. case 5: {date+="MAI"; } break;
  2176. case 6: {date+="JUIN";} break;
  2177. case 7: {date+="JUIL";} break;
  2178. case 8: {date+="AOUT";} break;
  2179. case 9: {date+="SEPT";} break;
  2180. case 10: {date+="OCT"; } break;
  2181. case 11: {date+="NOV"; } break;
  2182. case 12: {date+="DEC"; } break;
  2183. }
  2184. date += " "+String(annee_actuelle);
  2185. //date;
  2186.  
  2187. uint16_t x0=290, y0=75;
  2188.  
  2189. TFT480.Set_Text_Size(2);
  2190. TFT480.Set_Text_Back_colour(NOIR);
  2191. TFT480.Set_Text_colour(GRIS_CLAIR);
  2192. TFT480.Print_String(date, x0+45, y0);
  2193.  
  2194. calcul_jour_de_la_semaine();
  2195.  
  2196.  
  2197. switch (jour_de_la_semaine)
  2198. {
  2199. case 0: { TFT480.Print_String("DIM", x0, y0);} break;
  2200. case 1: { TFT480.Print_String("LUN", x0, y0);} break;
  2201. case 2: { TFT480.Print_String("MAR", x0, y0);} break;
  2202. case 3: { TFT480.Print_String("MER", x0, y0);} break;
  2203. case 4: { TFT480.Print_String("JEU", x0, y0);} break;
  2204. case 5: { TFT480.Print_String("VEN", x0, y0);} break;
  2205. case 6: { TFT480.Print_String("SAM", x0, y0);} break;
  2206. }
  2207. }
  2208.  
  2209.  
  2210.  
  2211.  
  2212. void print_meteo_on_SDcard()
  2213. {
  2214. String date;
  2215. String heure;
  2216. String Str1;
  2217. // Led1.setCouleur(VERT);
  2218. // pour éviter les problèmes avec les températures en °C négatives (< 0°C l'hiver), on passe en kelvin
  2219. uint16_t T_EXT_kelvin = T_EXT_retenue +2730; // en prenant T0abs= -273°C (et pas -273,15 °C...)
  2220. uint16_t T_INTE_kelvin = T_INTE_lue +2730;
  2221.  
  2222. date = String(annee_actuelle)+"-"+conv_time(mois_actuel)+"-"+conv_time(jour_actuel);
  2223. heure = conv_time(heure_actuelle)+":"+conv_time(minute_actuelle);
  2224. Str1 = date +" [ "+ heure + " ]";
  2225.  
  2226. Str1 += " ; T(ext)=" + String(T_EXT_kelvin)+ " ; T(int)=" + String(T_INTE_kelvin);
  2227. Str1 +=" ; H=" +String(H_out_lue)+ " ; P=" +String(Pression_lue);
  2228.  
  2229. Serial.println(" ");
  2230. Serial.println("ecriture data sur SDcard :");
  2231. Serial.print(Str1); // sur le port USB, pour info, à lire avec un terminal série (CuteCom...)
  2232. Serial.println(" ");
  2233.  
  2234. File dataFile = SD.open("data.txt", FILE_WRITE); // ouVERTure du fichier en écriture
  2235. if (dataFile)
  2236. {
  2237. dataFile.println(Str1); // écriture 1 ligne à la fin du fichier "data.txt" sur la micro SDcard
  2238. dataFile.close(); // referme le fichier
  2239.  
  2240. // résultat sur la SDcard : ajout d'une ligne comme celle-ci :
  2241. // 2020-09-19 [ 15:17 ] ; T(ext)=3004 ; T(int)=3018 ; H=62 ; P=1003
  2242.  
  2243. //Note : pour lire les températures il faut retrancher 2730 puis /10
  2244. }
  2245. else { Serial.println("error opening data.txt");} // pour info
  2246. delay(100);
  2247. // Led1.setCouleur(NOIR);
  2248.  
  2249. nb_wr_SD++;
  2250.  
  2251. /*
  2252. TFT480.Set_Text_Size(1);
  2253. TFT480.Set_Text_Back_colour(NOIR);
  2254. TFT480.Set_Text_colour(BLANC);
  2255. TFT480.Print_Number_Int(nb_wr_SD,440,70,6,' ',10);
  2256. */
  2257. }
  2258.  
  2259.  
  2260. void write_scope_on_SDcard() // enregistre en binaire la courbe de T°C affichée sur le scope
  2261. {
  2262. todo_wr_scope_on_sd=0;
  2263. if (SDcardOk==0) {return;}
  2264. Serial.println("write_scope_on_SDcard()");
  2265. // enregistre le contenu du "scope" afin de le réafficher après une coupure de l'alimentation
  2266. // Led1.setCouleur(BLEU_CLAIR);
  2267.  
  2268. if(SD.exists("scope.dat")) {SD.remove("scope.dat");} // efface le fichier précédent s'il existe
  2269. File binFile1 = SD.open("scope.dat", FILE_WRITE); //re-création et ouverture du fichier binaire (vierge) en écriture
  2270. if (binFile1)
  2271. {
  2272. binFile1.write((const uint8_t *)&lst_records, sizeof(lst_records));
  2273. binFile1.close(); // referme le fichier
  2274. }
  2275. // Led1.setCouleur(NOIR);
  2276.  
  2277. }
  2278.  
  2279.  
  2280. void read_scope_on_SDcard()
  2281. {
  2282. if (SDcardOk==0) {return;}
  2283. Serial.println(" ");
  2284. Serial.println("lecture du fichier scope.dat sur SDcard");
  2285. Serial.println(" ");
  2286.  
  2287. File binFile1 = SD.open("scope.dat", FILE_READ); //ouverture du fichier en lecture
  2288. if (binFile1)
  2289. {
  2290. binFile1.read((uint8_t *)&lst_records, sizeof(lst_records));
  2291. binFile1.close(); // referme le fichier
  2292. }
  2293. }
  2294.  
  2295.  
  2296.  
  2297. void RAZ_data()
  2298. {
  2299. Serial.println(" "); Serial.println("RAZ_data()");
  2300. todo_init_record =0;
  2301.  
  2302. // TFT480.Set_Draw_color(NOIR);
  2303. // TFT480.Fill_Rectangle(19,146, 467,316);
  2304. Scope_1.efface_surface();
  2305.  
  2306. // Led3.setCouleur(NOIR);
  2307. TFT480.Set_Text_Back_colour(NOIR);
  2308. TFT480.Set_Text_colour(VIOLET);
  2309. TFT480.Set_Text_Size(3);
  2310. TFT480.Print_String("RAZ SCOPE DATA", 120, 250);
  2311. delay(1000);
  2312.  
  2313. Scope_1.efface_surface();
  2314.  
  2315. init_lst_records();
  2316. write_scope_on_SDcard();
  2317. read_scope_on_SDcard();
  2318. trace_sur_Scope();
  2319. }
  2320.  
  2321.  
  2322. void tt_les_1mn()
  2323. {
  2324. Serial.println("----------------------------") ;
  2325. Serial.print("tt_les_1mn() ") ;
  2326. Serial.print(heure_actuelle); Serial.print(":"); Serial.println(minute_actuelle);
  2327. Serial.print("acqui_valide=");Serial.println(acqui_valide);
  2328. // TT2=0;
  2329. // TT3+=1;
  2330. // TFT480.Set_Text_Size(1);
  2331. // TFT480.Print_Number_Int(TT3,390,15,3,' ',10);
  2332. num_acquisition=0;
  2333. calcul_confiance();
  2334. T_EXT_retenue = meilleure_valeur();
  2335.  
  2336. //determine_Tmin_Tmax();
  2337. fixe_Tmin_tmax();
  2338.  
  2339. calcul_Gradu_ech_T();
  2340. acqui_PressionTemperature();
  2341. affiche_meteo(); // dans les cadres du pannel, mais PAS dans le "scope"
  2342. if ((todo_init_record==1)&&(acqui_valide)) {RAZ_data();}
  2343. if (todo_wr_scope_on_sd==1) {write_scope_on_SDcard();}
  2344.  
  2345.  
  2346. //trace_sur_Scope(); // ne pas décommenter ! sauf pour test
  2347. }
  2348.  
  2349.  
  2350. void tt_les_5mn()
  2351. {
  2352. uint16_t x2;
  2353. uint16_t y2;
  2354.  
  2355. Serial.println("----------------------------") ;
  2356. Serial.print("tt_les_5mn() ");
  2357. Serial.print(heure_actuelle); Serial.print(":"); Serial.println(minute_actuelle);
  2358.  
  2359. //Led4.setCouleur(BLANC);
  2360. record_enr_actuel();
  2361. decale_enregistrements(n_record_max);
  2362. trace_sur_Scope();
  2363.  
  2364. affiche_date();
  2365.  
  2366. /*
  2367. TFT480.Set_Text_Back_colour(NOIR);
  2368. TFT480.Set_Text_colour(BLANC);
  2369. TFT480.Set_Text_Size(1);
  2370.  
  2371. x2 = 300;
  2372. y2 = 70;
  2373. TFT480.Print_String("WR SDcard", x2, y2);
  2374. TFT480.Print_Number_Int(10-TT3,x2+55,y2,3,' ',10); //affiche le temps restant avant enregistrement sur la SDcard
  2375. TFT480.Print_String("mn", x2+70, y2);
  2376. Led4.setCouleur(NOIR);
  2377. */
  2378. }
  2379.  
  2380.  
  2381. void tt_les_30mn()
  2382. {
  2383. Serial.println("----------------------------") ;
  2384. Serial.print("tt_les_30mn() ");
  2385. Serial.print(heure_actuelle); Serial.print(":"); Serial.println(minute_actuelle);
  2386.  
  2387. print_meteo_on_SDcard(); // en ASCII dans le fichier "data.txt" (ajout à la fin du fichier, en conservant la totalité des acquis)
  2388. delay(500);
  2389. write_scope_on_SDcard(); // en binaire dans le fichier "scope.dat" (remplace le fichier - ne mémorise que 36h au total)
  2390. delay(500);
  2391.  
  2392. affiche_Lune();
  2393.  
  2394. }
  2395.  
  2396.  
  2397.  
  2398. void loop()
  2399. {
  2400.  
  2401. memo_etat = etat;
  2402. etat = digitalRead(INPUT_PIN);
  2403. if (etat != memo_etat)
  2404. {
  2405. analyse_signal_primaire();
  2406. }
  2407.  
  2408. if ((portPIN_switch0 & pin_switch0) == 0)
  2409. {
  2410. write_TFT_on_SDcard();
  2411.  
  2412. /*
  2413. todo_init_record =1;
  2414. // Led3.setCouleur(ROUGE);
  2415. TFT480.Set_Text_Back_colour(NOIR);
  2416. TFT480.Set_Text_colour(BLANC);
  2417. TFT480.Set_Text_Size(2);
  2418. TFT480.Print_String("demande de RAZ scope.dat", 80, 150);
  2419. TFT480.Print_String("elle se fera sur la minute", 70, 170);
  2420. TFT480.Print_String("suivant acquisition valide", 70, 190);
  2421. Serial.println("demande de RAZ scope.dat");
  2422. while ((portPIN_switch0 & pin_switch0) == 0 ) {;} // attente relachement du bouton
  2423. delay(1000);
  2424. */
  2425. }
  2426.  
  2427. TT1+=1;
  2428. if (TT1 >= 1000) // tous les 1000 passages dans la boucle pour ne pas trop charger le processeur
  2429. {
  2430. TT1=0;
  2431.  
  2432. temps_ecoule = micros() - memo_micros2;
  2433. if (temps_ecoule >= 1E6) // (>=) et pas strictement égal (==) parce qu'alors on rate l'instant en question
  2434. // toutefois cette façon de procéder introduit une petite imprécision sur la chronologie des évenements de l'ordre de +1s/mn
  2435. // les enregistrement sur la SDcard restent toutefois datés exactement par le module RTC
  2436. // l'affichage sur le scope, lui, est un peu imprécis.
  2437. {
  2438. // ici toutes les 1s
  2439.  
  2440. memo_micros2 = micros();
  2441.  
  2442. //TT2+=1;
  2443. //TFT480.Set_Text_Back_colour(NOIR);
  2444. //TFT480.Set_Text_colour(BLANC);
  2445. //TFT480.Set_Text_Size(1);
  2446.  
  2447. //TFT480.Print_Number_Int(60-TT2,370,84,3,' ',10); // petits chiffres à droite ()chronomètre)
  2448. affiche_heure();
  2449. Led2.setCouleur(NOIR);
  2450. }
  2451. }
  2452. }
  2453.  
  2454.  
  2455.  
  2456.  
  2457.  
  2458. /** ***********************************************************************************
  2459. AFFICHAGE IMAGE.bmp
  2460. ***************************************************************************************/
  2461.  
  2462. /**
  2463. Rappel et décryptage de la fonction Color_To_565 : (elle se trouve dans le fichier LCDWIKI_KBV.cpp)
  2464.  
  2465. //Pass 8-bit (each) R,G,B, get back 16-bit packed color
  2466.  
  2467. uint16_t Color_To_565(uint8_t r, uint8_t g, uint8_t b)
  2468. {
  2469. return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
  2470. }
  2471.  
  2472. 0xF8 = 11111000
  2473. 0xFC = 11111100
  2474.  
  2475. (r & 0xF8) -> 5 bit de gauche de r (on ignore donc les 3 bits de poids faible)
  2476. (g & 0xFC) -> 6 bit de gauche de g (on ignore donc les 2 bits de poids faible)
  2477. (b & 0xF8) -> 5 bit de gauche de b (on ignore donc les 3 bits de poids faible)
  2478.  
  2479. rrrrr---
  2480. gggggg--
  2481. bbbbb---
  2482.  
  2483. après les décallages on obtient les 16 bits suivants:
  2484.  
  2485. rrrrr---========
  2486.   gggggg--===
  2487.   ===bbbbb
  2488.  
  2489. soit après le ou :
  2490.  
  2491. rrrrrggggggbbbbb
  2492.  
  2493. calcul de la Fonction inverse :
  2494. RGB565_to_888
  2495. **/
  2496.  
  2497.  
  2498.  
  2499.  
  2500. void RGB565_to_888(uint16_t color565, uint8_t *R, uint8_t *G, uint8_t *B)
  2501. {
  2502. *R=(color565 & 0xFFFFF800) >> 8;
  2503. *G=(color565 & 0x7E0) >> 3;
  2504. *B=(color565 & 0x1F) << 3 ;
  2505. }
  2506.  
  2507.  
  2508.  
  2509.  
  2510. uint32_t bmp_width;
  2511. uint32_t bmp_heigh;
  2512.  
  2513.  
  2514. uint16_t read_16(File fp)
  2515. {
  2516. uint8_t low;
  2517. uint16_t high;
  2518. low = fp.read();
  2519. high = fp.read();
  2520. return (high<<8)|low;
  2521. }
  2522.  
  2523.  
  2524.  
  2525. uint32_t read_32(File fp)
  2526. {
  2527. uint16_t low;
  2528. uint32_t high;
  2529. low = read_16(fp);
  2530. high = read_16(fp);
  2531. return (high<<8)|low;
  2532. }
  2533.  
  2534.  
  2535.  
  2536. void write_16(uint16_t v16, File fp)
  2537. {
  2538. uint8_t low, high;
  2539.  
  2540. low = v16 & 0xFF;
  2541. high= v16 >>8;
  2542.  
  2543. fp.write(low);
  2544. fp.write(high);
  2545. }
  2546.  
  2547.  
  2548. void write_32(uint32_t v32, File fp)
  2549. {
  2550. uint16_t low, high;
  2551.  
  2552. low = v32 & 0xFFFF;
  2553. high= v32 >>16;
  2554.  
  2555. write_16(low, fp);
  2556. write_16(high, fp);
  2557. }
  2558.  
  2559.  
  2560.  
  2561.  
  2562. bool teste_bmp_header(File fp)
  2563. {
  2564. if(read_16(fp) != 0x4D42) { return false; } // (2 bytes) The header field used to identify the BMP
  2565. read_32(fp); // (4 bytes) get bmp size (nombre total d'octets)
  2566. read_32(fp); // (4 bytes) get creator information
  2567. bmp_offset = read_32(fp); // (4 bytes) get offset information
  2568. read_32(fp);//get DIB information
  2569.  
  2570. bmp_width = read_32(fp); //get width and heigh information
  2571. bmp_heigh = read_32(fp);
  2572.  
  2573. if(read_16(fp)!= 1) {return false;}
  2574. read_16(fp);
  2575. if(read_32(fp)!= 0) {return false;}
  2576. return true;
  2577. }
  2578.  
  2579.  
  2580.  
  2581.  
  2582.  
  2583. void draw_bmp(uint16_t x0, uint16_t y0, File* fp)
  2584. {
  2585. //sram = freeRam(); Serial.print("03-freeRam="); Serial.println(sram);
  2586. uint16_t i,j,k,p,m=0;
  2587. uint8_t bmp_data[2*3]={0};
  2588. uint16_t bmp_color[2];
  2589.  
  2590. fp->seek(bmp_offset);
  2591. for(i=0; i<bmp_heigh; i++)
  2592. {
  2593. for(j=0; j<(bmp_width/2); j++)
  2594. {
  2595. m=0;
  2596. fp->read(bmp_data,2*3);
  2597. for(k=0; k<2; k++)
  2598. {
  2599. bmp_color[k]= TFT480.Color_To_565(bmp_data[m+2], bmp_data[m+1], bmp_data[m+0]);
  2600. m+=3;
  2601. }
  2602. for(p=0; p<2; p++)
  2603. {
  2604. TFT480.Set_Draw_color(bmp_color[p]);
  2605. TFT480.Draw_Pixel(y0+j*2+p, x0+i);
  2606. }
  2607. }
  2608. }
  2609. }
  2610.  
  2611.  
  2612.  
  2613.  
  2614. void affi_img(uint16_t x0, uint16_t y0, const char* filename1)
  2615. {
  2616.  
  2617. File bmp_file;
  2618.  
  2619. bmp_file = SD.open(filename1);
  2620. if(!bmp_file)
  2621. {
  2622. TFT480.Set_Text_Back_colour(NOIR);
  2623. TFT480.Set_Text_colour(BLANC);
  2624. TFT480.Set_Text_Size(2);
  2625. TFT480.Print_String("didnt find bmp",0,10);
  2626. delay(2000);
  2627. }
  2628. if(!teste_bmp_header(bmp_file))
  2629. {
  2630. TFT480.Set_Text_Back_colour(NOIR);
  2631. TFT480.Set_Text_colour(BLANC);
  2632. TFT480.Set_Text_Size(2);
  2633. TFT480.Print_String("bad bmp !",0,0);
  2634. delay(2000);
  2635. return;
  2636. }
  2637. draw_bmp(x0, y0, &bmp_file);
  2638.  
  2639. bmp_file.close();
  2640. // delay(1000);
  2641.  
  2642. }
  2643.  
  2644. /** ***********************************************************************************
  2645. CAPTURE D'ECRAN vers SDcard
  2646. ***************************************************************************************/
  2647.  
  2648.  
  2649.  
  2650. void write_TFT_on_SDcard() // enregistre
  2651. {
  2652. if (SDcardOk==0) {return;}
  2653. uint16_t x, y;
  2654. uint16_t color565;
  2655. uint16_t bmp_color;
  2656. uint8_t R, G, B;
  2657.  
  2658. if( ! SD.exists("/bmp/capture2.bmp")) {return;}
  2659. File File1 = SD.open("/bmp/capture2.bmp", FILE_WRITE); // ouverture du fichier binaire (vierge) en écriture
  2660. if (File1)
  2661. {
  2662. /*
  2663. Les images en couleurs réelles BMP888 utilisent 24 bits par pixel:
  2664. Il faut 3 octets pour coder chaque pixel, en respectant l'ordre de l'alternance bleu, vert et rouge.
  2665. */
  2666. uint16_t bmp_offset = 138;
  2667. File1.seek(bmp_offset);
  2668.  
  2669. TFT480.Set_Draw_color(NOIR);
  2670.  
  2671. TFT480.Set_Text_colour(BLANC);
  2672. TFT480.Set_Text_Size(1);
  2673. for (y=320; y>0; y--)
  2674. {
  2675. for (x=0; x<480; x++)
  2676. {
  2677. color565=TFT480.Read_Pixel(x, y);
  2678. RGB565_to_888(color565, &R, &G, &B);
  2679. File1.write(B); //G
  2680. File1.write(G); //R
  2681. File1.write(R); //B
  2682. }
  2683. TFT480.Print_Number_Int(y/10, 50, 300, 3, '0', 10); // affiche compte à rebour
  2684. }
  2685.  
  2686. File1.close(); // referme le fichier
  2687.  
  2688. TFT480.Fill_Rectangle(50, 300, 65, 310); // efface le compte à rebour
  2689. }
  2690.  
  2691. }
  2692.  
  2693.  
  2694.  
  2695. /** ***************************************************************************************
  2696. CLASS Etiq3 // affiche un nombre ou un petit texte dans un rectangle
  2697. ainsi que (en plus petit) deux valeurs supplémentaires, par ex: les valeurs mini et maxi
  2698. ********************************************************************************************/
  2699.  
  2700. // Constructeur
  2701. Etiq3::Etiq3()
  2702. {
  2703.  
  2704. }
  2705.  
  2706.  
  2707. void Etiq3::init(uint16_t xi, uint16_t yi, uint16_t dxi, uint16_t dyi, char nom_i[12])
  2708. {
  2709. x0 = xi;
  2710. y0 = yi;
  2711. dx = dxi;
  2712. dy = dyi;
  2713.  
  2714. for (int i=0; i<12; i++) {nom[i]=nom_i[i];}
  2715. nom[12]='\0'; // zero terminal
  2716.  
  2717. TFT480.Set_Text_Back_colour(0, 0, 0);
  2718. TFT480.Set_Text_colour(10, 10, 5);
  2719.  
  2720. traceCadre();
  2721. affi_nom();
  2722.  
  2723. }
  2724.  
  2725. void Etiq3::traceCadre()
  2726. {
  2727. TFT480.Set_Draw_color(couleur_cadre);
  2728. TFT480.Draw_Rectangle(x0, y0+5, x0+dx, y0+dy);
  2729. }
  2730.  
  2731.  
  2732. void Etiq3::efface()
  2733. {
  2734. TFT480.Set_Draw_color(couleur_fond);
  2735. TFT480.Fill_Rectangle(x0+1, y0+6, x0+dx-1, y0+dy-1);
  2736. affi_nom();
  2737. }
  2738.  
  2739.  
  2740. void Etiq3::affi_nom()
  2741. {
  2742. // sur le coin en haut à gauche
  2743. TFT480.Set_Text_Back_colour(couleur_fond);
  2744.  
  2745. TFT480.Set_Text_colour(couleur_nom);
  2746. TFT480.Set_Text_Size(2);
  2747. TFT480.Print_String(nom, x0, y0);
  2748. }
  2749.  
  2750.  
  2751. void Etiq3::setCouleurTxt(uint16_t couleur_i)
  2752. {
  2753. couleur_txt = couleur_i;
  2754. }
  2755.  
  2756.  
  2757. void Etiq3::setCouleurCadre(uint16_t couleur_i)
  2758. {
  2759. couleur_cadre = couleur_i;
  2760. }
  2761.  
  2762.  
  2763. void Etiq3::setCouleurFond(uint16_t couleur_i)
  2764. {
  2765. couleur_fond = couleur_i;
  2766. }
  2767.  
  2768.  
  2769. void Etiq3::setCouleurNom(uint16_t couleur_i)
  2770. {
  2771. couleur_nom = couleur_i;
  2772. }
  2773.  
  2774.  
  2775.  
  2776. void Etiq3::flashFond(uint16_t couleur_i)
  2777. {
  2778. couleur_fond = couleur_i;
  2779. TFT480.Set_Text_colour(couleur_fond);
  2780. TFT480.Fill_Rectangle(x0, y0, x0+dx, y0+dy);
  2781. delay(10);
  2782. TFT480.Set_Text_colour(NOIR);
  2783. TFT480.Fill_Rectangle(x0, y0, x0+dx, y0+dy);
  2784. traceCadre();
  2785. affi_nom();
  2786. }
  2787.  
  2788.  
  2789. void Etiq3::affiche_int(uint32_t valeur, uint8_t nb_chiffres, char txt_unite_i[3], uint32_t v_min, uint32_t v_max)
  2790. {
  2791. // 'valeur' sera afficée en gros, 'v_min' et 'v_max' en plus petit dans le coin du cadre (facultativement)
  2792. // pour ne pas afficher 'v_min' et 'v_max', il faut que toutes les deux soient ==0
  2793.  
  2794. uint16_t z;
  2795.  
  2796. for (int i=0; i<3; i++) {txt_unite[i]=txt_unite_i[i];}
  2797. txt_unite[3]='\0'; // zero terminal
  2798.  
  2799. efface(); // efface le contenu précédent
  2800.  
  2801. TFT480.Set_Text_Back_colour(NOIR);
  2802. TFT480.Set_Text_colour(couleur_txt);
  2803. TFT480.Set_Text_Size(4);
  2804.  
  2805. z=0; if ((valeur<1000)&&(valeur>100)) {z=20;}
  2806. TFT480.Print_Number_Int(valeur, x0+10+z, y0+18, nb_chiffres, ' ', 10);
  2807.  
  2808. TFT480.Set_Text_colour(couleur_txt);
  2809. TFT480.Set_Text_Size(2);
  2810. TFT480.Print_String(txt_unite, x0+140,y0+35); // ex : mm, kHz, etc...
  2811.  
  2812. if((v_min !=0 )&&(v_max !=0 ))
  2813. {
  2814. // affiche valeurs min et max en haut à droite
  2815. TFT480.Set_Text_colour(GRIS_CLAIR);
  2816. TFT480.Set_Text_Size(1);
  2817.  
  2818. z=0; if (v_max<1000) {z=5;}
  2819. TFT480.Print_Number_Int(v_max,x0+140+z,y0+9,3,' ',10);
  2820.  
  2821. z=0; if (v_min<1000) {z=5;}
  2822. TFT480.Print_Number_Int(v_min,x0+140+z,y0+17,3,' ',10);
  2823. }
  2824. }
  2825.  
  2826.  
  2827.  
  2828. void Etiq3::affiche_float(float valeur, uint8_t nb_chiffres, uint8_t nb_dec, char txt_unite_i[3], float v_min, float v_max)
  2829. {
  2830. for (int i=0; i<3; i++) {txt_unite[i]=txt_unite_i[i];}
  2831. txt_unite[3]='\0'; // zero terminal
  2832.  
  2833. efface(); // efface le contenu précédent
  2834.  
  2835. TFT480.Set_Text_Back_colour(NOIR);
  2836. TFT480.Set_Text_colour(couleur_txt);
  2837. TFT480.Set_Text_Size(4);
  2838.  
  2839. //RAPPEL: Print_Number_Float(double num, uint8_t dec, int16_t x, int16_t y, uint8_t divider, int16_t length, uint8_t filler);
  2840. TFT480.Print_Number_Float(valeur, nb_dec, x0+20, y0+18, '.', nb_chiffres, ' ');
  2841.  
  2842. TFT480.Set_Text_colour(couleur_txt);
  2843. TFT480.Set_Text_Size(2);
  2844. TFT480.Print_String(txt_unite, x0+140,y0+35); // ex : deg, hPa, mm, kHz ...
  2845.  
  2846.  
  2847. if((v_min !=0 )||(v_max !=0 ))
  2848. {
  2849. uint16_t z;
  2850.  
  2851. // affiche valeurs min et max en haut à droite
  2852. TFT480.Set_Text_Back_colour(NOIR);
  2853. TFT480.Set_Text_colour(GRIS_CLAIR);
  2854. TFT480.Set_Text_Size(1);
  2855.  
  2856. z=0; if (v_max<10) {z=6;}
  2857. TFT480.Print_Number_Float(v_max, 1, x0+140+z, y0+9, '.', 3, ' ');
  2858.  
  2859. z=0; if (v_min<10) {z=6;}
  2860. TFT480.Print_Number_Float(v_min, 1, x0+140+z, y0+17, '.', 3, ' ');
  2861. }
  2862. }
  2863.  
  2864.  
  2865.  
  2866.  
  2867. void Etiq3::affiche_HEXA(uint32_t valeur)
  2868. {
  2869. // affiche un nombre en representation hexadécimale
  2870. // 16 nb_signes hexa max
  2871.  
  2872. uint8_t r;
  2873. uint8_t i;
  2874.  
  2875. char tbl[9];
  2876. char signes[17] = "0123456789ABCDEF";
  2877.  
  2878. for (i=0; i<8; i++)
  2879. {
  2880. r= valeur % 16; // modulo (reste de la division)
  2881. valeur /= 16; // quotient
  2882. tbl[7-i]=signes[r];
  2883. };
  2884. tbl[8]='\0';
  2885.  
  2886. TFT480.Set_Text_Back_colour(NOIR);
  2887. TFT480.Set_Text_colour(CYAN);
  2888. // TFT480.setFont(SmallFont);
  2889. TFT480.Print_String(tbl, x0+10,y0+15);
  2890. }
  2891.  
  2892.  
  2893.  
  2894.  
  2895. void Etiq3::affiche_texte(char txt_i[10])
  2896. {
  2897. for (int i=0; i<10; i++) {texte[i]=txt_i[i];}
  2898. texte[10]='\0'; // zero terminal
  2899.  
  2900. TFT480.Set_Text_Back_colour(NOIR);
  2901. TFT480.Set_Text_colour(BLANC);
  2902. // TFT480.setFont(BigFont);
  2903. TFT480.Set_Text_Size(3);
  2904. TFT480.Print_String(texte, x0+5,y0+18);
  2905. }
  2906.  
  2907.  
  2908. void Etiq3::affiche_string(String txt_i)
  2909. {
  2910.  
  2911. TFT480.Set_Text_Back_colour(0, 0, 0);
  2912. TFT480.Set_Text_colour(BLANC);
  2913. // TFT480.setFont(BigFont);
  2914. TFT480.Set_Text_Size(3);
  2915. TFT480.Print_String(txt_i, x0+8,y0+18);
  2916. }
  2917.  
  2918.  
  2919.  
  2920. /** ***********************************************************************************
  2921. CLASS Scope // affiche des courbes dans une surface rectangulaire
  2922. ***************************************************************************************/
  2923.  
  2924. // Constructeur
  2925. Scope::Scope()
  2926. {
  2927.  
  2928. }
  2929.  
  2930.  
  2931. void Scope::init(uint16_t xi, uint16_t yi, uint16_t dxi, uint16_t dyi)
  2932. {
  2933. x0 = xi;
  2934. y0 = yi;
  2935. dx = dxi;
  2936. dy = dyi;
  2937.  
  2938. TFT480.Set_Draw_color(couleur_cadre);
  2939. TFT480.Draw_Rectangle(x0, y0, x0+dx, y0+dy);
  2940.  
  2941. }
  2942.  
  2943.  
  2944. void Scope::efface_surface()
  2945. {
  2946. Serial.println("Scope::efface_surface()");
  2947. TFT480.Set_Draw_color(NOIR);
  2948. TFT480.Fill_Rectangle(x0+1, y0+1, x0+dx-2, y0+dy-2);
  2949.  
  2950. // Rappel : Scope_1.init(18,145, 450,172);
  2951. // TFT480.Fill_Rectangle(19,146, 467,316); // ok
  2952.  
  2953. }
  2954.  
  2955.  
  2956. void Scope::setCouleurCadre(uint16_t couleur_i)
  2957. {
  2958. couleur_cadre = couleur_i;
  2959.  
  2960. }
  2961.  
  2962. void Scope::setCouleurTrace(uint16_t couleur_i)
  2963. {
  2964. couleur_trace = couleur_i;
  2965. }
  2966.  
  2967.  
  2968. void Scope::traceCadre()
  2969. {
  2970. TFT480.Set_Draw_color(couleur_cadre);
  2971. TFT480.Draw_Rectangle(x0, y0, x0+dx, y0+dy);
  2972. TFT480.Set_Draw_color(NOIR);
  2973. TFT480.Fill_Rectangle(x0+1, y0+1, x0+dx-2, y0+dy-2);
  2974.  
  2975. }
  2976.  
  2977.  
  2978. void Scope::efface_libel_gradu()
  2979. {
  2980. TFT480.Set_Draw_color(NOIR);
  2981. TFT480.Fill_Rectangle(x0-20, y0+1, x0-2, y0+dy-2);
  2982. }
  2983.  
  2984.  
  2985. void Scope::traceGraduation()
  2986. {
  2987. int16_t n, nombre;
  2988. float y1,Ti;
  2989. int16_t y2;
  2990. uint16_t xi;
  2991. uint16_t i;
  2992.  
  2993. efface_surface();
  2994. efface_libel_gradu();
  2995. setCouleurTrace(GRIS);
  2996.  
  2997. TFT480.Set_Text_Back_colour(NOIR);
  2998. TFT480.Set_Text_colour(JAUNE);
  2999. TFT480.Set_Text_Size(1);
  3000.  
  3001. for (n=gradu_minT; n<=gradu_maxT; n+=20) // 500->50°C
  3002. {
  3003. Ti = (float)n;
  3004. Serial.print("n=");
  3005. Serial.println(n);
  3006.  
  3007. //lignes horizontales :
  3008.  
  3009. y1 = Scope_1.dy/2.0 + (Ti-Tmoy) / echelle_T;
  3010.  
  3011. Tiret(1, (uint16_t)y1, dx-1, (uint16_t)y1); // trace la ligne horizontale
  3012. nombre = n/10;
  3013.  
  3014. y2 = y0+dy-3 -y1;
  3015. if (y2>(y0-5)&& // pour ne pas afficher plus haut que le haut du scope
  3016. (y2 <= (y0+dy-5)))// pour ne pas afficher trop bas (du cadre du scope et par conséquent du TFT))
  3017. {
  3018. TFT480.Print_Number_Int(nombre ,x0-15, y2, 3, ' ', 10); // graduation : petits chiffres à gauche
  3019. }
  3020.  
  3021. }
  3022.  
  3023.  
  3024. //lignes VERTicales :
  3025. i=0;
  3026. for (xi=450; xi>12; xi-=12) // 1 trait de graduation VERTical tous les 12 px
  3027. {
  3028. // s=0;
  3029. // if ( (i%12)==0) {s=10;} //pour un tiret de graduation +grand toutes les 12h
  3030. // if ( (i%24)==0) {s=40;}
  3031.  
  3032.  
  3033. /*
  3034. echelle_T horizontale (temporelle) :
  3035. 1 mesure(=1px)toutes les 5mn -> 450px*5 = 2250mn ;
  3036. 2250mn/60 =37.5h
  3037. 450px / 37.5h = 12px/h
  3038. */
  3039.  
  3040. // setCouleurTrace(GRIS_fonce); if ((i%12) == 0) {setCouleurTrace(GRIS_clair);}
  3041. // Tiret(xi-1, 20, xi-1, dy-2);
  3042.  
  3043. i++;
  3044. }
  3045.  
  3046. /*
  3047. TFT480.Set_Text_Size(1);
  3048. TFT480.Set_Text_colour(BLANC);
  3049. TFT480.Print_String("-12h", x0+300, y0+dy-10);
  3050. TFT480.Print_String("-24h", x0+156, y0+dy-10);
  3051. TFT480.Print_String("-36h", x0+12, y0+dy-10);
  3052.  
  3053.  
  3054. */
  3055.  
  3056.  
  3057. }
  3058.  
  3059.  
  3060. void Scope::Plot(uint16_t x, uint16_t y)
  3061. {
  3062. TFT480.Set_Draw_color(couleur_trace);
  3063. TFT480.Draw_Pixel(x0+x, y0+y);
  3064. }
  3065.  
  3066.  
  3067. void Scope::Cercle(uint16_t x1, uint16_t y1, uint16_t r1, uint16_t couleur_i)
  3068. {
  3069. if (x1>(dx-r1)) {return;} // pour ne pas déborder du cadre
  3070. TFT480.Set_Draw_color(couleur_i);
  3071. TFT480.Draw_Circle(x0+x1, y0+dy-y1, r1);
  3072. }
  3073.  
  3074.  
  3075.  
  3076. void Scope::Tiret(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
  3077. {
  3078. if (x1==0) {x1=1;}
  3079. if (x2==0) {x2=1;}
  3080.  
  3081. if (x1>=dx-1) {x1=dx-2;}
  3082. if (x2>=dx-1) {x2=dx-2;}
  3083.  
  3084. TFT480.Set_Draw_color(couleur_trace);
  3085. TFT480.Draw_Line(x0+x1, y0+dy-y1, x0+x2, y0+dy-y2);
  3086. }
  3087.  
  3088. /** ***********************************************************************************
  3089. CLASS LED // affiche une petite LED
  3090. ***************************************************************************************/
  3091.  
  3092. // Constructeur
  3093. LED::LED()
  3094. {
  3095.  
  3096. }
  3097.  
  3098.  
  3099. void LED::init(uint16_t xi, uint16_t yi, uint16_t dxi, uint16_t dyi)
  3100. {
  3101. x0 = xi;
  3102. y0 = yi;
  3103. dx = dxi;
  3104. dy = dyi;
  3105.  
  3106. TFT480.Set_Draw_color(BLANC);
  3107. TFT480.Draw_Rectangle(x0, y0, x0+dx, y0+dy);
  3108. TFT480.Set_Draw_color(0, 0, 0);
  3109. TFT480.Fill_Rectangle(x0+1, y0+1, x0+dx-1, y0+dy-1);
  3110. }
  3111.  
  3112.  
  3113. void LED::setCouleur(uint16_t couleur_i)
  3114. {
  3115. TFT480.Set_Draw_color(couleur_i);
  3116. TFT480.Fill_Rectangle(x0+1, y0+1, x0+dx-1, y0+dy-1);
  3117. }
  3118.  
  3119.  
  3120.  
  3121.  
  3122.  
  3123.  


5 Le fichier Station_meteo .h

CODE SOURCE en C++
  1.  
  2. #ifndef STATION_METEO_H
  3. #define STATION_METEO_H
  4.  
  5. #include <stdint.h>
  6. #include "Arduino.h"
  7.  
  8. #include <LCDWIKI_GUI.h> //Core graphics library
  9. #include <LCDWIKI_KBV.h> //Hardware-specific library
  10.  
  11. #include <Wire.h>
  12. #include <TimeLib.h>
  13. #include <DS1307RTC.h>
  14.  
  15. #include <SPI.h>
  16. #include <Adafruit_Sensor.h>
  17. #include <Adafruit_BMP280.h>
  18.  
  19. #include <SD.h>
  20.  
  21.  
  22.  
  23. //if the IC model is known or the modules is unreadable,you can use this constructed function
  24. LCDWIKI_KBV TFT480(ILI9486,A3,A2,A1,A0,A4); //model,cs,cd,wr,rd,reset
  25.  
  26. //if the IC model is not known and the modules is readable,you can use this constructed function
  27. //LCDWIKI_KBV TFT480(320,480,A3,A2,A1,A0,A4);//width,height,cs,cd,wr,rd,reset
  28.  
  29. /** ***********************************************************************************
  30. CLASS Etiq3 // affiche un nombre ou un petit texte dans un rectangle
  31. ***************************************************************************************/
  32.  
  33.  
  34.  
  35. class Etiq3
  36. {
  37. public:
  38.  
  39. uint16_t x0; //position
  40. uint16_t y0;
  41. uint16_t dx; //dimension
  42. uint16_t dy;
  43.  
  44. //couleurs
  45. uint16_t couleur_cadre;
  46. uint16_t couleur_fond;
  47. uint16_t couleur_nom;
  48. uint16_t couleur_txt;
  49.  
  50.  
  51. Etiq3();
  52.  
  53. void init(uint16_t x, uint16_t y, uint16_t dx, uint16_t dy,char nom[10]);
  54. void setCouleurCadre(uint16_t couleur_i);
  55. void setCouleurNom(uint16_t couleur_i);
  56. void setCouleurTxt(uint16_t couleur_i);
  57. void setCouleurFond(uint16_t couleur_i);
  58. void efface();
  59. void flashFond(uint16_t couleur_i);
  60. void affiche_int(uint32_t valeur, uint8_t nb_chiffres, char txt_unite_i[3], uint32_t v_min, uint32_t v_max);
  61. void affiche_float(float valeur, uint8_t nb_chiffres, uint8_t nb_dec, char txt_unite_i[3], float v_min, float v_max);
  62. void affiche_HEXA(uint32_t valeur);
  63. void affiche_texte(char txt_i[5]);
  64. void affiche_string(String txt_i);
  65.  
  66.  
  67. private:
  68. char nom[13];
  69. char txt_unite[4];
  70. char texte[11];
  71.  
  72. void traceCadre();
  73. void affi_nom();
  74.  
  75. };
  76.  
  77.  
  78. /** ***********************************************************************************
  79. CLASS Scope // affiche des courbes dans une surface rectangulaire
  80. ************************************************************************************* */
  81.  
  82. class Scope
  83. {
  84. public:
  85.  
  86. uint16_t x0; //position
  87. uint16_t y0;
  88. uint16_t dx; //dimension
  89. uint16_t dy;
  90.  
  91. //couleurs
  92. uint16_t couleur_trace;
  93. uint16_t couleur_cadre;
  94.  
  95. Scope();
  96.  
  97. void init(uint16_t x, uint16_t y, uint16_t dx, uint16_t dy);
  98. void setCouleurCadre(uint16_t couleur_i);
  99. void setCouleurTrace(uint16_t couleur_i);
  100. void traceCadre();
  101. void efface_surface();
  102. void efface_libel_gradu();
  103. void traceGraduation();
  104. void Plot(uint16_t x, uint16_t y);
  105. void Cercle(uint16_t x1, uint16_t y1, uint16_t r1, uint16_t couleur_i);
  106. void Tiret(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
  107.  
  108.  
  109. private:
  110.  
  111.  
  112. };
  113.  
  114.  
  115. class LED
  116. {
  117. public:
  118.