Ohmsches Gesetz in C-Programm?


  • Gesperrt

    Dieser Beitrag wurde gelöscht!

  • Gesperrt

    Dieser Beitrag wurde gelöscht!

  • Mod

    Dieser Beitrag wurde gelöscht!

  • Gesperrt

    Dieser Beitrag wurde gelöscht!

  • Gesperrt

    Dieser Beitrag wurde gelöscht!


  • @Leon0402 sagte in Ohmsches Gesetz in C-Programm?:

    Ehrlicherweise weiß ich nicht zu 100% wie man das im Taschenrechner berechnet bzw. was man überhaupt hier berechnen soll.

    Man kann mit Hilfe der gegebenen R1,R2,,R8R_1, R_2, \ldots, R_8 einen effektiv Widerstand RER_E errechnen, der dann statt der 8 Einzelnen Widerstände den gleichen Widerstand hat. Man kann für jede Masche die Spannungen und die Stromstärken berechnen … siehe Kirchhoffsche Gesetz. Da es keine LC-Elemente oder aktive Elemente in der Schaltung gibt braucht man keine komplexe Wechselstromrechung und für zeitveränderliche Spannungen ist das alles trivial zu betrachten.



  • Danke für eure Beiträge. Ich bin inzwischen weitergekommen und denke, ich schaffe das mit Tutorials alleine. Tatsächlich haben wir erst gestern damit angefangen (auch die Azubis).


  • Mod

    Hier eine mögliche Lösung in Python. Beziehungsweise zuerst einmal der Schaltplan in einer maschinenlesbaren Form. Ich habe ohne tiefgehenden Grund JSON gewählt. Das ist ein gutes Format, um beliebig verschachtelte Daten (wie man sie hier hat) darzustellen, und trotzdem noch lesbar zu bleiben. Meine Idee hier ist, dass ein Schaltkreis aus Widerständen, sowie Reihen-, und Parallelschaltungen besteht. Reihen- und Parallelschaltungen können wiederum aus einer beliebigen Menge von weiteren dieser Schaltungselementen bestehen.

    Die Komplexität des Schaltplans in der Aufgabe bedeutet auch, dass der JSON-Schaltplan entsprechend kompliziert ausschaut.

    {
      "series": [
        {
          "parallel": [
            {
              "series": [
                {
                  "parallel": [
                    {
                      "resistor": {
                        "note": "R1",
                        "band1": "blue",
                        "band2": "yellow",
                        "multiplier": "red",
                        "tolerance": "silver"
                      }
                    },
                    {
                      "resistor": {
                        "note": "R2",
                        "band1": "violet",
                        "band2": "white",
                        "multiplier": "orange",
                        "tolerance": "gold"
                      }
                    }
                  ]
                },
                {
                  "resistor": {
                    "note": "R4",
                    "band1": "gray",
                    "band2": "white",
                    "multiplier": "orange",
                    "tolerance": "gold"
                  }
                }
              ]
            },
            {
              "resistor": {
                "note": "R3",
                "band1": "red",
                "band2": "red",
                "multiplier": "red",
                "tolerance": "silver"
              }
            }
          ]
        },
        {
          "resistor": {
            "note": "R5",
            "band1": "red",
            "band2": "green",
            "multiplier": "brown",
            "tolerance": "silver"
          }
        },
        {
          "resistor": {
            "note": "R6",
            "band1": "yellow",
            "band2": "orange",
            "multiplier": "brown",
            "tolerance": "gold"
          }
        },
        {
          "resistor": {
            "note": "R7",
            "band1": "brown",
            "band2": "black",
            "multiplier": "black",
            "tolerance": "silver"
          }
        },
        {
          "resistor": {
            "note": "R8",
            "band1": "red",
            "band2": "blue",
            "multiplier": "brown",
            "tolerance": "gold"
          }
        }
      ]
    }
    

    Und jetzt das eigentliche Pythonprogramm dazu. Ich bin ja ein Fan von Überkorrektheit bei der Datenmodellierung. Die Hälfte dieses Programms ist bloß Farbdefinition. Fast der gesamte Rest sind Datenmodell, das eigentlich gar nichts tut, außer mir bei der eigentlichen Rechnung das Leben einfach zu machen. Dadurch kann ich die eigentliche Rechnung dann sehr kompakt (und hoffentlich verständlich!) in ein paar wenigen Zeilen konzentrieren.

    import json
    
    # Erst einmal ganz viel Fachwissen, das eigentlich überhaupt nichts tut. Irgendwoher muss der Computer ja wissen, welche
    # Farbe welchen Widerstandswert bedeutet.
    
    color_values = {
        "pink": -3,
        "silver": -2,
        "gold": -1,
        "black": 0,
        "brown": 1,
        "red": 2,
        "orange": 3,
        "yellow": 4,
        "green": 5,
        "blue": 6,
        "violet": 7,
        "gray": 8,
        "white": 9,
    }
    
    color_tolerances = {
        "silver": 10,
        "gold": 5,
        "brown": 1,
        "red": 2,
        "orange": 0.05,
        "yellow": 0.02,
        "green": 0.5,
        "blue": 0.25,
        "violet": 0.1,
        "gray": 0.01,
    }
    
    
    class CircuitElement:
        # Tut eigentlich auch nichts, außer als Dokumentation zu dienen, wie wir uns den Aufbau der Daten vorstellen:
        # Die Schaltung ist aus lauter Elementen aufgebaut, die jeder einen Widerstand und eine Toleranz haben. Was
        # solche Schaltelemente sind, definieren wir unten.
        def ohm_value(self) -> float:
            """
            Resistance in Ohm of the CircuitElement
            """
            raise NotImplementedError()
    
        def tolerance(self) -> float:
            """
            Relative tolerance (as a scalar, not in percent!) of the CircuitElement
            """
            raise NotImplementedError()
    
    
    class Resistor(CircuitElement):
        # Ein Widerstand ist ein mögliches Bauteil.
        def __init__(self, *, band1: str, band2: str, multiplier: str, tolerance: str, note: str):
            # Die note fange ich nur sinnlos auf, damit ich die Kommentare im JSON haben kann. Ist so eine dumme
            # Eigenschaft von (primitivem) JSON, dass man keine richtigen Kommentare haben kann.
    
            # Hier berechnen wir aus den Farbringen den Widerstand und die Fertigungstoleranz
            self._ohm_value = (color_values[band1] * 10 + color_values[band2]) * 10 ** color_values[multiplier]
            self._tolerance = color_tolerances[tolerance] / 100
    
        def ohm_value(self) -> float:
            return self._ohm_value
    
        def tolerance(self) -> float:
            return self._tolerance
    
    
    class SeriesConnection(CircuitElement):
        # Eine Reihenschaltung von anderen Schaltungselementen ist wieder ein Schaltungselement
        def __init__(self, *, circuit_elements: list[CircuitElement]):
            self.circuit_elements = circuit_elements
    
        def ohm_value(self) -> float:
            # Das erste Mal, dass wir tatsächlich etwas Elektrisches berechnen. Der Widerstand einer Reihenschaltung ist
            # die Summe der in Reihe geschalteten Widerstände.
            return sum(circuit_element.ohm_value() for circuit_element in self.circuit_elements)
    
        def tolerance(self) -> float:
            # Hier muss jemand mit Elektronikfachwissen korrigieren, wie man die Gesamttoleranz dort üblicherweise berechnet
            # Ich habe mich bewusst gegen eine Fehlerfortpflanzung wie bei Messwerten entschieden, denn das sind ja keine
            # Messwerte, sondern Fertigungstoleranzen. Ich nehme von daher an, dass die Gesamttoleranz einer Serie die
            # Summe der absoluten(!) Einzeltoleranzen ist. Wenn das unüblich ist, dann bitte korrigieren.
            absolute_tolerance = sum(circuit_element.tolerance() * circuit_element.ohm_value()
                                           for circuit_element in self.circuit_elements)
            relative_tolerance = absolute_tolerance / self.ohm_value()
            return relative_tolerance
    
    class ParallelConnection(CircuitElement):
        # Eine Parallelschaltung von anderen Schaltungselementen ist wieder ein Schaltungselement
        def __init__(self, *, circuit_elements: list[CircuitElement]):
            self.circuit_elements = circuit_elements
    
        def ohm_value(self) -> float:
            # Der reziproke Widerstand einer Reihenschaltung ist die Summe der reziproken Einzelwiderstände
            reciprocal_ohm_value = sum(1 / circuit_element.ohm_value() for circuit_element in self.circuit_elements)
            return 1 / reciprocal_ohm_value
    
        def tolerance(self) -> float:
            # Mit der gleichen Logik wie bei der Reihenschaltung wende ich keine Fehlerfortpflanzung wie bei Messwerten an.
            # Ohne das nötige Fachwissen wähle ich die maximale Einzeltoleranz als grobe Schätzung für die Gesamttoleranz
            return max(circuit_element.tolerance() for circuit_element in self.circuit_elements)
    
    
    def json_to_circuit_element(json_dict: dict):
        # Übersetzt einen Teil des Schaltplans in eines der oben definierten Elemente. Man beachte, dass diese Funktion
        # sich wieder aufrufen kann, denn eine Reihen- oder Parallelschaltung bestehen ja wieder aus anderen
        # Schaltungselementen.
        if "resistor" in json_dict:
            return Resistor(**json_dict["resistor"])
        if "series" in json_dict:
            return SeriesConnection(circuit_elements=[json_to_circuit_element(sub_dict) for sub_dict in json_dict["series"]])
        if "parallel" in json_dict:
            return ParallelConnection(circuit_elements=[json_to_circuit_element(sub_dict) for sub_dict in json_dict["parallel"]])
    
    def main():
        circuit_dict = json.load(open("circuit.json", "r"))
        circuit = json_to_circuit_element(circuit_dict)
        ohm_value = circuit.ohm_value()
        tolerance = circuit.tolerance()
        absolute_tolerance = ohm_value * tolerance
        print(f"Gesamtwiderstand: {ohm_value:.0f} Ohm. Toleranz: {tolerance*100:.0f}% ({absolute_tolerance:.0f} Ohm)")
    
    main()
    

    Die Grundidee ist die gleiche wie beim JSON-Modell des Schaltplans: Eine Schaltung besteht aus Schaltelementen, jedes mit Widerstand und Toleranz. Widerstände sind solche Schaltelemente, aber auch Reihen- und Parallelschaltungen, die wiederum aus anderen Schaltelementen bestehen können. So kann man für jedes solche Schaltelement recht trivial angeben, was Widerstand und Toleranz sind. Die ganze Komplexität des Schaltplans wird darauf abgewälzt, dass diese Bauteile beliebig verschachtelt sein können. Aber für diesen Aufbau braucht man keine spezielle Rechnung zu programmieren, das ist einfach wie ich die Daten aufgebaut habe.

    Ausgabe:
    Gesamtwiderstand: 3100 Ohm. Toleranz: 9% (276 Ohm)

    Meine Toleranzberechnung ist, wie im Code kommentiert, ein bisschen mit Vorsicht zu genießen. Ich hatte auch mal damit experimentiert, die Parallelschaltungsformel richtig abzuleiten, aber da kamen recht absurde Werte raus. Ich vermute, ich habe mich da irgendwo verrechnet. Da das nur ein Beispiel zum allgemeinen Aufbau eines solchen Programms ist, habe ich dann eine einfachere Wahl getroffen, die mir realistisch vorkam. Wenn der Fachmann eine bessere Formel kennt, kann er sie ja ganz einfach an der entsprechenden Stelle einsetzen.

    Mir macht Mut, dass der (auf das ganze Ohm gerundete) Widerstand eine so glatte Zahl ist. Das ist gewiss von der Aufgabe her bewusst so gewählt. Die Toleranz von knapp 10% klingt auch realistisch.

    Wenn ich nicht unnötig Zeit darauf verbraten hätte, die Toleranz einer Reihenschaltung genauer abzuschätzen, hätte ich das so runterschreiben können, mit meiner Tippgeschwindigkeit, plus etwas Zeit um die ganzen Farben nachzugucken und die Formeln nochmal zu prüfen. Das heißt, ein guter Programmierer kann so etwas in ~30-60 Minuten machen. Zumindest in Python, wo man sich leichter auf das wesentliche konzentrieren kann. In C kann man die Grundideen genauso umsetzen, wird man vor allem aber an zwei Punkten Schwierigkeiten haben:

    1. Die Eigenschaft, dass Schaltelelemente aus beliebig vielen anderen Elementen bestehen können, bedarf der Programmierung spezieller Datenstrukturen, die es so in C nicht direkt gibt. Da man aber im Vorhinein weiß, wie viele Subelemente ein jedes Element hat, reicht eine einfache Kombination eines dynamischen Arrays mit einer Längenangabe.
    2. Die Zeile circuit_dict = json.load(open("circuit.json", "r")) ist alleine ein riesiges C-Programm, mit komplizierten Datenstrukturen. Hier muss die Datenstruktur auch so einiges können, da sie beliebig schachtelbar sein muss, d.h. hier sind Indirektionen und die berüchtigten Pointer unvermeidbar.


  • Cool 😎



  • @SeppJ Auf alle Fälle danke, dass du dir die Zeit genommen hast, dich damit zu befassen. 👍


Anmelden zum Antworten