conversion simple précision en décimal

micro_33

New Member
Bonsoir

J'utilise un appareil de mesure qui est géré par un soft sous windows, par une liaison série.

Pour ne pas avoir à lancer le logiciel, je désire lire une donnée dans une trame RS232 à l'aide d'un Picaxe.
Cette donnée est sur 4 bytes (nombre simple précision).

La conversion hexa ----> décimal parait hors de portée de mes connaissances, nulles en programmation.

Existe t-il une routine ou quelqu'un a-t-il résolu cette conversion.
Un exemple de donnée : 0xBD 08 E7BC7 ----> 0.03 c'est ce que le logiciel affiche.

J'ai lu en long et en large le wiki sur le sujet, je crois avoir compris,mais la manipulation des bits est une inconnue.

En fait, la lecture n'a pas besoin de toute la précision que permet ce codage. Le nombre concerné est compris entre 0.00 et +/- 1, la conversion sera-t-elle plus simple?

J'ai pour l'instant, fait une table qui teste le byte de poids fort de la mantisse, mais ce n'est pas très élégant.

Merci de votre aide

JP
 
Last edited:

PieM

Senior Member
Bonsoir,

Un exemple de donnée : 0xBD 08 E7BC7 ----> 0.03 c'est ce que le logiciel affiche.
Je pense qu'il y a une erreur dans votre 0xBD 08 E7BC7: Il ne s'agirait pas de 0xBD 08 E7 C7 ? Quant au résultat , ça ne serait pas plutôt -3.3 E-2, cad -0.033

Toutefois je pense qu'il ne faut pas espérer pouvoir faire cette conversion.
Le calcul de l'exposant peut faire appel à une puissance négative, chose que le Picaxe ne sait pas faire.
D'autre part, le calcul de la mantisse demande des calculs de puissance négative de 2 puisque celle ci est comprise entre 1 et 2. Ne pas oublier qu'il faut ajouter 1 avant les 23 bits de la mantisse.
Donc si elle est de 011, ça veut dire qu'il faut calculer avec 1.011, soit (1*2^0) + (0* 2^-1) + (1*2^-2) + (1*2^-3) .
 
Last edited:

micro_33

New Member
Bonsoir PieM

Merci de votre réponse et des corrections judicieuses.
Les résultats dont j'ai besoin, sont sur 1 ou 2 digits, je ne comprends pas pourquoi le fabricant à utilisé ce codage pour donner une température ou une erreur sur 3 digits.

je suis en train d'essayer une solution dont j'ai honte, mais qui me permettrait d'avoir une valeur proche de la réalité.
Le nombre à récupérer est compris entre 0.00 et +/-1.
En fait ce nombre est l'erreur entre la valeur de la fréquence du standard et la valeur qu'il devrait faire, ceci à la puissance 10-11 ( oui vous avez bien lu), cette valeur fluctuant de */- 2 à chaque lecture toutes les secondes.
Il n'est donc pas nécessaire pour mon utilisation d'avoir plus 2 digits.
Pour mon cas particulier j'ai observé que le premier octet correspondait aux valeurs suivantes
3BA3 -> +0.005
3C23 -> +0.01
--------------
3F80 -> +1

BBA3 -> -0.005
BC23 -> -0.01
-------------
BF80 -> -1

Le premier caractère donne le signe, les 3 autres la valeur, par comparaison dans une table, la valeur en 0.xx5 est là pour faire l'arrondi, ce n'est pas élégant, mais, mes connaissances nulles en la matière, ne me permettent pas de faire beaucoup mieux.

Merci encore de votre réponse
JP
 

PieM

Senior Member
Bonsoir,

Le premier caractère donne le signe, les 3 autres la valeur, par comparaison dans une table
Hélas, pas si simple !!

le principe de calcul en simple précision est le suivant , avec votre exemple de 3B A3:

3B va donner en binaire 00111011 (a)
A3 ------------------------->10100011 (b)


(a) est composé du signe , positif si le premier bit est 0 négatif sinon.
Cas du BB A3 ou BB = 10111011 qui donnera la même valeur d'exposant et de mantisse mais avec le signe moins.

Ici le signe sera donc positif.

ensuite, il faut 8 bits pour l'exposant, (7 bits de (a) plus un bit de (b)) donc 01110111 soit 119 en décimal
le calcul de l'exposant réel est de 2 à la puissance 119 moins le décalage, qui est de 127.
Donc l'exposant est de 2 -8 soit 0.00390625

