SLEEP und Interrupt mit MySensors

Begonnen von Ranseyer, 25 Juni 2017, 15:25:58

Vorheriges Thema - Nächstes Thema

Ranseyer

Mal ne Dumme Frage. Ich habe nen Sensor, der soll:
-Regen sofort melden (per Interupt am Arduino)
-Helligkeit gelegentlich melden zu definierten Zeiten

Wie müsste ich das richtig machen ?
Zitat// wie richtig ???
//  // Sleep until interrupt comes in on motion sensor. Send update every two minute.
//  sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME);


  sleep(SLEEP_TIME);




// 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 9600
#define MY_NODE_ID 111


#include <SPI.h>
#include <MySensors.h> 
#include <BH1750.h>
#include <Wire.h>


#define CHILD_ID_LIGHT 0
#define CHILD_ID_Rain 1   // Id of the sensor child
unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
#define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your rain sensor.  (Only 2 and 3 generates interrupt!)



BH1750 lightSensor;
// V_LIGHT_LEVEL should only be used for uncalibrated light level 0-100%.
// If your controller supports the new V_LEVEL variable, use this instead for
// transmitting LUX light level.
MyMessage msgLight(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
uint16_t lastlux;
// Initialize motion message
MyMessage msgRain(CHILD_ID_Rain, V_TRIPPED);



void setup() 
{
  lightSensor.begin();
  pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
}

void presentation()  {
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo("Light Rain Sensor", "0.0.1");

  // Register all sensors to gateway (they will be created as child devices)
  present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
  present(CHILD_ID_Rain, S_MOTION);

}

void loop()     
{     
  uint16_t lux = lightSensor.readLightLevel();// Get Lux value
  Serial.println(lux);
  if (lux != lastlux) {
      send(msgLight.set(lux));
      lastlux = lux;
  }


  // Read digital motion value
  bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;

  Serial.println(tripped);
  send(msgRain.set(tripped?"1":"0"));  // Send tripped value to gw

// wie richtig ???
//  // Sleep until interrupt comes in on motion sensor. Send update every two minute.
//  sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME);


  sleep(SLEEP_TIME);
}
FHEM mit FTUI. Homematic-Funk für Thermostate und Licht. MySensors als Basis für eigene HW.
Zentrale ist der MAPLE-CUL mit RFM69+HModUART-AddOn.
Doku zu meinen Projekten: Github/Ranseyer. Platinen falls verfügbar gerne auf Anfrage.
Support: gerne wenn ich Zeit+Lust habe im Forum. Nicht per PN!

Beta-User

Zitat von: Ranseyer am 25 Juni 2017, 15:25:58
Mal ne Dumme Frage. Ich habe nen Sensor, der soll:
-Regen sofort melden (per Interupt am Arduino)
-Helligkeit gelegentlich melden zu definierten Zeiten

Wie müsste ich das richtig machen ?


sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME); statt sleep(SLEEP_TIME); sollte gehen, oder Du machst das mit einer seperaten Interruptroutine, Beispiel für so eine ISR wäre der EnergyPulseMeter (dar aber in dem Rahmen nicht gleich sendet). Habe mal sowas ähnliches gemacht mit 2 Motion-Sensoren.

Gruß, Beta-User
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Ranseyer

@Beta-User:
Danke, das scheint zu funktionieren. (Ich bleibe dran und werde die Langzeitstabilität beobachten...)
FHEM mit FTUI. Homematic-Funk für Thermostate und Licht. MySensors als Basis für eigene HW.
Zentrale ist der MAPLE-CUL mit RFM69+HModUART-AddOn.
Doku zu meinen Projekten: Github/Ranseyer. Platinen falls verfügbar gerne auf Anfrage.
Support: gerne wenn ich Zeit+Lust habe im Forum. Nicht per PN!

Ranseyer

