2 galva analogique sur tft : trigonométrie/math spécialiste ?

Bonjour,

en partant du magnifique travail de bodmer analog tft instructables
je voulais ajouter un 2eme galva sous le premier : étant nul en maths et trigo, j’aurais besoin de beaucoup d’aide…
je reconnais que c’est assez difficile à expliquer
j’ai recopié la fonction “analogmeter” qui dessine l’échelle et le fond du galva en changeant une seule coordonnée Y, puis l’autre fonction d’affichage aiguille avec nouvelle valeur “plotNeedle”

  1. l’aiguille ne s’efface pas apres une nouvelle valeur dans aucun des 2 galva
  2. a chaque updateTime chaque galva affiche d’abord la valeur qui ne lui est pas destiné puis ensuite la valeur adéquate

croquis

les fonctions digitalMeter et showDigital ne sont plus utilisées pour ce croquis

si vous avez des questions/remarques
Merci pour toute aide

le code

/*
 *   l'échelle se trouve bien à l'endroit 2eme galva 
 *   l'aiguille rouge ne s'efface pas les instructions ecrire du blanc sur le tft se font au mauvais endroit
 *   seond pblme : chaque galva lit les 2 variables temp et hum a chaque updatetime
  */

  // These are the connections for the UNO to display
#define sclk 13  // Don't change
#define mosi 11  // Don't change
#define cs   10  // If cs and dc pin allocations are changed then 
#define dc   9   // comment out #define F_AS_T line in "Adafruit_ILI9341_FAST.h"
                 // (which is inside "Adafriit_ILI9341_AS" library)

#define rst  8  // Can alternatively connect this to the Arduino reset
#include <DHT.h>
#include <Adafruit_GFX_AS.h>     // Core graphics library
#include <Adafruit_ILI9341_AS.h> // Fast hardware-specific library
#include <SPI.h>

#define ILI9341_GREY 0x5AEB
DHT DHT_sens(7, DHT22);
Adafruit_ILI9341_AS tft = Adafruit_ILI9341_AS(cs, dc, rst); // Invoke custom library

float ltx = 0;    // Saved x coord of bottom of needle
uint16_t osx = 120, osy = 120; // Saved x & y coords
uint32_t updateTime = 0;       // time for next update
float p; 
int h;
int old_analog =  -999; // Value last displayed
int old_digital = -999; // Value last displayed

void setup(void) {
  tft.init();
  tft.setRotation(2);
  tft.fillScreen(ILI9341_BLACK);
  DHT_sens.begin();
  analogMeter(); // Draw analogue meter
  //digitalMeter(); // Draw digital meter
  analogMeter1();
  updateTime = millis(); // Next update time
}

void loop() {
  if (updateTime <= millis()) {
    updateTime = millis() + 500;

    p= (round(DHT_sens.readTemperature()*10)/10);
    h= int(DHT_sens.readHumidity());
    //showDigital(p); // Update digital reading
    
    plotNeedle(h, 8); // Update analogue meter, 8ms delay per needle increment
    plotNeedle_1(p, 8);
  }
}

les fonctions : je ne peux pas envoyer le code complet

