Code pour meteo sous forme wordclock

Bonsoir à tous,
Je réalise un affichage meteo sous forme d'un cadre avec leds et un écran 4 digits 7 segments. J'ai pris un ESP32 qui se connecte à internet, me géolocalise puis va chercher les infos météo de là où je suis. La température doit s'afficher sur les 4 digits 7 segments (4D7S), les autres infos ( force du vent, direction du vent et prévisions météo dans 3 heures) s'affichent via des leds.
J'ai fait le code. La compil est sans erreur MAIS le température ne s'affiche pas sur le 4D7S, les leds non plus. J'ai cherché et recherché mon erreur. Je ne trouve pas. J'ai demandé à chatGPT de m'aider mais pas de solutions proposées. Alors je me tourne vers l'intelligence pas artificielle !
Mon code ci-dessous. Merci à ceux qui pourront le regarder. Je parie qu'un oeil extérieur va tout de suite voir ce qui ne va pas.

t#include <WiFi.h>
#include <Adafruit_NeoPixel.h>
#include <WifiLocation.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <ArduinoOTA.h>
#include <WiFiMulti.h>
#include <SevSeg.h>


//Declaration 4D7S
SevSeg sevseg;


//Declaration bande leds
#define N_LEDS 60  //60 pour test, 67 au final.
#define RGBLEDPIN 26

Adafruit_NeoPixel strip(N_LEDS, RGBLEDPIN, NEO_GRB + NEO_KHZ800);

// Luminosite
int the_brightness_night = 5;
int the_brightness = 30;

WiFiMulti WiFiMulti;

//les acces
const char* googleApiKey = "AIzaSyCx10K3Hlso";
const char* openWeatherMapApiKey = "fcd77aa010f4df8";
const char* ssid = "Fr9221";
const char* passwd = "6x7hd";


//geolocalisation
WifiLocation location(googleApiKey);

struct tm timeinfo;