Nochmals ne Dumme Frage (in diesem Thread weil es hier im Forum (noch?) keinen mySenors Bereich gibt: https://forum.fhem.de/index.php/topic,73580.0.html)


Ich versuche gerade meinen Wintergartensteuerung um MySensors zu erweitern. Beispielsweis im Test oder auch später bei Problemen kann diese keinen Kontakt zum Gateway aufbauen. Die Hauptschleife soll aber trotzdem funktionieren. Geht das ?

Wenn es funktionieren würde, dann sollte ja auch der seriellen Konsole gelegentlich mal eine Uhrzeit zu sehen sein...

Zitatvoid loop()
{
  // Read digital motion value
  bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
  Serial.println(tripped);
  send(msgRain.set(tripped?"0":"1"));  // Send tripped value to gw
  displayTime();
  sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME);


Hier mal das ganze inkl displayTime
// (C) www.neuby.de
//V2.001
// 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 9600
#define MY_NODE_ID 118

#include <MySensors.h>
#include <Arduino.h>
#include <SPI.h>
#include <Wgs.h>
// For RTC
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68

#define CHILD_ID_LIGHT 0
#define CHILD_ID_Rain 1   // Id of the sensor child
unsigned long SLEEP_TIME = 10000; // Sleep time between reads (in milliseconds)

// Initialize motion message
MyMessage msgRain(CHILD_ID_Rain, V_RAIN);
#define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your rain sensor.  (Only 2 and 3 generates interrupt!)




// Input Pins for Switch Markise Up/Down
const int SwMarkUp = 8;
const int SwMarkDown = 9;
// Input Pins for Switch Jalosie Up/Down
const int SwJalUp = 7;
const int SwJalDown = 6;
//Notfall
const int SwEmergency = 5;


// Output Pins
const int JalOn = 10;
const int JalDown = 11;
const int JalRevers = 12;
const int MarkOn = 13;
const int MarkDown = 14;

int MarkUpState = 0;
int MarkDownState = 0;
int JalUpState = 0;
int JalDownState = 0;
int JalReverseState = 0;
int EmergencyState = 0;

//autostart
const int autostart_time = 9;

const int autostart_check_delay = 200; //in ticks
int autostart_check_tick = 200; //in ticks
boolean autostart_done = false;


Wgs mark(MarkOn, MarkDown, 55000);
Wgs jal(JalOn, JalDown, 65000);

byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}


void setup()
{
  // Initialize In-/Outputs
  pinMode(SwMarkUp, INPUT_PULLUP);
  pinMode(SwMarkDown, INPUT_PULLUP);
  pinMode(SwJalUp, INPUT_PULLUP);
  pinMode(SwJalDown, INPUT_PULLUP);
  pinMode(SwEmergency, INPUT_PULLUP);
  pinMode(MarkOn, OUTPUT);
  pinMode(MarkDown, OUTPUT);
  pinMode(JalOn, OUTPUT);
  pinMode(JalDown, OUTPUT);
  digitalWrite(MarkOn, HIGH);
  digitalWrite(MarkDown, HIGH);
  digitalWrite(JalOn, HIGH);
  digitalWrite(JalDown, HIGH);

  Wire.begin();
  //  Serial.begin(57600);

}

void presentation()  {
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo("Light Rain Sensor", "0.1.0");

  // Register all sensors to gateway (they will be created as child devices)
  present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
  present(CHILD_ID_Rain, S_RAIN);

}





void loop()
{
  // Read digital motion value
  bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
  Serial.println(tripped);
  send(msgRain.set(tripped?"0":"1"));  // Send tripped value to gw
  displayTime();
  sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME);


  bool button_mark_up = digitalRead(SwMarkUp) == LOW;
  bool button_mark_down = digitalRead(SwMarkDown) == LOW;
  bool button_jal_up = digitalRead(SwJalUp) == LOW;
  bool button_jal_down = digitalRead(SwJalDown) == LOW;
  bool emergency = digitalRead(SwEmergency) == LOW; //Current use: in case of rain

  mark.setDisable(emergency);

  //Autostart code
  autostart_check_tick++;
  if(autostart_check_tick >= autostart_check_delay){
    autostart_check_tick = 0;


    // Darf das mehrfach sein ?
    byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
    readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);



    if(autostart_done){ //Already done
      if(hour > autostart_time){
        autostart_done = false;
      }
    }else{
      if(hour == autostart_time &! emergency){
        button_mark_down = true;
        autostart_done = true;
      }
    }

  }


  mark.loop(button_mark_up, button_mark_down);
  jal.loop(button_jal_up, button_jal_down);


}








void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void displayTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  // retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  &year);
  // send it to the serial monitor
  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute<10)
  {
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second<10)
  {
    Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.println(year, DEC);


}
FHEM mit FTUI. Homematic-Funk für Thermostate und Licht. MySensors als Basis für eigene HW.
Zentrale ist der MAPLE-CUL mit RFM69+HModUART-AddOn.
Doku zu meinen Projekten: Github/Ranseyer. Platinen falls verfügbar gerne auf Anfrage.
Support: gerne wenn ich Zeit+Lust habe im Forum. Nicht per PN!

