Ersatzwiderstandsberechnung mit Hilfe eines C Programms...
-
tanGERra schrieb:
Die Formel ist mir schon klar,...
Nur das Ganze in C umzusetzten ist mein Problem.kannst die formel so übernehmen wie sie da steht
int R1, R2, R3, Rges; ... // hier R1, R2, R3 mit werten belegen ... Rges = (R1+R2)*R3/(R1+R2+R3); ... // hier Rges ausgeben oder weiterrechnen damit ...
:xmas2:
-
ten schrieb:
kannst die formel so übernehmen wie sie da steht
Nein, er sucht ja R1, R2, R3 und hat Rges gegeben.
-
Bashar schrieb:
ten schrieb:
kannst die formel so übernehmen wie sie da steht
Nein, er sucht ja R1, R2, R3 und hat Rges gegeben.
ahso, ist irgendwie untergegangen. eine gleichung mit 3 unbekannten
@tangera
einfachste lösung:
- gesuchten widerstandswert auf 1...10 normalisieren
- mit obiger formel alle kombinationen der e12'er reihe (1.0...8.2) 'brute-forcen' und den wert, der der lösung am nächsten ist nehmen (1728 versuche maximal).
:xmas2:
-
ten, genau das würd ich so gern realisieren...
Wäre dir dankbar um ein paar Tipps, wie ich den Ersatzwiederstand normisiere auf 1...10, wie ich dann das "Suchverfahren" programmiere und den ermittelten Widerstand dann wieder auf Ursprungsgröße bringe...
Die fast 2000 Kombinationen sollten ja bei heutiger Rechengeschwindigkeit kein Problem mehr darstellen, oder?Vielen Dank und allen ein schönes Weihanchtsfest!!!
LG Martin
-
hi,
versuch mal so:#include <stdio.h> #include <math.h> double e12[] = {1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2}; double calc_rges (double r1, double r2, double r3) { return (r1+r2)*r3/(r1+r2+r3); } void brute (double r, double mult) { int i, j, k; double diff = 10.0; for (i=0; i<12; i++) for (j=0; j<12; j++) for (k=0; k<12; k++) { double rges = calc_rges (e12[i], e12[j], e12[k]); if (fabs(rges - r) < diff) { diff = fabs(rges - r); printf ("%lf: RGes:%lf R1:%1.1lf R2:%1.1lf R3:%1.1lf\n", diff, mult*rges, mult*e12[i], mult*e12[j], mult*e12[k]); } } } int main() { double x = 1234.0; double mult = pow(10,floor(log10(x))); double norm = x/mult; brute (norm, mult); printf ("-------\ngesucht waren: %lf ohm\n", x); }
die letzte zeile (vor den ------) ist die beste kombination.
:xmas2:
-
Die Toleranzen der zuhörigen Widerstände ergeben theoretisch keine Lücken.
Es sie denn in der Fertigung sind die präziser als auf dem Datenblatt.
Was hindert dich eine einfache Reihen- oder Parallelschaltung zu nehmen?
Rauscheffekte oder sonstige Nebeneffekte der Widerstände?Wenn exakte Werte für die Schaltung notwendig sind, nimm die passende E-Reihe
oder mess die einzelnen Bausteine aus.MfG f.-th.
-
f.-th. schrieb:
Die Toleranzen der zuhörigen Widerstände ergeben theoretisch keine Lücken.
spielverderber! *g*
:xmas1:
-
Wow, vielen Dank, das Programm tut genau das, was ich gesucht habe!!!
Edit: Mir ist noch ein kleiner "Fehler" aufgefallen: Wenn man zB den Ersatzwiderstand für 9000 Ohm berechnen lässt, dann wird 5466.66 ausgegeben. Optimal wäre dann doch, wenn dann der Parallelwiderstand weggelassen würde, oder?
Zum Verständnis: Was bedeutet 'brute'? Und wie wird der Teiler bzw Multiplikator berechnet, also welcher mathematische Weg?
Danke
-
tanGERra schrieb:
Wow, vielen Dank, das Programm tut genau das, was ich gesucht habe!!!
huh? wirklich? war eigentlich nur als einfaches beispiel gedacht. es werden ja nur die e12-er widerstände einer zehnerpotenz genommen. wenn man alle nimmt wird's genauer...
tanGERra schrieb:
Edit: Mir ist noch ein kleiner "Fehler" aufgefallen: Wenn man zB den Ersatzwiderstand für 9000 Ohm berechnen lässt, dann wird 5466.66 ausgegeben. Optimal wäre dann doch, wenn dann der Parallelwiderstand weggelassen würde, oder?
hier mal 'ne aufgepäppelte version, die auch 0.0 und DBL_MAX in die berechnung einbezieht (kann sein dass es abstürzt bei dir):
#include <stdio.h> #include <math.h> #include <float.h> double e12[] = {0.0, 1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2, DBL_MAX}; double calc_rges (double r1, double r2, double r3) { return (r1+r2)*r3/(r1+r2+r3); } void brute (double r, double mult) { int i, j, k; double diff = 10.0; for (i=0; i<sizeof(e12)/sizeof(double); i++) for (j=0; j<sizeof(e12)/sizeof(double); j++) for (k=0; k<sizeof(e12)/sizeof(double); k++) { double rges = calc_rges (e12[i], e12[j], e12[k]); if (fabs(rges - r) < diff) { diff = fabs(rges - r); printf ("%lf: RGes:%lf R1:%1.1lf R2:%1.1lf R3:%1.1lf\n", diff, mult*rges, mult*e12[i], mult*e12[j], mult*e12[k]); } } } int main() { double x = 9000.0; double mult = pow(10,floor(log10(x))); double norm = x/mult; brute (norm, mult); printf ("-------\ngesucht waren: %lf ohm\n", x); }
tanGERra schrieb:
Zum Verständnis: Was bedeutet 'brute'? Und wie wird der Teiler bzw Multiplikator berechnet, also welcher mathematische Weg?
naja, 'brute force' eben. ein dummes programm, das alle kombinationen durchtestet und versucht, dem gesuchten wert so nah wie möglich zu kommen...
-
Nochmals vielen Dank. Ich habe die neue Version mal ausprobiert. Bin noch zufriedener! *g*
DBL_MAX ist in der float.h definiert, ist das ANSI-C konform?
Die Funktion von "brute" versteh ich nun. Es werden alle Kombinationen durchprobiert und sobald eine Kombination näher am gesuchten Wert ist, wird diese ausgegeben.
In den Schleifen schreibst du "i < sizeof(e12)/sizeof(double)". Welchen Vorteil hat das gegenüber "i < 14" bzw. was bewirkt es?
Zur Berechnung des Mulitplikators / Teilers nutzt du "double mult = pow(10,floor(log10(x)))". Kannst du das etwas ausführlicher beschreiben?
Wenn ich mir für 1.0 Ohm den Ersatzwiderstand berechnen lassen (ich weiß, prinzipiell unnötig), dann gibt er einen extrem großen R3 an, wieso?
Ich möchte das Programm noch erweitern, so dass ich den Widerstandswert eingeben kann. Nach Möglichkeit sollte man nur richige Float Zahlen eingeben können, keine Buchstaben, Mischformen oder Kommata.
Ich habe es so Versucht:
do { printf(" Widerstandswert: "); // ww einlesen if (scanf("%f", &ww)!=1) // Prüfen ob ww eine korrekte Zahl ist { while( getchar() != '\n' ) ; printf("\n Es duerfen nur Zahlen eingegeben werden.\n\n");} else end_ww = 1; } while ( end_ww != 1 );
... aber ganz optimal ist es noch nicht.
Gibt´s auch dafür ne besserere Lösung?
Im Grunde reicht es mir, dass es überhaupt funktioniert, aber meine Neugier treibt mich dazu, es auch verstehen zu wollen...
LG Martin
-
tanGERra schrieb:
DBL_MAX ist in der float.h definiert, ist das ANSI-C konform?
ja, ich glaub das steht auch inner iso/iec spec.
tanGERra schrieb:
In den Schleifen schreibst du "i < sizeof(e12)/sizeof(double)". Welchen Vorteil hat das gegenüber "i < 14" bzw. was bewirkt es?
wenn man an's array was anhängt oder wegnimmt muss man diese stellen im code nicht jedesmal ändern...
tanGERra schrieb:
Zur Berechnung des Mulitplikators / Teilers nutzt du "double mult = pow(10,floor(log10(x)))". Kannst du das etwas ausführlicher beschreiben?
log10() liefert den zehnerlogarithmus von x. das kann aber 'ne ziemlich krumme zahl sein (10^diese_zahl muss ja wieder genau x ergeben). also werden mit floor() die nachkommastellen weggemacht. wenn man dann 10 mit dieser beschnittenen zahl potenziert, hat man nicht x wieder zurück, sondern die zehnerpotenz des bereichs in dem x sich befindet (ich bin kein mathelehrer. kann sein dass das nicht ganz korrekt erklärt ist, aber ich hoffe du hast es gecheckt).
tanGERra schrieb:
Wenn ich mir für 1.0 Ohm den Ersatzwiderstand berechnen lassen (ich weiß, prinzipiell unnötig), dann gibt er einen extrem großen R3 an, wieso?
na, riesengross heisst, dass man den ganz weglassen kann
...und null heisst: drahtbrücke nehmen
-
Soweit alles verstanden!
tanGERra schrieb:
Wenn ich mir für 1.0 Ohm den Ersatzwiderstand berechnen lassen (ich weiß, prinzipiell unnötig), dann gibt er einen extrem großen R3 an, wieso?
na, riesengross heisst, dass man den ganz weglassen kann
...und null heisst: drahtbrücke nehmenEinleuchtend, manchmal schreibt er ja auch für zB R3: 1.#J was für mich als unendlich hoch gilt, also weglassen. Aber wenn man den R ers für 1.0 berechnen lässt erscheint für R3 eine 4 Zeilen lange Zahl mit zig Nullen, wieso?
Jemand nen Vorschlag, wie man meine Eingabe noch verbessern könnte?
LG
-
tanGERra schrieb:
Einleuchtend, manchmal schreibt er ja auch für zB R3: 1.#J was für mich als unendlich hoch gilt, also weglassen. Aber wenn man den R ers für 1.0 berechnen lässt erscheint für R3 eine 4 Zeilen lange Zahl mit zig Nullen, wieso?
das ist das DBL_MAX, das so hässlich aussieht
hier haste mal 'ne version, die das nicht mehr macht und auch nicht mehr durch 0 teilt...#include <stdio.h> #include <math.h> #include <float.h> double e12[] = {DBL_MIN, 1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2, DBL_MAX}; double calc_rges (double r1, double r2, double r3) { return (r1+r2)*r3/(r1+r2+r3); } char *value_as_text (double value, double mult) { static char txt[256]; if (value == DBL_MAX) return "Weglassen"; if (value <= DBL_MIN) return "Drahtbruecke"; sprintf (txt, "%1.1lf", mult*value); return txt; } void brute (double r, double mult) { int i, j, k; double diff = DBL_MAX; for (i=0; i<sizeof(e12)/sizeof(double); i++) for (j=0; j<sizeof(e12)/sizeof(double); j++) for (k=0; k<sizeof(e12)/sizeof(double); k++) { double rges = calc_rges (e12[i], e12[j], e12[k]); if (fabs(rges - r) < diff) { diff = fabs(rges - r); printf ("%lf: ", diff); printf ("RGes:%s ", value_as_text (rges, mult)); printf ("R1:%s ", value_as_text (e12[i], mult)); printf ("R2:%s ", value_as_text (e12[j], mult)); printf ("R3:%s\n", value_as_text (e12[k], mult)); } } } int main() { double x = 77889.0; double mult = pow(10,floor(log10(x))); double norm = x/mult; brute (norm, mult); printf ("-------\ngesucht waren: %lf ohm\n", x); }
-
Wow, Respekt für die Arbeit und Zeit die du hier für mich opferst.
Funktionieren tut die neue Version noch besser, allerdings verstehe ich den Abschnitt Value_as_text nicht...Kannst du versuchen es zu erläutern oder gibt es noch eine einfachere Möglichkeit den langen DBL_MAX Wert wegzubekommen?
Gibt es kein Formatelement, welches den endlichlangen DBL_MAX Wert als xx.xx * E^ xx angibt oder einfach K, M oder G für Kilo, Mega oder Giga anfügt?!
-
tanGERra schrieb:
Wow, Respekt für die Arbeit und Zeit die du hier für mich opferst.
kein problem, ich schau ja öfters hier rein und mach das so nebenbei. das kostet kaum zeit. für dich als anfänger mag das ein ganz tolles programm sein, aber eigentlich war das nur 'ne fixe idee von mir und dann hab' ich's als schnellen hack hier hingepostet. das programm ist keinesfalls optimal. man kann noch vieles verbessern (z.b. alle tests mit einem parallelwiderstand, der kleiner als der gesuchte wert ist, von vorn herein weglassen. sowieso ist so'ne brute-force suche immer mies. meistens geht es besser (man muss nur drauf kommen)
tanGERra schrieb:
Funktionieren tut die neue Version noch besser, allerdings verstehe ich den Abschnitt Value_as_text nicht...
hast du dir die funktion angeguckt? die ist eigentlich leicht verständlich
tanGERra schrieb:
Gibt es kein Formatelement, welches den endlichlangen DBL_MAX Wert als xx.xx * E^ xx angibt oder einfach K, M oder G für Kilo, Mega oder Giga anfügt?!
gibt's bestimmt. guck' mal in die helpfiles deines compilers, wie doubles noch formatiert werden können...
-
Also ich nutze Dev-C++ und habe auch das Buch 'Programmieren in C' von Kernighan / Ritchie, finde aber kein tolles Formatelement...
In der Tat sieht dein Programm schon sehr professionell für mich aus!
Vllt findest du ja noch die Zeit um nen kurzen Kommentar neben die Zeilen zu schreiben:
char *value_as_text (double value, double mult) { static char txt[256]; if (value == DBL_MAX) return "Weglassen"; if (value <= DBL_MIN) return "Drahtbruecke"; sprintf (txt, "%1.1lf", mult*value); return txt;
Danke und gute Nacht!
-
tanGERra schrieb:
Vllt findest du ja noch die Zeit um nen kurzen Kommentar neben die Zeilen zu schreiben:
char *value_as_text (double value, double mult) { static char txt[256]; // speicher für fprintf reservieren if (value == DBL_MAX) // wenn der wert riesengross ist... return "Weglassen"; // 'weglassen' zurückgeben und funktion verlassen if (value <= DBL_MIN) // wenn der wert total klein ist... return "Drahtbruecke"; // 'drahtbrücke' zurückgeben und funktion verlassen sprintf (txt, "%1.1lf", mult*value); // sonst: wert hochrechnen und als string in txt speichern... return txt; // und txt zurückgeben und funktion verlassen
weil du die funktion nicht ohne kommentare entziffern kannst: dir scheinen die elementarsten C-grundlagen zu fehlen? such mal bei google 'c programming filetype:pdf' da findest du genug material. falls du was handfestes brauchst: http://www.oreilly.com/catalog/cinanut/ (ich finde das ist das beste c-buch, für einsteiger und fortgeschrittene, was es zur zeit gibt). ...und lass dir bloss nicht das 'pronix' machwerk aufschwatzen
-
THX :xmas2:
-
Hallo!
Ich wollte mir auch gerade mal die Funktion des Programmes klar machen.Leider versteh ich nicht was diese Zeile bringt:
double mult = pow(10,floor(log10(x)));Wenn wir zb. ein x = 400.12 haben.
Dann haben wir dort :
double mult = pow(10,floor(log10(400.12)));
double mult = pow(10,floor(2.602...));
double mult = pow(10,2.0);
mult = 10²richtig soweit?
Das macht dann 100.
Nun kommt:
double norm = x/mult;
double norm = 400.12/100;Das macht dann 4.0012.
Nur was bringt uns das? Was passiert dann mit dieser Zahl?
VIELEN DANK an euch!
MfG
Joker
-
Mit den beiden von dir angesprochenen Zeilen wird erreicht, das der beliebig eingegebene Widerstandswert immer in den Bereich von 1.0 bis 9.99 gebracht wird und man so die Ersatzschaltung aus den im Array gespeicherten Werten berechnen kann!
Vielen Dank noch mal an alle hier für die nette Hilfe.