Beiträge von crYteK2601

VPN/Proxy erkannt

Es scheint, dass Sie einen VPN- oder Proxy-Dienst verwenden. Bitte beachten Sie, dass die Nutzung eines solchen Dienstes die Funktionalität dieser Webseite einschränken kann.

    Guten Abend zusammen.

    schreckus

    Das Wort Machbarkeitsstudie trifft es tatsächlich sehr genau. ;)8o Zum Thema Stromaufnahme/-verbrauch. Shelly 1PM kann doch den Stromverbrauch messen. Hier eine kleine Abfrage und schon geht das System auf Störung wenn die Stromaufnahme des Motors bei Blockade über einen vorgegebenen Wert steigt.


    borsti0

    Wie "schreckus" schon geschrieben hat. Machbarkeitsstudie aber vor allem Spaß am Bau (Konstruktion) und der "Programmierung". Der Ertrag ist eigentlich nebensächlich.

    Es ist bereits seit 6 Jahren eine PV Anlage mit Speicher vorhanden.
    29,8kWp (50:50 - OST_WEST)
    2x SMA Tripower 15000TL
    3x Sunny Island 8.0H S18.0H-13
    3x BYD B-Box 13.8 (nutzbar 37,3kWh)

    Warum so groß? Jährlicher Stromverbrauch lag im Mittel bei 32.000kWh.

    Für alle die es eventuell interessiert.
    Ich glaube ich bin einen ganzen Schritt weiter.

    Hab das Skript jetzt weitestgehend fertig. Hier und da noch ein paar Feinheiten.
    Zur Prüfung des Skript's habe ich auch noch eine Simulation gebaut.
    Da bin ich tatsächlich etwas stolz drauf.

    Wer Lust hat kann es sich ja mal ansehen.

    Code in eine .txt einfügen, die Endung .txt in .html ändern und einfach mal im Browser öffnen.

    Tag starten und laufen lassen oder einfach den manuellen Modus starten (Klick auf "Uhr&Sonne: EIN).

    Motorlast 25W. Schieberegler nach Rechts erhöht die Motorlast bis hin zum auslösen der Blockade-Erkennung.
    Reset und es läuft wieder weiter.


    In der Simulation läuft es schon mal.
    Datei mit der Endung .html erstellen, Skript einfügen und einfach mal testen.

    Position 0% = Ost
    Position 100% = West

    Leider zählt die Variable [Position] den Wert weiter hoch obwohl der Motor steht aber das ist in der Simulation eigentlich egal.



    <!DOCTYPE html>
    <html lang="de">
    <head>
    <meta charset="UTF-8">
    <title>Solar Nachführung Simulation</title>
    <style>
    body { font-family: sans-serif; text-align: center; margin-top: 20px; }
    .box { display: inline-block; width: 100px; height: 50px; margin: 10px; line-height: 20px; color: white; font-weight: bold; border-radius: 10px; font-size: 12px; }
    .inactive { background: #888; }
    .active { background: #28a745; }
    .moving { background: #ffc107; color: #000; }
    .halt { background: #dc3545; }
    #status { width: 100px; height: 20px; line-height: 20px; margin-top: 20px; }
    #pulseDisplay { width: 600px; height: 20px; background: #eee; margin: 10px auto; border-radius: 10px; overflow: hidden; position: relative; }
    #pulseBar { height: 100%; width: 0%; transition: width 0.1s, background 0.1s; }
    table { margin: 20px auto; border-collapse: collapse; font-size: 14px; }
    td, th { border: 1px solid #ccc; padding: 4px 8px; }
    th { background: #eee; }
    </style>
    </head>
    <body>

    <h1>Solar Nachführung Simulation</h1>

    <div id="ldrOst" class="box inactive">LDR OST</div>
    <div id="ldrWest" class="box inactive">LDR WEST</div><br>
    <div id="motorOst" class="box inactive">Motor OST</div>
    <div id="motorWest" class="box inactive">Motor WEST</div><br>
    <div id="status" class="box inactive">Status: OK</div>
    <div id="homingPhase">Homing: -</div>
    <div id="driveTime">Fahrtzeit OST->WEST: 50 Sekunden</div>

    <h3>Pulsanzeige</h3>
    <div id="pulseDisplay">
    <div id="pulseBar"></div>
    </div>

    <h2>Live STATE Dashboard</h2>
    <table id="dashboard">
    <thead>
    <tr><th>Variable</th><th>Wert</th></tr>
    </thead>
    <tbody></tbody>
    </table>

    <h3>Steuerung über Tasten:</h3>
    <p>Drücke die Pfeiltasten: ↑ um LDR Ost zu erhöhen, ↓ um LDR West zu erhöhen</p>

    <script>
    // ================== CONFIG ==================
    let CONFIG = {
    ip_Uni_West: "192.168.178.61",
    ip_1PM_Ost: "192.168.178.70",
    ip_1PM_West: "192.168.178.71",
    max_power_block: 45,
    nominal_power: 25,
    wear_threshold: 1.3,
    full_drive_time: 50000, // Gesamtfahrzeit (30000ms = 30s)
    updateInterval: 100, // Update Intervall von 1000ms auf 200ms reduzieren (macht es langsamer)
    nextMoveDelay: 1500,
    safetyTimeout: 500,
    homingTimeMorning: "05:00",
    homingTimeEvening: "18:00",
    darknessThreshold: 10,
    minLdrDifference: 7, // MINIMALER Unterschied zwischen LDR Ost und West
    pulseSmall: 200,
    pulseMedium: 500,
    pulseLarge: 900
    };

    // ================== STATE ==================
    let STATE = {
    currentPos: 50,
    isMoving: false,
    lastDirection: null,
    systemHalt: false,
    eveningCheckDone: false,
    ostReachedTime: 0,
    powerSamples: [],
    blockCounter: 0,
    nextMoveAllowed: 0,
    homingPhase: null,
    homingStartTime: 0,
    ldrOstValue: 50, // Startwert für LDR in der Mitte
    ldrWestValue: 50, // Startwert für LDR in der Mitte
    simulatedPower: 20,
    lastPulse: 0,
    lastPulseType: ''
    };

    // ================== HELPER ==================
    function updateLDR() {
    document.getElementById('ldrOst').className = 'box ' + (STATE.ldrOstValue > CONFIG.darknessThreshold ? 'active':'inactive');
    document.getElementById('ldrOst').innerText = `LDR OST\n${Math.round(STATE.ldrOstValue)}%`;
    document.getElementById('ldrWest').className = 'box ' + (STATE.ldrWestValue > CONFIG.darknessThreshold ? 'active':'inactive');
    document.getElementById('ldrWest').innerText = `LDR WEST\n${Math.round(STATE.ldrWestValue)}%`;
    }

    function updatePulseDisplay(pulseDuration, pulseType) {
    let bar = document.getElementById('pulseBar');
    STATE.lastPulseType = pulseType;

    // Farbe je Pulsart
    let color = pulseType === 'small' ? '#ff9800' :
    pulseType === 'medium' ? '#ffeb3b' :
    '#f44336';
    bar.style.background = color;

    bar.style.width = (pulseDuration / CONFIG.full_drive_time * 100) + '%';
    setTimeout(() => { bar.style.width = '0%'; }, pulseDuration);
    }

    function drive(direction, pulseDuration = null, pulseType = 'small') {
    // Wenn Systemhalt oder schon eine Fahrt läuft, nichts tun
    if (STATE.systemHalt || STATE.isMoving || Date.now() < STATE.nextMoveAllowed) return;

    // Überprüfen, ob die Position die Grenzen erreicht hat
    if (direction === 'OST' && STATE.currentPos <= 0) {
    console.log("Position 0% erreicht, kann nicht weiter nach Osten fahren");
    return; // Keine Bewegung nach Osten, wenn Position 0% erreicht
    }
    if (direction === 'WEST' && STATE.currentPos >= 100) {
    console.log("Position 100% erreicht, kann nicht weiter nach Westen fahren");
    return; // Keine Bewegung nach Westen, wenn Position 100% erreicht
    }

    STATE.isMoving = true;
    STATE.lastDirection = direction;

    // Zuerst alle Motoren auf OFF setzen
    document.getElementById('motorOst').className = 'box inactive';
    document.getElementById('motorWest').className = 'box inactive';

    // Nur den aktuellen Motor auf ON setzen
    if (direction === 'OST') document.getElementById('motorOst').className = 'box moving';
    else document.getElementById('motorWest').className = 'box moving';

    let duration = pulseDuration || CONFIG.full_drive_time;
    STATE.lastPulse = duration;
    updatePulseDisplay(duration, pulseType);

    let startPos = STATE.currentPos;
    let targetChange = direction === 'WEST' ? 100 - STATE.currentPos : 0 - STATE.currentPos;

    let startTime = Date.now();
    let interval = setInterval(() => {
    let elapsed = Date.now() - startTime;
    if (elapsed >= duration) elapsed = duration;
    STATE.currentPos = startPos + targetChange * (elapsed / duration);

    // Aktualisiere die Dashboard-Position
    updateStateDashboard();

    if (elapsed >= duration) {
    clearInterval(interval);
    STATE.isMoving = false;
    STATE.nextMoveAllowed = Date.now() + CONFIG.nextMoveDelay;

    // Nach Fahrt Motor wieder auf OFF
    document.getElementById('motorOst').className = 'box inactive';
    document.getElementById('motorWest').className = 'box inactive';

    // Pulsanzeige zurücksetzen
    document.getElementById('pulseBar').style.width = '0%';

    // Position bleibt sofort an der aktuellen Stelle (wie ein sofort stopppender Motor)
    STATE.currentPos = STATE.currentPos; // Position einfrieren
    }
    }, CONFIG.updateInterval);
    }

    // ================== SIMULATION LOOP ==================
    function solveLogic() {
    if (STATE.systemHalt) return;

    updateLDR(); // LDR-Werte aktualisieren
    updateStateDashboard(); // Live Dashboard aktualisieren

    // Berechne den LDR-Unterschied
    const ldrDifference = Math.abs(STATE.ldrOstValue - STATE.ldrWestValue);

    // Wenn der Unterschied zu klein ist, stoppe den Motor
    if (ldrDifference <= CONFIG.minLdrDifference) {
    console.log("LDR Unterschied zu klein, stoppe Bewegung");

    // Falls der Motor sich gerade bewegt, stoppen
    if (STATE.isMoving) {
    STATE.isMoving = false;
    document.getElementById('motorOst').className = 'box inactive';
    document.getElementById('motorWest').className = 'box inactive';

    // Pulsanzeige zurücksetzen
    document.getElementById('pulseBar').style.width = '0%';

    // Position bleibt sofort an ihrem aktuellen Wert
    STATE.currentPos = STATE.currentPos; // Position einfrieren
    }
    }
    // Wenn der Unterschied größer als der Schwellenwert ist, fahre zur Sonne
    else {
    console.log("LDR Unterschied ausreichend, starte Bewegung");
    if (STATE.ldrOstValue < STATE.ldrWestValue) {
    console.log("Fahre nach Osten");
    drive('OST', CONFIG.pulseLarge, 'large');
    } else {
    console.log("Fahre nach Westen");
    drive('WEST', CONFIG.pulseLarge, 'large');
    }
    }
    }

    // Funktion, die das Dashboard regelmäßig aktualisiert
    function updateStateDashboard() {
    const tbody = document.querySelector('#dashboard tbody');
    tbody.innerHTML = ''; // Vorherige Werte löschen

    // Dashboard mit den aktuellen Werten füllen
    const stateData = [
    { name: 'Position', value: `${STATE.currentPos.toFixed(2)} %` },
    { name: 'LDR Ost', value: `${Math.round(STATE.ldrOstValue)} %` },
    { name: 'LDR West', value: `${Math.round(STATE.ldrWestValue)} %` },
    { name: 'Motor Bewegung', value: STATE.isMoving ? 'Ja' : 'Nein' },
    { name: 'Letzte Richtung', value: STATE.lastDirection || 'N/A' },
    { name: 'Homing Phase', value: STATE.homingPhase || 'Nicht aktiv' },
    ];

    stateData.forEach(item => {
    const tr = document.createElement('tr');
    const tdName = document.createElement('td');
    const tdValue = document.createElement('td');
    tdName.textContent = item.name;
    tdValue.textContent = item.value;
    tr.appendChild(tdName);
    tr.appendChild(tdValue);
    tbody.appendChild(tr);
    });
    }

    // Steuerung mit den Pfeiltasten
    document.addEventListener('keydown', (event) => {
    if (event.key === "ArrowUp") {
    if (STATE.ldrOstValue < 100) {
    STATE.ldrOstValue += 1;
    STATE.ldrWestValue = 100 - STATE.ldrOstValue;
    }
    }
    if (event.key === "ArrowDown") {
    if (STATE.ldrWestValue < 100) {
    STATE.ldrWestValue += 1;
    STATE.ldrOstValue = 100 - STATE.ldrWestValue;
    }
    }
    });

    // Starte die Simulation
    setInterval(solveLogic, CONFIG.updateInterval);
    </script>
    </body>
    </html>

    horkatz

    Das war tatsächlich mein erster Gedanke. Ich möchte jedoch nur ungerne den astronomische Sonnenverlauf zur Nachführung nutzen.

    Ich möchte damit, sobald das Skript den finalen Stand erreicht hat einen Prototypen im Miniaturformat bauen um die Funktionen alle nochmals zu prüfen.
    Erst wenn dieser Prototyp gebaut und dessen Funktion überprüft wurde möchte ich das 1:1 Modell starten.

    Zu deiner Aussage bzgl. Rückmeldung der aktuellen Positionen.
    Durch den Endschalter auf Position OST und den zweiten Endschalter auf Position SÜD kann die Logik die Laufzeit von OST nach SÜD feststellen.
    Diesen Wert nimmt er *2 und kann so die Laufzeit von OST nach WEST berechnen. Als Beispiel wurde im Skript (full_drive_time: 30000) gesetzt. Dieser Wert muss während der Erstinbetriebnahme noch korrigiert werden.

    Die Werte sind in Prozent zu verstehen.
    OST = 0%
    SÜD = 50%
    WEST = 100%

    Die Logik sollte also bei 100% halt machen. Dadurch erspare ich mir beispielsweise Potentiometer zur Positionserkennung.

    Servus zusammen.

    Ich bin der Marcus, 36 Jahre alt und komme aus der schönen, aktuell sehr verschneiten Oberpfalz.
    Ich bin seit etwa einem Jahr im Shelly Universe zugange und konnte bereits viele Projekte zum Thema Hausautomation verwirklichen.
    Mir entgeht quasi kein Watt welches hier am Grundstück verbraucht oder tatsächlich auch erzeugt wird. ;););)

    Ich freue mich auf rege Unterhaltungen und eine gute Diskussion über das Thema Shelly.

    Seid gegrüßt:beer:

    Hier das aktuelle Skript.
    script_east-west_rev1_030125.txt
    ____________________________________________


    // KONFIGURATION
    let CONFIG = {
    ip_Uni_West: "192.168.178.xx",
    ip_1PM_Ost: "192.168.178.xx",
    ip_1PM_West: "192.168.178.xx",
       
    max_power_block: 45, // Harter Stopp (Blockade)
    nominal_power: 25, // Erwartete Leistung (wird vom Skript angepasst)
    wear_threshold: 1.3, // Faktor 1.3 = 30% über Normalwert gilt als Verschleiß
    full_drive_time: 30000,
    updateInterval: 1500,
    homingTimeMorning: "05:00",
    homingTimeEvening: "18:00",
    darknessThreshold: 10
    };

    let STATE = {
    currentPos: 50,
    isMoving: false,
    isHoming: false,
    lastDirection: null,
    startTime: 0,
    nextMoveAllowed: 0,
    systemHalt: false,
    eveningCheckDone: false,
    ostReachedTime: 0,
    powerSamples: [], // Speichert Leistungswerte für Durchschnitt
    };

    // --- STEUERUNG ---

    function emergencyStop(reason) {
    if (!STATE.systemHalt) {
    print("!!! STOPP: " + reason + " !!!");
    STATE.systemHalt = true;
    }
    Shelly.call("HTTP.GET", { url: "http://" + CONFIG.ip_1PM_Ost + "/rpc/Switch.Set?id=0&on=false" });
    Shelly.call("HTTP.GET", { url: "http://" + CONFIG.ip_1PM_West + "/rpc/Switch.Set?id=0&on=false" });
    STATE.isMoving = false;
    STATE.isHoming = false;
    }

    // --- VERSCHLEISS-ANALYSE ---

    function checkWear(currentPower) {
    if (currentPower < 5) return; // Motor läuft noch nicht richtig an

    // 1. Harte Blockade prüfen
    if (currentPower > CONFIG.max_power_block) {
    emergencyStop("Mechanische Blockade (" + Math.round(currentPower) + "W)");
    return;
    }

    // 2. Verschleiß-Warnung (Schwergängigkeit)
    let limit = CONFIG.nominal_power * CONFIG.wear_threshold;
    if (currentPower > limit) {
    print("HINWEIS: Erhöhter Widerstand erkannt! Aktuell: " + Math.round(currentPower) + "W (Normal: " + Math.round(CONFIG.nominal_power) + "W)");
    }

    // 3. Den Normalwert schleichend anpassen (Lerneffekt für gesunde Mechanik)
    // Wir nehmen nur Werte auf, die keine Blockade sind
    CONFIG.nominal_power = (CONFIG.nominal_power * 0.95) + (currentPower * 0.05);
    }

    // --- MONITORING ---

    function monitor() {
    let now = new Date();
    let currentTime = ("0" + now.getHours()).slice(-2) + ":" + ("0" + now.getMinutes()).slice(-2);
       
    if (currentTime === "00:00") STATE.eveningCheckDone = false;

    // Homing Logik (Ost/Süd)
    if ((currentTime === CONFIG.homingTimeMorning || (currentTime >= CONFIG.homingTimeEvening && !STATE.eveningCheckDone))
    && !STATE.isHoming && !STATE.isMoving && !STATE.systemHalt) {
    STATE.isHoming = true;
    drive("OST", false);
    }

    // Endschalter-Abfragen
    Shelly.call("Input.GetStatus", { id: 2 }, function(res) {
    if (res && res.state && STATE.isHoming && STATE.lastDirection === "OST") {
    STATE.currentPos = 0;
    STATE.ostReachedTime = Date.now();
    drive("WEST", false);
    }
    });

    Shelly.call("Input.GetStatus", { id: 1 }, function(res) {
    if (res && res.state && STATE.isHoming && STATE.lastDirection === "WEST") {
    let travelTime = Date.now() - STATE.ostReachedTime;
    CONFIG.full_drive_time = (CONFIG.full_drive_time * 0.7) + (travelTime * 2 * 0.3);
    print("Laufzeit-Kalibrierung: 100% Weg = " + (CONFIG.full_drive_time/1000).toFixed(2) + "s");
    emergencyStop("Referenzpunkt erreicht");
    STATE.currentPos = 50.0;
    STATE.systemHalt = false;
    STATE.isHoming = false;
    STATE.eveningCheckDone = true;
    }
    });

    // Stromaufnahme während der Fahrt prüfen
    if (STATE.isMoving) {
    let activeIP = (STATE.lastDirection === "WEST") ? CONFIG.ip_1PM_West : CONFIG.ip_1PM_Ost;
    Shelly.call("HTTP.GET", { url: "http://" + activeIP + "/rpc/Switch.GetStatus?id=0" }, function(res) {
    if (res && res.code === 200) {
    let status = JSON.parse(res.body);
    checkWear(status.apower); // Hier wird auf Verschleiß geprüft
    }
    });
    }
    }

    // --- HAUPTLOGIK (Drive & Sync) ---

    function drive(direction, isPulse, duration) {
    if (STATE.systemHalt) return;
    let targetIP = (direction === "OST") ? CONFIG.ip_1PM_Ost : CONFIG.ip_1PM_West;
    let otherIP = (direction === "OST") ? CONFIG.ip_1PM_West : CONFIG.ip_1PM_Ost;
    Shelly.call("HTTP.GET", { url: "http://" + otherIP + "/rpc/Switch.Set?id=0&on=false" });
    Shelly.call("HTTP.GET", { url: "http://" + targetIP + "/rpc/Switch.Set?id=0&on=true" });
    STATE.isMoving = true;
    STATE.lastDirection = direction;
    if (isPulse) {
    Timer.set(duration, false, function() {
    Shelly.call("HTTP.GET", { url: "http://" + targetIP + "/rpc/Switch.Set?id=0&on=false" });
    STATE.currentPos += (STATE.lastDirection === "WEST" ? 1 : -1) * (duration / CONFIG.full_drive_time) * 100;
    STATE.isMoving = false;
    STATE.nextMoveAllowed = Date.now() + 3000;
    });
    }
    }

    function solveLogic() {
    let devices = [CONFIG.ip_Uni_West, CONFIG.ip_1PM_Ost, CONFIG.ip_1PM_West];
    let checks = 0; let errors = 0;
    for (let i = 0; i < devices.length; i++) {
    Shelly.call("HTTP.GET", { url: "http://" + devices[i] + "/rpc/Shelly.GetDeviceInfo", timeout: 2 }, function(r, e) {
    checks++; if (e !== 0) errors++;
    if (checks === devices.length) {
    if (errors > 0) { emergencyStop("Hardware offline"); return; }
    if (STATE.systemHalt) STATE.systemHalt = false;
    monitor();
    if (STATE.isMoving || STATE.isHoming || Date.now() < STATE.nextMoveAllowed) return;
                   
    // LDR Auswertung
    Shelly.call("Input.GetStatus", { id: 0 }, function(vOst) {
    let valOst = vOst.xpercent;
    Shelly.call("HTTP.GET", { url: "http://" + CONFIG.ip_Uni_West + "/rpc/Input.GetStatus?id=0" }, function(res) {
    if (!res || res.code !== 200) return;
    let valWest = JSON.parse(res.body).xpercent;
    if (valOst < CONFIG.darknessThreshold && valWest < CONFIG.darknessThreshold) return;
    let diff = Math.abs(valOst - valWest);
    let pulse = diff > 20 ? 900 : (diff >= 10 ? 500 : (diff > 3 ? 250 : 0));
    if (pulse > 0) {
    if (valOst > valWest && STATE.currentPos > 0) drive("OST", true, pulse);
    else if (valWest > valOst && STATE.currentPos < 100) drive("WEST", true, pulse);
    }
    });
    });
    }
    });
    }
    }

    Timer.set(CONFIG.updateInterval, true, solveLogic);

    Guten zusammen und allen noch ein gesundes neues Jahr.

    Ich bin nun schon einige Zeit im Shelly Universum unterwegs und habe bereits mein Haus teil "Shelly'siert".
    Ihr kennt das ja alle. Wenn man einmal mit dem Thema angefangen hat finden sich immer mehr Möglichkeiten/Anwendungsbereiche in denen man zumindest theoretisch Shelly's einsetzen könnte.
    Aufgrund der Vielseitigkeit und der humanen Preise findet man sich plötzlich am "Labortisch" wieder.
    Aktuell wieder so geschehen. :-)

    Nun zum eigentlichen Thema.
    Umsetzung einer Solarnachführung mit diversen Shelly Modulen.
    Wie ein solches Gestell aussieht könnt ihr euch mit Sicherheit ja vorstellen, vermutlich kennt die Großteil diese Gestelle sogar aus dem Netz.
    Kurze Gedankenspiel um euch zum Aufbau und Ablauf abzuholen.

    Das Gestell ist eine Eigenkonstruktion.
    Fundament 100x100x60cm.
    Höhe des Stehers etwa 3,5m.
    Modulhalterung aus Maytec Profil.
    4 Module a 500W welche sich automatisch zur Sonne ausrichten sollen.
    Antrieb für Elevation (NORD-SÜD-Ausrichtung) Linearantrieb mit etwa 300mm Hub.
    Antrieb für Azimut (OST-WEST-Ausrichtung) Linearantrieb oder Schrittmotor. Die Entscheidung ist noch nicht zu 100% gefallen. Präferiert wird jedoch ein Schrittmotor.

    Nun zum Thema Steuerung.
    Die Steuerung soll über Home Assistant in Verbindung mit Shelly Plus UNI laufen.

    Aufbau:

    Fotowiderstände angebracht an Modulhalterung mit kleinen Edelstahlblech um einen Schattenwurf zu generieren.
    Jeweils einer davon an den enden Ost-Süd-West-Nord angebracht.

    ShellyUNI_A misst über den Analog-Eingang den abgegebenen Spannungswert für Sensor OST und stellt diesen in Prozent (%) zur Weiterverarbeitung zu Verfügung.
    ShellyUNI_B misst über den Analog-Eingang den abgegebenen Spannungswert für Sensor WEST und stellt diesen in Prozent (%) zur Weiterverarbeitung zu Verfügung.
    ShellyUNI_C misst über den Analog-Eingang den abgegebenen Spannungswert für Sensor NORD und stellt diesen in Prozent (%) zur Weiterverarbeitung zu Verfügung.
    ShellyUNI_D misst über den Analog-Eingang den abgegebenen Spannungswert für Sensor SÜD und stellt diesen in Prozent (%) zur Weiterverarbeitung zu Verfügung.

    Zusätzlich:
    ShellyUNI_A misst über den Digital-IN 1 einen Endschalter-Kontakt angebracht an Position max. OST der Azimut-Achse.
    ShellyUNI_A misst über den Digital-IN 2 einen Endschalter-Kontakt angebracht an Position SÜD der Azimut-Achse.
    Dadurch wird die Laufzeit überprüft welche vergeht wenn der Schrittmotor das Gestell von OST nach SÜD dreht. Dieser Wert (x2) ist gleich die Gesamtlaufzeit von OST nach WEST.
    Dient zur Verschleißkontrolle wenn die Konstruktion etwas schwergängig werden sollte (Verschleiß oder Schmutz in Laufschienen/Gelenken).

    ShellyUNI_A übernimmt die Steuerung von Shelly1PM_OST. Zusätzlich überwacht ShellyUNI_A die Stromaufnahme von Shelly1PM_OST.
    ShellyUNI_B übernimmt die Steuerung von Shelly1PM_WEST. Zusätzlich überwacht ShellyUNI_B die Stromaufnahme von Shelly1PM_WEST.
    Pause-Zeit zwischen den Schaltvorgängen ~3 Sekunden. Dient zum Schutz des Stellantriebs und der Shellys vor Kurzschluss.
    Die Überwachung der Stromaufnahme dient zur Überwachung einer Blockade während der Fahrt von OST->WEST oder WEST->OST.

    Elevation (NORD-SÜD) thematisiere ich vorerst mal nicht in diesem Thread.
    Ein Dreieck-Stern-Anemometer zur Überwachung der Windgeschwindigkeit wird aktuell noch nicht Berücksichtigt. Dieses Wird Später an einen Count-IN angeschlossen.
    Gedanke hierbei wäre, X m/s > ~15m/s = Elevation Fahrt in Position Waagerecht (0%)

    Ich habe mir Gedanken zu dem Skript gemacht.
    Was muss alles beachtet werden, Sicherheitseinrichtung, Verschleißüberwachung inkl. Warnung, Referenz-Stellungen über Endschalterabfrage und diverse andere Kleinigkeiten.

    In Zusammenarbeit mit der KI habe ich ein Skript erstellt welches für mich als Skript-Laie grundsätzlich nicht schlecht aussieht.
    Aber wir wissen ja alle, Kontrolle ist besser als Vertrauen. :-)

    Vielleicht gibt es hier ja einen Findigen Skript-Künstler der sich die Sache mal ansehen möchte und noch auf eventuelle Probleme Hinweisen kann oder im schlimmsten Fall die Funktion dieses Skript's in Frage stellt und seine Bedenken fachlich belegen kann.

    Ich wäre sehr dankbar für sämtliche Arten von Hilfestellung/Unterstützung.

    Skript folgt ->