Autor Thema: Fragen zur Stromversorgung, RS485 und Programmierung der Nodes  (Gelesen 12672 mal)

Offline Beta-User

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 9646
  • eigentlich eher "user" wie "developer"
Antw:Fragen zur Stromversorgung usw. der Nodes
« Antwort #60 am: 04 Dezember 2019, 13:57:23 »
Hmm, alle %-Werte auf einmal finde ich schwierig, das braucht relativ viel Auswertelogik beim Empfang der Nachricht. Würde das eher über getrennte Infos lösen.

Also, mal angenommen du hast bis 5 Kreise:

Dann nutzt du "Custom" (value1-value5 an - sagen wir - child 100), um für jeden der Kreise einen "Basiszeitwert" festzulegen. Optimalerweise würde ich einen Minutenwert oder 30-Sek.-Wert vorschlagen, dann kann der ohne allzugroße Umstände im EEPROM gespeichert werden (vorgesehen ist 1 BYTE/Child, da mußt du dann schon tricksen...), andernfalls holt sich die Node den bei jedem Start.

Dann definierst du einen Dimmer, mit dem kannst du "Notaus" und "an" mit einem Prozentwert einstellen.
Aus dem einen Prozentwert und den Minutenangaben machst du dann die Anschaltdauern (in millis) auf der Node (simple Mathematik), und kannst dann auch einzelne Kreise (child 1-5?) ein- und ausschalten. Schaltest du einen via FHEM oder lokalem Taster aus, wird einfach dann bei "generell-an" der nächste genommen, auch vor Zeitablauf usw..

Es gibt aber afaik auch schon einen sketch im MySensors-Forum. Müßte man sich mal ansehen, was der wie haben will (ich bastle dann auch gerne ein attrTemplate draus...).
Server: HP-T620@Debian 10, aktuelles FHEM + ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | BT@OpenMQTTGateway
svn:MySensors, WeekdayTimer, RandomTimer, AttrTemplate => {mqtt2, mysensors, httpmod}

Offline frober

  • Full Member
  • ***
  • Beiträge: 303
Antw:Fragen zur Stromversorgung usw. der Nodes
« Antwort #61 am: 04 Dezember 2019, 18:55:58 »
Danke für die gedanklichen Anstöße. Ich merke ich muss noch mehr bedenken.

Ich habe einen Node mit 2 und einen mit 3 Kreise. Die Sprinkler sind noch nicht installiert und entsprechend habe ich noch keine Durchflussmenge pro Kreis. Daher weiß ich auch noch nicht wie ich sie zusammen, bzw. In welcher Reihenfolge ich sie betreibe, damit es mit der Brunnenpumpe harmoniert.

Ich werde es erstmal, wenn ich soweit bin, über Fhem die Zeiten steuern und wenn alles steht auf die Nodes übertragen. Bis dato wird es vermutlich nächsten Winter.

Eine Frage noch:
Ein sleep in Perl ist blockiernd, soweit klar. Wie verhält es sich mit Schleifen (while, for, etc.)?
Wenn ich z.B. über ein at eine sub in MyUtils starte und darin ist eine Schleife die mehrere Minuten dauert.
Raspi 3b mit Raspbian Jessie und Fhem,  einiges umgesetzt, vieles in Planung :-)

Offline Beta-User

  • Moderator
  • Hero Member
  • ***
  • Beiträge: 9646
  • eigentlich eher "user" wie "developer"
Antw:Fragen zur Stromversorgung usw. der Nodes
« Antwort #62 am: 05 Dezember 2019, 08:08:46 »
...ich glaube, diesen Thread sollte "jemand" mal splitten, ist ziemlich viel Zeug hier drin, das mit Stromversorgung nichts zu tun hat...

Zur Sache: Sorry, wenn ich das so deutlich sage, aber es gruselt mich, wenn ich lese, dass eine Schleife länger dauern soll. Es ist extrem wichtig, FHEM (genauer phem.pl) nicht zu blockieren, also sollte man alles auslagern, was länger dauert, entweder  in einen separaten Prozess oder eben auf die Hardware, oder den Programmablauf nicht blockierend gestalten. Aber eine "Ereignisprüfungsschleife" mit while (so hatte ich das verstanden) ist mMn. unbedingt zu vermeiden.

Wie man was auslagert, wäre z.B. hier erläutert (oh Wunder, es geht um Gartenbewässerung...):
https://forum.fhem.de/index.php/topic,6436.msg26685.html#msg26685

