Motståndsberäknare

Berätta om dina pågående projekt.
Användarvisningsbild
RDX*
EF Sponsor
Inlägg: 1652
Blev medlem: 28 maj 2003, 22:52:04
Ort: Skåne - Lund

Motståndsberäknare

Inlägg av RDX* »

Det sägs att nöden är uppfinningarnas moder och det stämmer i detta fall. Den senaste tiden har jag räknat ganska mycket på OP-kopplingar med filter. Problemet har varigt att det är ganska många motstånd som är inblandade för att få rätt förstärkning. Detta tillsammans med att jag inte direkt vet vilka motstånd jag har hemma har gjort det svårt att hitta rätt motstånd. Därför har jag nu slängt ihop ett MATLAB skript som räknar igenom alla alternativ utifrån en viss motståndsserie och presenterar de motstånd som ger rätt förstärkning.

Skriptet är inte det vackraste men det fungerar (kanske:). Skriptet fungerar så här:

Den läser in en Excel-fil med motståndsserier:

Kod: Markera allt

"Motstånd.xls"
E12    Hemma
10      10
12     56
15     200
21     470
27     560
33     1200
39     1500
47     2000
56     ...
68
82
...
Sen editerar man m-skriptet så det passar.

Man ändar:
Namnet på serien man vill använda tex. 'Hemma'.

Uttrycket man vill beräkna (i string format). Tex om man vill beräkna en icke-inverterande op så skriver man '1+( Hemma(i) / Hemma(j))'.

Vilken förstärkning man vill ha tex. 9.5 ggr.

Sen kan man ange en tolerans på svaren tex. +/- 1 %

Man anger även min och max resistanser om man inte vill använda hela serien.

Sen är det bara att köra igång skriptet. Man kan använda upp till 4 variabler i uttrycket. Det är nog bara fantasin, tiden och Matlab som sätter begränsningar i hur avancerat uttrycket kan vara.

Kod: Markera allt

%MATLAB skript:

clear 
clc
tic
%%%%%%%%%%%%%%%%% EDIT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%

[ndata, headertext] = xlsread('Motstånd.xls'); % Excel file with the resistor series. example: [ndata, headertext] = xlsread('Motstånd.xls')
Serie='E12'; %Name of the series you want to use example: Serie='E12';
uttryck='1+(E12(i)/E12(j))'; %Writh the expresion example: uttryck='(E12(i)+ E12(j))/E12(k)'; The script supports up to 4 varibles, i,j,k,l
AntalTal=2; % number of varibles

Amplification=9.5; % The result for the expresion
tolerans=1; % Tolerance for the result in +/-%
minresistance=100;  %Min Resistance 
maxresistance=1000000; %Max Resistance 