//parametrage heure
void setClock() {
  configTime(0, 0, "pool.ntp.org", "time.nist.gov");
  Serial.print("Waiting for NTP time sync: ");
  time_t now = time(nullptr);
  while (now < 8 * 3600 * 2) {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  gmtime_r(&now, &timeinfo);
  Serial.print("\n");
  Serial.print("Current time: ");
  Serial.print(asctime(&timeinfo));
}




void setup() {
  byte numDigits = 4;
  byte digitPins[] = { 13, 12, 14, 27 };
  byte segmentPins[] = { 15, 2, 4, 16, 17, 5, 18, 19 };
  bool resistorsOnSegments = false;
  byte hardwareConfig = COMMON_CATHODE;
  bool updateWithDelays = false;
  bool leadingZeros = false;
  bool disableDecPoint = false;

  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros, disableDecPoint);


  //Ok wifi
  Serial.begin(115200);
  WiFiMulti.addAP(ssid, passwd);

  while (WiFiMulti.run() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  //mise a l"heure
  setClock();


  ArduinoOTA.setHostname("MeteoLED");
  ArduinoOTA.begin();

  strip.begin();
  strip.show();

  strip.setBrightness(the_brightness);
}
void loop() {

  if ((timeinfo.tm_hour >= 21 || timeinfo.tm_hour < 7)) {
    strip.setBrightness(the_brightness_night);
  } else {
    strip.setBrightness(the_brightness);
  }

  location_t loc = location.getGeoFromWiFi();
  float latitude = loc.lat;
  float longitude = loc.lon;

  Serial.print("Lat:");
  Serial.println(latitude);
  Serial.print("lon:");
  Serial.println(longitude);

  String url = "http://api.openweathermap.org/data/2.5/forecast?lat=" + String(latitude) + "&lon=" + String(longitude) + "&appid=" + openWeatherMapApiKey + "&cnt=4";

  HTTPClient http;
  http.begin(url);
  int httpCode = http.GET();

  if (httpCode == HTTP_CODE_OK) {
    String payload = http.getString();
    DynamicJsonDocument doc(3072);
    deserializeJson(doc, payload);

    //recupération temperature et affichage sur 4D7S
    float temperatureKelvin = doc["list"][0]["main"]["feels_like"];
    float temperatureCelsius = temperatureKelvin - 273.1;  // Convertir en entier
    int temp_ress = round(temperatureCelsius);             // Obtenir la partie décimale
    Serial.print("Température ressentie: ");
    Serial.print(temp_ress);  // Afficher la partie entière
    Serial.println(" °C");
    Serial.println(temperatureCelsius, 1);

    sevseg.setNumber(temperatureCelsius, 1);  //
    sevseg.refreshDisplay();

    // recuperation conditions meteo dans 3 heures et affichage
    String description = doc["list"][1]["weather"][0]["description"].as<String>();
    Serial.print("Description : ");
    Serial.println(description);

    // code for setting LED colors based on weather and wind data)
    if (description == "clear sky") {          //ensoleillé
      strip.setPixelColor(60, 255, 255, 0);    //jaune
    } else if (description == "few clouds") {  //nuageux
      strip.setPixelColor(63, 240, 230, 140);
    } else if (description == "thunderstorm") {      //orage
      strip.setPixelColor(52, 248, 0, 211);          //violet
    } else if (description == "scattered clouds") {  // eclaircies
      strip.setPixelColor(62, 211, 211, 211);        //gris
    } else if (description == "rain") {              //pluie
      strip.setPixelColor(65, 220, 20, 60);          //rougeatre
    } else if (description == "shower rain") {       //grosse pluie
      strip.setPixelColor(66, 255, 69, 0);           //
    } else if (description == "broken clouds") {     //tres nuageux
      strip.setPixelColor(63, 255, 255, 255);
    } else if (description == "snow") {  //neige
      strip.setPixelColor(54, 255, 255, 255);
    } else if (description == "mist") {        //brouillard
      strip.setPixelColor(58, 220, 220, 220);  //gris clair
    }

    //recuperation vitesse vent et affichage

    float windSpeed = doc["list"][0]["wind"]["speed"];


    // Logique de couleur pour le vent
    if (windSpeed < 0.3) {  //calme
      for (int i = 0; i < 2; i++) {
        strip.setPixelColor(i, 255, 255, 255);
      }
      Serial.println("Calme");
    } else if (windSpeed >= 0.3 && windSpeed < 1.6) {  //force 1
      for (int i = 3; i < 7; i++) {
        strip.setPixelColor(i, 121, 248, 248);
      }
      Serial.println("Force 1");
    } else if (windSpeed >= 1.6 && windSpeed < 3.4) {  //force 2
      for (int i = 7; i < 11; i++) {
        strip.setPixelColor(i, 70, 225, 225);
      }
      Serial.println("Force 2");
    } else if (windSpeed >= 3.4 && windSpeed < 5.5) {  //force 3
      for (int i = 11; i < 15; i++) {
        strip.setPixelColor(i, 38, 196, 236);
      }
      Serial.println("Force 3");
    } else if (windSpeed >= 5.5 && windSpeed < 8.0) {  //force 4
      for (int i = 15; i < 19; i++) {
        strip.setPixelColor(i, 127, 255, 0);
      }
      Serial.println("Force 4");
    } else if (windSpeed >= 8.0 && windSpeed < 10.8) {  //force 5
      for (int i = 19; i < 24; i++) {
        strip.setPixelColor(i, 247, 255, 60);
      }
      Serial.println("Force 5");
    } else if (windSpeed >= 10.8 && windSpeed < 13.9) {  // force 6
      for (int i = 24; i < 27; i++) {
        strip.setPixelColor(i, 255, 255, 0);
      }
      Serial.println("Force 6");
    } else if (windSpeed >= 13.9 && windSpeed < 17.2) {  // force 7
      for (int i = 27; i < 31; i++) {
        strip.setPixelColor(i, 255, 215, 0);
      }
      Serial.println("Force 7");
    } else if (windSpeed >= 17.2 && windSpeed < 20.8) {  // force 8
      for (int i = 31; i < 35; i++) {
        strip.setPixelColor(i, 207, 10, 29);
      }
      Serial.println("Force 8");
    } else if (windSpeed >= 20.8 && windSpeed < 24.5) {  // force 9
      for (int i = 35; i < 40; i++) {
        strip.setPixelColor(i, 232, 0, 9);
      }
      Serial.println("Force 9");
    } else if (windSpeed >= 24.5 && windSpeed < 28.5) {  // force 10
      for (int i = 40; i < 43; i++) {
        strip.setPixelColor(i, 255, 9, 3);
      }
      Serial.println("Force 10");
    } else if (windSpeed >= 28.5 && windSpeed < 32.7) {  // force 11
      for (int i = 43; i < 48; i++) {
        strip.setPixelColor(i, 240, 0, 32);
      }
      Serial.println("Force 11");
    } else {  //force 12 et plus
      for (int i = 48; i < 51; i++) {
        strip.setPixelColor(i, 167, 19, 24);
      }
      Serial.println("Force 12 et plus");
      Serial.println("Vitesse en km/h");
      Serial.println(windSpeed * 3.6);
    }

    //recuperation direction du vent
    int windDirection = doc["list"][0]["wind"]["deg"];

    if ((windDirection >= 337.5 && windDirection <= 360) || (windDirection >= 0 && windDirection <= 22.5)) {
      strip.setPixelColor(56, 255, 255, 255);
      Serial.println("Nord");  //blanc
    } else if (windDirection > 22.5 && windDirection <= 67.5) {
      strip.setPixelColor(55, 0, 255, 255);  //bleu azur
      Serial.println("Nord-Est");
    } else if (windDirection > 67.5 && windDirection <= 112.5) {
      strip.setPixelColor(53, 0, 0, 255);  //bleue
      Serial.println("Est");
    } else if (windDirection > 112.5 && windDirection <= 157.5) {
      strip.setPixelColor(51, 0, 255, 0);  //vert
      Serial.println("Sud-Est");
    } else if (windDirection > 157.5 && windDirection <= 202.5) {
      strip.setPixelColor(64, 255, 255, 0);  //jaune
      Serial.println("Sud");
    } else if (windDirection > 202.5 && windDirection <= 247.5) {
      strip.setPixelColor(61, 255, 140, 0);  //orange
      Serial.println("Sud-Ouest");
    } else if (windDirection > 247.5 && windDirection <= 292.5) {
      strip.setPixelColor(59, 255, 0, 0);  //rouge
      Serial.println("Ouest");
    } else if (windDirection > 292.5 && windDirection <= 337.5) {
      strip.setPixelColor(57, 255, 0, 255);
      Serial.println("Nord-Ouest");  //magenta
    } else {
      Serial.println("Direction inconnue");
    }
  }



  strip.show();
  http.end();
  delay(60000 * 15);

  ArduinoOTA.handle();
}
ype or paste code here

Déjà, avais-tu essayé de faire fonctionner l'afficheur 4 digits et les LEDs séparément avec les programmes de test qui sont installés avec les librairies?

Bonsoir,
Oui j'ai testé le 4 digits avec SevSeg sur cet ESP32 et tout fonctionne bien. Idem pour les leds. C'est pourquoi je pense que mon soucis n'est pas matériel mais bien une erreur dans mon code ( je suis dans la catégorie débutant). erreur que je ne trouve pas. La compil se passe bien mais il doit y avoir un truc dans mon code...

d'après la documentation tu dois appeler refreshDisplay régulièrement, il devrait plutôt être au même niveau que ton strip.show.
De même pourquoi tu fais un delay de plus d'une minute?

Bonjour terwal,
J'avais essayé en positionnant le sevseg juste avant le strip.show, sans succès. Je vais réessayer en mettant en plus un delay de 1 mn.
J'avais mis 15 mn car je n'ai pas besoin d'une mise à jour de la météo toutes les minutes. Les 15 minutes étaient surtout pour les variations de la temperature et de la force du vent, les autres données changent pas aussi vite (une fois par heure me suffirait). Je donnerai le résultat de ce nouveau test. Merci encore.

Je ne sais pas si tu utilise cette librairie

Mais si c'est le cas la documentation indique bien que tu dois appeler la fonction à plusieurs reprise pour afficher un numéro.
C'est d'ailleurs bien ce que fait les exemples.

Si tu enlève ton delay le problème persiste ?
Si tu prends l'exemple testDisplay de la librairie que j'ai mis en lien, tu vois bien que la fonction est appelé avec une fréquence très élevée à chaque appel de la fonction loop et que l'animation par contre est appelée à intervalle moins fréquent(500ms dans l'exemple).