Beta-User

Zitat von: Ranseyer am 09 Juli 2017, 09:07:26
... kann diese keinen Kontakt zum Gateway aufbauen. Die Hauptschleife soll aber trotzdem funktionieren. Geht das ?
Da gibt es ein #define für den Header, etwas mehr auch zur Stelle, wo das reingehört im Zusammenhang:
// Enable and select radio type attached
#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
#define MY_NODE_ID 101
//#define MY_TRANSPORT_RELAXED
#define MY_TRANSPORT_WAIT_READY_MS 3000

Aus dem Starter-Guide (ziemlich hinten):
Zitateine Node im Normalfall nicht in loop() geht, solange die presentation() nicht erfolgreich war (also solange der Controller nicht verfügbar ist). Eine Failsafe-Initialisierung von Schnittstellen sollte demnach in preHwInit() oder before() erfolgen. Es kann zusätzlich seit 2.1.1 auch die Option MY_TRANSPORT_WAIT_READY_MS min. auf 1 gesetzt werden, dann startet die loop() auch ohne Verbindung zum Gateway.

Gruß, Beta-User
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Ranseyer

Danke, genau das habe ich gesucht ! (Ich glaube das hattest Du auch auf dem Treffen erwähnt...)
FHEM mit FTUI. Homematic-Funk für Thermostate und Licht. MySensors als Basis für eigene HW.
Zentrale ist der MAPLE-CUL mit RFM69+HModUART-AddOn.
Doku zu meinen Projekten: Github/Ranseyer. Platinen falls verfügbar gerne auf Anfrage.
Support: gerne wenn ich Zeit+Lust habe im Forum. Nicht per PN!

Ranseyer

Ich könnte nochmals nen Tipp zur Verzögerung gebrauchen.

"Damit" flute ich gerade den Dubug Anschluss mit 100 Meldungen pro Sekunde.
Zitatunsigned long SLEEP_TIME = 10; // Sleep time between reads (in milliseconds)
...
sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME);
Eigentlich bräuchte ich aber nur alle 30 Sekunden eine Meldung+bei Änderungen. Änderungen sind auch Tastendrücke, die ohne Interupt erfolgen.
Hätte dafür auch jemand nee Idee ?

Derke erst wenn das besser ist kann ich weiter Programmieren (in meinem Fall eher Murksen) 8)



// (C) www.neuby.de
//V2.003
// 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 9600
#define MY_NODE_ID 118
//#define MY_TRANSPORT_RELAXED
#define MY_TRANSPORT_WAIT_READY_MS 2000
//#define MY_TRANSPORT_RELAXED
#define MY_TRANSPORT_WAIT_READY_MS 3000
#include <MySensors.h>
#include <Arduino.h>
#include <SPI.h>
#include <Bounce2.h>
#include <Wgs.h>
// For RTC
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68

#define CHILD_ID_LIGHT 0
#define CHILD_ID_Rain 1   // Id of the sensor child
unsigned long SLEEP_TIME = 10; // Sleep time between reads (in milliseconds)

// Initialize motion message
MyMessage msgRain(CHILD_ID_Rain, V_RAIN);
#define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your rain sensor.  (Only 2 and 3 generates interrupt!)




// Buttons
Bounce debounceJalUp    = Bounce();
Bounce debounceJalDown  = Bounce();
Bounce debounceMarkEmergency  = Bounce();
Bounce debounceMarkUp    = Bounce();
Bounce debounceMarkDown  = Bounce();

#define BT_PRESS_None             0                   //
#define BT_PRESS_JalUp            1                   //
#define BT_PRESS_JalDown          2                   //
#define BT_PRESS_Stop             3                   //
#define BT_PRESS_MarkUp           4                   //
#define BT_PRESS_MarkDown         5                   //
#define BT_PRESS_MarkEmergency    6                   //




// Input Pins for Switch Markise Up/Down
const int SwMarkUp = 8;
const int SwMarkDown = 9;
// Input Pins for Switch Jalosie Up/Down
const int SwJalUp = 7;
const int SwJalDown = 6;
//Notfall
const int SwEmergency = 5;


// Output Pins
const int JalUp = 10;
const int JalDown = 11;
//const int JalRevers = 12;
const int MarkUp = 13;
const int MarkDown = 14;