%%%%%%%%%%%%%%%%% END EDIT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%result=zeros(1, AntalTal+2);
r=1;
f=['i' 'j' 'k' 'l' 'm' 'n' 'o' 'p'];
min=NaN;
max=NaN;
for i=1:length(ndata(1,:))
    assignin('base',cell2mat(headertext(:,i)),ndata(:,i)');    
    eval([cell2mat(headertext(:,i)) '=' cell2mat(headertext(:,i)) '(~isnan(' cell2mat(headertext(:,i)) '));']);
end

for i=1:length(eval(Serie))
    if  (eval([Serie '(' num2str(i) ')'])>=minresistance) & isnan(min)
        min=i;
    end
    if  (eval([Serie '(' num2str(i) ')'])>=maxresistance) & isnan(max)
        max=i;
    end
end

if isnan (max) & ~isnan(min)
    eval([Serie '=' Serie '(' num2str(min) ':length(' Serie  '));']);
elseif isnan (min) & ~isnan(max)
    eval([Serie '=' Serie '(1:' num2str(max) ');']);
elseif isnan(min) & isnan(max)
    eval([Serie '=' Serie '(1:length(' Serie  '));']);
else
    eval([Serie '=' Serie '(' num2str(min) ':' num2str(max) ');']);
end

l=0;
tolupper=(Amplification + Amplification*tolerans/100)
tollower=(Amplification - Amplification*tolerans/100)
while l<length(eval(Serie))
    k=0;
    l=l+1;
    while k<length(eval(Serie))
        j=0; 
        k=k+1;
        while j<length(eval(Serie))
            i=0;
            j=j+1;
           while i <length(eval(Serie))      
            i=i+1;
            if (AntalTal==2)
                l=length(eval(Serie));
                k=length(eval(Serie));
            elseif (AntalTal==3)
                l=length(eval(Serie));
            end
            ratio(l,k,j,i)=eval(uttryck); 
            if((ratio(l,k,j,i)<=tolupper) & (ratio(l,k,j,i)>=(tollower)))             
                 str='';
                 for a=1:AntalTal                            
                     str= [str Serie '(' f(a) ') ' ];    
                 end
                 result(r,:) =[eval([ '[' str ']']) 0 ratio(l,k,j,i)];
                 r=r+1;     
             end 
         end
     end
 end
end
toc
openvar('result')
Skriptet ovan ger följande resultat:

Kod: Markera allt

3300	     390       9.4615
33000	    3900      9.4615
330000      39000	  9.4615
Användarvisningsbild
digitaliz
Inlägg: 278
Blev medlem: 10 oktober 2003, 21:27:38
Ort: Stockholm, Sverige

Inlägg av digitaliz »

Coolt :) synd bara att det var skrivet i matlab, annars hade man kanske kunnat använda det... :wink:
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Den här gamla tråden kanske också kan vara av intresse.
Användarvisningsbild
digitaliz
Inlägg: 278
Blev medlem: 10 oktober 2003, 21:27:38
Ort: Stockholm, Sverige

Inlägg av digitaliz »

Gjorde ett litet program i C# (snabbt hack, men verkar funka :) ):

Kod: Markera allt

using System;

namespace Resopt
{
    class Program
    {
        private static int[] e12 = { 10, 12, 15, 18, 22, 27, 33, 39, 47, 56, 68, 82};

        static void Main(string[] args)
        {
            VoltageDivider bestMatch = null;
            double error = 9999;
            double desired = 0.991;
            int decades = 6;

            int x = 0;
            int y = 0;

            for (x = 0; x < e12.Length * decades; x++)
            {
                for (y = 0; y < e12.Length * decades; y++)
                {
                    int R1 = (int)(e12[x%e12.Length]*Math.Pow(10, (int) ((x+1)/e12.Length)));
                    int R2 = (int)(e12[y % e12.Length] * Math.Pow(10, (int)((y+1) / e12.Length)));
                    VoltageDivider divider = new VoltageDivider(R1, R2);
                    double err = Math.Abs(desired - divider.Ratio);
                    if (err < error)
                    {
                        bestMatch = divider;
                        error = err;
                    }
                }
            }

            Console.WriteLine("R1 = {0}, R2 = {1}, Error = {2}, Ratio = {3}", bestMatch.R1, bestMatch.R2, error, bestMatch.Ratio);
            Console.ReadKey();
        }

        
    }

    class VoltageDivider
    {
        private double r1;
        private double r2;

        public double R2 { get { return r2; } }
        public double R1 { get { return r1; } }
        public double Ratio { get { return R2/(R2 + R1); } }

        public VoltageDivider(double r1, double r2)
        {
            this.r1 = r1; this.r2 = r2;
        }
    }
}
Användarvisningsbild
RDX*
EF Sponsor
Inlägg: 1652
Blev medlem: 28 maj 2003, 22:52:04
Ort: Skåne - Lund

Inlägg av RDX* »

Fördelen med min kod är att man kan använda den till alla problem med upp till 4 variabler. Du ändar bara textsträngen för uttrycket till tex en OP-koppling eller spänningsdelning så fixar programmet resten. Men det är sant, att man måste ha matlab är en stor nackdel.
Användarvisningsbild
digitaliz
Inlägg: 278
Blev medlem: 10 oktober 2003, 21:27:38
Ort: Stockholm, Sverige

Inlägg av digitaliz »

Jo, den är säkert mycket bättre. Nackdelen är att jag inte kan läsa den... :lol:
Skriv svar