Attention, la suppression du delay() pour pouvoir rafraîchir le contenu de l'afficheur oblige à modifier la structure de loop(). Il faut limiter les accès à OpenWeatherMap car il y a une limite en nombre de requêtes par heure et par jour. Il faut donc supprimer les delay() dans la boucle et utiliser millis() pour activer périodiquement l'appel à OpenWeatherMap.
De même, les lignes suivantes ne devraient apparaître que dans le setup(), il me semble. Il n'y a, à priori, aucune raison de rechercher la position à chaque appel à OpenWeatherMap.

  location_t loc = location.getGeoFromWiFi();
  float latitude = loc.lat;
  float longitude = loc.lon;

  Serial.print("Lat:");
  Serial.println(latitude);
  Serial.print("lon:");
  Serial.println(longitude);

oui la suppression n'est que pour vérifier l'origine du problème, il faut prendre exemple sur l'exemple de la librairie qui montre comment utiliser la fonction millis simplement en remplacement du delay.

Il est effectivement pas nécessaire de relancer la géolocalisation donc je l'ai déplacé dans le setup.
En faisant une mise à jour toutes les 15 mn je suis dans les tolérances de Openweathermap d'où ce délai. Si besoin, je ne ferai des mises à jour que de 6h à 23h par exemple.
Suis je obligé de passer par millis(), je pensais qu'avec un delay de 15 mn le loop ne se ferait que toutes les 15 mn, ce qui me suffit en fréquence de récupération des données. Je vais faire de nouveaux tests cet après midi.

Non tu n'ai pas obligé, mais tu ne pourra rien faire d'autre pendant ce temps.
Et si on en croit la documentation de ta librairie, elle veut que tu appel testDisplay très régulièrement, donc pendant c'est fameux 15 minutes.

un autre test que tu peux faire, c'est désactiver l'appel à openweathermap et enlever ton delay.
Que se passe t-il alors ?

La récupération des données c'est une chose et l'affichage en est une autre.
L'affichage est multiplexé, il n'y a pas d'intelligence dans l'afficheur. Il faut donc balayer constamment les digits afin de les allumer à tour de role et très rapidement pour ne pas avoir de clignotement des caractères.
Pour donner un ordre d'idée, il faut les balayer au minimum 25 fois par seconde pour avoir un affichage stable visuellement, 50 fois étant souhaitable pour un plus grand confort visuel.

Le temps d'accès internet étant relativement long, il n'est pas impossible que tu ais un papillotement (voir une extinction) de l'affichage lorsque tu entreras dans la fonction de récupération des informations météorologiques. il faudra peut-être bricoler quelque chose de ce coté lorsque l'affichage fonctionnera.

Donc oui, millis() est indispensable pour gérer la demande périodique d'info météo tout en maintenant un affichage correct.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.