int MarkUpState = 0;
int MarkDownState = 0;
int JalUpState = 0;
int JalDownState = 0;
int JalReverseState = 0;
int EmergencyState = 0;

//autostart
const int autostart_time = 9;

const int autostart_check_delay = 200; //in ticks
int autostart_check_tick = 200; //in ticks
boolean autostart_done = false;

boolean MDown = false;
boolean MUp = false;

Wgs mark(MarkUp, MarkDown, 55000);
Wgs jal(JalUp, JalDown, 65000);

byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}


void setup()
{
  // Initialize In-/Outputs
  pinMode(SwMarkUp, INPUT_PULLUP);
  pinMode(SwMarkDown, INPUT_PULLUP);
  pinMode(SwJalUp, INPUT_PULLUP);
  pinMode(SwJalDown, INPUT_PULLUP);
  pinMode(SwEmergency, INPUT_PULLUP);
  pinMode(MarkUp, OUTPUT);
  pinMode(MarkDown, OUTPUT);
  pinMode(JalUp, OUTPUT);
  pinMode(JalDown, OUTPUT);
  digitalWrite(MarkUp, HIGH);
  digitalWrite(MarkDown, HIGH);
  digitalWrite(JalUp, HIGH);
  digitalWrite(JalDown, HIGH);

  // After setting up the button, setup debouncer
  debounceJalUp.attach(SwJalUp);
  debounceJalUp.interval(5);
  debounceJalDown.attach(SwJalDown);
  debounceJalDown.interval(5);
  debounceMarkUp.attach(SwMarkUp);
  debounceMarkUp.interval(5);
  debounceMarkDown.attach(SwMarkDown);
  debounceMarkDown.interval(5);

  debounceMarkEmergency.attach(SwEmergency);
  debounceMarkEmergency.interval(5);




  Wire.begin();
  //  Serial.begin(57600);

}

void presentation()  {
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo("Light Rain Sensor", "0.1.0");

  // Register all sensors to gateway (they will be created as child devices)
  present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
  present(CHILD_ID_Rain, S_RAIN);

}





void loop()
{
Serial.print("Loop/");
    #ifdef MY_OTA_FIRMWARE_FEATURE
    #endif

    // Read buttons, interface
    uint8_t buttonPressed = 0;
    buttonPressed = processButtons();
    switch (buttonPressed) {
      case BT_PRESS_MarkUp:
////////////////////
        //setPosition(100);
        MUp=true;
        MDown=false;
        //send(msgUp.set(1), 1);
        Serial.print("Mup/");
        break;

      case BT_PRESS_MarkDown:
        //setPosition(0);
        MDown=true;
        MUp=false;
        //send(msgDown.set(1), 1);
        Serial.print("MDown/");
        break;

  //    case BT_PRESS_Stop:
  //      ShutterStop();
  //      //send(msgStop.set(1), 1);
  //      break;
    }




  // Read digital motion value
  bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
  Serial.println(tripped);
  send(msgRain.set(tripped?"0":"1"));  // Send tripped value to gw
  displayTime();


//  bool button_mark_up = digitalRead(SwMarkUp) == LOW;
//  bool button_mark_down = digitalRead(SwMarkDown) == LOW;
//  bool button_jal_up = digitalRead(SwJalUp) == LOW;
//  bool button_jal_down = digitalRead(SwJalDown) == LOW;
bool emergency = digitalRead(SwEmergency) == LOW; //Current use: in case of rain

//wieder rein !!!!!
mark.setDisable(emergency);

  //Autostart code
  autostart_check_tick++;
  if(autostart_check_tick >= autostart_check_delay){
    autostart_check_tick = 0;


    // Darf das mehrfach sein ?
    byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
    readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);



    if(autostart_done){ //Already done
      if(hour > autostart_time){
        autostart_done = false;
      }
    }else{
      if(hour == autostart_time &! emergency){
        MDown = true;
        autostart_done = true;
      }
    }

  }


  mark.loop(MUp, MDown);
  //jal.loop(button_jal_up, button_jal_down);

sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME);

}


FHEM mit FTUI. Homematic-Funk für Thermostate und Licht. MySensors als Basis für eigene HW.
Zentrale ist der MAPLE-CUL mit RFM69+HModUART-AddOn.
Doku zu meinen Projekten: Github/Ranseyer. Platinen falls verfügbar gerne auf Anfrage.
Support: gerne wenn ich Zeit+Lust habe im Forum. Nicht per PN!