Wenn es innerhalb FHEM laufen soll, kann man (direkt oder indirekt) InternalTimer nutzen. Das braucht halt einen Funktionsaufruf. Ein Beispiel wäre (neben dem Suchwort Dimmer) z.B. in RandomTimer zu finden. RandomTimer_Exec ruft sich am Ende auch immer wieder selbst auf, nachdem es geprüft hat, ob es (wie) schalten muß und ermittelt dabei (mit RandomTimer_getSecsToNextAbschaltTest) den nächsten Zeitpunkt bzw., ob überhaupt noch ein Durchlauf erforderlich ist.
Server: HP-T620@Debian 10, aktuelles FHEM + ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | BT@OpenMQTTGateway
svn:MySensors, WeekdayTimer, RandomTimer, AttrTemplate => {mqtt2, mysensors, httpmod}

Offline frober

  • Full Member
  • ***
  • Beiträge: 303
Antw:Fragen zur Stromversorgung usw. der Nodes
« Antwort #63 am: 05 Dezember 2019, 10:11:21 »
Ist mir gestern auch aufgefallen, dass das hier eigentlich zu OT ist.
Bzgl. Perl werde ich bei weiteren Fragen einen neuen Thread aufmachen.

Bezgl. Schleife habe ich vermutet, das es blockiert, wollte nur sicher gehen.

Den Rest werde ich mir anschauen und nach einer Guten Lösung suchen. Es gibt noch viel zu lernen....

Nochmals Danke für die Tipps
« Letzte Änderung: 05 Dezember 2019, 13:06:45 von frober »
Raspi 3b mit Raspbian Jessie und Fhem,  einiges umgesetzt, vieles in Planung :-)

Offline frober

  • Full Member
  • ***
  • Beiträge: 303
Antw:Fragen zur Stromversorgung, RS485 und Programmierung der Nodes
« Antwort #64 am: 10 Dezember 2019, 18:59:33 »
Wieder ein Stück weiter. :)

Den Betreff habe ich mal angepasst, da mittlerweile sehr viel dazugekommen ist.


Ich denke, ich habe die für mich optimale Lösung gefunden:

Die Zeitsteuerung der Relais läuft autark auf den Nodes.
Die Zeit kann nach Berechnung über Fhem (MyUtils) in einem "Rutsch" an die Nodes für alle Relays übergeben werden.
Danach wird das erste Relay geschaltet und über notify's (evtl. DOIF o.ä.) die restlichen Relais in bestimmter Reihenfolge nacheinander/parallel geschaltet. 



Vielleicht hilft es jemanden, hier mein aktueller Code (falls es Verbesserungspotential gibt, immer her damit):

/**
   The MySensors Arduino library handles the wireless radio link and protocol
   between your home built sensors/actuators and HA controller of choice.
   The sensors forms a self healing radio network with optional repeaters. Each
   repeater and gateway builds a routing tables in EEPROM which keeps track of the
   network topology allowing messages to be routed to nodes.

   Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
   Copyright (C) 2013-2015 Sensnology AB
   Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors

   Documentation: http://www.mysensors.org
   Support Forum: http://forum.mysensors.org

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   version 2 as published by the Free Software Foundation.
*/

/*
 * Relays mit Zeitsteuerung (0-100 Minuten oder 0-100 Sekunden)
 * Bei Reboot wird der letzte Status aus Fhem übernommen
 *
 * Bei Benutzung von z.B. einem MAX485 muss der DE-Pin deklariert werden
 *
 * Bedienung:
 * 1. setzen der Laufzeit (Zeiten können alle vor den ersten Start gesetzt werden)
 * 2. einschalten des/der Relays
 *
 */

#define SN "TimerRelays"
#define SV "0.1"

// Enable debug prints to serial monitor
#define MY_DEBUG

// Enable RS485 transport layer
#define MY_RS485

// Define this to enables DE-pin management on defined pin
//#define MY_RS485_DE_PIN 2

// Set RS485 baud rate to use
#define MY_RS485_BAUD_RATE 19200

// Enable this if RS485 is connected to a hardware serial port
//#define MY_RS485_HWSERIAL Serial1

#define MY_NODE_ID 2   // Id of the Node
#define MY_TRANSPORT_WAIT_READY_MS 3000  //loop is beginning at 3000ms whitout connection


#include <MySensors.h>


//++++++++ Relays +++++++++
#define RELAY_ON 1                         // switch around for ACTIVE LOW / ACTIVE HIGH relay
#define RELAY_OFF 0
#define noRelays 3                         // min 2
const int relayPin[] = {10, 11, 12};       // switch around pins to your desire
uint32_t relayTime[] = {0, 0, 0};          // on time for Relay to set from Fhem
volatile uint32_t startTime[] = {0, 0, 0}; // time to switch Relay on
const uint32_t timeFactor = 1000UL;        // to send minutes = 60000UL or seconds = 1000UL; UL says compiler is unsigned long!!!

