TIPE - Contrôle non destructif par courants de Foucault

TIPE : Courants de Foucault

    Sommaire :

  1. Présentation du problème

    1. Présentation
    2. Frontières de l'étude
    3. Géométrie du problème
    4. Contraintes du sujet
  2. Méthode analogique : pont de Maxwell

    1. Protocole
    2. Présentation montage
    3. Résultats obtenus
    4. Conclusion
  3. Méthode numérique

    1. Présentation du programme
    2. Importance du filtrage numérique
    3. Résultats obtenus
    4. Rajouter Bloc
  4. Conclusion

    1. Confrontation des méthodes expérimentales
    2. Critique des résultats
    3. Pour aller plus loin
    4. Ici aussi
  1. Présentation du problème

    1. Présentation

      On veut détecter une fissure dans un matériau conducteur. Pour cela on va faire passer un courant de foucault à travers le métal par induction grace à une bobine ce qui créera un changement d’induction et de résistance interne de la bobine. En mesurant ces variations, on pourra déterminer le courant de foucault circulant dans le matériau. En cas de fissure, on a une chute conséquente et mesurable du courant de foucault, ce que l’on tachera de mesurer. Nous expérimenterons trois méthodes de détection que l’on comparera après.

        Défauts surfaciques ou internes (Dumont-Fillon 1996)
      • Surfacique :plus problématique : peut mener à des fissures et une rupture d’aspect
      • Interne  :peut altérer la santé du matériau
      Répartition des courants de Foucault dans une pièce en fonction de la profondeur z
    2. Frontières de l'étude

      On s’intéresse à la détection de microfissures dans un matériau conducteur par la mesure de courants de foucault induits par une bobine à sa surface. Nous allons nous limiter à de franches fissures à travers le matériau, afin d’avoir un écart important et facile à mesurer. Le but étant de réduire au maximum la circulation de courants de foucault dans ce conducteur lors de la présence d’une fissure. Nous allons donc entièrement trancher dans le métal. De plus nous ne ferons qu’une étude superficielle du matériau, en détectant des fissures visibles. La visée industrielle étant de détecter des fissures invisibles à l’œil nu. De plus, nos fissures seront d’une taille conséquente.
      Enfin, nous utiliserons une bobine de taille assez grande, ce qui nous oblige à faire de grandes fissures.
      On a pas de capteurs à magnétorésistance géante (cf bibli)

    3. Géométrie du problème

      Nous allons en premier leur nous interesser à une géométrie cylindrique, c’est à dire un tube, que nous trancherons dans l’axe de révolution.
      Ensuite, nous nous pencherons sur l’étude d’une géométrie plan à l’aide d’une poêle que nous trancherons radialement.

      La poêle utilisée pour nos expériences
    4. Contraintes du sujet

      Les principales contraintes ici sont des contraintes matérielles, nous n’avons pas la possibilité de pousser l’étude jusqu’aux microfissures alors que l’on trouve dans l’industrie une sensibilité de 0.1mm.

  2. Méthode analogique : pont de Maxwell

    1. Protocole

    2. Présentation montage

    3. Résultats obtenus

    4. Conclusion

  3. Méthode numérique

    1. Présentation du programme

      Cette méthode a pour but de mesurer la variation de résistance et d'inductance interne de la bobine lors de l'approche d'une masse métallique. Pour cela, nous allons récupérer des mesures brutes du montage, puis nous allons filtrer les courbes puis les traiter informatiquement. Pour cela, nous avons écrit plusieurs fonctions :

      • Le filtrage

        def filtrer(u2): u2_filtre = [] for k in range(100,len(u2)-100): liste = [u2[i] for i in range(k-100, k+100)] liste = sorted(liste) u2_filtre.append(valeur_moyenne(liste)) return u2_filtre

        On fait ici un filtrage par moyenne des 100 valeurs autour de chaque point. On obtient les résultats suivants :

        Résultat du filtrage
      • Le traitement

        Frequence = [] InductanceAvec = [] ResistanceAvec = [] InductanceSans = [] ResistanceSans = [] InductanceFaille = [] ResistanceFaille = [] chaine = '' i = 0 for file in fichiers: print(file) temps,U1,U2=lecture(file) # fabrication effective des 3 listes signal1 = U1 signal2 = U2 U1 = filtrer(U1) U2 = filtrer(U2) # *************************************************************************** # Preliminaires # *************************************************************************** # print(meme_taille(temps,U1,U2)) duree=temps[-1]-temps[0] # print("La duree totale des mesures est de ",duree, "secondes") # print("="*60) # Tracer la courbe U1(t) en bleu avec la courbe U2(t) dans le meme repere # plt.plot(temps,signal1,"b") # plt.plot(temps,signal2,"r") # plt.plot(temps, [0 for i in range(len(temps))],'black') # plt.show() # *************************************************************************** # Periode et frequence d'echantillonnage # *************************************************************************** Te=valeur_moyenne(increment(temps)) fe=1/Te # print("La periode d'echantillonnage en secondes est egale a",Te) # print("La frequence d'echantillonnage en Hz est egale a",fe) # print("="*60) # *************************************************************************** # Annulations # *************************************************************************** index_annul_1=index_points_d_annulation(U1) index_annul_2=index_points_d_annulation(U2) # print("les index de passage par 0 en montant du signal 1 sont", index_annul_1) # print("Longueur de la liste ", len(index_annul_1)) # print("les index de passage par 0 en montant du signal 2 sont", index_annul_2) # print("Longueur de la liste ", len(index_annul_2)) # print("="*60) # *************************************************************************** # Periode # *************************************************************************** instant_annul_1=[temps[k] for k in index_annul_1] # on transforme les listes d'index instant_annul_2=[temps[k] for k in index_annul_2] # en listes d'instants ''' VIDAL : Ici, on va virer les index en trop si ils existent... ''' difference = len(instant_annul_1)-len(instant_annul_2) if difference > 0: for i in range(difference): instant_annul_1.pop() if difference < 0: for i in range(difference): instant_annul_2.pop() ''' Fin Vidal ''' liste_T1=increment(instant_annul_1) # on construit la liste des ecarts liste_T2=increment(instant_annul_2) T1_moy=valeur_moyenne(liste_T1) # on calcule les periodes en faisant la moyenne des ecarts T2_moy=valeur_moyenne(liste_T2) nb_T1=int(duree/T1_moy) nb_T2=int(duree/T2_moy) # print("la periode du signal 1 en secondes vaut",T1_moy) # print("la periode du signal 2 en secondes vaut",T2_moy) # print("le nombre de periodes enregistrees du signal 1 vaut",nb_T1) # print("le nombre de periodes enregistrees du signal 2 vaut",nb_T2) # print("="*60) Fe1 = 1/T1_moy Fe2 = 1/T2_moy # *************************************************************************** # Decalage entre les deux signaux # *************************************************************************** delta_t=valeur_moyenne(decalage(instant_annul_1,instant_annul_2)) # print("le decalage temporel en secondes vaut",delta_t) # *************************************************************************** # Dephasage # *************************************************************************** phi_deg=360*delta_t/T1_moy phi_deg = phi_deg # print("le dephasage entre les deux signaux en degres vaut",phi_deg) # *************************************************************************** # Amplitude des signaux # *************************************************************************** U1m=max(U1) U2m=max(U2) # print("l'amplitude du signal 1 vaut", U1m) # print("l'amplitude du signal 2 vaut", U2m) # *************************************************************************** # Impedance complexe # *************************************************************************** module_Z=U1m/U2m*1000 Reel_Z=abs(module_Z*cos(2*np.pi*phi_deg/360)) Imag_Z=abs(module_Z*sin(2*np.pi*phi_deg/360)) # print("le module de l'impedance vaut en ohms",module_Z ) # print("la partie reelle de l'impedance vaut en ohms",Reel_Z) # print("la partie imaginaire de l'impedance vaut en ohms",Imag_Z) # *************************************************************************** # Resistance et inductance de la bobine # *************************************************************************** R=abs(Reel_Z) L=Imag_Z/(2*3.14159/T1_moy) # print("la resistance en ohms vaut en ohms",R ) # print("l'inductance de la bobine en henry vaut ",L) # chaine = chaine+str(file)+';'+str(fe)+';'+str(R)+';'+str(L)+'\n' chaine = chaine+str(i)+';'+str(module_Z)+'\n' i = i+1 Frequence.append(fe) if(file[0] == 'a'): InductanceAvec.append(L) ResistanceAvec.append(R) if(file[0] == 's'): InductanceSans.append(L) ResistanceSans.append(R) if(file[0] == 'f'): InductanceFaille.append(L) ResistanceFaille.append(R) # print('R = '+str(R)) # print('L = '+str(L))

        Le principe du code ici est de calculer la période et donc la fréquence des signaux en comptant le nombre de passage par zéro, puis de calculer le déphasage entre EA0 et EA1 puis l'exprimer en complexe, afin de récupérer la résistance et l'inductance de la bobine en récupérant respectivement la partie réelle et la partie imaginaire du complexe obtenu.

      • L'affichage

        def recupererCoord(valeurs): x = [] y = [] for val in valeurs: if not(val[0][0] in x): x.append(val[0][0]) if not(val[0][1] in y): y.append(val[0][1]) return x, y def v_moy(x, y, valeurs): val_temp = [] for i in x: for j in y: vTemp = [] for val in valeurs: if(val[0] == [i,j]): vTemp.append(val) rMoy = 0 IMoy = 0 for t in vTemp: rMoy+=t[2] IMoy+=t[3] val_temp.append([[i,j],rMoy/3,IMoy/3]) return val_temp def matricialiser(x,y,valeurs): n = len(x) m = len(y) matR = [[0 for i in y] for j in x] matL = [[0 for i in y] for j in x] oui = 0 non = 1 for i in x: for j in y: temp = [] for val in valeurs: if([i,j] == val[0]): chier.append(val) if(len(temp)==0): # matL[i+8][j+10] = -0.2787998494027163 matL[i+8][j+10] = 0.2679468291761009 matR[i+8][j+10] = 1000.46830156941047 non+=1 else: matL[i+8][j+10] = chier[0][2] matR[i+8][j+10]= chier[0][1] oui+=1 print(oui) print(non) print(oui+non) for i in range(n): for j in range(m): if(matL[i][j] == 0): matL[i][j] = 0.2487998494027163 if(matR[i][j] == 0): matR[i][j] = 1.4770783683822 return matR,matL p = 0 j = 0 valeurs = [] for file in fichiers: j+=1 print(file) print(j) x,y,essai,ext = file.split('.') R, L = traiter_fichier(file) valeurs.append([[int(x), int(y)],essai,R,L]) x,y = recupererCoord(valeurs) val_moyenne = v_moy(x, y, valeurs) R, L = matricialiser(x,y, val_moyenne)

        On va ici chercher à afficher la cartographie de la poêle que nous avons relevé. Or pour avoir une fiabilité statistique, nous avons relevé cinq mesures par points. Donc pour chaque couple de coordonnées, nous avons du faire la moyenne arithmétique des résistances et inductances mesurées.
        Ensuite, il faut mettre en forme la matrice qui va servir à afficher les valeurs. Il y en a deux, une pour la réistance et l'autre pour l'inductance. On rapporte les coordonnées en mètre a des coordonnées de matrice, des entiers de 0 à n donc.

      • L'affichage

        def convolution(R, bool = True): n = len(R) m = len(R[0]) mat = np.zeros([2*n, 2*m]) for i in range(2*n): for j in range(2*m): mat[i][j] = R[int(i/2)][int(j/2)] n = len(mat) m = len(mat[0]) matT = np.zeros([n,m]) for i in range(n-2): for j in range(m-2): matT[i+1][j+1] = (mat[i][j]+mat[i+1][j]+mat[i+2][j]+mat[i+2][j+1]+mat[i+2][j+2]+mat[i+1][j+2]+mat[i][j+2]+mat[i][j+1])/9 matFinale = np.zeros([n-2,m-2]) for i in range(n-2): for j in range(m-2): matFinale[i][j] = matT[i+1][j+1] if(bool): plt.matshow(matFinale) return matFinale

        Nous avons affiché une matrice mais avec une forte discrétisation de la situation. Nous allons donc, pour des raisons de confort, chercher à rendre la situation continue, nous allons donc augmenter artificiellement le nombre de points, en passant de 32 points à 2500. Pour cela, nous découpons chaque pixel en quatre dont la valeur est la moyenne des 8 autour.

    2. Importance du filtrage numérique

      Le filtrage a été une étape cruciale pour un traitement correct des résultats. En effet nos résultats initiaux étaient extrêmement pollués et en filtrant on a eu un résultat très intéressant.

      Comparaison d'une même série de mesure avec et sans un fort filtrage

      On a utilisé plusieurs formes de filtrage :

      • Filtrage par transformée d'Euler : On lisse la courbe en utilisant une méthode d'Euler, en approximant la dérivée de la courbe au premier ordre en définissant une constante de temps. Le problème de cette méthode réside dans la difficulté de trouver la constante de temps optimale pour chaque fichier de mesure, ce qui était très délicat et peu concluant

        u2_filtre = [u2[0]] tau=0.0001 for k in range(1,len(u2)): u2_filtre.append(u2_filtre[k-1]+(- u2_filtre[k-1]+u2[k-1])*(temps[k]-temps[k-1])/tau)
        Filtrage par transformée d'Euler
      • Filtrage par médiane : Le filtrage ici a pour but de prendre la valeur médiane des n points autour de chaque point du graphe que l'on veut filtrer.

        u2_filtre = [] for k in range(10,len(u2)-10): liste = [u2[i] for i in range(k-10, k+10)] liste = sorted(liste) u2_filtre.append(liste[10])

        On a obtenu de très bons résultats, mais pas aussi bons que pour le filtrage par moyenne

      • Filtrage par moyenne : On va ici, pour chaque point, chercher à faire la moyenne des n points autour.

        u2_filtre = [] for k in range(30,len(u2)-30): liste = [u2[i] for i in range(k-30, k+30)] liste = sorted(liste) u2_filtre.append(valeur_moyenne(liste))

        On a ici obtenu de vraiment bons résultats, cependant, il est à noter que l'on a du changer l'ordre de filtrage (c'est à dire le nombre de points utiles pour faire la moyenne), passant de 10 points à 200 points selon la taille des fichiers.

        Filtrage par moyenne avec n=100
    3. Résultats obtenus

      Les résultats obtenus sont vraiment très encourageants.

      Cartographie de la poêle en inductance et en résistance - version discrétisée
  4. Conclusion

    1. Confrontation des méthodes expérimentales

    2. Critique des résultats

    3. Pour aller plus loin