Beta-User

Grundsätzlich würde ich keine "Verzögerung" einbauen, und auch sonst scheint mir manches nicht klar an Deinem Code.

Aufgefallen ist mir auf die Schnelle folgendes:
- ein Sleep und das Auslesen von PINs in der loop() vertragen sich m.E. nicht wirklich. Also entweder rein interrupt-basiert, dann aber mit eigener interrupt-routine (n). Das geht wohl auch mit weiteren PINs, allerdings müßte man dann dort in der ISR aussortieren, welcher PIN der Auslöser war.
- Besser wäre es hier, die loop() immer durchlaufen zu lassen, und dann mit millis() zu prüfen, ob die Mindestsendezeit abgelaufen ist (für Helligkeit und Regen).
Als Einstiegsbeispiel für millis() würde ich den Servo-Sketch empfehlen, der wartet auch immer auf Steuerbefehle, und macht ein detach() nach einer gewissen Zeit.

- Die presentation() der Buttons fehlt ganz, oder? Eigentlich braucht man die auch nicht, was interessiert, wäre ja die aktuelle Position bzw. die Bewegungsänderung des Motors. Den Teil würde ich im Sketch erledigen, ähnlich dem Servo-Beispiel, der ja auch 0-100% rückmeldet bzw. empfängt. Dazu bräuchte man wohl (mindestens) ein CUSTOM-Child, um Laufzeitinfo etc. mit dem Controller austauschen zu können. Laufzeitinfo würde ich auch vorbelegen, bzw. im EEPROM speichern (Achtung: ist vermutlich länger als das Byte, was MySensors üblicherweise vorsieht, das wäre bei der Adressvergabe zu beachten; Beispiel dazu wäre mein Dallas-Array-Sketch).

Unklar wäre mir dabei, wie nach dem Anschalten des Stroms die Positionsbestimmung sein soll (neige spontan dazu, eine Markise sicherheitshalber einzufahren)?

Insgesamt eine große Aufgabe, die Du Dir da gestellt hast ;) .

M.E. sollte man die weitere Diskussion dazu in einem seperaten Thread führen, und eigentlich ist das meiste nix MySensors-spezifisches ::) .


Gruß, Beta-User
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Ranseyer

#8
Hi,

also prinzipiell ist das ganze nicht fertig (Presentation von Buttons). Mein Ziel ist es nun unter Zeitdruck (ca 1 Woche + 1 Woche FHEM Einbindung ferngesteuert) zum Laufen zu bekommen.

Der Sleep soll ganz weg. Aber ich will auch nicht tausende Meldungen pro Sekunde => Ich schau mir mal den Servo an !
Position beim Einschalten: Hat für mich erst mal keine Prio.

Fakt ist; Ich muss das in "der Zeit" schaffen, sonst gibt es Kummer :'(... Habe ich also in 1-2 Tagen keine Ansatz muss ich alles in die Tonne kloppen und das ganze  ersetzen z.B.:

A) Homematic 4 Fach Relais
B) Zwei Roller Shutter Nodes (Der Code ist mir zu komplex um das sicher zu doppeln!): https://www.openhardware.io/view/22/Roller-Shutter-Node (Den Steuerungsteil zweimal mit Arduino nachbauen und die Outputs / Taster auf meine bestehende Platine führen)

Daher hoffe ich dass das "Servo" Muster den Durchbruch bringt. Danke also für den Input!
FHEM mit FTUI. Homematic-Funk für Thermostate und Licht. MySensors als Basis für eigene HW.
Zentrale ist der MAPLE-CUL mit RFM69+HModUART-AddOn.
Doku zu meinen Projekten: Github/Ranseyer. Platinen falls verfügbar gerne auf Anfrage.
Support: gerne wenn ich Zeit+Lust habe im Forum. Nicht per PN!

Beta-User

Hi, wenn es so eilig ist, anbei mal ein Rohgerüst ::) .

Die Variablen usw. habe ich nicht alle angepaßt, aber eine interrupt-Zählung für das Wasser mit Sende-Zyklen gemacht; den loop()-Teil kannst Du ja auch (nur) für den Lichtsensor nehmen. Sollte bei Regen immer direkt reingefahren werden, wäre das in der onPulse-Routine zu erledigen, da kannst Du auch einen Sendebefehl reinnehmen.

