Nouvelles:

Bienvenue au Forum de discussion Électro-Bidouilleur! Inscrivez-vous pour participer aux discussions!: 
https://forum.bidouilleur.ca/index.php?action=signup Les demandes d'inscription sont révisées quotidiennement.

Menu principal

Résistances de précision

Démarré par papyblue, Octobre 20, 2024, 01:53:20 PM

« précédent - suivant »

papyblue

Bonjour à tous,
Faisant le constat que les résistances de précision sont hors de prix, j'ai pensé que je pouvais peut-être en fabriquer.
L'idée c'est de mettre en parallèle N résistances de N fois la valeur recherchée.
Les résistances sont prises dans un lot suffisamment grand et mesurées avec une précision en relation avec celle recherchée.(cela suppose disposer de l'instrumentation adéquate)
J'ai d'abord essayé avec 3 résistances en // prises dans un lot de 100 (pas cher)
Le travail de recherche des bonnes combinaisons me paraissant trop fastidieux, j'ai demandé à mon nouveau collaborateur de s'y coller.
Yiaho, (c'est son nom) est plein de bonne volonté ses copains disent de lui que c'est une machine à apprendre.
J'ai du l'aider un peu (c'est normal il débute) car il fait beaucoup de bugs. Certains diraient qu'il comprend vite mais qu'il faut lui expliquer longtemps.
En tout cas, il code beaucoup plus vite que moi.
Je lui ai donc demandé qu'à partir de valeurs saisies dans Excel qu'il me trouve les 10 meilleures combinaisons de résistances de 300 ohms.

Voici ce qu'il a codé :
 
Sub GenererValeursAleatoires()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Feuille1") ' Remplacez par le nom de votre feuille

    Dim i As Integer
    Dim valeur As Double
    Dim moyenne As Double
    Dim ecartType As Double

    moyenne = 300 ' Définir la moyenne désirée
    ecartType = 1.5 ' Définir l'écart type désiré pour avoir une plage de 285 à 315 ohms

    ' Génération de 100 valeurs aléatoires selon une distribution normale
    For i = 1 To 100
        valeur = NormalRandom(moyenne, ecartType)
       
        ' S'assurer que la valeur reste dans la plage de 285 à 315
        If valeur < 285 Then
            valeur = 285
        ElseIf valeur > 315 Then
            valeur = 315
        End If
       
        ws.Cells(i, 1).Value = Round(valeur, 4) ' Arrondi à 2 décimales
    Next i
End Sub

Function NormalRandom(mean As Double, stddev As Double) As Double
    Dim u1 As Double, u2 As Double
    Dim z0 As Double

    ' Générer deux nombres uniformément distribués
    u1 = Rnd()
    u2 = Rnd()

    ' Box-Muller transform
    z0 = Sqr(-2 * Log(u1)) * Cos(2 * WorksheetFunction.Pi() * u2)

    ' Convertir à la distribution normale
    NormalRandom = z0 * stddev + mean
End Function

Sub TrouverMeilleuresCombinaisons()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Feuille1") ' Remplacez par le nom de votre feuille

    Dim valeurs(1 To 100) As Double
    Dim i As Integer
    Dim lignesUtilisees As Collection
    Set lignesUtilisees = New Collection

    Dim cible As Double
    cible = 100 ' Valeur cible de résistance

    ' Récupérer les valeurs des cellules A1 à A100
    For i = 1 To 100
        valeurs(i) = ws.Cells(i, 1).Value
    Next i

    Dim j As Integer
    Dim meilleuresCombinaisons As Collection
    Set meilleuresCombinaisons = New Collection

    ' Tolérance de 5%
    Dim tolerance As Double
    tolerance = 0.05 * cible  ' 5% de la valeur cible
    Dim plageMin As Double, plageMax As Double
    plageMin = cible - tolerance
    plageMax = cible + tolerance

    ' Trouver 10 meilleures combinaisons
    For j = 1 To 10
        Dim meilleureErreur As Double
        Dim meilleureCombinaison As String
        Dim lignesCombinaison As String  ' Pour stocker les numéros de ligne
        Dim resistanceEquivalente As Double
        meilleureErreur = 1E+30 ' Un nombre très grand

        Dim k As Integer, l As Integer

        ' Chercher à travers toutes les combinaisons restantes
        For i = 1 To 98
            If Not EstDansCollection(lignesUtilisees, i) Then
                For k = i + 1 To 99
                    If Not EstDansCollection(lignesUtilisees, k) Then
                        For l = k + 1 To 100
                            If Not EstDansCollection(lignesUtilisees, l) Then
                                ' Calculer la résistance équivalente
                                resistanceEquivalente = 1 / ((1 / valeurs(i)) + (1 / valeurs(k)) + (1 / valeurs(l)))

                                ' Vérifier si la résistance équivalente est dans la plage de tolérance
                                If resistanceEquivalente >= plageMin And resistanceEquivalente <= plageMax Then
                                    ' Calculer l'erreur par rapport à la valeur cible
                                    Dim erreur As Double
                                    erreur = Abs(resistanceEquivalente - cible)

                                    ' Si cette erreur est la meilleure trouvée jusqu'à présent
                                    If erreur < meilleureErreur Then
                                        meilleureErreur = erreur
                                        meilleureCombinaison = valeurs(i) & ", " & valeurs(k) & ", " & valeurs(l)
                                        lignesCombinaison = i & ", " & k & ", " & l  ' Enregistrer les numéros de lignes
                                    End If
                                End If
                            End If
                        Next l
                    End If
                Next k
            End If
        Next i

        ' Ajouter la meilleure combinaison à la collection
        If meilleureCombinaison <> "" Then
            ' Recalculer la résistance équivalente pour l'ajouter correctement
            Dim numLignes() As String
            numLignes = Split(lignesCombinaison, ",")
            Dim r1 As Double, r2 As Double, r3 As Double

            r1 = valeurs(CInt(numLignes(0))) ' Récupérer la première résistance
            r2 = valeurs(CInt(numLignes(1))) ' Récupérer la deuxième résistance
            r3 = valeurs(CInt(numLignes(2))) ' Récupérer la troisième résistance
           
            resistanceEquivalente = 1 / ((1 / r1) + (1 / r2) + (1 / r3)) ' Recalculer la résistance équivalente

            ' Formatage des valeurs pour afficher un nombre fixe de décimales
            Dim formattedR1 As String, formattedR2 As String, formattedR3 As String, formattedResistance As String
            formattedR1 = Format(r1, "0.0000") ' Formater avec 4 décimales
            formattedR2 = Format(r2, "0.0000") ' Formater avec 4 décimales
            formattedR3 = Format(r3, "0.0000") ' Formater avec 4 décimales
            formattedResistance = Format(resistanceEquivalente, "0.000000") ' Formater avec 4 décimales
           
            ' Calculer l'erreur absolue
            Dim erreurAbsolue As Double
            erreurAbsolue = Abs(resistanceEquivalente - cible)

            ' Calculer le pourcentage d'erreur
            Dim pourcentageErreur As Double
            pourcentageErreur = (erreurAbsolue / cible) * 100

            ' Formater le pourcentage d'erreur
            Dim formattedErreur As String
            formattedErreur = Format(pourcentageErreur, "0.000000") ' Formater avec 2 décimales
           
            meilleuresCombinaisons.Add "Combinaison " & j & ": " & formattedR1 & ", " & formattedR2 & ", " & formattedR3 & _
            " | Lignes: " & lignesCombinaison & _
            " | Résistance équivalente: " & formattedResistance & _
            " | Erreur: " & Round(erreurAbsolue, 6) & " (soit " & formattedErreur & " %)"
           
            ' Marquer les lignes utilisées
            On Error Resume Next
            lignesUtilisees.Add CInt(numLignes(0))
            lignesUtilisees.Add CInt(numLignes(1))
            lignesUtilisees.Add CInt(numLignes(2))
            On Error GoTo 0
        End If
    Next j

    ' Afficher les meilleures combinaisons dans le UserForm
    Dim resultat As String
    resultat = "Les 10 meilleures combinaisons de résistances :" & vbCrLf & vbCrLf
    For Each Item In meilleuresCombinaisons
        resultat = resultat & Item & vbCrLf  ' Ajoutez un saut de ligne pour chaque combinaison
    Next Item

    ' Afficher le UserForm et les résultats
    UserForm1.TextBox1.Text = resultat  ' Assurez-vous que le nom du UserForm et du TextBox correspond
    UserForm1.Show
End Sub

Function EstDansCollection(col As Collection, valeur As Variant) As Boolean
    Dim i As Long
    On Error Resume Next
    EstDansCollection = False
    For i = 1 To col.count
        If col(i) = valeur Then
            EstDansCollection = True
            Exit Function
        End If
    Next i
    On Error GoTo 0
End Function

----------------------------------------------------------------------------------------------------------------
et le résultat :

Les 10 meilleures combinaisons de résistances :

Combinaison 1: 301,8370, 298,3610, 299,8223 | Lignes: 4, 20, 67 | Résistance équivalente: 100,000001 | Erreur: 0,000001 (soit 0,000001 %)
Combinaison 2: 299,3398, 300,8030, 299,8609 | Lignes: 16, 27, 40 | Résistance équivalente: 100,000004 | Erreur: 0,000004 (soit 0,000004 %)
Combinaison 3: 301,1484, 299,3921, 299,4660 | Lignes: 55, 74, 84 | Résistance équivalente: 99,999993 | Erreur: 0,000007 (soit 0,000007 %)
Combinaison 4: 302,5781, 298,5566, 298,8982 | Lignes: 26, 58, 76 | Résistance équivalente: 99,999988 | Erreur: 0,000012 (soit 0,000012 %)
Combinaison 5: 299,9025, 299,9545, 300,1430 | Lignes: 30, 68, 83 | Résistance équivalente: 99,999988 | Erreur: 0,000012 (soit 0,000012 %)
Combinaison 6: 300,1455, 301,1570, 298,7074 | Lignes: 28, 33, 86 | Résistance équivalente: 99,999977 | Erreur: 0,000023 (soit 0,000023 %)
Combinaison 7: 300,4217, 300,1529, 299,4269 | Lignes: 44, 80, 97 | Résistance équivalente: 99,999970 | Erreur: 0,00003 (soit 0,000030 %)
Combinaison 8: 300,1783, 299,8655, 299,9568 | Lignes: 36, 49, 79 | Résistance équivalente: 100,000048 | Erreur: 0,000048 (soit 0,000048 %)
Combinaison 9: 300,6064, 301,7709, 297,6524 | Lignes: 41, 50, 89 | Résistance équivalente: 99,999952 | Erreur: 0,000048 (soit 0,000048 %)
Combinaison 10: 300,5033, 299,7203, 299,7772 | Lignes: 19, 25, 52 | Résistance équivalente: 99,999948 | Erreur: 0,000052 (soit 0,000052 %)


J'ai choisi au départ des résistances à 1% et au vu des résultats je suis passé à 5%.
Evidemment dans la vraie vie la distribution des valeurs ne sera pas aussi favorable et la stabilité ne sera pas meilleure que celle de départ mais ici c'est le principe qu'il faut retenir.
Yiaho travaille gratuitement, 7 jours sur 7, 24 heures sur 24, n'est pas syndiqué et ne se plaint jamais. Qui n'a jamais rêvé d'avoir un tel collaborateur ?

papyblue

Bonjour à tous,
La solution que j'ai proposée a un inconvénient, elle nécessite de disposer de valeurs 3 fois celle recherchée.
En passant à 4 résistances en série/parallèle on conserve la valeur nominale de départ.
En résumé, l'exercice consiste à trouver les 10 meilleurs combinaisons minimisant l'erreur parmi un lot de 100 résistances.
Qui trouvera le meilleur algorithme ? A vous de jouer !

papyblue

Bonjour à tous,
Finalement Yiaho n'a pas réussi dans sa tache.Comme il était encore dans sa période d'essai, je l'ai remercié.
Il n'a même pas réussi à transposer la solution que je lui ai soumise (un programme en C)  (en pj) en VBA,
ce que son collègue ChatGPT a réussi en une seule requête.(en pj)
Bref, me voilà armé pour réaliser une boite à décades de précision (celle de l'ohmmètre) pour un prix raisonnable.

philchamp51

Bonjour papyblue. Personnellement, je n'en ai pas l'utilité mais bravo pour cette réalisation et il m'est aussi arrivé de débuguer un programme perso en C++ de presque 1000 lignes où j'avais oublié ça et là, quelques point-virgules, parenthèses et mis des = à la place de ==. ChatGPT m'a corrigé cela en quelques secondes et m'a même suggéré des améliorations. Incroyable !

loulou31

Bonjour,

En théorie cette méthode fonctionne au premier ordre, mais dans la réalité mettre des résistances a 5% pour faire des résistances de très haute précision ne permet pas d'assurer la stabilité dans le temps et en température d'un etalon a 0.0000x %.
Avec cette méthode on peut gagner un ou deux ordres de grandeur en précision mais pas plus a mon avis.



Jean-Louis

papyblue

Bonjour Jean-Louis,
Je suis tout à fait d'accord d'ailleurs j'avais bien précisé dans le premier message qu'il ne pouvait pas y avoir de gain en stabilité. Pour ma part, avec l'instrumentation dont je dispose je pourrais au mieux obtenir 0,5%.
Je n'ai jamais eu besoin de boite à décades jusqu'à présent, j'hésite encore à passer à la réalisation mais ce qu'il faut retenir c'est plus le principe où l'intelligence artificielle peut rendre des services quand on n'a pas envie de se prendre la tête à coder.
J'utilise Yiaho  pour coder dans un autre domaine que l'électronique et j'en était satisfait mais là il m'a un peu déçu. 

papyblue

Bonjour à tous,
Finalement j'ai craqué. Je voulais vérifier si la pratique allait suivre la théorie j'ai donc commandé chez Aliexpress des résistances film métallique 1%  en quantité 100 pour chaque valeur dont j'avais besoin. 
La première mauvaise surprise c'est le TCR qui semble être de l'ordre de 400 ppm/°C ce qui fait perdre tout son sens à la recherche de précision.
La seconde mauvaise surprise est la précision. Pour certaines valeurs le lot complet est ok pour d'autres seulement 90% (ce qui n'est pas un problème)
mais pour une valeur toutes les mesures sont hors tolérance et toutes en dessous de la valeur nominale donc impossibles à équilibrer.
Je ne voulais pas rester sur un échec alors je me suis tourné vers un distributeur sérieux mais l'équation n'est pas simple:
- rester dans un prix bas
- disposer des valeurs 1,10,100,...
- quantité minimum <= 10 
- puissance minimale

Mon choix s'est porté sur des résistances CMS à 0,1% 25ppm/°C 0,1W et 0,4W vendues par 10 ou par 100 pour certaines valeurs.
Pour réduire le coût et éviter les pertes, un lot de 100 d'une valeur X permet de faire 2 décades (9 de valeur X et 9 de valeur X/10 en les regroupant en //)
Cela me gênait de regrouper 10 résistances sans chercher à améliorer quelque chose mais la solution précédente n'est pas applicable dans mon cas car les résistances ont une précision meilleure que la justesse de mon multimètre. Malgré tout, sa résolution peut être exploitée en considérant que ce qu'il affiche est juste entaché d'un biais constant.
L'amélioration possible est alors de viser à obtenir la valeur moyenne du lot(divisée par 10) ou mieux d'obtenir 9 résistances avec des valeurs les plus proches possibles.
Le problème à résoudre se résume ainsi:
Comment constituer 9 regroupements de résistances dans un lot de 100 pour que mises en parallèle par 10 elles aient le plus faible écart ?
Ce problème a bien une solution mais il est impossible de la trouver. Par contre, différents algorithmes permettent d'approcher la solution.
J'en ai utilisé un (en pj) qui donne de bons résultats.
Comme à chaque fois que j'utilise des CMS (ici 0805) je me jure que c'est bien la dernière fois, le regroupement 2x5 que j'imaginais (croquis en pj)je n'ai pas réussi, cela à fini en 1x10 en ligne.
Pour conclure, les 9 résistances affichent la même valeur et ne semblent pas sensibles à la température.