// fonction dessin echelle + fond bottom
void analogMeter()
{

// deuxieme galva en dessous contour+fond
  tft.fillRect(0, 185, 239, 311, ILI9341_GREY);
  tft.fillRect(5, 188, 230, 304, ILI9341_WHITE);
  
  tft.setTextColor(ILI9341_BLACK);  // Text colour
  
  // Draw ticks every 5 degrees from -50 to +50 degrees (100 deg. FSD swing)
  for (int i = -50; i < 51; i += 5) {
    // Long scale tick length
    int tl = 15;
    
    // Coodinates des graduations
    float sx = cos((i - 90) * 0.0174532925);
    float sy = sin((i - 90) * 0.0174532925);
    uint16_t x0 = sx * (100 + tl) + 120;
    uint16_t y0 = sy * (100 + tl) + 320;
    uint16_t x1 = sx * 100 + 120;
    uint16_t y1 = sy * 100 + 320;
    
    // Coordinates of next tick for zone fill
    float sx2 = cos((i + 5 - 90) * 0.0174532925);
    float sy2 = sin((i + 5 - 90) * 0.0174532925);
    int x2 = sx2 * (100 + tl) + 120;
    int y2 = sy2 * (100 + tl) + 320;
    int x3 = sx2 * 100 + 120;
    int y3 = sy2 * 100 + 320;


    // CYAN zone limits
    if (i >= -50 && i < -10) {
      tft.fillTriangle(x0, y0, x1, y1, x2, y2, ILI9341_CYAN);
     tft.fillTriangle(x1, y1, x2, y2, x3, y3, ILI9341_CYAN);
    }
    
    // Green zone limits
    if (i >= -10 && i < 25) {
      tft.fillTriangle(x0, y0, x1, y1, x2, y2, ILI9341_GREEN);
      tft.fillTriangle(x1, y1, x2, y2, x3, y3, ILI9341_GREEN);
    }

    // Orange zone limits
    if (i >= 25 && i < 50) {
      tft.fillTriangle(x0, y0, x1, y1, x2, y2, ILI9341_ORANGE);
      tft.fillTriangle(x1, y1, x2, y2, x3, y3, ILI9341_ORANGE);
    }
    
    // Short scale tick length
    if (i % 25 != 0) tl = 8;
    
    // Recalculate coords incase tick lenght changed
    x0 = sx * (100 + tl) + 120;
    y0 = sy * (100 + tl) + 320;
    x1 = sx * 100 + 120;
    y1 = sy * 100 + 320;
    
    // Draw tick
    tft.drawLine(x0, y0, x1, y1, ILI9341_BLACK);
    
    // Check if labels should be drawn, with position tweaks
    if (i % 25 == 0) {
      // Calculate label positions
      x0 = sx * (100 + tl + 10) + 120;
      y0 = sy * (100 + tl + 10) + 320;
      switch (i / 25) {
        case -2: tft.drawCentreString("0", x0, y0 - 12, 2); break;
        case -1: tft.drawCentreString("25", x0, y0 - 9, 2); break;
        case 0: tft.drawCentreString("50", x0, y0 - 6, 2); break;
        case 1: tft.drawCentreString("75", x0, y0 - 9, 2); break;
        case 2: tft.drawCentreString("100", x0, y0 - 12, 2); break;
      }
    }
    
    // Now draw the arc of the scale
    sx = cos((i + 5 - 90) * 0.0174532925);
    sy = sin((i + 5 - 90) * 0.0174532925);
    x0 = sx * 100 + 120;
    y0 = sy * 100 + 320;
    // Draw scale arc, don't draw the last part
    if (i < 50) tft.drawLine(x0, y0, x1, y1, ILI9341_BLACK);
  }
  
  tft.drawString("%RH", 5 + 230 - 40, 290 - 20, 2); // Units at bottom right
  //tft.drawCentreString("%RH", 120, 70, 4); // Comment out to avoid font 4
  //tft.drawRect(5, 3, 230, 119, ILI9341_BLACK); // Draw bezel line
  
  plotNeedle(0,0); // Put meter needle at 0
}


// fonction dessin+mouvement aiguille