Dann noch eine Empfangs-Routine, die die Befehle nach ChildID sortiert.

Fahrbefehle würde ich auslagern in eigene Anweisungen.

/ (C) www.neuby.de
//V2.003
// 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 9600
#define MY_NODE_ID 118
#define MY_TRANSPORT_WAIT_READY_MS 3000
#include <MySensors.h>
#include <Arduino.h>
#include <SPI.h>
#include <Bounce2.h>
#include <Wgs.h>
// For RTC
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68

#define CHILD_ID_LIGHT 0
#define CHILD_ID_Rain 1   // Id of the sensor child
#define CHILD_ID_MARKISE1 2
#define CHILD_ID_CONFIG1 102 // Id for Jal-settings

unsigned long SEND_FREQUENCY = 180000; // Sleep time between reads (in milliseconds)

// Initialize motion message
MyMessage msgRain(CHILD_ID_Rain, V_RAIN);
#define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your rain sensor.  (Only 2 and 3 generates interrupt!)
#define SENSOR_INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)

MyMessage msgMarkise1(CHILD_ID_MARKISE1, V_DIMMER);



// Buttons
Bounce debounceJalUp    = Bounce();
Bounce debounceJalDown  = Bounce();
Bounce debounceMarkEmergency  = Bounce();
Bounce debounceMarkUp    = Bounce();
Bounce debounceMarkDown  = Bounce();

#define BT_PRESS_None             0                   //
#define BT_PRESS_JalUp            1                   //
#define BT_PRESS_JalDown          2                   //
#define BT_PRESS_Stop             3                   //
#define BT_PRESS_MarkUp           4                   //
#define BT_PRESS_MarkDown         5                   //
#define BT_PRESS_MarkEmergency    6                   //




// Input Pins for Switch Markise Up/Down
const int SwMarkUp = 8;
const int SwMarkDown = 9;
// Input Pins for Switch Jalosie Up/Down
const int SwJalUp = 7;
const int SwJalDown = 6;
//Notfall
const int SwEmergency = 5;


// Output Pins
const int JalUp = 10;
const int JalDown = 11;
//const int JalRevers = 12;
const int MarkUp = 13;
const int MarkDown = 14;

int MarkUpState = 0;
int MarkDownState = 0;
int JalUpState = 0;
int JalDownState = 0;
int JalReverseState = 0;
int EmergencyState = 0;

//autostart
const int autostart_time = 9;

const int autostart_check_delay = 200; //in ticks
int autostart_check_tick = 200; //in ticks
boolean autostart_done = false;

boolean MDown = false;
boolean MUp = false;

Wgs mark(MarkUp, MarkDown, 55000);
Wgs jal(JalUp, JalDown, 65000);

byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}

void before() {

  // initialize our digital pins internal pullup resistor so one pulse switches from high to low (less distortion)
  pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP);
  digitalWrite(DIGITAL_INPUT_SENSOR, HIGH);
  pulseCount = oldPulseCount = 0;
  attachInterrupt(SENSOR_INTERRUPT, onPulse, FALLING);

  // Initialize In-/Outputs
  pinMode(SwMarkUp, INPUT_PULLUP);
  pinMode(SwMarkDown, INPUT_PULLUP);
  pinMode(SwJalUp, INPUT_PULLUP);
  pinMode(SwJalDown, INPUT_PULLUP);
  pinMode(SwEmergency, INPUT_PULLUP);
  pinMode(MarkUp, OUTPUT);
  pinMode(MarkDown, OUTPUT);
  pinMode(JalUp, OUTPUT);
  pinMode(JalDown, OUTPUT);
  digitalWrite(MarkUp, HIGH);
  digitalWrite(MarkDown, HIGH);
  digitalWrite(JalUp, HIGH);
  digitalWrite(JalDown, HIGH);

  // After setting up the button, setup debouncer
  debounceJalUp.attach(SwJalUp);
  debounceJalUp.interval(5);
  debounceJalDown.attach(SwJalDown);
  debounceJalDown.interval(5);
  debounceMarkUp.attach(SwMarkUp);
  debounceMarkUp.interval(5);
  debounceMarkDown.attach(SwMarkDown);
  debounceMarkDown.interval(5);

  debounceMarkEmergency.attach(SwEmergency);
  debounceMarkEmergency.interval(5);

  Wire.begin();
}