Puis la mantisse va être composée des bits suivants (jusqu'à 23) auxquels on ajoute en tête un 1
(un 1 dit implicite pour faire plaisir à PapyJP !!)

La mantisse devient donc 1.0100011

ce qui se calcule comme étant:

(1* 2^0) + (0*2^-1) + (1*2^-2) + (0*2^-3) + (0*2^-4) + (0*2^-5) + (1*2^-6) + (1*2^-7)
chaque bit est multiplié par un poids décroissant à partir de 0 pour le premier bit qui a été ajouté.

et ceci est égal à 1.2734375

Le calcul final lui, est donc

signe et mantisse x exposant: soit + 1.2734375 * 0.00390625

Ce qui donne un résultat de +0.00497437, qui est la vraie valeur de votre 0.005 qui est arrondi par votre logiciel.

Il n'y a donc aucune possibilité avec un picaxe de base d'effectuer ce type de calcul, ni d'utiliser une table de conversion de façon viable.
Je ne suis pas certain que l'adjonction d'un coprocesseur mathématique (je ne connais pas celui du Picaxe ) permette ce calcul.
 
Last edited:

BESQUEUT

Senior Member
Le copro ad hoc fait très certainement le travail :
http://www.picaxe.com/Hardware/Add-on-Modules/uM-FPU-Floating-Point-Coprocessor/
Toutefois, au vu des explications de PieM, ça ne me semble pas si infaisable :
Les puissances négatives successives de 2 peuvent être calculées au fur et à mesure de l'analyse des bits en divisant par 2 une variable auxiliaire :
w1=10000 *1= 10000
w1=w1/2 5000 *0
w1=w1/2 2500 *1
w1=w1/2 1250 *0
w1=w1/2 625 *0
w1=w1/2 312 *0
w1=w1/2 156 *1
w1=w1/2 78 *1
somme = 12734

De même 2^8 peut être calculé dans une boucle en multipliant 2 par lui même 8 fois :
2^8 = 2*2*2*2*2*2*2*2=256
Pour multiplier par 2^-8, il suffit de diviser par 2^8 donc
12734/256=49 ce qui n'est pas si mal
 

BESQUEUT

Senior Member
En fait, il me semble qu'il y a plus simple :
Multiplier la mantisse par 2^-8 (ou diviser 8 fois par 2) revient à dire qu'on n'aurait pas du calculer la mantisse à partir de 2^0 mais à partir de 2^-8 soit 3906.
De là, on divise chaque fois par 2 comme ci-dessus et on obtient :
3906+0+976+0+0+0+61+30=4973
qui me semble assez simple à calculer et pas si loin du résultat escompté.
 

PieM

Senior Member
En fait, il me semble qu'il y a plus simple :
Multiplier la mantisse par 2^-8 (ou diviser 8 fois par 2) revient à dire qu'on n'aurait pas du calculer la mantisse à partir de 2^0 mais à partir de 2^-8 soit 3906.
De là, on divise chaque fois par 2 comme ci-dessus et on obtient :
3906+0+976+0+0+0+61+30=4973
qui me semble assez simple à calculer et pas si loin du résultat escompté.
Bonjour,

Le problème ne se situe pas dans le calcul d'une puissance entière, qui est facilement réalisable.

Non, la mantisse n'est pas multipliée par 2^-8 ! elle est à la puissance 2^-8
C'est ce qui permet d'avoir une virgule flottante...
Sinon vous ne pouvez avoir que des entiers.

signe MANTISSE EXPOSANT
 
Last edited:

BESQUEUT

Senior Member
signe et mantisse à la puissance exposant: soit + 1.2734375 0.00390625
Ce qui donne un résultat de +0.00497437,
1.2734375 puissance 0.00390625 = 1.000944664 (en base 10 : on est bien d'accord ?)
par contre :
1.2734375 * 2 puissance -8 = 1.2734375 /256 fait bien +0.00497437
Si mon raisonnement est faux, pourquoi le résultat est-il juste alors que votre calcul conduit à un résultat erroné ?
 

BESQUEUT

Senior Member
Sinon vous ne pouvez avoir que des entiers.
Pour simplifier l'explication, j'ai omis de signaler que mon calcul est réalisé en 1/100 000 d'unités de façon à n'utiliser que des nombres entiers compatibles avec le PICAXE.
En réalité sur un ordinateur, les nombres décimaux n'existent pas ! Les ordinateurs ne font qu'approximer les nombres décimaux en utilisant des entiers et en décalant la virgule. C'est pourquoi le nombre de chiffres significatifs est toujours limité.
2 puissance -8 n'est pas un nombre entier !
Donc en multipliant un entier par 2^-8 on obtient bien un nombre décimal...
 

PieM

Senior Member
Y a comme un défaut !! ... je réfléchis :confused:
.............

Effectivement !! la fatigue !!!? La mantisse est bien multipliée par l'exposant ! Sorry ... je corrige dans mon post #4

Donc à priori le calcul devient effectivement possible sans coprocesseur...

Merci de veiller au grain ! :rolleyes:
 

micro_33

New Member
Bonsoir à tous

J’apprécie vos interventions, mais, bien qu'ayant compris la procédure, je suis incapable de la mettre en œuvre, la programmation, n'étant qu'un moyen pour arriver à mes fins.
Je met en standby mon projet, le temps de comprendre comment y arriver.
Je lis avec attention vos commentaires et vous remercie de votre patience vis à vis de ma compréhension sur le sujet.

Cordialement
JP
 

BESQUEUT

Senior Member
Bon : là je suis vraiment charette donc je ne pourrai pas m'y coller avant quelques jours. PieM a toutes les chances de me GRILLER...
Maintenant que la théorie est claire, reste effectivement à mettre ça en pratique. Ce serait bien d'avoir quelques précisions :
- vos données sont-elles effectivement transmises en hexa sur la ligne série, ou bien est-ce le logiciel que vous utiliser pour lire le port série qui les affiche en hexa ?
- êtes vous à l'aise pour écrire le code qui récupère les données ? Si oui, merci de publier votre code.
- avez-vous une idée des limites minimales et maximales des valeurs lues, ce qui permettrait éventuellement de simplifier le programme. Au vu du post #1, c'est entre -1 et +1, mais exprimé en 1/1 000 000 cela revient
à -1 000 000 ==> 1 000 000 ce qui va poser pas mal de problèmes vu que le Picaxe de connait ni les nombres négatifs, ni ceux supérieurs à 65535. Si vous savez que les valeurs lues sont en réalité entre
0.0030000 et 0.0039999 il est possible de se simplifier la vie. Sinon, on fera avec : le challenge n'en est que plus intéressant...
- qu'allez vous faire du résultat obtenu ? Affichage sur un LCD ?
==> ne disposant pas de votre configuration matérielle, nous ne pouvons tester la routine de conversion que dans le simulateur. Il faut quand même autant que possible que vous puissiez fournir le plus facilement possible les données en entrée et récupérer le résultat.
Cordialement,
 
Last edited:

micro_33

New Member
Bonjour à tous

Bon : là je suis vraiment charette donc je ne pourrai pas m'y coller avant quelques jours. PieM a toutes les chances de me GRILLER...
Maintenant que la théorie est claire, reste effectivement à mettre ça en pratique. Ce serait bien d'avoir quelques précisions :
- vos données sont-elles effectivement transmises en hexa sur la ligne série, ou bien est-ce le logiciel que vous utiliser pour lire le port série qui les affiche en hexa ?
_D'après la doc, ce serait bien en hexa, je vais me connecter le plus rapidement possible à la sortie série pour vérifier cela.

- êtes vous à l'aise pour écrire le code qui récupère les données ? Si oui, merci de publier votre code.
_A l'aise est un bien grand mot, mais j'ai programmé un PIC qui me délivre 2 trames différentes et sur le second PIC, je récupère bien la bonne trame et les bonnes données.
_J'apprend au fur et à mesure qu'une routine est nécessaire, cela prend du temps, mais c'est efficace, donc pour l'instant, je fais des bouts qui correspondent aux problèmes que je me pose.
- avez-vous une idée des limites minimales et maximales des valeurs lues, ce qui permettrait éventuellement de simplifier le programme. Au vu du post #1, c'est entre -1 et +1, mais exprimé en 1/1 000 000 cela revient
à -1 000 000 ==> 1 000 000 ce qui va poser pas mal de problèmes vu que le Picaxe de connait ni les nombres négatifs, ni ceux supérieurs à 65535. Si vous savez que les valeurs lues sont en réalité entre
0.0030000 et 0.0039999 il est possible de se simplifier la vie. Sinon, on fera avec : le challenge n'en est que plus intéressant...
_Pour les limites, de 0,00 à +/-1, mais l'on peut faire de 0 à +/-100, avec seulement 1 ou 2 digits, la précision d'affichage est secondaire, c'est seulement un tendance que l'on affiche.
- qu'allez vous faire du résultat obtenu ? Affichage sur un LCD ?
_L'idéal, serait un affichage sur un galva par une commande PWM (vous allez dire,il y en a qui n'ont peur de rien).
_En effet cette valeur, qui peut changer à chaque trame, chaque seconde, indique l'erreur de la fréquence délivrée, par rapport à la valeur théorique et ce en 10-9, ou si on raisonne en entier, en 10-11 (c'est pour cela que la précision de la lecture est secondaire, on est déjà assez bas)
==> ne disposant pas de votre configuration matérielle, nous ne pouvons tester la routine de conversion que dans le simulateur. Il faut quand même autant que possible que vous puissiez fournir le plus facilement possible les données en entrée et récupérer le résultat.
Cordialement,
_En parlant du simulateur, est-il possible, lorsqu'il le demande, de rentrer les valeurs de la trame en hexa?, je les rentre actuellement en décimal.

