Jauge Alertes (MD80, X-Plane 11, Arduino)

Avro

PILOTE DE LIGNE
Messages
1 870
Réactions
267
Points
301
Bonjour à tous,

J’ai une nouvelle jauge à vous montrer aujourd’hui qui utilise un écran à encre électronique.

IMG_20210905_181706.jpg


J’ai pris un écran LILYGO – e-papier T5-4.7 pouces équipé en standard d’une carte ESP32 V3 version 16 mo FLASH 8 mo PSRAM WIFI/Bluetooth pour Arduino. Tout pour faire fonctionner de manière indépendante l’écran. Il lui suffira d’une prise USB pour implanter le programme et en utilisation courante d’une simple alimentation 5v (Consommation uniquement lors des changements d'état). L’avantage de ces cartes Arduino étant de ne nécessiter aucun port USB une fois passée l'étape d'initialisation puisque l'on passe par la WiFi.

Pour rappel, j’ai déjà réalisé une jauge fuel à base d’un écran OLED 1.5 pouces de 128x128 pixels associé là aussi à une carte ESP32 :
https://www.flightpilote.fr/threads/jauge-fuel-qantity-rj85.3878/#post-79361

Voici le code de l'Arduino adapté de la jauge fuel (merci à @HB-EBC pour les excellents conseils) :

C-like:
#ifndef BOARD_HAS_PSRAM
#error "Please enable PSRAM !!!"
#endif

#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include "epd_driver.h"
#include "open24b.h"
#include "firasans.h"
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

//Ecran  *************************************************************************/
#define BATT_PIN            36
#define SD_MISO             12
#define SD_MOSI             13
#define SD_SCLK             14
#define SD_CS               15

//Variables **********************************************************************/
uint8_t *framebuffer;

Rect_t area = {
    .x = 100,
    .y = 160,
    .width = 300,
    .height = 60,
};

int cursor_x = 100;
int cursor_y = 100;

char  wifinet[25] = "WiFi: ";

// -------------------- VERSION 1.0.0 --------------------------------------------/


//Wifi  **************************************************************************/
const char* host     = "esp32AlertMessages";
const char* ssid = "Votre_SSID";
const char* password = "Le_Mot_De_Passe_De_Votre_SSID";

// config static IP
IPAddress ip(192, 168, 1, 501); // Remplacer les XXX pour faire correspondre à l'adresse IP que vous voulez donner au système
IPAddress gateway(192, 168, 1, 1); // Remplacer les XXX pour faire correspondre à l'adresse IP de la passerelle de votre reseau (generalement l'adresse IP de votre Box internet).
IPAddress subnet(255, 255, 255, 0); // le sous reseau (generalement pas besoin d'y toucher
IPAddress serveriocp(192, 168, 1, 20); // Remplacer les XXX pour faire correspondre à l'adresse IP du PC sur lequel est exécuté SIOC
IPAddress myDns1(1, 1, 1, 1);
IPAddress myDns2(8, 8, 8, 8);

//WebServer server(80);
WiFiClient client;
//int status = WL_IDLE_STATUS;
//byte mac[6];

//IOCP  **************************************************************************/
char line[64];

String stringVariable;
String stringNumVariable;
//bool debug = false;

float Variable[1500];

bool ConnectionIOCP = false;
int VariablesIn[] = {204,205,206,207,208,209,210,201,202,203}; // les variables SIOC écoutées
const int NbVariablesIn = (sizeof(VariablesIn) / sizeof(VariablesIn[0]));
  
// variables
int parkingBrakes = 0, BPB = 9;
int yawDamper = 0, BYD = 9;
int pitot = 0, BP = 9;
int EmerLight = 0, BEL = 9;
int Lgen = 0, BLG = 9;
int Rgen = 0, BRG = 9;
int antiSkid = 0, BAS = 9;
long lmain = 0;
long rmain = 0;
long ctr = 0;
int j = 0;
int Almain = 0, Armain = 0, Actr = 0;
int BAlmain = 0, BArmain = 0, BActr = 0;

//SETUP  **************************************************************************/
void setup()
{ 
    Serial.begin(115200);


    SPI.begin(SD_SCLK, SD_MISO, SD_MOSI);
    epd_init();


    framebuffer = (uint8_t *)ps_calloc(sizeof(uint8_t), EPD_WIDTH * EPD_HEIGHT / 2);
    if (!framebuffer) {
        writeln((GFXfont *)&FiraSans, "alloc memory failed !!!", &cursor_x, &cursor_y, NULL);
        while (1);
    }
    memset(framebuffer, 0xFF, EPD_WIDTH * EPD_HEIGHT / 2);


    epd_poweron();
    epd_clear();


    WiFi.mode(WIFI_STA);
    if (!WiFi.config(ip, gateway, subnet, myDns1, myDns2)) {
      writeln((GFXfont *)&FiraSans, "STA Failed to configure", &cursor_x, &cursor_y, NULL);
    }
 
    // Connect to WiFi network
    WiFi.begin(ssid, password);
    while (WiFi.waitForConnectResult() != WL_CONNECTED) {
      writeln((GFXfont *)&FiraSans, "Connection Failed! Rebooting...", &cursor_x, &cursor_y, NULL);
      delay(5000);
      ESP.restart();
    }


    strcat(wifinet, ssid); // concaténation de chaine
    writeln((GFXfont *)&FiraSans, wifinet, &cursor_x, &cursor_y, NULL);


    ArduinoOTA.onStart([]() {
      String type;
      if (ArduinoOTA.getCommand() == U_FLASH) {
        type = "sketch";
      } else { // U_SPIFFS
        type = "filesystem";
      }
      
      // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
      cursor_x = 100;
      cursor_y = 200;
      writeln((GFXfont *)&FiraSans, "Start updating ", &cursor_x, &cursor_y, NULL);
    });
    
    ArduinoOTA.onEnd([]() {
      //Serial.println("\nEnd");
    });
    ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
      Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    });
    ArduinoOTA.onError([](ota_error_t error) {
      Serial.printf("Error[%u]: ", error);
      cursor_x = 100;
      cursor_y = 200;
      if (error == OTA_AUTH_ERROR) {
        writeln((GFXfont *)&FiraSans, "Auth Failed", &cursor_x, &cursor_y, NULL);
      } else if (error == OTA_BEGIN_ERROR) {
        writeln((GFXfont *)&FiraSans, "Begin Failed", &cursor_x, &cursor_y, NULL);
      } else if (error == OTA_CONNECT_ERROR) {
        writeln((GFXfont *)&FiraSans, "Connect Failed", &cursor_x, &cursor_y, NULL);
      } else if (error == OTA_RECEIVE_ERROR) {
        writeln((GFXfont *)&FiraSans, "Receive Failed", &cursor_x, &cursor_y, NULL);
      } else if (error == OTA_END_ERROR) {
        writeln((GFXfont *)&FiraSans, "End Failed", &cursor_x, &cursor_y, NULL);
      }
    });
    ArduinoOTA.begin();


    cursor_x = 100;
    cursor_y = 200;
    writeln((GFXfont *)&FiraSans, "Waiting IOCP", &cursor_x, &cursor_y, NULL);
    
    ArduinoOTA.handle();
    while (!ConnectionIOCP) {
      cursor_x = 100;
      cursor_y = 200;
 
      ArduinoOTA.handle();
      // if you get a connection, report back via serial:
      if (client.connect(serveriocp, 8092)) {
        ConnectionIOCP = true;
         client.print("Arn.Inicio:");
      for (int i = 0; i < NbVariablesIn; i++) {
        sprintf(line, "%d:", VariablesIn[i]);
        client.print(line);
      }


      client.println("");
        epd_clear_area_cycles(area, 3, 100);
        writeln((GFXfont *)&FiraSans, "IOCP connected", &cursor_x, &cursor_y, NULL);
      } else {
        ConnectionIOCP = false;
        // if you didn't get a connection to the server:
         cursor_x = 100;
         cursor_y = 300;
         writeln((GFXfont *)&FiraSans, "connection to IOCP server failed", &cursor_x, &cursor_y, NULL);
      }
    }
    
    //epd_fill_rect(0, 0, 200, 200, 255, framebuffer);
    //epd_write_line(0, 0, 500, 500, 0, framebuffer);
    //epd_push_pixels(area, 10, 255);
    //epd_clear_area_cycles(area, 20, 10);
    //epd_draw_circle(300, 300, 200, 0, framebuffer);


    //epd_poweroff();


}


