Code GRAY

Python est le langage de prédilection du Raspberry Pi

Modérateurs : Francois, Manfraid

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Code GRAY

Message par MSG » lun. 3 févr. 2020 20:01

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 .

Bud Spencer
Raspinaute
Messages : 1090
Enregistré le : lun. 15 août 2016 21:38

Re: Code GRAY

Message par Bud Spencer » mar. 4 févr. 2020 11:29

Kado ;)
decbingray.png
decbingray.png (94.77 Kio) Vu 12754 fois
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Re: Code GRAY

Message par MSG » mar. 4 févr. 2020 18:57

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:

Bud Spencer
Raspinaute
Messages : 1090
Enregistré le : lun. 15 août 2016 21:38

Re: Code GRAY

Message par Bud Spencer » mar. 4 févr. 2020 19:32

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 12725 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)
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Re: Code GRAY

Message par MSG » mer. 5 févr. 2020 09:40

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 ! ;)

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Re: Code GRAY

Message par MSG » jeu. 6 févr. 2020 16:09

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
Modifié en dernier par MSG le jeu. 6 févr. 2020 17:43, modifié 1 fois.

Bud Spencer
Raspinaute
Messages : 1090
Enregistré le : lun. 15 août 2016 21:38

Re: Code GRAY

Message par Bud Spencer » jeu. 6 févr. 2020 17:42

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
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).

MSG
Raspinaute
Messages : 119
Enregistré le : ven. 26 déc. 2014 18:31

Re: Code GRAY

Message par MSG » jeu. 6 févr. 2020 17:49

le N( ) pour remplacer le SI( ) , ça doit marcher en N(OUX( ))/b]

Bud Spencer
Raspinaute
Messages : 1090
Enregistré le : lun. 15 août 2016 21:38

Re: Code GRAY

Message par Bud Spencer » jeu. 6 févr. 2020 19:39

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
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).

Artemus24
Raspinaute
Messages : 1093
Enregistré le : ven. 15 sept. 2017 19:15

Re: Code GRAY

Message par Artemus24 » ven. 7 févr. 2020 17:02

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.

@+
RPI4B/8GB + Argon FanHAt
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32

Répondre

Retourner vers « Python »