Pour ma défense, je suis à la retraite depuis 10 ans, cela vous donne l'état de mes neurones.

Cordialement
 
Last edited:

BESQUEUT

Senior Member
OK pour toutes ces précisions, reste à trouver un couple d'heures pour s'y mettre...
On part donc sur de l'hexa, mais ce serait bien de confirmer le premier point.
Suggestion pour la sortie : un LCD (ou un OLED) 2 lignes de 16 c
1ière ligne : valeur numérique
2ième ligne : bargraph (16 niveau possibles de base, 64 en définissant des caractères spéciaux...)
Mais le galva c'est plus simple et moins cher si vous l'avez en stock...
Dans ce cas, on suppose que le 0 est à 2,5 V,
-1 * 10 puissance -9 à 0V (affichage numérique : -100)
+1 * 10 puissance -9 à 5V (affichage numérique : +100)
 
Last edited:

PieM

Senior Member
Bonjour,

Je vais essayer de m'y atteler, mais je suis aussi un peu surbooké aussi en ce moment et le week-end muguet va m'imposer un petit break ...
Au vu des dernières réponses aux questions de Besqueut, je pense qu'on va arriver à quelque chose. OK pour la sortie galvanomètre, ou plutôt voltmètre 0 - 5V . Mais il faudra le graduer, avec un zéro en milieu d'échelle pour avoir une lecture +/- 100 par exemple.

En parlant du simulateur, est-il possible, lorsqu'il le demande, de rentrer les valeurs de la trame en hexa
Apparemment ça ne marche pas !
 

BESQUEUT

Senior Member
Bon, alors c'est loin d'être optimal, mais ça à l'air de marcher :
Code:
' conversion de nombre flottant en nombre entier
' L'utilisation pour le lanceur Arianne 5 est formellement prohibé
' voir fr.wikipedia.org/wiki/vol_501_d'Ariane_5

EEPROM 0,("3BA3 3C23 3F80 BBA3 BC23 BF80")
symbol Signe=b5
symbol Entier =b6
symbol Hex1=b7
symbol Hex2=b8
symbol II=b9
symbol Indice=b10

symbol Puiss=w10
symbol Mantisse=w11



for Indice = 0 to 25 step 5

	read Indice,Hex1			; lecture de l'EEPROM
	II=Indice+1
	read II,Hex2
	gosub Hex_Entier
	b0=entier
	
	II=Indice+2
	read II,Hex1
	II=Indice+3
	read II,Hex2
	gosub Hex_Entier
	b1=entier
	
	
	gosub Float_Entier
next Indice
end

