[PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné
Répondre à la discussion
Affichage des résultats 1 à 21 sur 21

[PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné



  1. #1
    Shantorian

    [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné


    ------

    Bonjour à tous,

    Après des heures de recherches, je ne trouve pas de réponses à mon problème.

    J'exploite et je traite un signal reçu sur la voie série, rien de bien compliqué.

    Je souhaite en faire une transformée de Fourrier.

    Les valeurs recues sont des tensions analogiques déjà échantillonnées par un CAN 16 bits, à 25Hz. Je convertis ces valeurs en un signal d'angle en fonction du temps.

    J'ai donc un tableau de valeurs et un tableau des temps correspondants.

    Comment à partir de ces deux tableaux faire un FFT grâces aux bibliothèques disponibles sous python ?

    Avec un signal continu, et un échantillonnage j'ai trouvé ce programme que je comprends à peu près ( pas assez pour l'adapter à mon problème).

    Sauriez-vous m'aider ?

    Merci d'avance !

    Code:
    # programme d'experimentation FFT FFTExperience1-0
    # Dominique Lefebvre pour TangenteX.com
    # 12 aout 2014
    #
    
    # importation des librairies
    from numpy import pi, sin, linspace, log10
    from numpy.fft import fft, fftfreq
    import matplotlib.pyplot as plt       
    
    # d�finition des constantes du signal
    K = 2*pi       # facteur conversion p�riode/fr�quence
    A0 = 4         # amplitude fr�quence fondamentale
    A1 = 8         # amplitude premi�re harmonique
    f0 = 2         # fr�quence fondamentale (Hz)
    f1 = 8         # fr�quence premi�re harmonique (Hz)
    
    # d�finition temporelle du signal
    t0 = 0         # d�but de l'acquisition du signal
    t1 = 10        # fin de l'acquisition (s)
    
    # d�finition des param�tres d'�chantillonnage
    FreqEch = 1024                  # fr�quence d'�chantillonage
    PerEch = 1./FreqEch             # p�riode d'�chantillonnage
    N = FreqEch*(t1 - t0)           # nombre de points �chantillonn�s sur l'intervalle
    
    # d�finition du temps
    t = linspace(t0, t1, N)
    
    # d�finition du signal
    signal = A0*sin(f0*K*t) + A1*sin(f1*K*t)
    
    # d�finition des donn�es de FFT
    FenAcq = signal.size             # taille de la fenetre temporelle
        
    # calcul de la TFD par l'algo de FFT
    signal_FFT = abs(fft(signal))    # on ne r�cup�re que les composantes r�elles
    
    # r�cup�ration du domaine fr�quentiel
    signal_freq = fftfreq(FenAcq,PerEch)
    
    # extraction des valeurs r�elles de la FFT et du domaine fr�quentiel
    signal_FFT = signal_FFT[0:len(signal_FFT)//2]
    signal_freq = signal_freq[0:len(signal_freq)//2]
    
    #affichage du signal
    plt.subplot(211)
    plt.title('Signal et son spectre')
    plt.ylim(-(A1+5), A1+5)
    plt.plot(t, signal)
    plt.xlabel('Temps (s)'); plt.ylabel('Amplitude')
    
    #affichage du spectre du signal
    plt.subplot(212)
    plt.xlim(0,f1+5)
    plt.plot(signal_freq,signal_FFT)
    plt.xlabel('Frequence (Hz)'); plt.ylabel('Amplitude')
    #plt.title('Signal et son spectre')
    plt.show()
    Voilà ce que je veux pour mon signal : figure_1.png

    Voici mon code python et l'allure de mon signal :

    Code:
    import serial 
    import matplotlib.pyplot as plt
    import time
    import numpy as np
    from numpy.fft import fft, fftfreq
     
    signal=[]
    temps=[]
     
    serie=serial.Serial('COM5',9600) 	# ouvre une liaison serie en 9600bps											
    
    plt.style.use('bmh')
    plt.ylabel("Delta (°)")
    plt.xlabel("Temps (sec)")
     
    plt.ion() 			# on entre en mode interactif
    start=time.time()	# mesure de l'instant initial
    
    i=0
    while (i<400):
    
        mesure1, mesure2 = map(float, serie.readline().split()) #lit la donnee sur la laison serie
        
        angle1 = mesure1 / (1/180)  #conversion tension - degrés (2V = 360°)
        angle2 = mesure2 / (1/180)
        
        if i == 3:       #les premières mesures ne sont pas fiables
            ref = (angle2-(angle1)*(1/25)) #différence entre theta et theta_theorique
        
        
        if abs(angle1) <= 1: 
            ref = (angle2-(angle1)*(1/25))
        
        instant=time.time()-start	# calcul du temps ecoule depuis l'instant initial
        if i >= 3:                   
        
        
            temps.append(instant)		# ajout de instant a la liste des temps
            valeur = (angle2-(angle1)*(1/25))-ref #on veut un écart autour de 0
            if abs(valeur) >= 1.5:
                valeur = 0
            
            signal.append(valeur) 
            print(valeur,instant)      # affiche dans la console les coordonnees du point
            
            
        plt.plot(temps,signal,marker='')  # trace la courbe
        plt.draw()                     # affiche la courbe en mode interactif
        i=i+1
        
    
    plt.show()
    plt.ioff() 		# on quitte le mode interactif pour rendre la main a l'utilisateur sur la courbe
    figure_1bis.jpg

    -----
    Dernière modification par Shantorian ; 28/09/2017 à 20h59.

  2. #2
    CM63

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Bonjour,

    Juste une précision (car je n'en connais pas davantage sur la question) : pour utiliser la FFT il faut que ton signal soit échantillonné sur un nombre de points qui soit une puissance de 2 : 2048 points ou 4096 points, etc. Si on ecrit les formules on s'aperçoit qu'il y a des termes qu'on calcule plusieurs fois, la technique de la FFT s’arrange pour ne les calculer qu'une fois.

  3. #3
    polo974

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Citation Envoyé par Shantorian Voir le message
    Bonjour à tous,
    ...
    Je souhaite en faire une transformée de Fourrier.

    Les valeurs recues sont des tensions analogiques déjà échantillonnées par un CAN 16 bits, à 25Hz. Je convertis ces valeurs en un signal d'angle en fonction du temps.

    J'ai donc un tableau de valeurs et un tableau des temps correspondants.
    ...
    Bonjour,
    d'un coté, tu dis avoir un signal échantillonné à 25 Hz, de l'autre tu as 2 tableaux dont l'un "des temps correspondants".
    la question est as-tu systématiquement un échantillon tous les 25 ième de seconde?
    si oui, le tableau temps n'apporte rien.
    si non, il faut l'utiliser pour interpoler les "points manquants".

    selon le temps d'échantillonnage (et donc le nombre d'échantillons),tu pourras avoir une résolution en fréquence plus ou moins grande.

    à part ça, il faut bien penser à appliquer un fenêtrage à ton échantillon avant de le jeter dans la fft, sinon, les ruptures en bout de tableau vont te polluer l'analyse.
    Jusqu'ici tout va bien...

  4. #4
    Shantorian

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Merci de m'avoir répondu.

    Non le problème c'est que le signal issu du CAN est échantillonné, seulement les irrégularités des transmissions du la voie série, la vitesse de traitement (arduino + python) font que je n'ai pas une mesure exactement toutes les 1/25 sec..

    Je ne vois pas trop comment faire, merci pour la précaution du fenêtrage.

    Ce type de calcul est-il plus simple avec Matlab, ou d'autres logiciels capables de communiquer sur la voie série ? Je sais seulement coder un peu en python et en C.

  5. A voir en vidéo sur Futura
  6. #5
    Jack
    Modérateur

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Non le problème c'est que le signal issu du CAN est échantillonné, seulement les irrégularités des transmissions du la voie série, la vitesse de traitement (arduino + python) font que je n'ai pas une mesure exactement toutes les 1/25 sec..
    Ca n'a aucun rapport: si le convertisseur échantillonne à 25 Hz, les mesures sont effectués toutes les 1/25èmes de secondes à la précision de l'horloge du convertisseur.

  7. #6
    polo974

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Bonjour,
    je n'avais pas lu ton code pour le moment.
    je vois que tu reçois des couples de valeurs, à quoi correspondent-elles (grandeurs et unités)?
    tu fais des calculs affreux:

    angle2 = mesure2 / (1/180) # heureusement qu'en pyhton3 (1/180) ne donne pas 0 comme python2...
    angle2 *= 180 # c'est plus clair, non ? ? ? en tout cas ça économise 2 divisions (rappelez-vous comme c'est pénible une division...)

    sinon, tu pouvais déclarer hors la boucle
    kangulaire=180.

    et faire ensuite dans la boucle
    angle2 *= kangulaire

    et puis:
    ref = (angle2-(angle1)*(1/25))
    tu divises (seulement) angle1 par 25 est-ce bien ce que tu veux faire ?
    ou bien est-ce 1/25 pour le 25 échantillons par seconde, qui doit s'appliquer partout

    du coup, autant le mettre dans le kangulaire...
    kangulaire = 180./25.

    la liste temps est totalement inutile (sauf à vouloir détecter un endormissement du PC...).

    le pb est comment détectes-tu un dépassement de buffer coté arduino (car peu de mémoire dans ces petits trucs, et parfois le PC s'occupe d'autre chose)... (il faut espérer que ce n'est pas pour une mesure destructive (donc lourde à reproduire)).
    Jusqu'ici tout va bien...

  8. #7
    Shantorian

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Citation Envoyé par Jack Voir le message
    Ca n'a aucun rapport: si le convertisseur échantillonne à 25 Hz, les mesures sont effectués toutes les 1/25èmes de secondes à la précision de l'horloge du convertisseur.
    Je suis d'accord, mais je constate que la période temporelle n'est pas exactement de 1/25 secondes de manière assez irrégulière.

    polo974 :

    Les valeurs sont des tensions lues avec un potentiomètre, converties en angles car je mesures des irrégularités de transmissions entre engrenages.

    En effet, j'aurais du y penser : j'ai recrée un fausse liste des temps (avec le bon pas constant théorique) et ça fonctionne (le résultat n'est pas très exploitable car mon tableau de valeurs n'est pas assez important pour faire apparaître des périodicité je pense. Néanmoins on distingue des pics prédits par l’étude théorique du système donc a priori l’algorithme me renvoie une bonne FFT malgré le fait que les valeurs ne soient pas mesurées tous les 1/25ème de sec.. )


    Nom : FFT1.jpg
Affichages : 921
Taille : 76,0 Ko
    Dernière modification par Shantorian ; 10/10/2017 à 22h54.

  9. #8
    Jack
    Modérateur

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Citation Envoyé par Shantorian Voir le message
    Je suis d'accord, mais je constate que la période temporelle n'est pas exactement de 1/25 secondes de manière assez irrégulière.
    Dans ce cas, c'est que tu as mal configuré ton ADC ou son horloge. C'est tout l'intérêt d'utiliser une horloge hardware pour ce type d'opération: la période est invariablement la même pour tous les échantillons.

    PS: à quoi vois-tu que la période varie?

  10. #9
    Shantorian

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    A la sortie de l'ADC, la période est parfaite, mais dans mon algo c'est python qui mesure la période en mesurant le temps entre deux données reçues sur la voie série. Mon CAN est bien un circuit physique avec une horloge externe, ce n'est pas l'arduino qui joue le role de CAN (son CAN est de seulement 8bits)


    Je vois qu'elle varie car quand je prends mon tableau temps dans le code et que je fais temps[i+1]-temps[i] ça ne fait jamais là même chose (à quelques millièmes de secondes, mais je travaille avec des valeurs faibles donc ça peut jouer peut être ?)
    Dernière modification par Shantorian ; 10/10/2017 à 23h50.

  11. #10
    Jack
    Modérateur

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Citation Envoyé par Shantorian Voir le message
    A la sortie de l'ADC, la période est parfaite, mais dans mon algo c'est python qui mesure la période en mesurant le temps entre deux données reçues sur la voie série.
    C'est une très mauvaise idée qui ne présente aucun intérêt. Tu n'as pas besoin de connaitre l'heure absolue de chaque échantillon. Il suffit de considérer que chaque échantillon est prélevé toutes les 1/25èmes de seconde et c'est tout.

  12. #11
    polo974

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    je ne comprends toujours pas ce qui rentre:
    Code:
    mesure1, mesure2 = map(float, serie.readline().split()) #lit la donnee sur la laison serie
    tu lis 2 valeurs par ligne, que représentent-elles?
    as-tu un double potar sinus/cosinus? (il faut alors calculer la position angulaire avec un poil de trigo)

    as-tu un simple potar à réponse linéaire (donc en dent de scie quand on reboucle) ? donc 2 échantillons temporels sur la même ligne ? (il faut gérer le passage de la "dent de scie".

    normalement, tu as un angle absolu, il faut faire une différence entre 2 échantillons continus pour ramener ça en vitesse angulaire ( et gérer les passages de la "dent de scie" (en gros pas de valeur négative)).

    sinon, au lieu de traiter en temps réel, commence par enregistrer "un certain temps" dans un fichier, et ensuite analyse ce que tu lis, ce que tu en fais, etc... (python a un module csv assez simple à employer pour enregistrer/lire (même moi j'y arrive...))
    (et puis, du coup, tu peux même nous faire profiter d'un jeu de test...)
    Jusqu'ici tout va bien...

  13. #12
    Shantorian

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Citation Envoyé par Jack Voir le message
    C'est une très mauvaise idée qui ne présente aucun intérêt. Tu n'as pas besoin de connaitre l'heure absolue de chaque échantillon. Il suffit de considérer que chaque échantillon est prélevé toutes les 1/25èmes de seconde et c'est tout.
    Effectivement... Je corrige mon algorithme.


    polo974 :

    Les deux valeurs sont deux tensions entre 0 et 2V mesurées par les potentiomètres je les convertis en angle. J'ai une expression qui me donne l'écart entre la valeur théorique de theta2 ( le deuxième angle) et la valeur mesurée en fonction theta1 et theta 2, donc en fonction des deux tensions issues des potentiomètres, je l'utilise dans mon algo.

    Cet écart est relatif il oscille donc autour de 0, les passages à la dents de scie sont gérés au niveaux hardware (suiveurs) et softaware (cf mon signal, pourtant passé par plusieurs "dents de scie").

    Pour ce qui est du signal, l’algorithme renvoie bien ce que je veux, tout est cohérent avec la théorie.

    Je ne vais pas rentrer dans les détails car mon problème fait partie d'une manipulation plus grande, mais pour résumer, chaque potentiomètre est branché sur un axe, les deux axes sont reliées par un liaison mécanique (roue - vis sans fin), et un des deux axes est entraîné par un moteur. La liaison mécanique présente des erreurs de transmission qui font qu'il existe un écart entre la position théorique et la position pratique (angulaire donc) sur le deuxième axe.

    Cette erreur est mon signal en degrés par secondes.

  14. #13
    Shantorian

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Désolé pour le doublon, j'ai oublié d'ajouter : en fait c'est une étude globale et une correction des erreurs périodiques dans les télescopes par analyse prédictive si jamais vous voulez plus de détails.

  15. #14
    polo974

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Ok, ça s’éclaircit...
    Tu as donc 2 angles normalement linéairement liés, mais pour de "sombres problèmes de la vraie vie", il y a des non linéarités et c'est ça qui t'intéresse...

    Sauf erreur, ta roue de vis sans fin fait 25 dents (vu la division par 25 sur un des angles).

    Finalement, la dimension temps n'est même pas nécessaire dans tes calculs, tu pourrais te baser sur un des angles, ce qui t'isolerait de la variation de vitesse d’entraînement (au cas où la vitesse de ton moteur ne serait pas régulière, genre le moteur ralenti lors de la rotation d'un truc pas équilibré). (Mais alors, il faudrait ré-échantillonner pour faire une fft)...
    Jusqu'ici tout va bien...

  16. #15
    Shantorian

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Oui je me base sur un des angles (d'où 2 potentiomètres), je ne connais même pas la fonction de transfert de mon moteur... C'est juste un moteur DC que je commande en tension !

    Dès que je retourne sur cette manip, je pourrai vérifier si la FFT ainsi faite est concluante.

    C'est vrai que le temps est inutile, je m'étais basé sur un programme modifié, je n'avais pas assez réfléchi. Cependant dans mes calcul le temps n'intervient pas (cf mon programme) hormis ce problème de FFT mais qui semble résolu.

    Merci à vous !
    Dernière modification par Shantorian ; 12/10/2017 à 14h32.

  17. #16
    Shantorian

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Citation Envoyé par polo974 Voir le message
    (Mais alors, il faudrait ré-échantillonner pour faire une fft)...
    Comment ça ?

  18. #17
    polo974

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    en prenant une des voies comme référence, si ton moteur n'est pas régulier, le pas ne le sera pas non plus, disons que si tu as en moyenne un delta de (au hasard) 10° entre chaque mesure, en fait tu peux avoir une suite du genre 10, 10.5, 10.25, 10, 9.5, si ta vitesse varie de 5%...

    En gros, tu places des erreurs non pas au pas de 10°, mais de 10 +/- 0.5°, et en toute logique, ça va étaler ou décaler (déphaser) le résultat (imagine que le moteur ralentisse au moment ou il y a plus de frottement dans un cycle complet puis ré-accélère après, le temps, donc l'indice de l'échantillon n'est plu linéairement lié à la positon angulaire de référence.

    Bref, tu as potentiellement une erreur (de second ordre) sur le résultat...

    Pour vérifier, le plus simple est de forcer le "bug", en ralentissant le moteur par exemple en modulant avec la position angulaire de sortie (une foi dans un sens, une fois dans l'autre...).
    Jusqu'ici tout va bien...

  19. #18
    Shantorian

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Merci pour la remarque, en effet ça pourrait être une piste d'amélioration.

    Je vais me contenter de la correction au premier ordre, mon moteur n'a pas l'air de fluctuer et la FFT me donne un fréquence suffisamment prédominante pour négliger le reste avec mes critères de précision !

    Nom : 250 sec.jpg
Affichages : 888
Taille : 64,0 Ko

  20. #19
    minushabens

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    Citation Envoyé par polo974 Voir le message
    angle2 *= 180 #

    sinon, tu pouvais déclarer hors la boucle
    kangulaire=180.

    et faire ensuite dans la boucle
    angle2 *= kangulaire
    ma question est sûrement bête (je ne connais pas du tout python) mais je la pose tout de même: quelle différence cela fait-il ? (multiplier par la constante 180 ou par le contenu de la variable kangulaire).

  21. #20
    polo974

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    python va réinterpréter à chaque boucle "argh, il faut que je prenne ce truc en base 10 pour le mettre dans un flottant"
    alors que si tu le fais au début, c'est rangé, et on n'en parle plus.

    de plus si plus bas tu veux reprendre cette variable dans un autre calcul et que plus tard, tu te rendes compte que c'est pas 180 mais 179, t'as un seul endroit à modifier... (bon, d'accord, c'est rare que le nombre de degrés change dans un demi tour, mais c'est une bonne habitude à prendre)

    regrouper les constantes ou quasi constantes te permet de ne retoucher que très peu de ton code si tu fais des ajustements.
    (genre, je change le nombre de dents d'un engrenage)
    et déclarer ça au début permet de mettre la formule complète sans raccourci et avec un peu de commentaires alors que si tu répètes ça partout, ça craint...

    à partir du moment où un truc est répété plus que 2 fois, il faut se poser des questions car le copié/collé, c'est le mal ...

    (argh, je dois reprendre mon code...)
    Jusqu'ici tout va bien...

  22. #21
    minushabens

    Re : [PYTHON] Transformée de Fourrier discrète sur un signal déjà échantillonné

    ok merci. L'aspect "programmation propre" je voyais mais je ne savais pas que ça changeait le temps d'exécution.

Discussions similaires

  1. Questions traitement de signal, transformée de fourrier
    Par UknownStudent dans le forum Mathématiques du supérieur
    Réponses: 8
    Dernier message: 26/11/2015, 17h36
  2. transformée de Fourrier
    Par wiwi24 dans le forum Mathématiques du supérieur
    Réponses: 11
    Dernier message: 19/12/2012, 17h47
  3. transformee de fourrier
    Par invite24599369 dans le forum Mathématiques du supérieur
    Réponses: 2
    Dernier message: 05/07/2012, 18h36
  4. Transformée de Fourrier
    Par invite715b0c13 dans le forum Électronique
    Réponses: 3
    Dernier message: 13/12/2006, 18h42