rapport de valeur entre 2 variables

Bonjour tout le monde,
Pour un projet au lycée j'ai du créer un programme qui devait allumer une led différente selon la position d'un potentiomètre.
Maintenant j'aimerai modifier le programme pour faire que les leds diminuent et augmentent leur luminosité en fonction de la position du potentiomètre, c'est plus joli que de faire un changement brusque de led.
Mon programme est donc découpé en 16 boucle 'if' pour 8 leds (8 pour augmenter la luminosité et 8 pour la réduire).
Mon potentiomètre qui fourni 1023 est donc découpé en parties de 64 mais je n'arrive pas à trouver un rapport de grandeur par rapport aux 255 de la luminosité.
je sais que 1023 = 4*64-1 mais chaque partie possède 64 des 1023 donc 1023 à 959 puis 959 à 895 etc.
si quelqu'un pouvait me donner une technique pour que dans chaque partie l'intensité lumineuse puisse varier de 0 à 255 et inversement, ou me donner une autre façon de faire le programme je lui en serai reconnaissant.
edit: je me suis servi de ce site pour m'aider Modifier l'intensité lumineuse d'une LED — Wiki L.A.B

c'est peut-être un peu tôt pour vous au niveau mathématiques mais pensez à une courbe de gauss

Elle a une forme caractéristique de courbe en cloche

Avec des coefficients bien choisis en fonction du No de la LED et de votre domaine (x entre 0 et 1023, y entre 0 et 255) vous pouvez fabriquer une fonction qui pour une valeur donnée du potentiomètre x vous donnera une valeur de la LED qui sera entre 0 et 255.

Par exemple pour la LED 0, vous voulez que le sommet de la cloche (255) soit centré sur x = 0 (quand le potentiomètre est à 0, la LED brille au max) puis quand vous augmentez la valeur du potentiomètre (x augmente) la luminosité de votre diode va suivre la courbe descendante de la cloche pour aller vers 0 et donc s'éteindre.

Pour la LED1 vous prenez une courbe en cloche similaire mais décalée pour qu'elle brille à fond quand le potentiomètre (x) est plus grand --> comme ça quand le potentiomètre x vaut 0 elle est sur la trajectoire montante de la courbe en cloche, quand vous arrivez à la bonne valeur du potentiomètre pour la LED1 il faut que vous soyez au sommet de la cloche (255) et quand vous allez continuer à augmenter la valeur du potentiomètre vous allez descendre de l'autre côté de la courbe en cloche et donc votre LED va briller moins fort jusqu'à s'éteindre.

