Problème math et programmation
Modérateurs : Papy.G, fneck, Carl
- gleike
- Messages : 1341
- Inscription : 16 oct. 2014 11:12
- Localisation : Ludres (54710) Meurthe & Moselle
Problème math et programmation
Bonjour,
J'ai un petit problème de programmation que je n'arrive pas à résoudre,
j'ai un petit SBC programmable en basic avec un convertisseur ADC qui me donne une valeur entre 0 et 255
suivant la position d'un potentiomètre,
le microcontrôleur à un port avec 8 LEDS, si j'envoie la valeur lue du potar sur le port,
j'ai son affichage en binaire sur les LEDS,
je voudrais avoir une seule LED qui s'allume et se déplace en fonction de la valeur lue du potar,
autrement dit convertir proportionnellement les valeurs de 0 à 255 en valeur 0,1,2,4,8,16,32,64,128
de façon élégante en basic en évitant de faire trop de tests.
Avez-vous une solution ?
Je sèche dessus depuis 2 jours
Merci.
J'ai un petit problème de programmation que je n'arrive pas à résoudre,
j'ai un petit SBC programmable en basic avec un convertisseur ADC qui me donne une valeur entre 0 et 255
suivant la position d'un potentiomètre,
le microcontrôleur à un port avec 8 LEDS, si j'envoie la valeur lue du potar sur le port,
j'ai son affichage en binaire sur les LEDS,
je voudrais avoir une seule LED qui s'allume et se déplace en fonction de la valeur lue du potar,
autrement dit convertir proportionnellement les valeurs de 0 à 255 en valeur 0,1,2,4,8,16,32,64,128
de façon élégante en basic en évitant de faire trop de tests.
Avez-vous une solution ?
Je sèche dessus depuis 2 jours
Merci.
-
- Messages : 7923
- Inscription : 18 sept. 2010 12:08
- Localisation : Brest et parfois les Flandres
Re: Problème math et programmation
Tu te fais une table precalculée qui associé pour chacune des entrées possibles la sortie associée par la formule 2^arrondi_vers_le_bas(input/32).
Si ton sbc a assez de puissance et que tu veux économiser la ram tu peux faire la formule en asm avec des décalages: 1<<(input>>5). Soit tu prends l’entrée, tu la décale à droite 5 fois (c’est une division par 32) ça te donne le nombre de fois à décaler 1 à gauche (c’est une puissance de 2).
Bon le hic c’est que tu ne sors pas 0. Pour cela il faut faire un truc genre x=2^((input+1)/32)-1, et tabuler y=x&-x (le "et logique bit à bit" entre x et son opposé: cela ne garde que le bit de poids fort de x) pour toutes les inputs de 0 à 255. Ça doit se faire en basic sans soucis. Si tu tabules uniquement x, tu auras une barre de leds et pas juste le pixel du haut. Ça peut être bien aussi.
Si ton sbc a assez de puissance et que tu veux économiser la ram tu peux faire la formule en asm avec des décalages: 1<<(input>>5). Soit tu prends l’entrée, tu la décale à droite 5 fois (c’est une division par 32) ça te donne le nombre de fois à décaler 1 à gauche (c’est une puissance de 2).
Bon le hic c’est que tu ne sors pas 0. Pour cela il faut faire un truc genre x=2^((input+1)/32)-1, et tabuler y=x&-x (le "et logique bit à bit" entre x et son opposé: cela ne garde que le bit de poids fort de x) pour toutes les inputs de 0 à 255. Ça doit se faire en basic sans soucis. Si tu tabules uniquement x, tu auras une barre de leds et pas juste le pixel du haut. Ça peut être bien aussi.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Re: Problème math et programmation
Tu as 8 LED et tu veux en allumer un seul qui indique une progression logarithmique binaire de ton potard ? je présume que ta sortie est un octet sur la même adresse I/O (chaque bit de cet octet encode une LED)
En pseudo language C :
J'ai fait en sorte de ne pas utiliser des opérateurs & (AND octet) et >> (décalage de bits) pour être transposable en BASIC.
Le coup du tableau à 256 éléments est effectivement une façon très rapide d'obtenir la valeur de sortie (car d'ordre O(1) !) pour peu que l'on ait suffisamment de place en mémoire et se taper un code d'initialisation pour ce tableau.
EDIT:
en BASIC, l'algo pourrait être quelque chose du genre :
En pseudo language C :
Code : Tout sélectionner
unsigned char E = IN(kADC); // notre valeur analogique
unsigned char S = 0; // notre valeur de sortie initialement à 0
unsigned char M = 128; // le masque de sortie le plus grand initialement
for (char I = 0; I < 8; ++I)
{
if (E >= M)
{
S = M;
break; // un bit de positionné puis on sort de la boucle !
}
M = M / 2;
}
OUT(kLED, S); // on n'allume que la led au poids le plus significatif ou aucune si l'entrée est 0
Le coup du tableau à 256 éléments est effectivement une façon très rapide d'obtenir la valeur de sortie (car d'ordre O(1) !) pour peu que l'on ait suffisamment de place en mémoire et se taper un code d'initialisation pour ce tableau.
EDIT:
en BASIC, l'algo pourrait être quelque chose du genre :
Code : Tout sélectionner
10 E = IN(IO_ADC) : S = 0 : M = 128
20 FOR I = 1 TO 8 : IF E >= M THEN S = M ELSE M = M / 2 : NEXT ' J'espère que NEXT ne s'exécute qu'après le ELSE...
30 OUT IO_LEDS, S
…
Dernière modification par hlide le 30 juil. 2022 21:41, modifié 1 fois.
-
- Messages : 7923
- Inscription : 18 sept. 2010 12:08
- Localisation : Brest et parfois les Flandres
Re: Problème math et programmation
Non c’est pas du log, mais de l’exponentielle plutôt (input linéaire et sortie en puissance de 2).
M’enfin le principe est là. La difficulté étant de mapper régulièrement 256 valeurs sur 9 valeurs (0, 1, 2, 4, 8, 16, 32, 64, 128 ca fait 9 valeurs).
En principe les basic savent faire du "et bit à bit", donc "x AND -x" doit bel et bien retourner le bit de poids fort de x, même en basic.
M’enfin le principe est là. La difficulté étant de mapper régulièrement 256 valeurs sur 9 valeurs (0, 1, 2, 4, 8, 16, 32, 64, 128 ca fait 9 valeurs).
En principe les basic savent faire du "et bit à bit", donc "x AND -x" doit bel et bien retourner le bit de poids fort de x, même en basic.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Re: Problème math et programmation
moi je ferai comme __Sam__ avec 2^(int(val/8)) ou quelque chose d'approchant pour tenir compte des limites inférieures et supérieures.
- gleike
- Messages : 1341
- Inscription : 16 oct. 2014 11:12
- Localisation : Ludres (54710) Meurthe & Moselle
Re: Problème math et programmation
Merci pour vos réponses, je vais faire des essais.
- gleike
- Messages : 1341
- Inscription : 16 oct. 2014 11:12
- Localisation : Ludres (54710) Meurthe & Moselle
Re: Problème math et programmation
Voilà le résultat de mes essais, ça fonctionne très bien comme ça, merci de m'avoir mis sur la bonne piste.
Re: Problème math et programmation
Bon ok la demande ne correspondait pas du tout à ce que je croyais.
Mois j'avais compris un log2 :
* 0 < adc < 2 => Led 0 allumé pour indiquer niveau 1
* 2 < adc < 4 => Led 1 allumé pour indiquer niveau 2
* 4 < adc < 8 => Led 2 allumé pour indiquer niveau 3
* 8 < adc < 16 => Led 3 allumé pour indiquer niveau 4
* 16 < adc < 32 => Led 4 allumé pour indiquer niveau 5
* 32< adc < 64 => Led 5 allumé pour indiquer niveau 6
* 64 < adc < 128 => Led 6 allumé pour indiquer niveau 7
* 128 < adc => Led 7 allumé pour indiquer niveau 8
Alors qu'en fait, vous vouliez faire juste un démultiplexeur 3->8 avec les 3 bits les plus significatifs de adc.
Mois j'avais compris un log2 :
* 0 < adc < 2 => Led 0 allumé pour indiquer niveau 1
* 2 < adc < 4 => Led 1 allumé pour indiquer niveau 2
* 4 < adc < 8 => Led 2 allumé pour indiquer niveau 3
* 8 < adc < 16 => Led 3 allumé pour indiquer niveau 4
* 16 < adc < 32 => Led 4 allumé pour indiquer niveau 5
* 32< adc < 64 => Led 5 allumé pour indiquer niveau 6
* 64 < adc < 128 => Led 6 allumé pour indiquer niveau 7
* 128 < adc => Led 7 allumé pour indiquer niveau 8
Alors qu'en fait, vous vouliez faire juste un démultiplexeur 3->8 avec les 3 bits les plus significatifs de adc.
- gleike
- Messages : 1341
- Inscription : 16 oct. 2014 11:12
- Localisation : Ludres (54710) Meurthe & Moselle
Re: Problème math et programmation
Oui, en fait, ma demande était plus simple et je cherchais à éviter d'utiliser un tableau
en trouvant une formule pouvant faire directement la conversion ADC>>PORT.
en trouvant une formule pouvant faire directement la conversion ADC>>PORT.
Re: Problème math et programmation
Est ce que la fonction mathématique compliquée à trouver pourrait être une régle de trois?
led=pot/255*8
en trichant un peu 256 ca se fait avec un decalage.
led=pot/255*8
en trichant un peu 256 ca se fait avec un decalage.
https://www.franck-pissotte.fr/ vide grenier
-
- Messages : 7923
- Inscription : 18 sept. 2010 12:08
- Localisation : Brest et parfois les Flandres
Re: Problème math et programmation
Ça n’aurait pas allumé les leds comme voulu. Les valeurs de 0 à 7 envoyés allument plusieurs leds en même temps (avec 3 leds au max, pour la valeur 7). Or il fallait n’allumer qu’au plus une des 8 leds.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
-
- Messages : 1254
- Inscription : 24 déc. 2021 09:46
- Localisation : Région parisienne
Re: Problème math et programmation
D'après ce que je comprends, il faut allumer une led. Cette led a un numéro entre 0 et 8 et représente les valeurs 0 à 128 en puissances de 2.
Il suffit de faire n=INT(LOG(V)/LOG(2))
Cela ne fonctionne pas pour 0, d'où le programme suivant
IF v=0 THEN n=1 ELSE n=1+INT(LOG(V)/LOG(2))
Si on dispose pas de la fonction LOG, il suffit de parcourir les bits du nombre en question, du bit le plus fort au bit le plus faible et de s'arrêter dès qu'on trouve un 1. On obtient alors la position de la led mais en ordre inverse (8 à 1 pour bit 7 à 0). Si aucun bit n'est à 1 alors on sort 0.
Édit : après avoir relu le poste initial, voici ma solution :
IF v=0 THEN n=0 ELSE n=2**INT(LOG(v)/LOG(2))
Il suffit de faire n=INT(LOG(V)/LOG(2))
Cela ne fonctionne pas pour 0, d'où le programme suivant
IF v=0 THEN n=1 ELSE n=1+INT(LOG(V)/LOG(2))
Si on dispose pas de la fonction LOG, il suffit de parcourir les bits du nombre en question, du bit le plus fort au bit le plus faible et de s'arrêter dès qu'on trouve un 1. On obtient alors la position de la led mais en ordre inverse (8 à 1 pour bit 7 à 0). Si aucun bit n'est à 1 alors on sort 0.
Édit : après avoir relu le poste initial, voici ma solution :
IF v=0 THEN n=0 ELSE n=2**INT(LOG(v)/LOG(2))
-
- Messages : 7923
- Inscription : 18 sept. 2010 12:08
- Localisation : Brest et parfois les Flandres
Re: Problème math et programmation
Non pas exactement. Gleike dit clairement qu’il veut convertir les valeurs de 0 à 255 proportionnellement dans l’ensemble de 9 valeurs v(0), v(1), ..., v(8) (bref des v(i)),D'après ce que je comprends, il faut allumer une led. Cette led a un numéro entre 0 et 8 et représente les valeurs 0 à 128 en puissances de 2.
A partir de là on a résolu le problème: il faut queautrement dit convertir proportionnellement les valeurs de 0 à 255 en valeur 0,1,2,4,8,16,32,64,128
de façon élégante en basic en évitant de faire trop de tests.
Code : Tout sélectionner
i=input*8/255 (arrondir â l’entier le plus proche)
Ah oui j’ai oublié de dire ce que sont les v(0)..v(8). En fait ce sont ce qu’on veut pour la sortie. Ça peut être des trucs arbitraires: 8,1, 9, 17, ... défini par un tableau de valeurs dependant du hard. Le problème s’arrêté alors la. On utilise le tableau et c’est tout.
Bon il se trouve qu’ici on a de la chance car on peut aussi exprimer les v(i) par une puissance de 2 : v(i)=arrondi_vers_le_bas(2 puissance (i-1)), donc pas besoin de tableau intermédiaire, mais juste enchaîner du calcul sur des réels à faire en basic:
Code : Tout sélectionner
i = input*8/255.0 : rem On ignore l’arrondi au plus proche ici, c’est pas grave.
o = INT(2^(i-1)) : rem calcul du v(i)
Note: On peut évidemment combiner les deux étapes de calcul en une seule, mais je crois que ça complexifie inutilement les choses en perdant ceux qui n’aiment pas trop les équations et leur sens caché. J’espère avoir été plus didactique que ma 1ère réponse ce coup ci.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
-
- Messages : 1254
- Inscription : 24 déc. 2021 09:46
- Localisation : Région parisienne
Re: Problème math et programmation
Je crois qu'il y a une incompréhension sur le terme "proportionnellement" que j'ai mal compris à cause de cela :
"j'ai son affichage en binaire sur les LEDS,
je voudrais avoir une seule LED qui s'allume et se déplace en fonction de la valeur lue du potar,"
J'en ai conclu qu'il suffisait de supprimer les diodes supplémentaires qui s'affichent.
Maintenant si le déplacement de la diode est proportionnel à la valeur entre 0 et 255, alors il faut effectivement une règle de 3.
Mais j'écrirais cela plutôt comme cela :
i=int(((input+1)*9)/257)
o=int(2**(i-1))
Voici le résultat pour les valeurs de 0 à 255 :
Et si on veut la variante où il y a toujours une diode allumée :
i=int(((input+1)*8)/257)
o=int(2**i)
Voici les valeurs obtenue pour input de 0 à 255 :
"j'ai son affichage en binaire sur les LEDS,
je voudrais avoir une seule LED qui s'allume et se déplace en fonction de la valeur lue du potar,"
J'en ai conclu qu'il suffisait de supprimer les diodes supplémentaires qui s'affichent.
Maintenant si le déplacement de la diode est proportionnel à la valeur entre 0 et 255, alors il faut effectivement une règle de 3.
Mais j'écrirais cela plutôt comme cela :
i=int(((input+1)*9)/257)
o=int(2**(i-1))
Voici le résultat pour les valeurs de 0 à 255 :
Code : Tout sélectionner
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001
00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010
00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100
00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000
00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000
00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000
01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000
10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000
Et si on veut la variante où il y a toujours une diode allumée :
i=int(((input+1)*8)/257)
o=int(2**i)
Voici les valeurs obtenue pour input de 0 à 255 :
Code : Tout sélectionner
00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001
00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010 00000010
00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100 00000100
00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000 00001000
00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000 00010000
00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000 00100000
01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000 01000000
10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000
- gleike
- Messages : 1341
- Inscription : 16 oct. 2014 11:12
- Localisation : Ludres (54710) Meurthe & Moselle
Re: Problème math et programmation
J'ai testé les différentes méthodes proposées, et celle qui fonctionne le mieux et celle-ci :
À part que mon potar a pleins de mauvais contacts et provoque des sauts dans l'affichage, mais bon, il a au moins 50 ans.
Merci à tous pour votre implication
Je ne l'aurais pas trouvé tous seul
À part que mon potar a pleins de mauvais contacts et provoque des sauts dans l'affichage, mais bon, il a au moins 50 ans.
Merci à tous pour votre implication