void plotNeedle(int value, byte ms_delay) // aiguille galva bottom
{
  tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
  char buf[8]; dtostrf(value, 4, 0, buf);
  tft.drawRightString(buf, 40, 290 - 20, 2);

  if (value < -10) value = -10; // Limit value to emulate needle end stops
  if (value > 110) value = 110;

  // Move the needle util new value reached
  while (!(value == old_analog)) {
    if (old_analog < value) old_analog++;
    else old_analog--;
    
    if (ms_delay == 0) old_analog = value; // Update immediately id delay is 0
    
    float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle 
    // Calcualte tip of needle coords
    float sx = cos(sdeg * 0.0174532925);
    float sy = sin(sdeg * 0.0174532925);

    // Calculate x delta of needle start (does not start at pivot point)
    float tx = tan((sdeg+90) * 0.0174532925);
    
    // Erase old needle image
    tft.drawLine(120 + 20 * ltx - 1, 320 - 20, osx - 1, osy, ILI9341_WHITE);
    tft.drawLine(120 + 20 * ltx, 320 - 20, osx, osy, ILI9341_WHITE);
    tft.drawLine(120 + 20 * ltx + 1, 320 - 20, osx + 1, osy, ILI9341_WHITE);
    
    // Re-plot text under needle
    //tft.setTextColor(ILI9341_BLACK);
    //tft.drawCentreString("%RH", 120, 70, 4); // // Comment out to avoid font 4
    
    // Store new needle end coords for next erase
    ltx = tx;
    osx = sx * 98 + 120;
    osy = sy * 98 + 320;
    
    // Draw the needle in the new postion, magenta makes needle a bit bolder
    // draws 3 lines to thicken needle
    tft.drawLine(120 + 20 * ltx - 1, 320 - 20, osx - 1, osy, ILI9341_RED);
    tft.drawLine(120 + 20 * ltx, 320 - 20, osx, osy, ILI9341_MAGENTA);
    tft.drawLine(120 + 20 * ltx + 1, 320 - 20, osx + 1, osy, ILI9341_RED);
    
    // Slow needle down slightly as it approaches new postion
    if (abs(old_analog - value) < 10) ms_delay += ms_delay / 5;
    
    // Wait before next update
    delay(ms_delay);
  }
}
void plotNeedle_1(int value, byte ms_delay) //aiguille galva haut
{
  tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
  char buf2[8]; dtostrf(value, 4, 0, buf2);
  tft.drawRightString(buf2, 40, 119 - 20, 2);

  if (value < -10) value = -10; // Limit value to emulate needle end stops
  if (value > 110) value = 110;

  // Move the needle util new value reached
  while (!(value == old_analog)) {
    if (old_analog < value) old_analog++;
    else old_analog--;
    
    if (ms_delay == 0) old_analog = value; // Update immediately id delay is 0
    
    float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle 
    // Calcualte tip of needle coords
    float sx = cos(sdeg * 0.0174532925);
    float sy = sin(sdeg * 0.0174532925);

    // Calculate x delta of needle start (does not start at pivot point)
    float tx = tan((sdeg+90) * 0.0174532925);
    
    // Erase old needle image
    tft.drawLine(120 + 20 * ltx - 1, 140 - 20, osx - 1, osy, ILI9341_WHITE);
    tft.drawLine(120 + 20 * ltx, 140 - 20, osx, osy, ILI9341_WHITE);
    tft.drawLine(120 + 20 * ltx + 1, 140 - 20, osx + 1, osy, ILI9341_WHITE);
    
    // Re-plot text under needle
    //tft.setTextColor(ILI9341_BLACK);
    //tft.drawCentreString("%RH", 120, 70, 4); // // Comment out to avoid font 4
    
    // Store new needle end coords for next erase
    ltx = tx;
    osx = sx * 98 + 120;
    osy = sy * 98 + 140;
    
    // Draw the needle in the new postion, magenta makes needle a bit bolder
    // draws 3 lines to thicken needle
    tft.drawLine(120 + 20 * ltx - 1, 140 - 20, osx - 1, osy, ILI9341_RED);
    tft.drawLine(120 + 20 * ltx, 140 - 20, osx, osy, ILI9341_MAGENTA);
    tft.drawLine(120 + 20 * ltx + 1, 140 - 20, osx + 1, osy, ILI9341_RED);
    
    // Slow needle down slightly as it approaches new postion
    if (abs(old_analog - value) < 10) ms_delay += ms_delay / 5;
    
    // Wait before next update
    delay(ms_delay);
  }
}

suite code

void analogMeter1() // dessin echelle+fond haut

