Comment redimensionner un nombre / plage de nombres en c

Je veux pouvoir afficher l’altitude en ft allant de 0 à 20000 pieds sur mon module LCD. Les chiffres sont lus à partir d’un potentiomètre que je peux faire pivoter pour modifier les valeurs. Pour le moment, le potentiomètre affiche de 0 à 1023 mais je dois les mettre à l’échelle de manière appropriée pour qu’ils lisent entre 0 et 20000 pieds. De plus, je souhaite que la ligne ci-dessous affiche un «graphique à barres» représentant l’augmentation de l’altitude. L’écran à cristaux liquides a 20 blocs par ligne, de sorte que le graphique à barres peut aller de 1 à 20 blocs.

sprintf(buf, "Altitude: %d ", DELVAL2); // display altitude level lcd_putxy(1,0,buf); for (delay = 0; delay < 50000; delay++); // introduce a delay sprintf(buf, "*", DELVAL2 ); // display bar graph lcd_putxy(2,0,buf); for (delay = 0; delay < 50000; delay++); // introduce a delay 

Ceci est mon code jusqu’à présent. Il lit la valeur du potentiomètre DELVAL2 et l’affiche sur l’écran LCD. Quelqu’un peut-il s’il vous plaît expliquer une méthode permettant de mettre les données à l’échelle de manière appropriée pour produire une altitude et un graphique à barres.

Si votre DELVAL2 est dans la plage 0-1023, vous pouvez l’adapter à 0-20000, mais vous ne pouvez pas obtenir une résolution supérieure à (1/1024) * 20000. Pourquoi? La valeur minimale (un seul bit) que vous pouvez lire est 1/1024. Votre valeur maximale est 20000, donc un changement de bit sur DELVAL2 entraînera un changement de 20000/1024 = 19,53 sur la valeur mise à l’échelle.

Vous pouvez calculer comment le redimensionner, cela est déjà décrit dans stackoverflow: comment réduire une plage de nombres avec une valeur min et max connue

Vous devez garder à l’esprit que vous pouvez tomber en opération de virgule flottante et c’est quelque chose que vous voudrez peut-être éviter. Par exemple, vous pouvez faire quelque chose comme ça

 scaled = (DELVAL2 * 1953) / 1000; 

au lieu de

 scaled = DELVAL2 * 19.53; 

N’oubliez pas que la valeur maximale que vous pouvez obtenir dans ce calcul sera 1024 * 1953 = 1999872, vous avez donc besoin d’une variable 32 bits. Une dissortingbution supplémentaire peut être nécessaire, selon votre architecture et votre compilateur, par exemple:

 scaled = (DELVAL2 * (uint32_t)1953) / 1000; 

Deuxième question – graphique à barres – vous êtes sur la bonne voie. Calculez le nombre de symboles dont vous avez besoin et dessinez-les. C’est réduire au lieu de monter. Une simple division devrait suffire. Quand vous savez combien de symboles vous avez besoin, générez-les en boucle simple

 for(int i = 0; i < num; i++) buf[i] = '*'; buf[i] = 0; //last symbol is 0 to stop drawing lcd_putxy(2,0,buf); 

Pour mettre à l’échelle [0...1023] à [0...20000] multipliez par 20 000 puis divisez par 1023.

 int altitude = (int) ((potentiometer*20000L + 1023/2)/1023); 

Le code utilise long multiplication long car int ne peut être que 16 bits sur un micro-contrôleur. Non nécessaire si INT_MAX == 0x7FFFFFFF .

Le + 1023/2 doit fournir une conversion arrondie.

Vraisemblablement, buf est un entier de 16 bits et contient la valeur du pot. Vraisemblablement, vous pouvez vous fier à sa limitation aux valeurs [0, 1023].

Si tu fais

  int scaledbuf; scaledbuf = buf >> 5; 

vous obtiendrez une valeur de scaledbuf dans l’intervalle [0, 32736]. Vous pourriez alors faire

  if (scaledbuf > 20000) scaledbuf = 20000; 

Au prix de sacrifier une partie de la plage de votre pot, cela vous donnera une valeur dans la plage [0,20000] sans aucune multiplication, seulement un décalage à gauche.

Cependant, vos cycles de délai allument des cycles, de sorte que vous pouvez probablement gérer le coût d’une multiplication par 20.

  int scaledbuf; scaledbuf = buf * 20; if (scaledbuf > 20000) scaledbuf = 20000; 

Cela préserve considérablement la gamme de votre pot tout en vous gardant dans le domaine de l’arithmétique 16 bits.