void loop()
{
    ArduinoOTA.handle();
    TaskRead();
    // lecture des variables
    yawDamper     = Variable[VariablesIn[0]];
    parkingBrakes = Variable[VariablesIn[1]];
    pitot         = Variable[VariablesIn[2]];
    EmerLight     = Variable[VariablesIn[3]];
    Lgen          = Variable[VariablesIn[4]];
    Rgen          = Variable[VariablesIn[5]];
    antiSkid      = Variable[VariablesIn[6]];
    lmain         = round(Variable[VariablesIn[7]]*4255); // 4255 nombre de kg de kero
    rmain         = round(Variable[VariablesIn[8]]*4255);
    ctr           = round(Variable[VariablesIn[9]]*9238);


    if (lmain < 9) {
      Almain = 1;
    }
    if (rmain < 9) {
      Armain = 1;
    }
    if (ctr < 15) {
      Actr = 1;
    }
    if (lmain < 1) {
      Almain = 2;
    }
    if (rmain < 1) {
      Armain = 2;
    }
    if (ctr < 1) {
      Actr = 2;
    }
    
    if (parkingBrakes != BPB || yawDamper != BYD || pitot != BP || BAlmain != Almain || BArmain != Armain || BActr != Actr || antiSkid != BAS || Lgen != BLG || Rgen != BRG || EmerLight != BEL ) {
      char *texte[] = {"","","","","","","","","","",""};
      j = 0;
      if (parkingBrakes == 32767) {
        texte[j] = "FLT RECORDER OFF";
        j = j +1;
        texte[j] = "PARKING BRAKES ON";
        j = j +1;
      }
      if (yawDamper == 0) {
        texte[j] = "YAW DAMPER OFF";
        j = j +1;
      }
      if (pitot == 0) {
        texte[j] = "PITOT/STALL HEAT OFF";
        j = j +1;
      }
      if (Almain == 1) {
        texte[j] = "INLET FUEL PRES LOW";
        j = j +1;
      }
      if (Armain == 1) {
        texte[j] = "INLET FUEL PRES LOW";
        j = j +1;
      }
      if (Actr == 1) {
        texte[j] = "CTR FUEL PRE LOW";
        j = j +1;
      }
      if (antiSkid == 0) {
        texte[j] = "L INBD ANTI SKID";
        j = j +1;
        texte[j] = "R INBD ANTI SKID";
        j = j +1;
        texte[j] = "L OUTBD ANTI SKID";
        j = j +1;
        texte[j] = "R OUTBD ANTI SKID";
        j = j +1;
      }
      if (EmerLight == 0) {
        texte[j] = "EMER LIGHT NOT ARMED";
        j = j +1;
      }
      if (Lgen == 0) {
        texte[j] = "L GEN OFF";
        j = j +1;
      }
      if (Rgen == 0) {
        texte[j] = "BATTERY CHARGER";
        j = j +1;
        texte[j] = "R GEN OFF";
        j = j +1;
      }


      // Valeurs courantes
      BPB = parkingBrakes;
      BYD = yawDamper;
      BP  = pitot;
      BAlmain = Almain;
      BArmain = Armain;
      BActr   = Actr;
      BAS     = antiSkid;
      BLG     = Lgen;
      BRG     = Rgen;
      BEL     = EmerLight;


      // Afficher les messages
      epd_clear();
      cursor_x = 0;
      cursor_y = 47;
      writeln((GFXfont *)&OpenSans24B, texte[0], &cursor_x, &cursor_y, NULL);
      cursor_x = 0;
      cursor_y = cursor_y + 61;
      writeln((GFXfont *)&OpenSans24B, texte[1], &cursor_x, &cursor_y, NULL);
      cursor_x = 0;
      cursor_y = cursor_y + 61;
      writeln((GFXfont *)&OpenSans24B, texte[2], &cursor_x, &cursor_y, NULL);
      cursor_x = 0;
      cursor_y = cursor_y + 61;
      writeln((GFXfont *)&OpenSans24B, texte[3], &cursor_x, &cursor_y, NULL);
      cursor_x = 0;
      cursor_y = cursor_y + 61;
      writeln((GFXfont *)&OpenSans24B, texte[4], &cursor_x, &cursor_y, NULL);
      cursor_x = 0;
      cursor_y = cursor_y + 61;
      writeln((GFXfont *)&OpenSans24B, texte[5], &cursor_x, &cursor_y, NULL);
      cursor_x = 0;
      cursor_y = cursor_y + 61;
      writeln((GFXfont *)&OpenSans24B, texte[6], &cursor_x, &cursor_y, NULL);
      cursor_x = 0;
      cursor_y = cursor_y + 61;
      writeln((GFXfont *)&OpenSans24B, texte[7], &cursor_x, &cursor_y, NULL);
      cursor_x = 0;
      cursor_y = cursor_y + 61;
      writeln((GFXfont *)&OpenSans24B, texte[8], &cursor_x, &cursor_y, NULL);
      cursor_x = 0;
      cursor_y = cursor_y + 61;
      writeln((GFXfont *)&OpenSans24B, texte[9], &cursor_x, &cursor_y, NULL);

    }

    epd_poweroff_all();

}