Par exemple voici (sous geogebra, je suppose que vous avez déjà utilisé cela pour l'école) le tracé de la fonction mathématique

Vous voyez que la cloche est centrée en 400, qu'elle a une amplitude de 255.

Le coefficient 20 (en fait 20/1000) va jouer sur la largeur de la cloche. Plus il est grand plus la cloche sera "pointue", ici par exemple avec 30. vous voyez que quand x vaut 350, y vaut toujours ~25 alors qu'il valait ~75 avant

ça vous donne des idées ?? :slight_smile:

gaby200:
je sais que 1023 = 4*64-1

Il me semblait plutôt que 1023 = 4 * 256 - 1...

Ca ressemble à une usine à gaz, ton truc.
Bon, on a huit leds, donc ok pour dire que la première sera allumée entre 0 et 127 sur le potentiomètre, la deuxième entre 128 et 255, etc.

Pour rester dans la simplicité (parce que la courbe de gauss est une solution élégante, mais un peu compliquée (moi-même j'ai oublié depuis longtemps comment les calculer)...
Tu as donc, si tu numérotes tes leds de 0 à 7, le numéro de ta led qui t'es donné par la valeur lue sur le potentiomètre, modulo 8.
Soit:

indexLed = valeurPot % 8;

C'est un bon début, puisque ça te permet d'obtenir le numéro de ta led à partir de la valeur lue. L'intérêt est que tu peux utiliser un tableau de 8 valeurs pour stocker le numéro de broche attribué à chaque led, et ainsi rendre automatique l'affectation de sa valeur.

byte portLed[8];

byte indexLed = valeurPot % 8;

analogWrite(portLed[indexLed], valeurLed);

Maintenant, pour calculer la valeur de la led: elle correspond à la différence qu'il y a entre la valeur lue pour le potentiomètre, et la valeur mini que prend le potentiomètre pour cette led.
Si c'est la led 0, la valeur du potentiomètre doit être comprise entre 0 et 127. Pas de problème.
Si c'est la led 1, 128 et 255.
Chaque led "utilise" 128 valeurs. Il faut donc multiplier 128 par l'index de la led (qui donne la valeur la plus basse pour cette led), et soustraire ce nombre à la valeur du potentiomètre.

byte valeurLed = valeurPot - indexLed * 128;

Si la valeur obtenue est inférieure à 64, on la garde telle quelle (rien à faire). Si elle est supérieure ou égale à 64, on lui soustrait 64 (ce qui nous ramène à une valeur comprise entre 0 et 63), puis on soustrait la valeur obtenue de 64 (ce qui effectue la "symétrie").
Pour finir, puisque les sorties PWM ont une résolution de 8 bits, on multiplie cette valeur par 4, pour la réétalonner entre 0 et 255

if(valeurLed >=64){
    valeurLed -= 64;
    valeurLed = 64 - valeurLed;
}
valeurLed *= 4;

De cette manière, tu gères à la fois automatiquement la led que tu contrôles en fonction de la valeur lue, et la led devrait suivre une courbe linéaire en croissant et en décroissant.

A l'attention de J-M-L: c'est joli ces courbes de gauss, et présenté comme ça ça semble être plus simple que quand j'étais en DUT. Je vais me replonger sur la question, je sens que ça pourrait être très utile ici ou là! :slight_smile:

j'suis un matheux :slight_smile: j'ai toujours adoré ça..

Votre approche est pragmatique, c'est bien mais c'est pas le modulo qu'il faut prendre pour trouver la LED c'est le résultat de la division

vous voulez couper 0-1023 en 8 intervalles il faut diviser par 128 et c'est le résultat entier de la division qui est le numéro de la LED (en commençant à 0)

Led #0 pour x entre 0 et 127
Led #1 pour x entre 128 et 255
Led #2 pour x entre 256 et 383
Led #3 pour x entre 384 et 511
Led #4 pour x entre 512 et 639
Led #5 pour x entre 640 et 767
Led #6 pour x entre 768 et 895
Led #7 pour x entre 896 et 1023

donc byte indexLed = valeurPot / 128;

ensuite quand vous ditesbyte valeurLed = valeurPot - indexLed * 128; en fait c'est là que vous calculez le modulo. donc autant faire byte valeurLed =valeurPot % 128; // valeur entre 0 et 127
comme on fait juste avant la division, ça va être rapide car quand on fait une division le microprecesseur se retrouve déjà avec le modulo dans un registre et les bons compilateurs sont assez malins pour le voir et aller récupérer le résultat sans refaire de calcul .

bref -->

const byte potPin = A0; // pin sur laquelle le potentiomètre est connecté
...
int valeurPot = analogRead(potPin);
byte indexLed = valeurPot / 128; // No de la LED entre 0 et 7
byte valeurLed = valeurPot % 128; // valeur entre 0 et 127

ensuite effectivement pour cette valeur comprise entre 0 et 127 vous pouvez avoir une petite fonction qui dit si je suis entre 0 et 63 alors je passe de 0 à 255 si je suis entre 64 et 127 alors je passe de 255 à 0

on peut éventuellement le faire avec deux fonctions préprogrammées de l'arduino map() et constrain() qui font une rampe linéaire (fonction affine pour la première - mise en escalier car entière puis limitée à un intervalle pour la seconde )

A noter qu'avec cette approche une seule LED n'est allumée à la fois cependant et quand je suis à 128 tout est éteint par exemple. l'approche avec les "cloches" en fonction de la largeur de la cloche va faire que le bandeau aura plusieurs LED allumées en même temps

Merci à tous pour vos réponses, vous vous en doutez surement je suis néophyte en la matière, j'ai plutôt du mal à comprendre tout ce dont vous parlez, cela dit il est un peu tard donc je me pencherai sur le sujet demain dans la journée, je vous tiens au courant

@J-M-L: En effet, bien que j'ai vérifié deux fois, j'ai inversé le modulo et la division dans le premier calcul. Il aurait fallu une troisième vérification! :slight_smile:
Et d'accord aussi pour le modulo dans le deuxième calcul. C'est dommage d'avoir passé autant de temps à rédiger une réponse qui part sur des principes justes et qui est mal appliquée! J'essaierai de faire en sorte que l'on ne m'y reprenne plus.

En effet le comportement ne sera pas du tout le même, en fait en lisant l'ennoncé de départ je l'ai interprété comme ça. la solution de la courbe de gauss est plus élégante, il me semble. Elle permet en effet de moduler plus finement l'effet, d'avoir toujours une led allumée, et de "moyenner" la position du potentiomètre. Et peut-être de compenser en partie la non-linéarité de la réponse des leds?

@gaby200: Pas de problème pour le temps qu'il faudra pour intégrer ces données. Les explications que j'ai donné, si elles ne sont pas très complexes, peuvent paraître un peu abstraite au premier abord. Pour ma part je n'ai découvert l'opérateur modulo qu'en programmant, il m'a fallu un temps pour comprendre son intérêt. Et en ce qui concerne les courbes de Gauss, je ne les avais apprises qu'en DUT. Jamais entendu parler avant, pourtant en SSI ça n'aurait pas été déplacé. Peut-être les programmes ont-ils évolués depuis? Quoi qu'il en soit les explications de J-M-P sont suffisantes pour implémenter cette solution-là, libre à toi d'aller faire des recherches pour comprendre plus finement comment cela fonctionne, et les nombreuses applications et extensions que l'on trouve à ce type de courbe!

Oui c'est vite fait de se tromper - pas de soucis !