class Relay                                // relay class, store all relevant data (equivalent to struct)
{
  public:
    int relayPin;                          // physical pin number of relay
    boolean relayState;                    // relay status (also stored in EEPROM)
    uint32_t relayTime;                    // on time for Relay
    uint32_t startTime;                    // time to switch Relay on
};

Relay Relays[noRelays];
MyMessage msgRelay[noRelays];
MyMessage msgTime[noRelays];


void before()
{
}

void presentation()
{
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo(SN, SV);

  //++++++++ Relays +++++++++
   for (int i = 0; i < noRelays; i++)
  {
    present(i, S_DIMMER);                                  // present sensor to gateway
    wait(20);
  }
 }

void setup()
{   
  //++++++++ Relays +++++++++
  for (int i = 0; i < noRelays; i++) {   
    Relays[i].relayPin = relayPin[i];           // assign physical pins
    Relays[i].startTime = startTime[i];         // assign time to switch relay on
    Relays[i].relayTime = relayTime[i];         // assign time for relay on
    msgRelay[i].sensor = i;                     // initialize messages
    msgRelay[i].type = V_STATUS;
    msgTime[i].sensor = i;                       
    msgTime[i].type = V_PERCENTAGE;
    pinMode(Relays[i].relayPin, OUTPUT);
    Relays[i].relayState = RELAY_OFF;           // set all relaysState off
    digitalWrite(Relays[i].relayPin, Relays[i].relayState ? RELAY_ON : RELAY_OFF); // write all relays off
    //send(msgRelay[i].set(Relays[i].relayState ? true : false));
    wait(20);
    }
  for (int i = 0; i < noRelays; i++)
  {
    request(i, V_STATUS);                        // Set relay to last known state
    wait(20);
    request(i, V_PERCENTAGE);
    wait(20);
  }
}

void loop()
{
    uint32_t currentTime = millis();

   
  //++++++++ Relays +++++++++
 
  //Zeitsteuerung der Relays
  for (byte i = 0; i < noRelays; i++) {
    if ( Relays[i].relayState == RELAY_ON && (currentTime - Relays[i].startTime > Relays[i].relayTime)) {
      digitalWrite(Relays[i].relayPin, !Relays[i].relayState ? RELAY_ON : RELAY_OFF);
      Relays[i].relayState = !Relays[i].relayState;
      send(msgRelay[i].set(Relays[i].relayState ? true : false));
      Relays[i].relayTime = 0;
      send(msgTime[i].set(Relays[i].relayTime));
      // save sensor state in EEPROM (location == sensor number)
      //saveState( i, Relays[i].relayState );
      #ifdef MY_DEBUG
        Serial.print("relayTime reached:");
        Serial.print(Relays[i].relayState);
        Serial.print(" time: ");
        Serial.println(Relays[i].relayTime);
      #endif
     }
  }
}

void receive(const MyMessage &message) {
   //++++++++ Relays +++++++++
  if (message.type == V_STATUS) {
    if (message.sensor < noRelays) {          // check if message is valid for relays..... previous line  [[[ if (message.sensor <=noRelays){ ]]]
      Relays[message.sensor].relayState = message.getBool();
      digitalWrite(Relays[message.sensor].relayPin, Relays[message.sensor].relayState ? RELAY_ON : RELAY_OFF); // and set relays accordingly
      //saveState( message.sensor, Relays[message.sensor].relayState ); // save sensor state in EEPROM (location == sensor number)
      }
    if (Relays[message.sensor].relayState == RELAY_ON) {
      Relays[message.sensor].startTime = millis();
    }
    #ifdef MY_DEBUG
      Serial.print("Incoming change for sensor:");
      Serial.print(message.sensor);
      Serial.print(", New status: ");
      Serial.println(message.getBool());
    #endif
 }
 if (message.type == V_PERCENTAGE) {
    if (message.sensor < noRelays) {          // check if message is valid for relays..... previous line  [[[ if (message.sensor <=noRelays){ ]]]
      Relays[message.sensor].relayTime = (message.getByte() * timeFactor);    // calculate to millis
      }
    #ifdef MY_DEBUG
      Serial.print("Incoming change for sensor:");
      Serial.print(message.sensor);
      Serial.print(", New time: ");
      Serial.print(message.getByte());
      Serial.print(" (min|sec), millis: ");
      Serial.println(Relays[message.sensor].relayTime);
    #endif
 }
}
 

Gruß und Danke für die Hilfe, ohne die ich soweit nicht gekommen wäre :)

Bernd
Raspi 3b mit Raspbian Jessie und Fhem,  einiges umgesetzt, vieles in Planung :-)
Gefällt mir Gefällt mir x 1 Liste anzeigen

 

decade-submarginal