Float_Entier:		' le flottant à convertir est dans W0
	if bit7=0 then
		Signe="+"
	else
		Signe="-"
	endif

	b0=b0*2 			' shift left
	bit0=bit15			' on copie le bit de gauche de b1 dans celui de droite de b0
	b0=127-b0
	
	bit15=1			' 1 implicite à gauche de la mantisse
	
	select case b0
	case 0 : Puiss=10000
	
	case 1 : Puiss=50000
	case 2 : Puiss=25000
	case 3 : Puiss=12500	
	
	case 4 : Puiss=62500
	case 5 : Puiss=31250
	case 6 : Puiss=15625
	case 7 : Puiss=7813
	
	case 8 : Puiss=39062
	case 9 : Puiss=19531
	case 10 :Puiss=9766
	
	case 11 :Puiss=48828
	case 12 :Puiss=24414
	case 13 :Puiss=12207
	
	case >13 : Puiss=61035
	end select
	
	Mantisse=0
	Mantisse=bit15*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit14*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit13*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit12*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit11*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit10*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit9*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit8*Puiss+Mantisse
	
	select case b0
	case 0:sertxd ("Resultat=" , Signe,#mantisse)
	case <4 :  sertxd ("Resultat= " , Signe,"0,",#mantisse)
	case <8 :  sertxd ("Resultat= " , Signe,"0,0",#mantisse)
	case <11 : sertxd ("Resultat= " , Signe,"0,00",#mantisse)
	case <14 : sertxd ("Resultat= " , Signe,"0,000 0",#mantisse)
	case >13 : sertxd ("Resultat= " , Signe,"0,000 00")
	end select
return


Hex_Entier:
	sertxd ("HEX=" ,hex1,hex2)
	Entier=Hex1-48
	if Entier>9 then 
		Entier=Entier-7
	endif
	
	Hex2=Hex2-48
	if Hex2>9 then
		Hex2=Hex2-7
	endif
	Entier=Entier*16+Hex2
	
return
 

micro_33

New Member
Je ne peux m'empécher de réponder immédiatement, même si je n'ai pas d'infos spéciales, ayant travaillé au jardin ce matin.
D'abord pour vos neurones à tous les deux, çà a l'air de péter la forme, mais n'allez pas trop vite, je ne vais pas suivre, je commence à écrire la route de conversion, à l'aide de vos explications, mais je crois que je vais jouer les flemmards et prendre le tout cuit.

Merci à vous deux.

Hélas, pour l'age, j'aimerai être dans la zone que vous m'attribuez, mais j'ai 68 ans.

cordialement
JP

Ps: terrible la routine, je vous accorde quelques jours de repos pour essayer de la digérer, merci.
 
Last edited:

PieM

Senior Member
Bonjour,

Faut pas s'absenter longtemps avec Besqueut ! Il programme plus vite que son ombre ... :)

Bravo !
 

micro_33

New Member
Bonjour à tous les deux

Oh PieM, vous avez encore votre chance, la routine de Besqueut a quelques ratées, en particulier à partir des valeurs 3DA3 et plus.

Pour Besqueut :
Je n'ai pas compris comment transmettre à la routine, à la place de la ligne EEPROM, les 2 valeurs des octets récupérés par les variables du style @bptr que j'ai dans la ligne serrxd.

Si j'ai bien compris, vous travaillez par demi octets? j'avoue que j'ai du mal à suivre, mais c'est trés intructif .

Cordialement
 

PieM

Senior Member
Bonjour,

Je trouve pour 3DA3 une valeur de 0.0795898, et effectivement la routine donne un résultat différent . Mais on va bien trouver !

Quant aux octets récupérés via un @bptr, il n'y aura pas de problème puisqu'il sont déjà sous forme numérique.
Dans la routine Besqueut, ces valeurs sont rentrées sous forme de chaîne de caractère d'où la manip du "for Indice = 0 to 25 step 5" et la suite , pour la lecture de l'EEPROM.

Enfin Besqueut confirmera... ou non ! :)
 

BESQUEUT

Senior Member
Il programme plus vite que son ombre ... :)
Le problème, c'est que ne suis plus que l'ombre de moi-même...
Code:
' conversion de nombre flottant en nombre entier
' L'utilisation pour le lanceur Arianne 5 est formellement prohibé
' voir fr.wikipedia.org/wiki/vol_501_d'Ariane_5

EEPROM 0,("3DA3 3BA3 3C23 3F80 BBA3 BC23 BF80")
 ' 0.0795898  +0.005 +0.01 +1 -0.005 -0.01 -1
symbol Signe=b5
symbol Entier =b6
symbol Hex1=b7
symbol Hex2=b8
symbol II=b9
symbol Indice=b10

symbol Puiss=w10
symbol Mantisse=w11


II=0
for Indice = 1 to 6
	read II,Hex1			; lecture de l'EEPROM
	II=II+1
	read II,Hex2
	gosub Hex_Entier
	b0=entier
	
	II=II+1
	read II,Hex1
	II=II+1
	read II,Hex2
	gosub Hex_Entier
	b1=entier
	
	
	gosub Float_Entier
	II=II+2
next Indice
end

Float_Entier:		' le flottant à convertir est dans W0
	if bit7=0 then
		Signe="+"
	else
		Signe="-"
	endif

	b0=b0*2 			' shift left
	bit0=bit15			' on copie le bit de gauche de b1 dans celui de droite de b0
	b0=127-b0
	
	bit15=1			' 1 implicite à gauche de la mantisse
	
	select case b0
	case 0 : Puiss=10000
	
	case 1 : Puiss=5000
	
	case 2 : Puiss=25000
	case 3 : Puiss=12500	
	case 4 : Puiss=6250
	
	case 5 : Puiss=31250
	case 6 : Puiss=15625
	case 7 : Puiss=7813	
	case 8 : Puiss=3906
	
	case 9 : Puiss=19531
	case 10 :Puiss=9766
	case 11 :Puiss=4883
	
	case 12 :Puiss=24414
	case 13 :Puiss=12207
	case 14 : Puiss=6103
	
	case >14 : Puiss=30518
	end select
	
'	sertxd ("Puiss=",#puiss," b0=",#b0)
'	sertxd (#bit15,#bit14,#bit13,#bit12,#bit11,#bit10,#bit9,#bit8)
	
	Mantisse=0
	Mantisse=bit15*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit14*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit13*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit12*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit11*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit10*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit9*Puiss+Mantisse
	Puiss=Puiss/2
	Mantisse=bit8*Puiss+Mantisse
	
	select case b0
	case 0    :sertxd ("Resultat=" , Signe,#mantisse)
	case <2 :  sertxd ("Resultat= " , Signe,"0,",#mantisse)
	case <5 :  sertxd ("Resultat= " , Signe,"0,0",#mantisse)
	case <9 :  sertxd ("Resultat= " , Signe,"0,00",#mantisse)
	case <12 : sertxd ("Resultat= " , Signe,"0,000",#mantisse)
	case <15 : sertxd ("Resultat= " , Signe,"0,000 00",#mantisse)
	case >14 : sertxd ("Resultat= " , Signe,"0,000 000")
	end select
return


Hex_Entier:
	sertxd ("HEX=" ,hex1,hex2)
	Entier=Hex1-48
	if Entier>9 then 
		Entier=Entier-7
	endif
	
	Hex2=Hex2-48
	if Hex2>9 then
		Hex2=Hex2-7
	endif
	Entier=Entier*16+Hex2
	
return
Il y avait un dépassement de capacité dans la somme qui calcule la mantisse.
J'en ai profité pour simplifier la lecture des données de test.
Comme indiqué en commentaire, le flottant à convertir doit être placé dans W0.
C'est le but du début du programme qui converti les 4 caractères hexadécimaux en 2 octets (b0 et b1 ou w0 : c'est la même chose)
A noter que si l'exposant vaut 0, l'affichage n'est pas bon : c'est pas évident d'insérer la virgule sans les fonctions de chaines de caractères.
Dans les améliorations, il faudrait aussi traiter les puissances positives (ce qui est plus simple puisqu'elles sont directement calculables).
 
Last edited:

BESQUEUT

Senior Member
Si j'ai bien compris, vous travaillez par demi octets?
Ben le programme prends les caractères un par un, comme c'est sensé être le cas sur le port série.
Et oui, il faut deux caractères hexa pour faire un octet... (hex1 & hex2 dans le programme)
 

micro_33

New Member
bonjour à tous

Bigre que c'est dur la culture.

D'abord je me met à genoux,que dis-je, à plat ventre.

Ben le programme prends les caractères un par un, comme c'est sensé être le cas sur le port série.
Et oui, il faut deux caractères hexa pour faire un octet... (hex1 & hex2 dans le programme)
En épluchant votre routine (c'est comme l'oignon, ça me fait pleurer), je n'avais pas compris la signification de la demante : "la transmission est-elle faite en hexa", sous entendu, caractère par caractère pour chaque octet. C'est bien cela ?
Je viens de comprendre:
Ben non, c'est octet par octet càd 2 caractères à la fois.

J'analyse le fonctionnement ligne par ligne et j'essaie de réécrire la routine afin de comprendre
je vous tiens au courant de l'avancement.

JP
 

micro_33

New Member
Vu le beau temps dans la région cet aprés midi, j'ai incorporé la routine dans mon soft.

J'ai oté la partie traitant des demi-octets (hex1 et 2), je récupère bien mais signaux série (toujours en simulation),ça fonctionne bien.
Il y a encore quelques valeurs qui ne passent pas, cela va m'obliger à bien comprendre la philosophie du décodage.

JP
 

micro_33

New Member
Bonjour

Je viens de lire cela sur un forum US

The ThunderBolt data is in ASCII Hex&#65279; and needs to be converted
Pouvez vous me dire ce que cela signifie ?
Aviez vous raison pour la forme du codage série, caractère par caractère?, cela ne correspondrait pas à la longueur de la trame dont je livre un exemple.

Voici un exemple de trame relevée dans la doc.
Receive COM1 Packet ID:47 Data Length: 25
8D 00 00 00 00 00 00 00 00 00 00 00 00 3F 80 00 00 1B 19 0C 04 1D 0E 09 0F

Je suis en plein doute sur le peu que je croyais avoir compris.

voilà le code et les quelques ajustements que j'ai ajouté , un exemple de trame est en REM.
#rem
Lecture des trames Thunderbolt.
Choix de la trame 0xAC, donnée 10Mhz offset en position 20 à 23 ( 4 bytes )
#endrem

#picaxe 08M2
setfreq m8 'permet le 9600

symbol Signe=b5
symbol Entier =b6
symbol Indice=b10
symbol Puiss=w10
symbol Mantisse=w11

reception:

'trame envoyée pour simulation 16,143,172,172,7,0,0,0,0,0,0,0,0,0,128,0,0,0,0,65,66,67,68,60,163,231,199

bptr = 32 'initialise le pointeur dans la zone mémoire
serrxd ($10,$8F,$AC),@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptr
bptr = 52 'adresse contenant le premier byte du nombre recherché
b0 = @bptrinc 'byte 1
b1 = @bptrinc 'byte 2

Float_Entier: 'le flottant à convertir est dans W0
if bit7=0 then 'test signe + ou - sur le bit 7
Signe="+" 'met le signe dans b5
else
Signe="-"
endif

b0 = b0 * 2 'shift left pour n'avoir que l'exposant
bit0 = bit15 'on copie le bit de gauche de b1 dans celui de droite de b0
if bit7 = 1 then
b0=b0-127 'on calcule l'exposant
else
b0=127-b0
endif

bit15=1 ' 1 implicite à gauche de la mantisse

sertxd ("Case=",#bit7," ",#bit6," ",#bit5," ",#bit4," ",#bit3," ",#bit2," ",#bit1," ",#bit0)
select case b0
case 0 : Puiss=1'0000 pour afficher 1 et non 10 000
case 1 : Puiss=5000

case 2 : Puiss=25000
case 3 : Puiss=12500
case 4 : Puiss=6250

case 5 : Puiss=31250
case 6 : Puiss=15625
case 7 : Puiss=7813
case 8 : Puiss=3906

case 9 : Puiss=19531
case 10 :puiss=9766
case 11 :puiss=4883

case 12 :puiss=24414
case 13 :puiss=12207
case 14 :puiss=6103

case >14 : Puiss=30518
end select

sertxd ("Puiss=",#puiss," b0=",#b0)

Mantisse=0
Mantisse=bit15*Puiss+Mantisse
Puiss=Puiss/2
Mantisse=bit14*Puiss+Mantisse
Puiss=Puiss/2
Mantisse=bit13*Puiss+Mantisse
Puiss=Puiss/2
Mantisse=bit12*Puiss+Mantisse
Puiss=Puiss/2
Mantisse=bit11*Puiss+Mantisse
Puiss=Puiss/2
Mantisse=bit10*Puiss+Mantisse
Puiss=Puiss/2
Mantisse=bit9*Puiss+Mantisse
Puiss=Puiss/2
Mantisse=bit8*Puiss+Mantisse

sertxd (#bit15," ",#bit14," ",#bit13," ",#bit12," ",#bit11," ",#bit10," ",#bit9," ",#bit8)

select case b0
case 0 :sertxd ("Resultat=" , Signe,#mantisse)
case =<3 : sertxd ("Resultat= " , Signe,"0,",#mantisse)
case =<6 : sertxd ("Resultat= " , Signe,"0,0",#mantisse) 'modifié de 5 à 6
case =<8 : sertxd ("Resultat= " , Signe,"0,00")',#mantisse) 'modifié de 7 à 8
case <12 : sertxd ("Resultat= " , Signe,"0,00") 'résultat petit ne pas afficher
case <15 : sertxd ("Resultat= " , Signe,"0,00")
case >14 : sertxd ("Resultat= " , Signe,"0,00")
end select
goto reception
les différents sertxd dans le prog sont pour le test.
Je m'attelle tout de suite au hard pour voir ce que je peux lire.

Merci de votre patience

JP
 

BESQUEUT

Senior Member
Je suis en plein doute sur le peu que je croyais avoir compris.
Je m'attelle tout de suite au hard pour voir ce que je peux lire.
Au vu de la trame, si vous recevez 25 caractères, ce n'est pas de l'ASCII HEX mais directemeny du binaire.
Par contre, si vous recevez 50 caractères, tous compris entre 48 & 57 ou 65 & 68 (en décimal !), alors ce sont bien des caractères hexadécimaux écrits en ASCII.
Dans les 2 cas, vous avez les outils...
PS : quand vous publiez du code, merci d'utiliser les balises [ CODE] & [/CODE]
Je n'ai pas vérifié, mais il me semble qu'il y a une incohérence entre la valeur initiale de Puiss (premier SELECT CASE) pour les puissance -6 & -7 et le nombre de zéros (deuxième sélect case).
De même, il n'est pas logique que les puissances -4 & -5 partagent le même nombre de zéros, alors que la valeur initiale est décalée d'une puissance de 10 ?
Dans le cas de la puissance zéro, le traitement est un peu plus compliqué (comme je l'ai écrit en #23) puisqu'il faudrait intercaler une virgule entre le premier chiffre de la mantisse et les chiffres suivants.
Je ne l'ai pas fait parce que vous semblez préférer un galvanomètre à un écran LCD, et que dans ce cas, il est inutile de se casser la tête à afficher la virgule.
Ceci pose néanmoins un problème pour la "gamme" du galvanomètre. En effet :
- si le générateur PWM est calculé pour afficher les valeurs d'erreur de 0 à +- 0,99
mais que l'erreur réelle est comprise entre 0,0000 et +- 0,0099, alors le galva restera tj à zéro.

- si le générateur PWM est calculé pour afficher les valeurs d'erreur de 0 à +- 0,0099
mais que l'erreur réelle est comprise entre 0,00 et +- 0,99, alors le galva restera bloqué à 1 ou -1 (overflow)
(exactement comme un voltmètre positionné sur une gamme inadaptée à la tension mesurée)

Soit vous connaissez l'étendue réelle de l'erreur, soit il faut prévoir un commutateur de gamme, soit il faut afficher sur un LCD...

Votre solution est radicale, mais ne fonctionne que si le flottant vaut strictement 1.
Toute autre valeur comprise entre 0.1000001 et 0.9999999 sera affichée 0.0000000 ce qui ne me semble pas être le but visé...


Dans les explications de PieM, je viens de m'appercevoir qu'il n'est pas possible de coder le zéro !
Je suis donc allé voir les explications sur Internet et effectivement le zéro est codé différemment !
En fait, zéro est codé zéro...
C'est tout simple mais ça ne correspond pas au même algorithme. Il y a d'autres cas particuliers qui ne devraient pas concerner votre application.
Par contre, il me semble posible que l'erreur que vous traquez évolue de moins quelque chose à plus autre chose en passant par zéro...
Il faut donc que ce cas soit correctement traité.
A suivre donc...
 
Last edited:

BESQUEUT

Senior Member
Ou alors, dans le genre solution radicale, vous pourriez n'utiliser que l'exposant (ce qui avec un galva revient à afficher le log de l'erreur). Les graduations seraient du genre :

-1 -0.1 -0.01 -0.001 -0.0001 0 +0.0001 +0.001 +0.01 +0.1 +1 (11 valeurs de tension à calculer en fonction de l'excursion du galva)

Le calcul des valeurs intermédiaires (1024 valeurs) doit être faisable, mais il faut raisonner sur une échelle logarithmique et non linéaire, donc l'algo est un peu différent.

En fait, pour que le programme soit plus efficace, il faudrait raisonner dans l'autre sens :
A quel nombre flottant doit être associé chaque valeur de PWMDUTY de zéro à 1023 ?
-1 => 0 (0 V)
-? => 1 (0,005 V)
-? => 10 (0,05 V)
-? => 100 (0,5 V)
-? => 510 (2,495V)
0 => 511 (2,5 V)
+1 => 1023 (5 V)
 
Last edited:

BESQUEUT

Senior Member
Donc voici une version qui ne cherche pas à convertir le flottant en entier, mais juste à calculer un PWM Duty pour un galvanomètre à zéro central.
La conversion est pseudo logarithmique (approximation linéaire entre deux puissances de deux).
Mais compte-tenu de la précision demandée, c'est suffisant.
J'ai ajouté des valeurs de test : ça à l'air de bien couvrir la zone d'erreur annoncée et dans le bon ordre...
Mais ça ne veut pas dire que ce soit exempt d'erreurs...
Code:
' conversion de nombre flottant en PWM Duty
' L'utilisation pour le lanceur Arianne 5 est formellement prohibé
' voir fr.wikipedia.org/wiki/vol_501_d'Ariane_5

'EEPROM 0,("3DA3 3BA3 3C23 3F80 BBA3 BC23 BF80 0000")
 ' 0.0795898  +0.005 +0.01 +1 -0.005 -0.01 -1 zero
 
EEPROM 0, ("BF80 BF66 BF4C BF33 BF19 BF00 BECC BE99 BE4C")
'           -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2

EEPROM 45, ("BDCC BC23 BA83 B8D1 B727 B586 0000 3586 3727")
'           -0.1 -0.01 -0.001
'                          -0.000 1
'                               -0.000 01
'                                    -0.000 001
'                                         ZERO
'                                              +0.000 001
'                                                   +0.000 01

EEPROM 90, ("38D1 3A83 3C23 3DCC 3F00 3F80 3FC0 4000 4080")
'            +0.000 1
'                 +0.001
'                      +0.01
'                           +0.1
'                                +0.5
'                                     +1
'                                          +1.5 2    4




symbol Signe=b5
symbol Entier =b6
symbol Hex1=b7
symbol Hex2=b8
symbol II=b9
symbol Indice=b10

symbol Puiss=w10
symbol Mantisse=w11
symbol PWMDu=w12


II=0
for Indice = 1 to 27
	ii=indice-1*5
	read II,Hex1			; lecture de l'EEPROM
	II=II+1
	read II,Hex2
	gosub Hex_Entier
	b0=entier
	
	II=II+1
	read II,Hex1
	II=II+1
	read II,Hex2
	gosub Hex_Entier
	b1=entier
	
	
	gosub Float_Entier
next Indice
end

Float_Entier:		' le flottant à convertir est dans W0
	if bit7=0 then
		Signe="+"
	else
		Signe="-"
	endif

	b0=b0*2 			' shift left
	bit0=bit15			' on copie le bit de gauche de b1 dans celui de droite de b0
	b0=127-b0
	
	
	bit15=0	' on s'intéresse à la partie fractionnaire de la mantisse.
	if b0>14 then
		pwmdu=512
	else
		pwmdu=b0*511/14	' 511 pas jusqu'à la puissance -14
		b30=b1*36/128
		pwmdu=pwmdu-b30
		if signe="+" then
			pwmdu=1023-pwmdu
		endif
	endif
	
	sertxd ("Exp=",#b0," b1=",#b1," PWM Duty ",#pwmdu)
return


Hex_Entier:
	sertxd ("HEX=" ,hex1,hex2)
	Entier=Hex1-48
	if Entier>9 then 
		Entier=Entier-7
	endif
	
	Hex2=Hex2-48
	if Hex2>9 then
		Hex2=Hex2-7
	endif
	Entier=Entier*16+Hex2
	
return
 

micro_33

New Member
Bonjour BESQUEUT

Merci de votre "acharnement" sur le pb, mais c'est vrai que cela sort de l'ordinaire.

Je suis obligé de mettre en standby quelques jours, j'ai cassé la sortie RS de mon PC, le +15 n'existe plus, le temps de récupérer une carte.

Dès que j'ai le type de signaux en sortie du standard, je le communique.

cordialement
JP
 
Last edited:

micro_33

New Member
Bonsoir à tous

Ma simulation de lecture d'une valeur de la trame, grace à vous, avance bien, j'ai testé l'affichage sur un LCD 2 lignes, cela fonctionne en simulant un galva.

Maintenant, la capture de la trame, après bien des problèmes, l'affichage n'est plus en chinois, j'utilise l'instruction SERIN sur le port C.1 à 9600 bauds ( vitesse du 8M2 8Mhz).
La lecture des données est stable jusqu'au 10ième byte, au-delà, la position de la capture shifte de +/- 1 octet.

Pouvez vous décoder les 4 premiers octets de la trame ? , c'est celle que j'exploite.

Votre réponse me permettra de poser d'autres questions et surtout de ne pas dire trop de bétises.

Par contre, je n'arrive pas à mettre l'image en lien, mais cela semble lisible en cliquant dessus.

Merci encore pour votre aide.

JP


Trame_8F_AC_2.jpg
 

PieM

Senior Member
Bonjour,

Je pense que vous décodez en fait deux groupe de deux octets ?

0000 1000 et 1111 0001 ($08 $F1)
puis
0011 0101 et 1110 0000 ($35 $ E0) ?

Si c'est le cas , je trouve + 1.4504 -33 pour le premier, et + 1.7956 -06 pour le second....

Par contre si vous utilisez les 32 bits, le résultat serait + 1.4557 -33 au lieu de + 1.4504 -33

La différence est faible, puisque ces bits supplémentaires s'ajoutent à la mantisse, dans des poids de + en + faibles.

(la mantisse qui ne peut varier qu'entre 1 et 2 devient 1,889648438 au lieu de 1,8828125)
 
Last edited:

BESQUEUT

Senior Member
Cette donnée est sur 4 bytes (nombre simple précision).
Quoiqu'il en soit, il serait intéressant de disposer de plusieurs trames successives, ce qu permettrait de repérer les similitudes éventuelles, en particulier l'ordre de grandeur.
Par ailleurs, si une aide est souhaitée, il est nécessaire de publier l'état actuel du ou des programmes en cours de mise au point.
Cordialement,
 

micro_33

New Member
Bonjour à tous les deux

Aie, votre décodage ne m'arrange pas, je ne parle pas du calcul, car ces octets sont seulement l'entête de la trame.

Je suis surpris que vous n'inversiez pas les 2 1/2 octets ,MSB et LSB, pour obtenir la valeur finale, me trompe-je ?

Je vous ai laissé faire le décodage, car j'ai un doute sur ma manip, la lecture de la trame par mon Pic ne donne pas la même valeur que ce que l'on pourrait lire sur la trace de l'oscillo, qui elle correspond bien à la doc : $10 $143 $ 171 si on lit les bits de la gauche vers la droite ????????

De ce que j'ai pu lire sur des forums US, cet appareil ( oscillateur piloté GPS Thunderbolt) aurait des spécificités, voir ci-dessous

Structure_trame.jpg

Vous comprenez mon embarras pour lire cette trame

Merci
JP
 

PieM

Senior Member
je ne parle pas du calcul, car ces octets sont seulement l'entête de la trame.
Il aurait été judicieux de signaler que cette trame était celle d'un oscillo et non d'un analyseur logique, qu'il ne s'agissait pas de la trame de données, et de savoir de quoi était constituée la trame que vous receviez !

Si c'est la trace oscillo, alors je ne comprends pas que vous lisiez les bits de gauche à droite, le MSB étant à droite.

Le byte code <DLE> 0x10 soit 00010000 en binaire n'apparaît pas dans cette trame
et concernant les $143 $171 que vous lisez sur cette trame, ce ne sont pas des valeurs de bytes !

J'avoue ne pas comprendre grand chose ... :confused:
 

BESQUEUT

Senior Member
Si je comprends bien ce qui est dit dans ce bout de notice, c'est que l'appareil en question ne respecte pas les conventions Intel.
C'est du Big endian alors que les système x86 Intel sont en little endian
http://fr.wikipedia.org/wiki/Endianness#Big_endian

Ca n'empêche pas d'utiliser serint pour lire les octets, mais il y a un chtit traitement à faire pour remettre les bits dans le bon ordre...

Quand aux 143 et 171, merci à PieM d'expliquer ce qui pose problème ? je ne vois rien d'anormal puisque nous parlons d'un système sur 8 bits ?
http://fr.wikipedia.org/wiki/Byte

Par contre, en se référent à la même doc, la trame est incomplète : il faudrait plus d'octets.
La doc elle-même est incomplète : il n'est pas fait mention des nombres flottants.
 
Last edited:

micro_33

New Member
Re bonjour

Ah il vous faut de la patience.
C'est vrai que le demandeur est pénible, il s'imagine que vous voyez et savez tout, sur ce que l'on ne vous dis pas.

Merci Besqueut pour les précisions
Pour PieM merci également, oui j'avais gaffé avec le $ devant les valeurs décimales, sorry

Bon, j'ai modifié mon post, je n'avais pas vu les réponses, je vois que c'est truc pénible, je ne vais pas d'avantage vous ennuyer.

Merci pour le travail que vous avez effectué, je reviendrai peut être si le besoin s'en fait sentir.

Cordialement
JP
 
Last edited:

BESQUEUT

Senior Member
je vois que c'est truc pénible, je ne vais pas d'avantage vous ennuyer.
Y a pas de problème : on n'est pas obligé de répondre ; et c'est d'ailleurs ce que j'ai fait pour un thread où l'auteur ne lisait pas les réponses faites.

Franchement, ce serait dommage d'abandonner si près du but, et nous avons tous hate de voir le bidule fonctionner !

J'ai quand même pu lire la version primitive de votre message...
En gros, ce n'est pas anormal, mais ce n'est pas comme celà que fonctionne un PC (et donc un Picaxe...)
Donc, il faut ajouter quelques lignes de code pour remettre les bits dans l'ordre. Rien de bien méchant (voir commande REV page 24 du manuel)
Je n'ai par contre pas eu le temps de récupérer votre code. Merci de le remettre en ligne.
Cordialement,
 
Last edited:
Top