{
    // 1er galva coordonées mode portrait
  tft.fillRect(0, 0, 239, 126, ILI9341_GREY); // contour gris
  tft.fillRect(5, 3, 230, 119, ILI9341_WHITE);
   tft.setTextColor(ILI9341_BLACK);  // Text colour

   for (int i = -50; i < 51; i += 5) {
    // Long scale tick length
    int tl = 15;

// Coodinates of tick to draw
    float sx = cos((i - 90) * 0.0174532925);
    float sy = sin((i - 90) * 0.0174532925);
    uint16_t x0 = sx * (100 + tl) + 120;
    uint16_t y0 = sy * (100 + tl) + 140;
    uint16_t x1 = sx * 100 + 120;
    uint16_t y1 = sy * 100 + 140;
    
    // Coordinates of next tick for zone fill
    float sx2 = cos((i + 5 - 90) * 0.0174532925);
    float sy2 = sin((i + 5 - 90) * 0.0174532925);
    int x2 = sx2 * (100 + tl) + 120;
    int y2 = sy2 * (100 + tl) + 140;
    int x3 = sx2 * 100 + 120;
    int y3 = sy2 * 100 + 140;

    // CYAN zone limits
    if (i >= -50 && i < -10) {
      tft.fillTriangle(x0, y0, x1, y1, x2, y2, ILI9341_CYAN);
     tft.fillTriangle(x1, y1, x2, y2, x3, y3, ILI9341_CYAN);
    }
    // Green zone limits
    if (i >= -10 && i < 25) {
      tft.fillTriangle(x0, y0, x1, y1, x2, y2, ILI9341_GREEN);
      tft.fillTriangle(x1, y1, x2, y2, x3, y3, ILI9341_GREEN);
    }
    // Orange zone limits
    if (i >= 25 && i < 50) {
      tft.fillTriangle(x0, y0, x1, y1, x2, y2, ILI9341_ORANGE);
      tft.fillTriangle(x1, y1, x2, y2, x3, y3, ILI9341_ORANGE);
    }
 // Short scale tick length
    if (i % 25 != 0) tl = 8;
    
    // Recalculate coords incase tick lenght changed
    x0 = sx * (100 + tl) + 120;
    y0 = sy * (100 + tl) + 140;
    x1 = sx * 100 + 120;
    y1 = sy * 100 + 140;
    
    // Draw tick
    tft.drawLine(x0, y0, x1, y1, ILI9341_BLACK);
    
    // Check if labels should be drawn, with position tweaks
    if (i % 25 == 0) {
      // Calculate label positions
      x0 = sx * (100 + tl + 10) + 120;
      y0 = sy * (100 + tl + 10) + 140;
      switch (i / 25) {
        case -2: tft.drawCentreString("0", x0, y0 - 12, 2); break;
        case -1: tft.drawCentreString("25", x0, y0 - 9, 2); break;
        case 0: tft.drawCentreString("50", x0, y0 - 6, 2); break;
        case 1: tft.drawCentreString("75", x0, y0 - 9, 2); break;
        case 2: tft.drawCentreString("100", x0, y0 - 12, 2); break;
      }
    }
    // Now draw the arc of the scale
    sx = cos((i + 5 - 90) * 0.0174532925);
    sy = sin((i + 5 - 90) * 0.0174532925);
    x0 = sx * 100 + 120;
    y0 = sy * 100 + 140;
    // Draw scale arc, don't draw the last part
    if (i < 50) tft.drawLine(x0, y0, x1, y1, ILI9341_BLACK);
  }
  
  tft.drawString("Ctemp", 5 + 230 - 40, 119 - 20, 2); // Units at bottom right

les photos : la deuxieme photo montre l'autre exemple de bodmer instructables qui est ok

Merci

Cette ligne est commune aux 2 fonctions d'affichage de l'aiguille.

uint16_t osx = 120, osy = 120; // Saved x & y coords

Au lieu de définir ces variables en global, il serait peut-être plus rusé de les définir localement à la fonction comme static afin qu'elles conservent les valeurs entre 2 appels à la fonction.

elektrax:
je voulais ajouter un 2eme galva sous le premier : étant nul en maths et trigo, j'aurais besoin de beaucoup d'aide...

Autre façon d'aborder le problème, avoir une fonction commune aux 2 galva et passer en argument le décalage en Y et les variables qui vont conserver la position de l'aiguille.

Alors, il ne faut pas se faire peur avec la trigonométrie. Tu n'as besoin de faire qu'un décalage en Y.
Actuellement, les calculs et le tracé sont réalisés pour un décalage nul en Y. Pour dessiner un second galva, il faut continuer à faire tous les calculs sans rien changer et introduire le décalage au moment de tracer.
Pour la faire courte, tu passes un argument offsetY à la fonction plotNeedle et dans toutes les commandes de tracé tu ajoutes offsetY à la coordonnée Y. A l'appel de plotNeedle pour tracer le premier galva tu passes 0 comme offset. A l'appel de plotNeedle pour tracer le second galva tu passes le décalage entre les 2 galva.

Concernant le stockage de l'ancienne position de l'aiguille là aussi 2 possibilités.
Pour ton besoin, les valeurs changent lentement donc le mouvement amorti n'a aucun intérêt tu pourrais très bien supprimer cette partie.
Sinon, il faut passer un pointeur sur les variables (et non leur valeur) pour que plotNedle puisse modifier le contenu des variables.

Il faut utiliser dans plotNeedle1 des variables globales qui sont propres à cette fonction, sinon elle utilise celles de plotNeedle et affiche alors l'autre valeur. Par exemple : old_analog, osx, osy, ltx devraient devenir old_analog1, osx1, osy1, ltx1

Merci pour les réponses