Page 1 sur 4

Code GRAY

Posté : lun. 3 févr. 2020 20:01
par MSG
Bonsoir ,

Il y a très longtemps , dans l'idée de construire une station météo , j'avais commencé par réalisé une girouette électronique .

Pour se faire , j'ai encoder sur un disque (vieux CD avec un filtre papier collé dessus) un code binaire Gray que je monte sur un axe .
Quelques Opto-coupleurs réfléchissants CNY70 pour lire la position sans frottements et le tour est joué .
Coté décodage , un 4514 ou un 4515 (mutiplexeur 1 parmi 15) et des leds branchés en fil volant .
Ça permet d'avoir 16 points cardinaux en lisant un binaire de 4 bits .

Désirant reprendre le projet mais avec un décodage logiciel , je me suis penché sur ce fameux code GRAY .
C'est pas encore le printemps , mais j'ai des idées qui bourgeonnes avec les beaux jours . :D

Après quelques tâtonnements , j'ai réussi à trouver la logique et à pondre le code d'encodage et le plus important , le décodage de ce fameux code binaire GRAY.
Je ne dirais pas merci à Wikipédia !!!

Je le met ici pour ceux que ça intéresserait :
Je n'ai pas vu de projet station météo avec girouette !!!

Code : Tout sélectionner

#!/usr/bin/python3

def Gray (valeur, decode=False) :
    """
    valeur = nombre décimal entier
    decode = False, True, 0, 1 
     
    Encodage : Bin => Gray
       Deux bits consécutifs identiques = 0
       Deux bits consécutifs différents = 1
    
    Décodage : Gray => Bin
       En partant de la gauche (MSB) , on additionne les bits lus
       Si la somme est un nombre pair   = 0 
       Si la somme est un nombre impair = 1
     
    Liste des 8 premiers codes
     
           Bin  , Gray                       210
       0 ,   00 ,   0 , 0 , eteint le bit 2  ---  
       1 ,   01 ,   1 , 1 , allume le bit 0  --█  
       2 ,  010 ,  11 , 3 , allume le bit 1  -██  
       3 ,  011 ,  10 , 2 , eteint le bit 0  -█-  
       4 , 0100 , 110 , 6 , allume le bit 2  ██-  
       5 , 0101 , 111 , 7 , allume le bit 0  ███  
       6 , 0110 , 101 , 5 , eteint le bit 1  █-█  
       7 , 0111 , 100 , 4 , eteint le bit 0  █--  
     
    Chronologiquement , 1 seul bit est permuté en code Gray
    """
     
    
    if decode :     # décodage 
        dec = somme = 0
        l = len(bin(valeur)[2:])        # nombre de bits à traiter
        mb = 2** l >> 1                 # masque du bit à lire
        for n in range (l) :
            somme += (valeur & mb) > 0
            dec =  (dec << 1) + (somme & 0b1)
            mb >>= 1                    # masque du bit suivant à droite
        return dec
    else :          # encodage    
        enc = 0
        for n in range (len(bin(valeur)[2:])) :
            bits = valeur & 0b11
            enc += 2 ** n * (bits is 0b01 or bits is 0b10)
            valeur >>= 1
        return enc
PS , ça peut servir aussi pour gérer le positionnement d'un rotor en azimut .

Re: Code GRAY

Posté : mar. 4 févr. 2020 11:29
par Bud Spencer
Kado ;)
decbingray.png
decbingray.png (94.77 Kio) Vu 14307 fois

Re: Code GRAY

Posté : mar. 4 févr. 2020 18:57
par MSG
Bonjour ,

On dit que la nuit porte conseil , j'ai repris mon code pour simplifier et avoir les fonctions séparés , ça donne ça :

Code : Tout sélectionner

#!/usr/bin/python3

def Gray_encode (nombre):   # encodage Gray
    encode = 0
    position = 1                                    # position du bit à droite
    while nombre :
        bits = nombre & 0b11                        # prend le couple de bits à droite
        difference = bits is 0b01 or bits is 0b10   # teste les différents
        encode += position * difference             # ecrit le bit correspondant
        position <<= 1                              # position ecriture du bit suivant
        nombre >>= 1                                # passe au couple de bits suivant
    return encode



def Gray_decode (nombre):   # décodage Gray
    decode = parite = 0
    position = 2** (len(bin(nombre)[2:]) - 1)   # position du bit le plus à gauche
    while position :
        parite ^= (nombre & position) > 0       # teste et bascule la parité
        decode += position * parite             # ecrit le bit correspondant
        position >>= 1                          # passe au bit suivant
    return decode



#
# Test 
#

for n in range (16):
    if not(n) : print ("Dec , Gray , Dec ,  Binaire , GrayCode")
    a = Gray_encode (n)
    b = Gray_decode (a)
    print ("%3i , %4i , %3i , %8s , %8s" %(n, a, b, bin(n)[2:], bin(a)[2:]))

Image

Bha oui , je suis bête ... l'encodage Gray , est tout bête (2 lignes seulement) . :D
Je me suis bien compliqué , mais ça marche .
Le décodage c'est pareil , à part que je suis trop bavard .