void setup()
{

  //  Serial.begin(57600);

}

void presentation()  {
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo("Light Rain Sensor", "0.1.0");

  // Register all sensors to gateway (they will be created as child devices)
  present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
  present(CHILD_ID_Rain, S_RAIN);
  present(CHILD_ID_MARKISE1, S_COVER);
  present(CHILD_ID_CONFIG1, S_CUSTOM);


}





void loop()
{
//Serial.print("Loop/");
    #ifdef MY_OTA_FIRMWARE_FEATURE
    #endif
unsigned long currentTime = millis();

  // Only send values at a maximum frequency or woken up from sleep
  if (currentTime - lastSend > SEND_FREQUENCY)
  {
    lastSend = currentTime;
    if (flow != oldflow) {
      oldflow = flow;
#ifdef MY_DEBUG_LOCAL
      Serial.print("l/min:");
      Serial.println(flow);
#endif
      // Check that we dont get unresonable large flow value.
      // could hapen when long wraps or false interrupt triggered
      if (flow < ((unsigned long)MAX_FLOW)) {
        send(flowMsg.set(flow, 2));                   // Send flow value to gw
      }
    }

    // No Pulse count received in 2min
    if (currentTime - lastPulse > 120000) {
      flow = 0;
    }

    // Pulse count has changed
    if (pulseCount != oldPulseCount) {
      oldPulseCount = pulseCount;
#ifdef MY_DEBUG_LOCAL
      Serial.print("pulsecnt:");
      Serial.println(pulseCount);
#endif
      send(lastCounterMsg.set(pulseCount));                  // Send  pulsecount value to gw in VAR1

      double volume = ((double)pulseCount / ((double)PULSE_FACTOR));
      if (volume != oldvolume) {
        oldvolume = volume;
#ifdef MY_DEBUG_LOCAL
        Serial.print("vol:");
        Serial.println(volume, 3);
#endif
        send(volumeMsg.set(volume, 3));               // Send volume value to gw
      }
    }
  }

    // Read buttons, interface
    uint8_t buttonPressed = 0;
    buttonPressed = processButtons();
    switch (buttonPressed) {
      case BT_PRESS_MarkUp:
////////////////////
        //setPosition(100);
        MUp=true;
        MDown=false;
        //send(msgUp.set(1), 1);
        Serial.print("Mup/");
        break;

      case BT_PRESS_MarkDown:
        //setPosition(0);
        MDown=true;
        MUp=false;
        //send(msgDown.set(1), 1);
        Serial.print("MDown/");
        break;

  //    case BT_PRESS_Stop:
  //      ShutterStop();
  //      //send(msgStop.set(1), 1);
  //      break;
    }




  // Read digital motion value
  bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
  Serial.println(tripped);
  send(msgRain.set(tripped?"0":"1"));  // Send tripped value to gw
  displayTime();


//  bool button_mark_up = digitalRead(SwMarkUp) == LOW;
//  bool button_mark_down = digitalRead(SwMarkDown) == LOW;
//  bool button_jal_up = digitalRead(SwJalUp) == LOW;
//  bool button_jal_down = digitalRead(SwJalDown) == LOW;
bool emergency = digitalRead(SwEmergency) == LOW; //Current use: in case of rain

//wieder rein !!!!!
mark.setDisable(emergency);

  //Autostart code
  autostart_check_tick++;
  if(autostart_check_tick >= autostart_check_delay){
    autostart_check_tick = 0;


    // Darf das mehrfach sein ?
    byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
    readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);



    if(autostart_done){ //Already done
      if(hour > autostart_time){
        autostart_done = false;
      }
    }else{
      if(hour == autostart_time &! emergency){
        MDown = true;
        autostart_done = true;
      }
    }

  }


  mark.loop(MUp, MDown);
  //jal.loop(button_jal_up, button_jal_down);



}