//Fonctions  *********************************************************************/
void TaskRead()  // This is a task.
{
  int NumVariable;
  double VarTemp;
  cursor_x = 100;
  cursor_y = 200;
  // if there are incoming bytes available
  // from the server, read them and print them:
  if (client)
  {
    String header = "";
    while (client.connected())
    {
      ArduinoOTA.handle();

      if (client.available())
      {


        char c = client.read();
        header += c;
                
        if (c == '\n')
        {         
          if (header.indexOf("Resp:") >= 0)
          {
            cursor_x = 200;
            cursor_y = 400;
            //writeln((GFXfont *)&OpenSans24B, "Yes", &cursor_x, &cursor_y, NULL);
            
            int NextEgalPos = 0;
            int Next2PointPos = 0;
            NextEgalPos = header.indexOf("=", NextEgalPos);
            Next2PointPos = header.indexOf(":", Next2PointPos);


            
            while ((Next2PointPos > 0) and (NextEgalPos > 0 ))
            {
              stringNumVariable = header.substring(Next2PointPos + 1, NextEgalPos);
              NumVariable = stringNumVariable.toInt();
              Next2PointPos = header.indexOf(":", Next2PointPos + 1);
              if (Next2PointPos <= 0) stringVariable = header.substring(NextEgalPos + 1, header.length());
              else stringVariable = header.substring(NextEgalPos + 1, Next2PointPos);
              VarTemp = stringVariable.toInt();
              Variable[NumVariable] = VarTemp;
              NextEgalPos = header.indexOf("=", NextEgalPos + 1);
            }
            break;
          }
          else if (header.indexOf("Vivo:") >= 0)
          {
            //cursor_x = 0;
            //cursor_y = 400;
            //writeln((GFXfont *)&OpenSans24B, "Echec", &cursor_x, &cursor_y, NULL);
            break;
          }
        }
      }
    }
    header = "";
  }
  else
  {
    ConnectionIOCP = false;
    while (!ConnectionIOCP) {
      cursor_x = 100;
      cursor_y = 200;
 
      ArduinoOTA.handle();
      // if you get a connection, report back via serial:
      if (client.connect(serveriocp, 8092)) {
        ConnectionIOCP = true;
         client.print("Arn.Inicio:");
      for (int i = 0; i < NbVariablesIn; i++) {
        sprintf(line, "%d:", VariablesIn[i]);
        client.print(line);
        Serial.print(line);
      }


      client.println("");
        //epd_clear_area_cycles(area, 3, 100);
        //writeln((GFXfont *)&FiraSans, "IOCP connected", &cursor_x, &cursor_y, NULL);
      } else {
        ConnectionIOCP = false;
        // if you didn't get a connection to the server:
         cursor_x = 100;
         cursor_y = 300;
         writeln((GFXfont *)&FiraSans, "connection to IOCP server failed", &cursor_x, &cursor_y, NULL);
      }
    }
  }
}