Comme on dit , pourquoi faire simple quand on peut faire compliqué ! :mrgreen:

Re: Code GRAY

Posté : mar. 4 févr. 2020 19:32
par Bud Spencer
MSG a écrit :
mar. 4 févr. 2020 18:57
...
Bha oui , je suis bête ... l'encodage Gray , est tout bête (2 lignes seulement) . :D
...
la conversion en gray c'est juste l'xor d'un décalage à droite. Quand j'en ais besoin, je le fait rapidos sous Excel
grayxls.png
grayxls.png (13.01 Kio) Vu 14278 fois
b2 = 0, c2 =b1,d2 =c1,e2 =d1
b3 =SI(OUX(B1;B2)=VRAI;1;0), C3 =SI(OUX(C1;C2)=VRAI;1;0), D3 =SI(OUX(D1;D2)=VRAI;1;0), E3 =SI(OUX(E1;E2)=VRAI;1;0)

Re: Code GRAY

Posté : mer. 5 févr. 2020 09:40
par MSG
Bonjour ,

Oui , j'ai compris !
Mon code fait l'encodage en série ( paire après paire ), donc plus long que le votre , en encodage parallèle ( mot_décale XOR mot ) donc plus rapide car seulement deux opérations .

Merci pour le tuyau ! ;)

Re: Code GRAY

Posté : jeu. 6 févr. 2020 16:09
par MSG
Bonjour ,

Sous Libre Office , c'est plus simple B3 = N ( XOR (B1;B2)) etc (y a qu'à tirer la formule vers la droite) , pas besoin de passer par les indiens ( SI(OUX ) :D

Image ;)

Format pour peindre les cases à 1
Décodage binaire par calcul : bit = mod( ent( n / rang); 2)
rang = 8,4,2,1

Re: Code GRAY

Posté : jeu. 6 févr. 2020 17:42
par Bud Spencer
MSG a écrit :
jeu. 6 févr. 2020 16:09
Sous Libre Office , c'est plus simple B3 = N ( XOR (B1;B2)) etc (y a qu'à tirer la formule vers la droite) , pas besoin de passer par les indiens ( SI(OUX ) :D
C'est pareil dans excel. j'avais juste simplifié la formule me faisait la coloration des cells 1 en noir et les 0 en blanc.
La seule différence, c'est quand dans excel en Français, ce n'est XOR mais OUX

Re: Code GRAY

Posté : jeu. 6 févr. 2020 17:49
par MSG
le N( ) pour remplacer le SI( ) , ça doit marcher en N(OUX( ))/b]

Re: Code GRAY

Posté : jeu. 6 févr. 2020 19:39
par Bud Spencer
MSG a écrit :
jeu. 6 févr. 2020 17:49
le N( ) pour remplacer le SI( ) , ça doit marcher en N(OUX( ))
C'est ce que t'ais écrit au dessus. Ca fonctionne puisque N() converti une valeur en nombre. C'est juste que dans mon fichier original, je n'écrit pas juste 1 ou 0 mais j'appel une fonction qui colore la cellule et qui me set des variables dans un vba pour d'autres usages. Pour simplifier l'exemple, J'ai juste fais un copié coller des cellules et remplacé l'appel de mes fonctions par 0 et 1

Re: Code GRAY

Posté : ven. 7 févr. 2020 17:02
par Artemus24
Salut à tous.

Je viens de jeter un coup d’œil à wikipedia, et je confirme que ce n'est pas clair du tout.
--> https://fr.wikipedia.org/wiki/Code_de_Gray

Si l'on regarde bien la construction du code de gray par colonne, hormis le début, on a :

colonne N°0 (celle qui est la plus à droite), il y a toujours une alternance de deux 0 puis de deux 1.
colonne N°1, il y a toujours une alternance de quatre 0 puis de quatre 1.
colonne N°2, il y a toujours une alternance de huit 0 puis de huit 1.
et ainsi de suite.

Et cette alternance de 1, commence pour la :
colonne N°0 par 1 zéro
colonne N°1 par 2 zéro
colonne N°2 par 4 zéro
colonne N°3 par 8 zéro
et ainsi de suite.


Inverser pour obtenir un nouveau nombre
Pas compréhensible du tout. Si quelqu'un sait faire, je suis preneur d'explication plus compréhensible.

Avec la symétrie
Cette méthode est compréhensible car il y a bien un effet miroir à partir de l'axe de symétrie.
Puis ensuite, ajouter la colonne de gauche, en mettant 0 si pas effet miroir et 1 si effet miroir.
Cela peut se programmer par récursivité.

Selon la parité
Au lieu du dernier, chiffre, le mieux est de dire que c'est le premier bit, celui à droite qu'il faut inverser.
Je n'ai pas testé, donc je ne sais pas si cela fonctionne.

Avec le OU exclusif
La méthode fonctionne.

Je me demande s'il existe une approche plus courte !
Voire même si on peut construire le code de gray à partir de son rang i, sans passer par les valeurs intermédiaires.

@+