void receive(const MyMessage & message) {
  if (message.sensor == CHILD_ID_SERVO) {
    myservo.attach(SERVO_DIGITAL_OUT_PIN);
    attachedServo = true;
    if (message.isAck()) {
      Serial.println("Ack from gw rec.");
    }
    if (message.type == V_DIMMER) { // This could be M_ACK_VARIABLE or M_SET_VARIABLE
      int val = message.getInt();
      if (val > 3) {
        val = 3;
      };
      //myservo.write(SERVO_MAX + (SERVO_MIN - SERVO_MAX) / 100 * val); // sets the servo position 0-180
      myservo.write(SERVO_MAX + (SERVO_MIN - SERVO_MAX) / 100 * (130 - val * 40)); // sets the servo position 0-180
      // Write some debug info
      //Serial.print("Servo change; state: ");
      //Serial.println(val);
    }
    timeOfLastChange = millis();
  }
  else if (message.sensor == CHILD_ID_GAS) {
    if (message.type == V_VAR1) {
      pulseCount = message.getULong();
      flow = oldflow = 0;
      //Serial.print("Rec. last pulse count from gw:");
      //Serial.println(pulseCount);
      pcReceived = true;
    }
  }
  else if (message.sensor == CHILD_ID_RELAY) {

    if (message.type == V_LIGHT) {
      // Change relay state
      state = message.getBool();
      digitalWrite(RELAY_PIN, state ? RELAY_ON : RELAY_OFF);
#ifdef MY_DEBUG
      // Write some debug info
      Serial.print("Gw change relay:");
      Serial.print(message.sensor);
      Serial.print(", New status: ");
      Serial.println(message.getBool());
#endif
    }
  }
  else if (message.sensor == CHILD_ID_CONFIG) {
    if (message.type == V_VAR1) {
      int tempMaxPump = message.getInt(); //upper temp level at warmwater circle pump
    }
    else if (message.type == V_VAR2) {
      int tempMaxHeatingPump = message.getInt(); //temperature to switch internal heating pump to highest level
    }
    else if (message.type == V_VAR3) {
      int tempLowExtToLevelIII = message.getInt(); //External low temperature to switch internal heating pump to highest level
    }
    else if (message.type == V_VAR4) {
      int tempLowExtToLevelII = message.getInt(); //External highest temperature to switch internal heating pump to medium level
    }
    else if (message.type == V_VAR5) {
      if (message.getBool()) {
        lastPumpSwitch = millis(); //if true: Reset timer (Heartbeat functionality)
#ifdef MY_DEBUG_LOCAL
        // Write some debug info
        Serial.print("Timer reset to ");
        Serial.print(lastPumpSwitch);
#endif
      } else {
        lastPumpSwitch = 0; //if false: switch immediately if necessary
#ifdef MY_DEBUG_LOCAL
        // Write some debug info
        Serial.print("Timer deleted, lastPumpSwitch=");
        Serial.print(lastPumpSwitch);
#endif
      }
    }
  }
  else if (message.sensor == CHILD_ID_CONFIG0) {
    if (message.type == V_VAR1) {
      autoMode = message.getBool(); //enable autoMode
    }
  }
}


/*
Interrupt-Routine
*/
void onPulse()
{
    unsigned long newBlink = micros();
    unsigned long interval = newBlink - lastBlink;

    if (interval != 0)
    {
      lastPulse = millis();
      if (interval < 1000000L) {
        // Sometimes we get interrupt on RISING,  1000000 = 1sek debounce ( max 60 l/min)
        return;
      }
      flow = (60000000.0 / interval) / ppl;
    }
    lastBlink = newBlink;
   pulseCount++;
}


Vielleicht packst Du das nach Github, dann kann ich dort gelegentlich drüberschauen, wenn das was hilft... 8)
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

Habe mir  mal scalz code angesehen.

So komplex scheint mir das nicht zu sein, sollte eigentlich kein größeres Problem sein, das auf zwei Jalousien aufzubohren...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

@Ranseyer:
Habe mir erlaubt, das mal abzutrennen (auch als Test).
War hoffentlich ok?
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Ranseyer

Cool, wie du hier Ordnung reinbringst.
Danke !
FHEM mit FTUI. Homematic-Funk für Thermostate und Licht. MySensors als Basis für eigene HW.
Zentrale ist der MAPLE-CUL mit RFM69+HModUART-AddOn.
Doku zu meinen Projekten: Github/Ranseyer. Platinen falls verfügbar gerne auf Anfrage.
Support: gerne wenn ich Zeit+Lust habe im Forum. Nicht per PN!

Beta-User

Danke für die Blumen ::) !
Ich denke, das war's jetzt erst mal. Die meisten anderen Fragen im Mega-Thread betreffen eher gelöste Themen oder Dinge, die im Starter-Guide etwas komprimierter zu finden sind (?).

Danke zurück für den Edit im Sticky Post, der kann und darf gerne noch besser werden, das war auch was "auf die Schnelle...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files