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.