Les offset pour gérer ces alertes ne sont tous implémentés en standard par XPUIPC. Par conséquent, j’ai utilisé des offsets libres à partir 0x66C0. Pour pouvoir les utiliser sous SIOC, il faut ajouter des lignes au fichier : \\SIMULATEUR\X-Plane 11\Resources\plugins\XPUIPC \XPUIPCOffsets.cfg


Code:
# Emergency Lights (offsets libres 66C0-66FF)
Dataref EmergLightRotate/md80/systems/emergency_lights_switchint
Offset0x66C0UINT81r$EmergLight

# Electrical Generators
Dataref LGenRotate/md80/electrical/generator_switch_0int
Offset0x66C1UINT81r$LGen
Dataref RGenRotate/md80/electrical/generator_switch_1int
Offset0x66C2UINT81r$RGen

# Anti skid
Dataref antiSkid Rotate/md80/hydraulic/anti_skid_arm int
Offset0x66C7UINT81r$antiSkid

Dans SIOC, j'ai ajouté 4 variables :

Code:
Var 0207, name ERMERGL, Link FSUIPC_IN, Offset $66C0, Length 1
Var 0208, name LGEN, Link FSUIPC_IN, Offset $66C1, Length 1
Var 0209, name RGEN, Link FSUIPC_IN, Offset $66C2, Length 1
Var 0210, name antiSkid, Link FSUIPC_IN, Offset $66C7, Length 1

Testé sous X-Plane 11 pour le MD88 Rotate avec XPUIPC.

Alertes.jpg
 
Retour
Haut