Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Troubleshooting
  3. Node only works for a few days

Node only works for a few days

Scheduled Pinned Locked Moved Troubleshooting
22 Posts 10 Posters 5.2k Views 7 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • raptorjrR Offline
    raptorjrR Offline
    raptorjr
    wrote on last edited by
    #1

    I have a problem with my node. It only works for a few days, then it stops receiving commands. If I restart it, it works immediately. How can I debug this?

    I'm using MySensors 2.1, or maybe some day after that. I downloaded from GitHub a day or two after I saw that 2.1 was released. I'm using a Ethernet gateway on my RPi3, and use Domoticz as controller.

    I think it only lasted from Monday to Wednesday, I saw that the leds on the Arduino board was using a different pattern but forgot to test it. Tested today and the node did not respond to my command.

    mfalkviddM 1 Reply Last reply
    0
    • raptorjrR raptorjr

      I have a problem with my node. It only works for a few days, then it stops receiving commands. If I restart it, it works immediately. How can I debug this?

      I'm using MySensors 2.1, or maybe some day after that. I downloaded from GitHub a day or two after I saw that 2.1 was released. I'm using a Ethernet gateway on my RPi3, and use Domoticz as controller.

      I think it only lasted from Monday to Wednesday, I saw that the leds on the Arduino board was using a different pattern but forgot to test it. Tested today and the node did not respond to my command.

      mfalkviddM Offline
      mfalkviddM Offline
      mfalkvidd
      Mod
      wrote on last edited by mfalkvidd
      #2

      @raptorjr the best way is probably to capture a debug log from the node (and preferably from the gateway at the same time)

      Also see the troubleshooting flowchart and recommendations at https://forum.mysensors.org/topic/666/debug-faq-and-how-ask-for-help

      raptorjrR 1 Reply Last reply
      0
      • mfalkviddM mfalkvidd

        @raptorjr the best way is probably to capture a debug log from the node (and preferably from the gateway at the same time)

        Also see the troubleshooting flowchart and recommendations at https://forum.mysensors.org/topic/666/debug-faq-and-how-ask-for-help

        raptorjrR Offline
        raptorjrR Offline
        raptorjr
        wrote on last edited by
        #3

        @mfalkvidd

        I enabled debug in my sketch, and captured the output from mysgw. This time it was only running over the night until it failed.
        And if I restart the sketch everything works again. Don't know why it failed faster with debug enabled. Before it has taken a few days until it failed.

        Sketch output:
        0_1484382591964_SketchOutput.txt

        mysgw output:
        0_1484382659338_mysgw.log

        Sketch:

        // Enable serial gateway
        //#define MY_GATEWAY_SERIAL 
        
        // Enable debug prints to serial monitor
        #define MY_DEBUG 
        
        // Enable and select radio type attached
        #define MY_RADIO_NRF24
        
        #include <SPI.h>
        #include <MySensors.h>  
        #include <OneWire.h>
        #include <DallasTemperature.h>
        
        #define TEMP_ID 1
        #define RELAY_ID 2
        #define WATERFLOW_ID 3
        
        //Temperatur sensor
        #define ONE_WIRE_BUS 4
        #define COMPARE_TEMP 1 // Send temperature only if changed? 1 = Yes 0 = No
        float lastTemperature = 0;
        MyMessage tempMsg(TEMP_ID, V_TEMP); // Initialize temperature message
        OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
        DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature. 
        unsigned long SLEEP_TIME = 5000; // Sleep time between reads (in milliseconds)
        
        //Relay to water valve
        #define RELAY_PIN 5  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
        #define RELAY_ON 1   // GPIO value to write to turn on attached relay
        #define RELAY_OFF 0  // GPIO value to write to turn off attached relay
        
        //Waterflow meter
        #define WATERFLOW_PIN 3
        #define WATERFLOW_INTERRUPT WATERFLOW_PIN - 2
        // The hall-effect flow sensor outputs approximately 4.5 pulses per second per
        // litre/minute of flow.
        float calibrationFactor = 4.5;
        volatile unsigned long pulseCounter = 0;
        float flowRate = 0;
        float lastFlowRate = 0;
        float totalLitres = 0;
        float lastTotalLitres = 0;
        unsigned long oldTime = 0;
        MyMessage flowMsg(WATERFLOW_ID, V_FLOW);
        MyMessage volumeMsg(WATERFLOW_ID, V_VOLUME);
        
        void setup(void)
        {
        	// start serial port
        	Serial.begin(115200);
        
        	pinMode(RELAY_PIN, OUTPUT);
        	digitalWrite(RELAY_PIN, RELAY_OFF);
        
        	pinMode(WATERFLOW_PIN, INPUT);
        	digitalWrite(WATERFLOW_PIN, HIGH);
        
        	// The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
        	// Configured to trigger on a FALLING state change (transition from HIGH
        	// state to LOW state)
        	attachInterrupt(WATERFLOW_INTERRUPT, onPulse, FALLING);
        
        }
        
        void presentation() 
        {
        	// Send the sketch version information to the gateway and Controller
        	sendSketchInfo("FishTank", "1.0");
        
        	present(TEMP_ID, S_TEMP, "Water temperature");
        
        	present(RELAY_ID, S_BINARY, "Water valve");
        
        	present(WATERFLOW_ID, S_WATER, "Water flow");
        
        	send(volumeMsg.set(totalLitres, 2));
        
        }
        
        void loop(void)
        {
        	DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address    
        	// For testing purposes, reset the bus every loop so we can see if any devices appear or fall off
        	sensors.begin();
        	sensors.requestTemperatures(); // Send the command to get temperatures
        	
        	// Search the wire for address
           if(sensors.getAddress(tempDeviceAddress, 0))
           {
        		float tempC = round(sensors.getTempC(tempDeviceAddress) * 10) / 10.0;
        		////Serial.print("Temperature=");
        		////Serial.print(tempC);
        		////Serial.print(", LastTemp=");
        		////Serial.println(lastTemperature);
        #if COMPARE_TEMP == 1
        		// Only send data if temperature has changed and no error
        		if (lastTemperature != tempC && tempC != -127.00 && tempC != 85.00)
        		{
        #else
        		if (tempC != -127.00 && tempC != 85.00)
        		{
        #endif
        			// Send in the new temperature
        			send(tempMsg.set(tempC, 1));
        			// Save new temperatures for next compare
        			lastTemperature = tempC;
        		}
           } 
        
        	if ((millis() - oldTime) > 1000)    // Only process counters once per second
        	{
        		// Disable the interrupt while calculating flow rate and sending the value to
        		// the host
        		detachInterrupt(WATERFLOW_INTERRUPT);
        
        		// Because this loop may not complete in exactly 1 second intervals we calculate
        		// the number of milliseconds that have passed since the last execution and use
        		// that to scale the output. We also apply the calibrationFactor to scale the output
        		// based on the number of pulses per second per units of measure (litres/minute in
        		// this case) coming from the sensor.
        		flowRate = ((1000.0 / (millis() - oldTime)) * pulseCounter) / calibrationFactor;
        		
        		if(lastFlowRate != flowRate)
        			send(flowMsg.set(flowRate, 2));
        
        		lastFlowRate = flowRate;
        
        		// Note the time this processing pass was executed. Note that because we've
        		// disabled interrupts the millis() function won't actually be incrementing right
        		// at this point, but it will still return the value it was set to just before
        		// interrupts went away.
        		oldTime = millis();
        
        		// Divide the flow rate in litres/minute by 60 to determine how many litres have
        		// passed through the sensor in this 1 second interval.
        		// Add the litres passed in this second to the cumulative total
        		totalLitres += (flowRate / 60);
        
        		if(lastTotalLitres != totalLitres)
        			send(volumeMsg.set(totalLitres, 2));
        
        		lastTotalLitres = totalLitres;
        
        		unsigned int frac;
        
        		// Print the flow rate for this second in litres / minute
        		////Serial.print("Flow rate: ");
        		////Serial.print(int(flowRate));  // Print the integer part of the variable
        		////Serial.print(".");             // Print the decimal point
        												 // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
        		frac = (flowRate - int(flowRate)) * 10;
        		////Serial.print(frac, DEC);      // Print the fractional part of the variable
        		////Serial.print("L/min");
        		// Print the number of litres flowed in this second
        		//Serial.print("  Current Liquid Flowing: ");             // Output separator
        		//Serial.print(flowLitres);
        		//Serial.print("L/Sec");
        
        		// Print the cumulative total of litres flowed since starting
        		////Serial.print("  Output Liquid Quantity: ");             // Output separator
        		////Serial.print(totalLitres);
        		////Serial.println("L");
        
        		// Reset the pulse counter so we can start incrementing again
        		pulseCounter = 0;
        
        		// Enable the interrupt again now that we've finished sending output
        		attachInterrupt(WATERFLOW_INTERRUPT, onPulse, FALLING);
        	}
        
        	wait(SLEEP_TIME);
        }
        
        void receive(const MyMessage &message) 
        {
        	// We only expect one type of message from controller. But we better check anyway.
        	if (message.type == V_STATUS && message.sensor == RELAY_ID)
        	{
        		// Change relay state
        		digitalWrite(RELAY_PIN, message.getBool() ? RELAY_ON : RELAY_OFF);
        		// Write some debug info
        		////Serial.print("Incoming change for sensor:");
        		////Serial.print(message.sensor);
        		////Serial.print(", New status: ");
        		////Serial.println(message.getBool());
        
        		//Reset the total litres, so we can start fresh when we open the valve
        		if (message.getBool() == RELAY_ON) 
        		{
        			totalLitres = 0;
        			send(volumeMsg.set(totalLitres, 2));
        		}
        	}
        }
        
        void onPulse()
        {
        	// Increment the pulse counter
        	pulseCounter++;
        }
        
        1 Reply Last reply
        0
        • Geert MassaG Offline
          Geert MassaG Offline
          Geert Massa
          wrote on last edited by
          #4

          it looks like the node lost connection to the gateway.
          Had the same issue.
          Had to add a repeater between the node and gateway.
          Hopefully someone else knows a better solution.

          raptorjrR 1 Reply Last reply
          0
          • Geert MassaG Geert Massa

            it looks like the node lost connection to the gateway.
            Had the same issue.
            Had to add a repeater between the node and gateway.
            Hopefully someone else knows a better solution.

            raptorjrR Offline
            raptorjrR Offline
            raptorjr
            wrote on last edited by
            #5

            @Geert-Massa

            Thank you for looking.
            I hope not a repeater is needed. They are only 2-3 meters apart. And that don't explain why it works for a few days after a restart.
            I have capacitors on both node and gateway, so that should not be a problem either.

            tekkaT 1 Reply Last reply
            0
            • b0rmannB Offline
              b0rmannB Offline
              b0rmann
              wrote on last edited by
              #6

              ...same problem :(

              1 Reply Last reply
              0
              • wallyllamaW Offline
                wallyllamaW Offline
                wallyllama
                wrote on last edited by
                #7

                My wild guess would be a memory leak in the code. Turning on debug uses more memory so it takes less time to fail.

                1 Reply Last reply
                0
                • F Offline
                  F Offline
                  Fabien
                  wrote on last edited by
                  #8

                  First switch your gateway to 2.1.0 stable.
                  I think sensors.begin must be in setup not in loop.
                  And I think you have perhaps TX problem on gateway side (after reading logs).
                  Retry with 2.1.0 on both sides, compile node sketch with sensors.begin in setup, turn on log on node and gw.
                  When you have failure, try to reboot only gateway and wait until node try to find parent. Make the same test but this time reboot only node.

                  raptorjrR 1 Reply Last reply
                  0
                  • raptorjrR raptorjr

                    @Geert-Massa

                    Thank you for looking.
                    I hope not a repeater is needed. They are only 2-3 meters apart. And that don't explain why it works for a few days after a restart.
                    I have capacitors on both node and gateway, so that should not be a problem either.

                    tekkaT Offline
                    tekkaT Offline
                    tekka
                    Admin
                    wrote on last edited by
                    #9

                    @raptorjr Looking at your logs

                    GW log, line 578

                    mysgw: TSF:MSG:READ,1-1-0,s=171,c=5,t=42,pt=7,l=13,sg=0:30713023823872.00000000
                    mysgw: !TSF:MSG:LEN,12!=20
                    

                    I assume a power/bad cable issue and/or a EMP interference caused by a switching relay.

                    1 Reply Last reply
                    0
                    • F Fabien

                      First switch your gateway to 2.1.0 stable.
                      I think sensors.begin must be in setup not in loop.
                      And I think you have perhaps TX problem on gateway side (after reading logs).
                      Retry with 2.1.0 on both sides, compile node sketch with sensors.begin in setup, turn on log on node and gw.
                      When you have failure, try to reboot only gateway and wait until node try to find parent. Make the same test but this time reboot only node.

                      raptorjrR Offline
                      raptorjrR Offline
                      raptorjr
                      wrote on last edited by
                      #10

                      @Fabien said:

                      First switch your gateway to 2.1.0 stable.
                      I think sensors.begin must be in setup not in loop.
                      And I think you have perhaps TX problem on gateway side (after reading logs).
                      Retry with 2.1.0 on both sides, compile node sketch with sensors.begin in setup, turn on log on node and gw.
                      When you have failure, try to reboot only gateway and wait until node try to find parent. Make the same test but this time reboot only node.

                      Will try this first. To me it feels that if it was something wrong with the hardware in some way it would happen right away, not only after a few days.

                      But I'll start with this before I consider to buy new hardware.

                      1 Reply Last reply
                      0
                      • gohanG Offline
                        gohanG Offline
                        gohan
                        Mod
                        wrote on last edited by
                        #11

                        Before buying new hw it's better to do some cross tests to pin point where the problem is.

                        1 Reply Last reply
                        0
                        • FotoFieberF Offline
                          FotoFieberF Offline
                          FotoFieber
                          Hardware Contributor
                          wrote on last edited by
                          #12

                          I had a similar problem with the control of a heating mixer and three dallas sensors. I solved the problem with:

                          • replacement of the relays with solid state relays
                          • moved conttroller more in distance of the high voltage parts

                          I also added a watchdog and a reboot mechanism in case of sensor problems.

                          Maybe this sketch can give you an inspiration: (work in progress, MYS-Part not tested in depth)

                          // Enable debug prints to serial monitor
                          //#define MY_DEBUG      // in Mysensors
                          #define EN_DEBUG      // in this sketch
                          //#define NO_MYS      // ohne Mysensors Unterstützung?
                          //#define SIMULATION
                          #define NO_AC_DETECT  // ohne AC sensor
                          #define NO_RTC
                          
                          // RTC nur zusammen mit Mysensors
                          #ifdef NO_MYS
                          #ifndef NO_RTC
                          #define NO_RTC
                          #endif
                          #endif
                          
                          #ifdef SIMULATION
                          // für Simulation ohne Sensoren
                          #define SIMULATE_VOR  35
                          #define SIMULATE_RUE  30
                          #define SIMULATE_ZU   65
                          
                          
                          #ifdef SIMULATE_VOR
                          #warning Achtung! Keine Echtentemperaturmessungen -> Simulation
                          #endif
                          
                          #ifdef SIMULATE_RUE
                          #warning Achtung! Keine Echtentemperaturmessungen -> Simulation
                          #endif
                          
                          #ifdef SIMULATE_ZU
                          #warning Achtung! Keine Echtentemperaturmessungen -> Simulation
                          #endif
                          #endif
                          
                          
                          #define START_TARGET_TEMP 40
                          #define EEPROM_TARGET_TEMP 900            // Save Porisiton. It is above the Mysensors range of lib 2.1
                          #define EEPROM_POWERSTATE  902            // Save Porisiton. It is above the Mysensors range of lib 2.1
                          #define MAX_TEMP 50
                          #define VORLAUF 0
                          #define RUECKLAUF 1
                          #define ZULAUF 2
                          #define PUMPE 0
                          #define MISCHER_ZU  1
                          #define MISCHER_AUF 2
                          #define POWERLED 7                        // 8. LED
                          #define TEMPDOWNLED 5                     // 6. Led
                          #define TEMPUPLED 6                       // 7. Led
                          #ifndef NO_AC_DETECT
                          #define BUDERUSLED 4                      // 5. Led
                          #endif
                          #define RETRY_TIMEOUT_PUMP 2*60*1000UL     // alle 2 Minuten testen, ob Vorlauf nicht besser (5 Sekunden pumpen)
                          #define REGULATION_TIMEOUT_PUMP 30*1000UL  // 30 Sekunden warten nach neuer Einstellung
                          #define PROBE_TIMEOUT_PUMP 5*1000UL        // 5 Sekunden Pumpe für Test einschalten, wenn Zulauf zu kalt
                          #define BUDERUS_PIN 3                     // Buderus Powererkennung Pumpe auf PIN 3
                          
                          #ifndef SIMULATION
                          #define MISCHER_RESET_TIME 120*1000UL      // 2 Minuten bis Nullstellung
                          #else
                          #define MISCHER_RESET_TIME 10*1000UL      // 10 Sekunden bis Nullstellung nei Simulation
                          #endif
                          
                          
                          
                          #ifdef EN_DEBUG
                          #define DEBUG_PRINT(x) Serial.print (x)
                          #else
                          #define DEBUG_PRINT(x)
                          #endif
                          
                          #ifdef EN_DEBUG
                          #define DEBUG_PRINTLN(x)  Serial.println (x)
                          #else
                          #define DEBUG_PRINTLN(x)
                          #endif
                          
                          #ifndef NO_MYS
                          // Radio Configuration
                          #define MY_TRANSPORT_WAIT_READY_MS (10000ul)
                          #define MY_RADIO_RFM69
                          #define MY_RFM69_FREQUENCY RF69_868MHZ
                          #define MY_RFM69_NETWORKID 13
                          #define MY_RFM69_ENABLE_ENCRYPTION
                          #define MY_NODE_ID 168
                          //#define MY_IS_RFM69HW
                          #endif
                          
                          
                          #include <Arduino.h>
                          #include <avr/wdt.h>
                          #include <EEPROM.h>
                          #include <MemoryFree.h>
                          
                          #ifndef NO_MYS
                          #define MIN_REPORT_INTERVAL  5 * 60 * 1000L   // mindestens alle 5 Minuten melden
                          #include <SPI.h>
                          #include <MySensors.h>
                          #include <Time.h>        //http://www.arduino.cc/playground/Code/Time
                          #include <Timezone.h>    //https://github.com/JChristensen/Timezone
                          #include <TimeLib.h>
                          
                          //Central European Time (Frankfurt, Paris)
                          TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120};     //Central European Summer Time
                          TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};       //Central European Standard Time
                          Timezone CE(CEST, CET);
                          bool timeReceived = false;
                          unsigned long lastUpdate = 0, lastRequest = 0;
                          #endif
                          
                          #ifndef NO_RTC
                          #include <DS3232RTC.h>  // A  DS3231/DS3232 library
                          #endif
                          
                          #define MAX_LEDS 8
                          
                          byte lastButtonState = 0;
                          #define RELAY_ON HIGH
                          #define RELAY_OFF LOW
                          #define RELAY_1  A0         // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
                          #define NUMBER_OF_RELAYS 4  // Total number of attached relays
                          
                          
                          boolean ledState[MAX_LEDS] = { false, false, false, false, false, false, false, false };
                          boolean relState[NUMBER_OF_RELAYS] = { false, false, false, false };
                          
                          #include <TM1638.h>
                          #include <DallasTemperature.h>
                          #include <OneWire.h>
                          
                          #define ONE_WIRE_BUS 6 // Pin where dallase sensor is connected 
                          #define TEMPERATURE_PRECISION 9
                          #define MAX_ATTACHED_DS18B20 3
                          
                          //28B404080000804A
                          DeviceAddress Probe01 = { 0x28, 0xB4, 0x04, 0x08, 0x00, 0x00, 0x80, 0x4A };
                          //28C606080000803F
                          DeviceAddress Probe02 = { 0x28, 0xC6, 0x06, 0x08, 0x00, 0x00, 0x80, 0x3F };
                          //28750808000080C3
                          DeviceAddress Probe03 = { 0x28, 0x75, 0x08, 0x08, 0x00, 0x00, 0x80, 0xC3 };
                          
                          OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
                          DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature.
                          int numSensors = 0;
                          int lastTemperature[MAX_ATTACHED_DS18B20] = { -100, -100, -100 };
                          int16_t conversionTime;
                          unsigned long previousTempMillis = -1;
                          static unsigned long nowms = millis();    // update at start of loop()
                          
                          
                          // define LCD module
                          TM1638 ledModule(8, 9, 7);
                          
                          int displayInfo = -1;
                          unsigned long previousDisplayMillis = 0;
                          
                          int targetTemp = START_TARGET_TEMP;
                          #ifdef SIMULATION
                          bool powerOn = true;
                          #ifndef NO_AC_DETECT
                          bool powerOnBuderus = true;
                          #endif
                          #else
                          bool powerOn = false;
                          #ifndef NO_AC_DETECT
                          bool powerOnBuderus = false;
                          #endif
                          #endif
                          bool resetMischer = true; // mischer zuerst in Nullstellung
                          
                          #ifndef NO_AC_DETECT
                          bool testStateBuderus = false;
                          unsigned long lastResetBuderus = -1;
                          #endif
                          
                          #ifndef NO_MYS
                          // Initialize messages
                          MyMessage msgTemp(0, V_TEMP);
                          MyMessage msgStatus(0, V_STATUS);
                          MyMessage msgTargetTemp(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS, V_HVAC_SETPOINT_HEAT);
                          MyMessage msgPower(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 1, V_STATUS);
                          #ifndef NO_AC_DETECT
                          MyMessage msgPowerBuderus(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 2, V_STATUS);
                          #endif
                          MyMessage msgDebug(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 3, V_TEXT);
                          #endif
                          
                          // the setup function runs once when you press reset or power the board
                          void setup() {
                            DEBUG_PRINTLN(F("Starte setup"));
                            wdt_enable(WDTO_8S);
                            Serial.begin(115200);
                          
                          #ifndef NO_RTC
                            // the function to get the time from the RTC
                            setSyncProvider(RTC.get);
                          #endif
                          #ifndef NO_MYS
                            // Request latest time from controller at startup
                            requestTime();
                          #endif
                          
                          
                          
                          
                            // Zieltemperatur aus EERPOM lesem:
                            targetTemp = EEPROM.read(EEPROM_TARGET_TEMP);
                            if ((targetTemp < 30) || (targetTemp > MAX_TEMP)) {
                              targetTemp = START_TARGET_TEMP;
                              EEPROM.write(EEPROM_TARGET_TEMP, targetTemp);
                            }
                          
                            int state = EEPROM.read(EEPROM_POWERSTATE);
                            if (state == 0) {
                              powerOn = false;
                            }
                            else powerOn = true;
                          
                          #ifndef NO_AC_DETECT
                            // Buderuserkennung auf PIN3
                            attachInterrupt(digitalPinToInterrupt(BUDERUS_PIN), buderusSet, CHANGE);
                            testStateBuderus = false;
                            lastResetBuderus = millis();
                          #ifndef NO_MYS
                            send(msgPowerBuderus.set(powerOnBuderus));
                          #endif
                          #endif
                          
                            // Relayausgänge initialisiern
                            for (int sensor = 1, pin = RELAY_1; sensor <= NUMBER_OF_RELAYS; sensor++, pin++) {
                              // Then set relay pins in output mode
                              pinMode(pin, OUTPUT);
                              // Set relay to last known state (using eeprom storage)
                              digitalWrite(pin, RELAY_OFF);
                            }
                          
                            // Dallas Temperatursensoren
                            sensors.begin();
                            sensors.setWaitForConversion(false);
                            numSensors = sensors.getDeviceCount();
                            DEBUG_PRINT(F("Dallas Sensoren "));
                            DEBUG_PRINTLN(numSensors);
                            DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address
                          
                            for (int i = 0; i < numSensors; i++)
                            {
                              wdt_reset();
                              // Search the wire for address
                              if (sensors.getAddress(tempDeviceAddress, i))
                              {
                                DEBUG_PRINT(F("Found device "));
                          #ifdef EN_DEBUG
                                Serial.print(i, DEC);
                          #endif
                                DEBUG_PRINT(F(" with address: "));
                                printAddress(tempDeviceAddress);
                                DEBUG_PRINTLN();
                          
                                DEBUG_PRINT(F("Setting resolution to "));
                          #ifdef EN_DEBUG
                                Serial.println(TEMPERATURE_PRECISION, DEC);
                          #endif
                                // set the resolution to 12 bit (Each Dallas/Maxim device is capable of several different resolutions)
                                sensors.setResolution(tempDeviceAddress, TEMPERATURE_PRECISION);
                          
                                DEBUG_PRINT(F("Resolution actually set to: "));
                          
                          #ifdef EN_DEBUG
                                Serial.print(sensors.getResolution(tempDeviceAddress), DEC);
                          #endif
                                DEBUG_PRINTLN();
                              } else {
                                DEBUG_PRINT(F("Found ghost device at "));
                          
                          #ifdef EN_DEBUG
                                Serial.print(i, DEC);
                          #endif
                                DEBUG_PRINT(F(" but could not detect address. Check power and cabling"));
                              }
                            }
                          
                            wdt_reset();
                            sensors.requestTemperatures();
                          
                            // query conversion time and sleep until conversion completed
                            conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
                          }
                          
                          /*****************************************************/
                          // the loop function runs over and over again forever
                          void loop() {
                            nowms = millis();
                          
                          #ifndef NO_MYS
                            // If no time has been received yet, request it every 10 second from controller
                            // When time has been received, request update every hour
                            if ((!timeReceived && (nowms - lastRequest) > (10UL * 1000UL))
                                || (timeReceived && (nowms - lastRequest) > (60UL * 1000UL * 60UL))) {
                              // Request time from controller.
                              DEBUG_PRINTLN("requesting time");
                              requestTime();
                              lastRequest = nowms;
                            }
                          #endif
                          
                            wdt_reset();
                          
                          #ifndef NO_AC_DETECT
                            readAC();
                          #endif
                          
                            readTemp();
                            readButtons();
                          
                            updateDisp();
                          
                            // Temperaturen senden
                          
                          #ifndef NO_MYS
                            sendTemp();
                          #endif
                          
                            // Kontroller
                            control();
                          
                            // Loop 2x pro Sekunde ist aureichend
                            unsigned long loopTime = millis() - nowms;
                            if (loopTime < 450) {
                          #ifdef NO_MYS
                              delay (500 - loopTime);
                          #else
                              wait (500 - loopTime);
                          #endif
                            }
                          }
                          // end loop
                          
                          /**************************************************************/
                          // Steuerung
                          void control()
                          {
                          
                            wdt_reset();
                          
                            static unsigned long lastPumpTest = 0;
                            static unsigned long lastRegulation = -REGULATION_TIMEOUT_PUMP;
                            static unsigned long resetStart = 0;                     // wann wurde die Rücksetzung des Mischers gestartet
                            static bool lastPower = powerOn;
                            static float moveSeconds = 0.0;                 // Zeiten für Stellmotor Mischer
                          
                            // controllerState
                            // 0 initialized
                            // 1 Pumpe für kurzen test aktiviert, warten auf Timeout für Deaktivierung
                            // 2 in der Regelung, warten auf Timeout für Deaktivierung
                            // 3 in Ausganglage fahren
                          
                            static int controllerState = 0;
                          
                            // Emergency
                            if  (lastTemperature[VORLAUF] > MAX_TEMP) {
                              if (resetStart == 0) {
                                if (relState[PUMPE]) {
                                  DEBUG_PRINT(F("Zu heiss. Emergency Mischer schliessen"));
                                  DEBUG_PRINTLN(lastTemperature[VORLAUF]);
                                }
                                closeMischer();
                                controllerState = 0;
                                return;
                              }
                            }
                          
                          
                            // Temperatur noch nicht gelesen;
                            if (lastTemperature[VORLAUF] == -100) return;
                          
                            // Fehler mit den Sensoren
                            if ((lastTemperature[VORLAUF] < 0) ||
                                (lastTemperature[VORLAUF] > 100) ||
                                (lastTemperature[RUECKLAUF] < 0) ||
                                (lastTemperature[RUECKLAUF] > 100) ||
                                (lastTemperature[ZULAUF] < 0) ||
                                (lastTemperature[ZULAUF] > 100)) {
                              relState[PUMPE] = false;
                              updateRelays();
                              ledState[PUMPE] = relState[PUMPE];
                              // Test
                              //powerOn = false;
                          #ifndef NO_MYS
                              //send(msgPower.set(powerOn));
                          #endif
                          
                              controllerState = 0;
                              DEBUG_PRINTLN(F("Fehler mit den Sensoren, Temperaturen unter 0 oder über 100. Poweroff!"));
                              return;
                            }
                          
                            if (resetMischer) {
                              DEBUG_PRINTLN(F("Mischer initialisieren"));
                              closeMischer();
                              resetStart = millis();
                              resetMischer = false;
                              controllerState = 0;
                              return;
                            }
                          
                            if (resetStart > 0) {
                              if ((millis() - resetStart) > MISCHER_RESET_TIME) {
                                DEBUG_PRINTLN(F("Mischer fertig initialisiert"));
                                relState[MISCHER_ZU] = false;
                                updateRelays();
                                ledState[PUMPE] = relState[PUMPE];
                                ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                                resetStart = 0;
                                controllerState = 0;
                              }
                              return;
                            }
                          
                            // wenn ausser Betrieb -> verlassen;
                            if (powerOn == false) {
                              if (lastPower == false) return;
                          
                              DEBUG_PRINTLN("Go to power off state");
                          
                          #ifndef NO_MYS
                              send(msgPower.set(powerOn));
                          #endif
                          
                              lastPower = false;
                              relState[PUMPE] = false;
                              relState[MISCHER_ZU] = false;
                              relState[MISCHER_AUF] = false;
                              updateRelays();
                              ledState[PUMPE] = relState[PUMPE];
                              ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                              ledState[MISCHER_AUF] = relState[MISCHER_AUF];
                              controllerState = 0;
                              EEPROM.write(EEPROM_POWERSTATE, 0);
                              return;
                            }
                            //DEBUG_PRINTLN("a");
                            lastPower = true;
                          
                            switch (controllerState) {
                              case  0:  // Initialisiert
                                if (lastTemperature[ZULAUF] < 30) {
                                  if ((millis() - lastPumpTest) > RETRY_TIMEOUT_PUMP) {
                                    controllerState = 1;
                                    lastPumpTest = millis();
                                    DEBUG_PRINTLN(F("Zulauf zu kalt. Schalte Pumpe für 5 Sekunden ein."));
                                    relState[PUMPE] = true;
                                    updateRelays();
                                    ledState[PUMPE] = relState[PUMPE];
                                  }
                                  return;
                                }
                                //DEBUG_PRINTLN("x");
                          
                                relState[PUMPE] = true;
                                updateRelays();
                                ledState[PUMPE] = relState[PUMPE];
                          
                          
                                // nicht regulieren, wenn schon genau genug
                                if (abs(lastTemperature[VORLAUF] - targetTemp) <= 1) {
                                  // DEBUG_PRINTLN("diff zu klein, keine Steuerung notwendig");
                                  return;
                                }
                          
                          
                                if ((millis() - lastRegulation) > REGULATION_TIMEOUT_PUMP) {
                                  controllerState = 2;
                                  lastRegulation = millis();
                          
                                  int diffZualaufRuecklauf = lastTemperature[ZULAUF] - lastTemperature[RUECKLAUF];
                          
                                  float actPercent = (float)(lastTemperature[VORLAUF] - lastTemperature[RUECKLAUF]) * 100.0 / (float)diffZualaufRuecklauf;
                                  float shoulPercent = (float)(targetTemp - lastTemperature[RUECKLAUF]) * 100.0 / (float)diffZualaufRuecklauf;
                          
                                  // 120 Sekunden für ganzen Weg
                                  moveSeconds = (float)MISCHER_RESET_TIME / 1000.0 / 100.0 * abs(shoulPercent - actPercent);
                                  DEBUG_PRINT(F("Berechnete Sekunden fuer Mischerumstellung "));
                                  DEBUG_PRINTLN(moveSeconds);
                                  if (moveSeconds > 8)
                                    moveSeconds = 8;
                          
                                  if (targetTemp > lastTemperature[VORLAUF]) {
                                    DEBUG_PRINTLN(F("Mischer auf"));
                                    relState[MISCHER_ZU] = false;
                                    relState[MISCHER_AUF] = true;
                                    updateRelays();
                                    ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                                    ledState[MISCHER_AUF] = relState[MISCHER_AUF];
                                  }
                                  else
                                  {
                                    DEBUG_PRINTLN(F("Mischer zu"));
                                    relState[MISCHER_ZU] = true;
                                    relState[MISCHER_AUF] = false;
                                    updateRelays();
                                    ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                                    ledState[MISCHER_AUF] = relState[MISCHER_AUF];
                                  }
                                  return;
                                }
                                return;
                                break;
                              case  1: // in Testmodus bei zu wenig  Temp im Zulauf
                                if ((millis() - lastPumpTest) > PROBE_TIMEOUT_PUMP) {
                                  relState[PUMPE] = false;
                                  updateRelays();
                                  ledState[PUMPE] = relState[PUMPE];
                                  DEBUG_PRINTLN(F("Pumpe ausgeschaltet"));
                                  controllerState = 0;
                                  lastPumpTest = millis();
                                }
                                return;
                                break;
                              case  2: // in der Regelung
                                if ((millis() - lastRegulation) > moveSeconds * 1000.0) {
                                  DEBUG_PRINTLN("Mischer zu.");
                                  relState[MISCHER_ZU] = false;
                                  relState[MISCHER_AUF] = false;
                                  updateRelays();
                                  ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                                  ledState[MISCHER_AUF] = relState[MISCHER_AUF];
                                  lastRegulation = millis();
                                  controllerState = 0;
                                }
                                return;
                                break;
                              default:
                                DEBUG_PRINT(F("ERROR, unknown state :"));
                                DEBUG_PRINTLN(controllerState);
                                controllerState = 0;
                                return;
                            }
                          }
                          
                          // function to print a device address
                          void printAddress(DeviceAddress deviceAddress)
                          {
                            for (uint8_t i = 0; i < 8; i++)
                            {
                              if (deviceAddress[i] < 16) DEBUG_PRINT("0");
                          
                          #ifdef EN_DEBUG
                              Serial.print(deviceAddress[i], HEX);
                          #endif
                            }
                          }
                          
                          void updateRelays() {
                            static boolean relayStateReported[8] = { false, false, false, false, false, false, false, false };
                          #ifndef NO_MYS
                            static unsigned long previousStateMillis[NUMBER_OF_RELAYS] = { 0, 0, 0, 0 };
                          #endif
                          
                            for (int i = 0; i < NUMBER_OF_RELAYS; i++) {
                              if (relState[i]) {
                                digitalWrite(RELAY_1 + i, RELAY_ON);
                              }
                              else
                              {
                                digitalWrite(RELAY_1 + i, RELAY_OFF);
                              }
                          
                          #ifndef NO_MYS
                              bool bSend = false;
                              if (previousStateMillis[i] == 0) {                               // noch nie gesendet
                                bSend = true;
                              }
                              else if (relayStateReported[i] != relState[i] ) { // Änderungen melden
                                bSend = true;
                              }
                              else if ((millis() - previousStateMillis[i]) > MIN_REPORT_INTERVAL) {
                                bSend = true;
                              }
                          
                              if (bSend) {
                                // TODO: Check if we want to look at the return value of send
                                send(msgStatus.setSensor(i + MAX_ATTACHED_DS18B20).set(relState[i] ? 1 : 0));
                                previousStateMillis[i] = millis();
                                relayStateReported[i] = relState[i];
                              }
                          #endif
                            }
                          }
                          
                          void updateDisp() {
                            static char s[8];
                            static unsigned long previousDisplayMillis = 0;
                          
                            // update display?
                            if ((millis() - previousDisplayMillis) > 1000) {
                              previousDisplayMillis = millis();
                              displayInfo++;
                          #ifdef NO_MYS
                              if (displayInfo > 4) displayInfo = 0;
                          #else
                              if (displayInfo > 5) displayInfo = 0;
                          #endif
                          
                          
                          
                              ledModule.clearDisplay();
                              // sind die Temperaturen schon gelesen worden? Wenn nicht, abbrechen.
                              if (lastTemperature[0] == -100) return;
                          
                              for (byte i = 0; i <= 7; i++) {
                                if (ledState[i])
                                  ledModule.setLED(1, i);
                                else
                                  ledModule.setLED(0, i);
                              }
                          
                              // 0 Vorlauf, 1 Rücklauf, 2 Zulauf, 3 Sollwert
                              switch (displayInfo) {
                                case 0: // Vorlauf
                                  sprintf(s, "Vor %2i",  lastTemperature[VORLAUF]);
                                  break;
                                case 1: // Rücklauf
                                  sprintf(s, "Rue %2i",  lastTemperature[RUECKLAUF]);
                                  break;
                                case 2: // Zulauf
                                  sprintf(s, "Zu %2i",  lastTemperature[ZULAUF]);
                                  break;
                                case 3: // Zielwert
                                  sprintf(s, "Soll %2i",  targetTemp);
                                  break;
                                case 4: // Power
                                  if (powerOn) {
                                    sprintf(s, "PowerOn");
                                  }
                                  else {
                                    sprintf(s, "PowerOff");
                                  }
                                  break;
                          #ifndef NO_MYS
                                case 5: //clock
                                  TimeChangeRule *tcr;
                                  time_t utc = millis();
                                  time_t t = CE.toLocal(utc, &tcr);
                                  unsigned long dispTime = hour(t) * 100 * 100 + minute(t) * 100 + second(t);
                                  if (hour(t) < 10) {
                                    sprintf(s, "U 0%lu",  dispTime);
                                  }
                                  else
                                  {
                                    sprintf(s, "U %lu",  dispTime);
                                  }
                                  break;
                          #endif
                              }
                          
                              ledModule.setDisplayToString(s);
                            }
                          }
                          
                          void closeMischer() {
                            relState[PUMPE] = false;
                            relState[MISCHER_ZU] = true;
                            relState[MISCHER_AUF] = false;
                            updateRelays();
                            ledState[PUMPE] = relState[PUMPE];
                            ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                            ledState[MISCHER_AUF] = relState[MISCHER_AUF];
                          }
                          
                          
                          #ifndef NO_MYS
                          
                          void before()
                          {
                          
                          }
                          
                          // 0 Vorlauf, 1 Rücklauf, 2 Zulauf
                          void presentation() {
                            // Send the sketch version information to the gateway and Controller
                            sendSketchInfo("Mischer Node", "1.1");
                          
                            // Fetch the number of attached temperature sensors
                            numSensors = sensors.getDeviceCount();
                            DEBUG_PRINT(F("Numsensors "));
                            DEBUG_PRINTLN(numSensors);
                          
                            // Present all sensors to controller
                            for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
                              present(i, S_TEMP);
                            }
                          
                            for (int sensor = MAX_ATTACHED_DS18B20, pin = RELAY_1; sensor < (MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS); sensor++, pin++) {
                              // Register all sensors to gw (they will be created as child devices)
                              present(sensor, S_BINARY);
                            }
                          
                            // Thermopunkt
                            present(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS, S_HVAC);
                          
                            // Power
                            present(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 1, S_HEATER);
                          
                          #ifndef NO_AC_DETECT
                            // AC Buderuus
                            present(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 2, S_BINATY);
                          #endif
                          
                            // Power
                            present(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 3, S_INFO);
                          
                            // Initialltemperatur mitteilen
                            send(msgTargetTemp.set(targetTemp));
                            send(msgPower.set(powerOn));
                          }
                          
                          
                          void receive(const MyMessage & message)
                          {
                            DEBUG_PRINT(F("Meldung an Sensor "));
                            DEBUG_PRINT(message.sensor);
                            DEBUG_PRINT(F(" mit type "));
                            DEBUG_PRINTLN(message.type);
                            if (message.type == V_STATUS) {
                              int i = message.sensor - MAX_ATTACHED_DS18B20;
                              if ((i >= 0) && (i < NUMBER_OF_RELAYS)) {
                                DEBUG_PRINT(F("Schaltbefehl für Relay "));
                                DEBUG_PRINT(i);
                                DEBUG_PRINT(F(" auf "));
                                DEBUG_PRINTLN(message.getBool());
                                relState[i] = message.getBool();
                                ledState[i] = relState[i];
                              }
                              else if (i == MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 1) {
                                powerOn = message.getBool();
                                send(msgPower.set(powerOn));
                          
                                if (powerOn)
                                  EEPROM.write(EEPROM_POWERSTATE, 1);
                                else
                                  EEPROM.write(EEPROM_POWERSTATE, 0);
                          
                                if (powerOn == false) {
                                  relState[PUMPE] = false;
                                  ledState[POWERLED] = false;
                                  DEBUG_PRINTLN(F("Befehl für PowerOff"));
                                }
                                else {
                                  ledState[POWERLED] = true;
                                  DEBUG_PRINTLN(F("Befehl für PowerOn"));
                                }
                              }
                          
                              updateRelays();
                            }
                            else if (message.type == V_HVAC_SETPOINT_HEAT) {
                              if (message.sensor == (MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS)) {
                                targetTemp = message.getInt();
                                DEBUG_PRINT(F("Zieltemp gesetzt auf "));
                                DEBUG_PRINTLN(targetTemp);
                                if (targetTemp > MAX_TEMP) targetTemp = START_TARGET_TEMP;
                                if (targetTemp < 20) targetTemp = 20;
                                send(msgTargetTemp.set(targetTemp));
                              }
                            }
                          }
                          
                          // This is called when a new time value was received
                          void receiveTime(unsigned long controllerTime) {
                            // Ok, set incoming time
                            DEBUG_PRINT(F("Time value received: "));
                            DEBUG_PRINTLN(controllerTime);
                          #ifndef NO_RTC
                            RTC.set(controllerTime);
                            else
                              setTime(controllerTime);
                          #endif
                            timeReceived = true;
                          }
                          
                          void sendTemp() {
                            static int lastSentTemperature[MAX_ATTACHED_DS18B20] = { -100, -100, -100 };
                            static unsigned long previousTempMillis[MAX_ATTACHED_DS18B20] = { 0, 0, 0 };
                          
                            for (int i = 0; i < MAX_ATTACHED_DS18B20 ; i++) {
                              if (lastTemperature[i] != -100) {
                                bool bSend = false;
                                if (previousTempMillis[i] == 0) {                               // noch nie gesendet
                                  bSend = true;
                                }
                                else if (abs(lastSentTemperature[i] - lastTemperature[i]) >= 2) { // Differenz von >= zwei Grad werden gemeldet
                                  bSend = true;
                                }
                                else if ((millis() - previousTempMillis[i]) > MIN_REPORT_INTERVAL) {
                                  bSend = true;
                                }
                          
                                if (bSend) {
                                  // TODO: Check if we want to look at the return value of send
                                  send(msgTemp.setSensor(i).set(lastTemperature[i], 1));
                                  previousTempMillis[i] = millis();
                                  lastSentTemperature[i] = lastTemperature[i];
                                }
                              }
                            }
                          }
                          #endif
                          
                          #ifndef NO_AC_DETECT
                          void buderusSet() {
                            testStateBuderus = true;
                          }
                          #endif
                          
                          void reboot() {
                            wdt_enable(WDTO_30MS);
                            while (1) {};
                          }
                          
                          void readButtons() {
                          
                            byte buttons = ledModule.getButtons();
                          
                            if (lastButtonState != buttons) {
                              lastButtonState = buttons;
                              if (buttons > 0) {
                                for (byte i = 0; i <= 7; i++) {
                                  if ((buttons >> i) & 1) {
                                    ledState[i] = !ledState[i];
                                    if (i < NUMBER_OF_RELAYS) relState[i] = ledState[i];
                                    updateRelays();
                                    if (ledState[i])
                                      ledModule.setLED(1, i);
                                    else
                                      ledModule.setLED(0, i);
                                    if (i == POWERLED) {
                                      powerOn = ledState[i];
                          #ifndef NO_MYS
                                      send(msgPower.set(powerOn));
                          #endif
                                      if (powerOn)
                                        EEPROM.write(EEPROM_POWERSTATE, 1);
                                      else
                                        EEPROM.write(EEPROM_POWERSTATE, 0);
                          
                                    }
                          
                                    if (i == TEMPDOWNLED) {
                                      targetTemp--;
                                      if (targetTemp < 30) targetTemp = 30;
                                      EEPROM.write(EEPROM_TARGET_TEMP, targetTemp);
                                    }
                                    if (i == TEMPUPLED) {
                                      targetTemp++;
                                      if (targetTemp > MAX_TEMP) targetTemp = MAX_TEMP;
                                      EEPROM.write(EEPROM_TARGET_TEMP, targetTemp);
                                    }
                                    DEBUG_PRINT(F("ButtonState changed "));
                                    DEBUG_PRINTLN(i);
                                  }
                                }
                              }
                            }
                          }
                          
                          void readTemp() {
                            static float temp;
                            static int tempi;
                            static unsigned long lastReadTemp1 = -1;
                            static unsigned long lastReadTemp2 = -1;
                            static unsigned long lastReadTemp3 = -1;
                          
                            if (previousTempMillis == -1) {
                              // Dallas
                              sensors.requestTemperatures();
                              previousTempMillis = nowms;
                            }
                          
                            if ((millis() - previousTempMillis) >= conversionTime) {
                              temp = sensors.getTempC(Probe01);
                              if (temp != DEVICE_DISCONNECTED_C) {
                                tempi = (int)(temp + 0.5);
                                lastTemperature[VORLAUF] = tempi;
                                lastReadTemp1 = nowms;
                              }
                          
                              if (temp != DEVICE_DISCONNECTED_C) {
                                temp = sensors.getTempC(Probe02);
                                tempi = (int)(temp + 0.5);
                                lastTemperature[RUECKLAUF] = tempi;
                                lastReadTemp2 = nowms;
                              }
                          
                              if (temp != DEVICE_DISCONNECTED_C) {
                                temp = sensors.getTempC(Probe03);
                                tempi = (int)(temp + 0.5);
                                lastTemperature[ZULAUF] = tempi;
                                lastReadTemp3 = nowms;
                              }
                          
                              if (nowms > 60000) {    // ersta nach einer minute prüfen
                                unsigned long compare = nowms - 60000; // vor 1 Minute
                                if ((lastReadTemp1 < compare) || (lastReadTemp2 < compare) || (lastReadTemp3 < compare)) {
                                  DEBUG_PRINTLN(F("Zu lange keine Temeratur -> reset"));
                                  lastReadTemp1 = -1;
                                  lastReadTemp2 = -1;
                                  lastReadTemp3 = -1;
                                  ledModule.setDisplayToString(F("ERR Reb"));
                                  delay(1000);
                                  reboot();
                                }
                              }
                          
                              previousTempMillis = -1;
                            }
                          
                          #ifdef SIMULATE_VOR
                            lastTemperature[VORLAUF] = SIMULATE_VOR;
                            lastReadTemp1 = nowms;
                          #endif
                          
                          #ifdef SIMULATE_RUE
                            lastTemperature[RUECKLAUF] = SIMULATE_RUE;
                            lastReadTemp3 = nowms;
                          #endif
                          
                          #ifdef SIMULATE_ZU
                            lastTemperature[ZULAUF] = SIMULATE_ZU;
                            lastReadTemp3 = nowms;
                          #endif
                          }
                          
                          #ifndef NO_AC_DETECT
                          
                          void readAC() {
                            if ((millis() - lastResetBuderus) > 100) // bei 50 HZ sind das 25 Durchgänge...
                            {
                              noInterrupts();
                              if (testStateBuderus != powerOnBuderus ) {
                                powerOnBuderus = testStateBuderus;
                                testStateBuderus = false;
                                interrupts();
                                ledState[BUDERUSLED] = powerOnBuderus;
                          #ifndef NO_MYS
                                send(msgPowerBuderus.set(powerOnBuderus));
                          #endif
                              }
                              lastResetBuderus = nowms;
                              testStateBuderus = false;
                            } else
                              interrupts();
                          }
                          #endif
                          
                          raptorjrR 1 Reply Last reply
                          1
                          • FotoFieberF FotoFieber

                            I had a similar problem with the control of a heating mixer and three dallas sensors. I solved the problem with:

                            • replacement of the relays with solid state relays
                            • moved conttroller more in distance of the high voltage parts

                            I also added a watchdog and a reboot mechanism in case of sensor problems.

                            Maybe this sketch can give you an inspiration: (work in progress, MYS-Part not tested in depth)

                            // Enable debug prints to serial monitor
                            //#define MY_DEBUG      // in Mysensors
                            #define EN_DEBUG      // in this sketch
                            //#define NO_MYS      // ohne Mysensors Unterstützung?
                            //#define SIMULATION
                            #define NO_AC_DETECT  // ohne AC sensor
                            #define NO_RTC
                            
                            // RTC nur zusammen mit Mysensors
                            #ifdef NO_MYS
                            #ifndef NO_RTC
                            #define NO_RTC
                            #endif
                            #endif
                            
                            #ifdef SIMULATION
                            // für Simulation ohne Sensoren
                            #define SIMULATE_VOR  35
                            #define SIMULATE_RUE  30
                            #define SIMULATE_ZU   65
                            
                            
                            #ifdef SIMULATE_VOR
                            #warning Achtung! Keine Echtentemperaturmessungen -> Simulation
                            #endif
                            
                            #ifdef SIMULATE_RUE
                            #warning Achtung! Keine Echtentemperaturmessungen -> Simulation
                            #endif
                            
                            #ifdef SIMULATE_ZU
                            #warning Achtung! Keine Echtentemperaturmessungen -> Simulation
                            #endif
                            #endif
                            
                            
                            #define START_TARGET_TEMP 40
                            #define EEPROM_TARGET_TEMP 900            // Save Porisiton. It is above the Mysensors range of lib 2.1
                            #define EEPROM_POWERSTATE  902            // Save Porisiton. It is above the Mysensors range of lib 2.1
                            #define MAX_TEMP 50
                            #define VORLAUF 0
                            #define RUECKLAUF 1
                            #define ZULAUF 2
                            #define PUMPE 0
                            #define MISCHER_ZU  1
                            #define MISCHER_AUF 2
                            #define POWERLED 7                        // 8. LED
                            #define TEMPDOWNLED 5                     // 6. Led
                            #define TEMPUPLED 6                       // 7. Led
                            #ifndef NO_AC_DETECT
                            #define BUDERUSLED 4                      // 5. Led
                            #endif
                            #define RETRY_TIMEOUT_PUMP 2*60*1000UL     // alle 2 Minuten testen, ob Vorlauf nicht besser (5 Sekunden pumpen)
                            #define REGULATION_TIMEOUT_PUMP 30*1000UL  // 30 Sekunden warten nach neuer Einstellung
                            #define PROBE_TIMEOUT_PUMP 5*1000UL        // 5 Sekunden Pumpe für Test einschalten, wenn Zulauf zu kalt
                            #define BUDERUS_PIN 3                     // Buderus Powererkennung Pumpe auf PIN 3
                            
                            #ifndef SIMULATION
                            #define MISCHER_RESET_TIME 120*1000UL      // 2 Minuten bis Nullstellung
                            #else
                            #define MISCHER_RESET_TIME 10*1000UL      // 10 Sekunden bis Nullstellung nei Simulation
                            #endif
                            
                            
                            
                            #ifdef EN_DEBUG
                            #define DEBUG_PRINT(x) Serial.print (x)
                            #else
                            #define DEBUG_PRINT(x)
                            #endif
                            
                            #ifdef EN_DEBUG
                            #define DEBUG_PRINTLN(x)  Serial.println (x)
                            #else
                            #define DEBUG_PRINTLN(x)
                            #endif
                            
                            #ifndef NO_MYS
                            // Radio Configuration
                            #define MY_TRANSPORT_WAIT_READY_MS (10000ul)
                            #define MY_RADIO_RFM69
                            #define MY_RFM69_FREQUENCY RF69_868MHZ
                            #define MY_RFM69_NETWORKID 13
                            #define MY_RFM69_ENABLE_ENCRYPTION
                            #define MY_NODE_ID 168
                            //#define MY_IS_RFM69HW
                            #endif
                            
                            
                            #include <Arduino.h>
                            #include <avr/wdt.h>
                            #include <EEPROM.h>
                            #include <MemoryFree.h>
                            
                            #ifndef NO_MYS
                            #define MIN_REPORT_INTERVAL  5 * 60 * 1000L   // mindestens alle 5 Minuten melden
                            #include <SPI.h>
                            #include <MySensors.h>
                            #include <Time.h>        //http://www.arduino.cc/playground/Code/Time
                            #include <Timezone.h>    //https://github.com/JChristensen/Timezone
                            #include <TimeLib.h>
                            
                            //Central European Time (Frankfurt, Paris)
                            TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120};     //Central European Summer Time
                            TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};       //Central European Standard Time
                            Timezone CE(CEST, CET);
                            bool timeReceived = false;
                            unsigned long lastUpdate = 0, lastRequest = 0;
                            #endif
                            
                            #ifndef NO_RTC
                            #include <DS3232RTC.h>  // A  DS3231/DS3232 library
                            #endif
                            
                            #define MAX_LEDS 8
                            
                            byte lastButtonState = 0;
                            #define RELAY_ON HIGH
                            #define RELAY_OFF LOW
                            #define RELAY_1  A0         // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
                            #define NUMBER_OF_RELAYS 4  // Total number of attached relays
                            
                            
                            boolean ledState[MAX_LEDS] = { false, false, false, false, false, false, false, false };
                            boolean relState[NUMBER_OF_RELAYS] = { false, false, false, false };
                            
                            #include <TM1638.h>
                            #include <DallasTemperature.h>
                            #include <OneWire.h>
                            
                            #define ONE_WIRE_BUS 6 // Pin where dallase sensor is connected 
                            #define TEMPERATURE_PRECISION 9
                            #define MAX_ATTACHED_DS18B20 3
                            
                            //28B404080000804A
                            DeviceAddress Probe01 = { 0x28, 0xB4, 0x04, 0x08, 0x00, 0x00, 0x80, 0x4A };
                            //28C606080000803F
                            DeviceAddress Probe02 = { 0x28, 0xC6, 0x06, 0x08, 0x00, 0x00, 0x80, 0x3F };
                            //28750808000080C3
                            DeviceAddress Probe03 = { 0x28, 0x75, 0x08, 0x08, 0x00, 0x00, 0x80, 0xC3 };
                            
                            OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
                            DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature.
                            int numSensors = 0;
                            int lastTemperature[MAX_ATTACHED_DS18B20] = { -100, -100, -100 };
                            int16_t conversionTime;
                            unsigned long previousTempMillis = -1;
                            static unsigned long nowms = millis();    // update at start of loop()
                            
                            
                            // define LCD module
                            TM1638 ledModule(8, 9, 7);
                            
                            int displayInfo = -1;
                            unsigned long previousDisplayMillis = 0;
                            
                            int targetTemp = START_TARGET_TEMP;
                            #ifdef SIMULATION
                            bool powerOn = true;
                            #ifndef NO_AC_DETECT
                            bool powerOnBuderus = true;
                            #endif
                            #else
                            bool powerOn = false;
                            #ifndef NO_AC_DETECT
                            bool powerOnBuderus = false;
                            #endif
                            #endif
                            bool resetMischer = true; // mischer zuerst in Nullstellung
                            
                            #ifndef NO_AC_DETECT
                            bool testStateBuderus = false;
                            unsigned long lastResetBuderus = -1;
                            #endif
                            
                            #ifndef NO_MYS
                            // Initialize messages
                            MyMessage msgTemp(0, V_TEMP);
                            MyMessage msgStatus(0, V_STATUS);
                            MyMessage msgTargetTemp(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS, V_HVAC_SETPOINT_HEAT);
                            MyMessage msgPower(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 1, V_STATUS);
                            #ifndef NO_AC_DETECT
                            MyMessage msgPowerBuderus(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 2, V_STATUS);
                            #endif
                            MyMessage msgDebug(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 3, V_TEXT);
                            #endif
                            
                            // the setup function runs once when you press reset or power the board
                            void setup() {
                              DEBUG_PRINTLN(F("Starte setup"));
                              wdt_enable(WDTO_8S);
                              Serial.begin(115200);
                            
                            #ifndef NO_RTC
                              // the function to get the time from the RTC
                              setSyncProvider(RTC.get);
                            #endif
                            #ifndef NO_MYS
                              // Request latest time from controller at startup
                              requestTime();
                            #endif
                            
                            
                            
                            
                              // Zieltemperatur aus EERPOM lesem:
                              targetTemp = EEPROM.read(EEPROM_TARGET_TEMP);
                              if ((targetTemp < 30) || (targetTemp > MAX_TEMP)) {
                                targetTemp = START_TARGET_TEMP;
                                EEPROM.write(EEPROM_TARGET_TEMP, targetTemp);
                              }
                            
                              int state = EEPROM.read(EEPROM_POWERSTATE);
                              if (state == 0) {
                                powerOn = false;
                              }
                              else powerOn = true;
                            
                            #ifndef NO_AC_DETECT
                              // Buderuserkennung auf PIN3
                              attachInterrupt(digitalPinToInterrupt(BUDERUS_PIN), buderusSet, CHANGE);
                              testStateBuderus = false;
                              lastResetBuderus = millis();
                            #ifndef NO_MYS
                              send(msgPowerBuderus.set(powerOnBuderus));
                            #endif
                            #endif
                            
                              // Relayausgänge initialisiern
                              for (int sensor = 1, pin = RELAY_1; sensor <= NUMBER_OF_RELAYS; sensor++, pin++) {
                                // Then set relay pins in output mode
                                pinMode(pin, OUTPUT);
                                // Set relay to last known state (using eeprom storage)
                                digitalWrite(pin, RELAY_OFF);
                              }
                            
                              // Dallas Temperatursensoren
                              sensors.begin();
                              sensors.setWaitForConversion(false);
                              numSensors = sensors.getDeviceCount();
                              DEBUG_PRINT(F("Dallas Sensoren "));
                              DEBUG_PRINTLN(numSensors);
                              DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address
                            
                              for (int i = 0; i < numSensors; i++)
                              {
                                wdt_reset();
                                // Search the wire for address
                                if (sensors.getAddress(tempDeviceAddress, i))
                                {
                                  DEBUG_PRINT(F("Found device "));
                            #ifdef EN_DEBUG
                                  Serial.print(i, DEC);
                            #endif
                                  DEBUG_PRINT(F(" with address: "));
                                  printAddress(tempDeviceAddress);
                                  DEBUG_PRINTLN();
                            
                                  DEBUG_PRINT(F("Setting resolution to "));
                            #ifdef EN_DEBUG
                                  Serial.println(TEMPERATURE_PRECISION, DEC);
                            #endif
                                  // set the resolution to 12 bit (Each Dallas/Maxim device is capable of several different resolutions)
                                  sensors.setResolution(tempDeviceAddress, TEMPERATURE_PRECISION);
                            
                                  DEBUG_PRINT(F("Resolution actually set to: "));
                            
                            #ifdef EN_DEBUG
                                  Serial.print(sensors.getResolution(tempDeviceAddress), DEC);
                            #endif
                                  DEBUG_PRINTLN();
                                } else {
                                  DEBUG_PRINT(F("Found ghost device at "));
                            
                            #ifdef EN_DEBUG
                                  Serial.print(i, DEC);
                            #endif
                                  DEBUG_PRINT(F(" but could not detect address. Check power and cabling"));
                                }
                              }
                            
                              wdt_reset();
                              sensors.requestTemperatures();
                            
                              // query conversion time and sleep until conversion completed
                              conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
                            }
                            
                            /*****************************************************/
                            // the loop function runs over and over again forever
                            void loop() {
                              nowms = millis();
                            
                            #ifndef NO_MYS
                              // If no time has been received yet, request it every 10 second from controller
                              // When time has been received, request update every hour
                              if ((!timeReceived && (nowms - lastRequest) > (10UL * 1000UL))
                                  || (timeReceived && (nowms - lastRequest) > (60UL * 1000UL * 60UL))) {
                                // Request time from controller.
                                DEBUG_PRINTLN("requesting time");
                                requestTime();
                                lastRequest = nowms;
                              }
                            #endif
                            
                              wdt_reset();
                            
                            #ifndef NO_AC_DETECT
                              readAC();
                            #endif
                            
                              readTemp();
                              readButtons();
                            
                              updateDisp();
                            
                              // Temperaturen senden
                            
                            #ifndef NO_MYS
                              sendTemp();
                            #endif
                            
                              // Kontroller
                              control();
                            
                              // Loop 2x pro Sekunde ist aureichend
                              unsigned long loopTime = millis() - nowms;
                              if (loopTime < 450) {
                            #ifdef NO_MYS
                                delay (500 - loopTime);
                            #else
                                wait (500 - loopTime);
                            #endif
                              }
                            }
                            // end loop
                            
                            /**************************************************************/
                            // Steuerung
                            void control()
                            {
                            
                              wdt_reset();
                            
                              static unsigned long lastPumpTest = 0;
                              static unsigned long lastRegulation = -REGULATION_TIMEOUT_PUMP;
                              static unsigned long resetStart = 0;                     // wann wurde die Rücksetzung des Mischers gestartet
                              static bool lastPower = powerOn;
                              static float moveSeconds = 0.0;                 // Zeiten für Stellmotor Mischer
                            
                              // controllerState
                              // 0 initialized
                              // 1 Pumpe für kurzen test aktiviert, warten auf Timeout für Deaktivierung
                              // 2 in der Regelung, warten auf Timeout für Deaktivierung
                              // 3 in Ausganglage fahren
                            
                              static int controllerState = 0;
                            
                              // Emergency
                              if  (lastTemperature[VORLAUF] > MAX_TEMP) {
                                if (resetStart == 0) {
                                  if (relState[PUMPE]) {
                                    DEBUG_PRINT(F("Zu heiss. Emergency Mischer schliessen"));
                                    DEBUG_PRINTLN(lastTemperature[VORLAUF]);
                                  }
                                  closeMischer();
                                  controllerState = 0;
                                  return;
                                }
                              }
                            
                            
                              // Temperatur noch nicht gelesen;
                              if (lastTemperature[VORLAUF] == -100) return;
                            
                              // Fehler mit den Sensoren
                              if ((lastTemperature[VORLAUF] < 0) ||
                                  (lastTemperature[VORLAUF] > 100) ||
                                  (lastTemperature[RUECKLAUF] < 0) ||
                                  (lastTemperature[RUECKLAUF] > 100) ||
                                  (lastTemperature[ZULAUF] < 0) ||
                                  (lastTemperature[ZULAUF] > 100)) {
                                relState[PUMPE] = false;
                                updateRelays();
                                ledState[PUMPE] = relState[PUMPE];
                                // Test
                                //powerOn = false;
                            #ifndef NO_MYS
                                //send(msgPower.set(powerOn));
                            #endif
                            
                                controllerState = 0;
                                DEBUG_PRINTLN(F("Fehler mit den Sensoren, Temperaturen unter 0 oder über 100. Poweroff!"));
                                return;
                              }
                            
                              if (resetMischer) {
                                DEBUG_PRINTLN(F("Mischer initialisieren"));
                                closeMischer();
                                resetStart = millis();
                                resetMischer = false;
                                controllerState = 0;
                                return;
                              }
                            
                              if (resetStart > 0) {
                                if ((millis() - resetStart) > MISCHER_RESET_TIME) {
                                  DEBUG_PRINTLN(F("Mischer fertig initialisiert"));
                                  relState[MISCHER_ZU] = false;
                                  updateRelays();
                                  ledState[PUMPE] = relState[PUMPE];
                                  ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                                  resetStart = 0;
                                  controllerState = 0;
                                }
                                return;
                              }
                            
                              // wenn ausser Betrieb -> verlassen;
                              if (powerOn == false) {
                                if (lastPower == false) return;
                            
                                DEBUG_PRINTLN("Go to power off state");
                            
                            #ifndef NO_MYS
                                send(msgPower.set(powerOn));
                            #endif
                            
                                lastPower = false;
                                relState[PUMPE] = false;
                                relState[MISCHER_ZU] = false;
                                relState[MISCHER_AUF] = false;
                                updateRelays();
                                ledState[PUMPE] = relState[PUMPE];
                                ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                                ledState[MISCHER_AUF] = relState[MISCHER_AUF];
                                controllerState = 0;
                                EEPROM.write(EEPROM_POWERSTATE, 0);
                                return;
                              }
                              //DEBUG_PRINTLN("a");
                              lastPower = true;
                            
                              switch (controllerState) {
                                case  0:  // Initialisiert
                                  if (lastTemperature[ZULAUF] < 30) {
                                    if ((millis() - lastPumpTest) > RETRY_TIMEOUT_PUMP) {
                                      controllerState = 1;
                                      lastPumpTest = millis();
                                      DEBUG_PRINTLN(F("Zulauf zu kalt. Schalte Pumpe für 5 Sekunden ein."));
                                      relState[PUMPE] = true;
                                      updateRelays();
                                      ledState[PUMPE] = relState[PUMPE];
                                    }
                                    return;
                                  }
                                  //DEBUG_PRINTLN("x");
                            
                                  relState[PUMPE] = true;
                                  updateRelays();
                                  ledState[PUMPE] = relState[PUMPE];
                            
                            
                                  // nicht regulieren, wenn schon genau genug
                                  if (abs(lastTemperature[VORLAUF] - targetTemp) <= 1) {
                                    // DEBUG_PRINTLN("diff zu klein, keine Steuerung notwendig");
                                    return;
                                  }
                            
                            
                                  if ((millis() - lastRegulation) > REGULATION_TIMEOUT_PUMP) {
                                    controllerState = 2;
                                    lastRegulation = millis();
                            
                                    int diffZualaufRuecklauf = lastTemperature[ZULAUF] - lastTemperature[RUECKLAUF];
                            
                                    float actPercent = (float)(lastTemperature[VORLAUF] - lastTemperature[RUECKLAUF]) * 100.0 / (float)diffZualaufRuecklauf;
                                    float shoulPercent = (float)(targetTemp - lastTemperature[RUECKLAUF]) * 100.0 / (float)diffZualaufRuecklauf;
                            
                                    // 120 Sekunden für ganzen Weg
                                    moveSeconds = (float)MISCHER_RESET_TIME / 1000.0 / 100.0 * abs(shoulPercent - actPercent);
                                    DEBUG_PRINT(F("Berechnete Sekunden fuer Mischerumstellung "));
                                    DEBUG_PRINTLN(moveSeconds);
                                    if (moveSeconds > 8)
                                      moveSeconds = 8;
                            
                                    if (targetTemp > lastTemperature[VORLAUF]) {
                                      DEBUG_PRINTLN(F("Mischer auf"));
                                      relState[MISCHER_ZU] = false;
                                      relState[MISCHER_AUF] = true;
                                      updateRelays();
                                      ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                                      ledState[MISCHER_AUF] = relState[MISCHER_AUF];
                                    }
                                    else
                                    {
                                      DEBUG_PRINTLN(F("Mischer zu"));
                                      relState[MISCHER_ZU] = true;
                                      relState[MISCHER_AUF] = false;
                                      updateRelays();
                                      ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                                      ledState[MISCHER_AUF] = relState[MISCHER_AUF];
                                    }
                                    return;
                                  }
                                  return;
                                  break;
                                case  1: // in Testmodus bei zu wenig  Temp im Zulauf
                                  if ((millis() - lastPumpTest) > PROBE_TIMEOUT_PUMP) {
                                    relState[PUMPE] = false;
                                    updateRelays();
                                    ledState[PUMPE] = relState[PUMPE];
                                    DEBUG_PRINTLN(F("Pumpe ausgeschaltet"));
                                    controllerState = 0;
                                    lastPumpTest = millis();
                                  }
                                  return;
                                  break;
                                case  2: // in der Regelung
                                  if ((millis() - lastRegulation) > moveSeconds * 1000.0) {
                                    DEBUG_PRINTLN("Mischer zu.");
                                    relState[MISCHER_ZU] = false;
                                    relState[MISCHER_AUF] = false;
                                    updateRelays();
                                    ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                                    ledState[MISCHER_AUF] = relState[MISCHER_AUF];
                                    lastRegulation = millis();
                                    controllerState = 0;
                                  }
                                  return;
                                  break;
                                default:
                                  DEBUG_PRINT(F("ERROR, unknown state :"));
                                  DEBUG_PRINTLN(controllerState);
                                  controllerState = 0;
                                  return;
                              }
                            }
                            
                            // function to print a device address
                            void printAddress(DeviceAddress deviceAddress)
                            {
                              for (uint8_t i = 0; i < 8; i++)
                              {
                                if (deviceAddress[i] < 16) DEBUG_PRINT("0");
                            
                            #ifdef EN_DEBUG
                                Serial.print(deviceAddress[i], HEX);
                            #endif
                              }
                            }
                            
                            void updateRelays() {
                              static boolean relayStateReported[8] = { false, false, false, false, false, false, false, false };
                            #ifndef NO_MYS
                              static unsigned long previousStateMillis[NUMBER_OF_RELAYS] = { 0, 0, 0, 0 };
                            #endif
                            
                              for (int i = 0; i < NUMBER_OF_RELAYS; i++) {
                                if (relState[i]) {
                                  digitalWrite(RELAY_1 + i, RELAY_ON);
                                }
                                else
                                {
                                  digitalWrite(RELAY_1 + i, RELAY_OFF);
                                }
                            
                            #ifndef NO_MYS
                                bool bSend = false;
                                if (previousStateMillis[i] == 0) {                               // noch nie gesendet
                                  bSend = true;
                                }
                                else if (relayStateReported[i] != relState[i] ) { // Änderungen melden
                                  bSend = true;
                                }
                                else if ((millis() - previousStateMillis[i]) > MIN_REPORT_INTERVAL) {
                                  bSend = true;
                                }
                            
                                if (bSend) {
                                  // TODO: Check if we want to look at the return value of send
                                  send(msgStatus.setSensor(i + MAX_ATTACHED_DS18B20).set(relState[i] ? 1 : 0));
                                  previousStateMillis[i] = millis();
                                  relayStateReported[i] = relState[i];
                                }
                            #endif
                              }
                            }
                            
                            void updateDisp() {
                              static char s[8];
                              static unsigned long previousDisplayMillis = 0;
                            
                              // update display?
                              if ((millis() - previousDisplayMillis) > 1000) {
                                previousDisplayMillis = millis();
                                displayInfo++;
                            #ifdef NO_MYS
                                if (displayInfo > 4) displayInfo = 0;
                            #else
                                if (displayInfo > 5) displayInfo = 0;
                            #endif
                            
                            
                            
                                ledModule.clearDisplay();
                                // sind die Temperaturen schon gelesen worden? Wenn nicht, abbrechen.
                                if (lastTemperature[0] == -100) return;
                            
                                for (byte i = 0; i <= 7; i++) {
                                  if (ledState[i])
                                    ledModule.setLED(1, i);
                                  else
                                    ledModule.setLED(0, i);
                                }
                            
                                // 0 Vorlauf, 1 Rücklauf, 2 Zulauf, 3 Sollwert
                                switch (displayInfo) {
                                  case 0: // Vorlauf
                                    sprintf(s, "Vor %2i",  lastTemperature[VORLAUF]);
                                    break;
                                  case 1: // Rücklauf
                                    sprintf(s, "Rue %2i",  lastTemperature[RUECKLAUF]);
                                    break;
                                  case 2: // Zulauf
                                    sprintf(s, "Zu %2i",  lastTemperature[ZULAUF]);
                                    break;
                                  case 3: // Zielwert
                                    sprintf(s, "Soll %2i",  targetTemp);
                                    break;
                                  case 4: // Power
                                    if (powerOn) {
                                      sprintf(s, "PowerOn");
                                    }
                                    else {
                                      sprintf(s, "PowerOff");
                                    }
                                    break;
                            #ifndef NO_MYS
                                  case 5: //clock
                                    TimeChangeRule *tcr;
                                    time_t utc = millis();
                                    time_t t = CE.toLocal(utc, &tcr);
                                    unsigned long dispTime = hour(t) * 100 * 100 + minute(t) * 100 + second(t);
                                    if (hour(t) < 10) {
                                      sprintf(s, "U 0%lu",  dispTime);
                                    }
                                    else
                                    {
                                      sprintf(s, "U %lu",  dispTime);
                                    }
                                    break;
                            #endif
                                }
                            
                                ledModule.setDisplayToString(s);
                              }
                            }
                            
                            void closeMischer() {
                              relState[PUMPE] = false;
                              relState[MISCHER_ZU] = true;
                              relState[MISCHER_AUF] = false;
                              updateRelays();
                              ledState[PUMPE] = relState[PUMPE];
                              ledState[MISCHER_ZU] = relState[MISCHER_ZU];
                              ledState[MISCHER_AUF] = relState[MISCHER_AUF];
                            }
                            
                            
                            #ifndef NO_MYS
                            
                            void before()
                            {
                            
                            }
                            
                            // 0 Vorlauf, 1 Rücklauf, 2 Zulauf
                            void presentation() {
                              // Send the sketch version information to the gateway and Controller
                              sendSketchInfo("Mischer Node", "1.1");
                            
                              // Fetch the number of attached temperature sensors
                              numSensors = sensors.getDeviceCount();
                              DEBUG_PRINT(F("Numsensors "));
                              DEBUG_PRINTLN(numSensors);
                            
                              // Present all sensors to controller
                              for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
                                present(i, S_TEMP);
                              }
                            
                              for (int sensor = MAX_ATTACHED_DS18B20, pin = RELAY_1; sensor < (MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS); sensor++, pin++) {
                                // Register all sensors to gw (they will be created as child devices)
                                present(sensor, S_BINARY);
                              }
                            
                              // Thermopunkt
                              present(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS, S_HVAC);
                            
                              // Power
                              present(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 1, S_HEATER);
                            
                            #ifndef NO_AC_DETECT
                              // AC Buderuus
                              present(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 2, S_BINATY);
                            #endif
                            
                              // Power
                              present(MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 3, S_INFO);
                            
                              // Initialltemperatur mitteilen
                              send(msgTargetTemp.set(targetTemp));
                              send(msgPower.set(powerOn));
                            }
                            
                            
                            void receive(const MyMessage & message)
                            {
                              DEBUG_PRINT(F("Meldung an Sensor "));
                              DEBUG_PRINT(message.sensor);
                              DEBUG_PRINT(F(" mit type "));
                              DEBUG_PRINTLN(message.type);
                              if (message.type == V_STATUS) {
                                int i = message.sensor - MAX_ATTACHED_DS18B20;
                                if ((i >= 0) && (i < NUMBER_OF_RELAYS)) {
                                  DEBUG_PRINT(F("Schaltbefehl für Relay "));
                                  DEBUG_PRINT(i);
                                  DEBUG_PRINT(F(" auf "));
                                  DEBUG_PRINTLN(message.getBool());
                                  relState[i] = message.getBool();
                                  ledState[i] = relState[i];
                                }
                                else if (i == MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS + 1) {
                                  powerOn = message.getBool();
                                  send(msgPower.set(powerOn));
                            
                                  if (powerOn)
                                    EEPROM.write(EEPROM_POWERSTATE, 1);
                                  else
                                    EEPROM.write(EEPROM_POWERSTATE, 0);
                            
                                  if (powerOn == false) {
                                    relState[PUMPE] = false;
                                    ledState[POWERLED] = false;
                                    DEBUG_PRINTLN(F("Befehl für PowerOff"));
                                  }
                                  else {
                                    ledState[POWERLED] = true;
                                    DEBUG_PRINTLN(F("Befehl für PowerOn"));
                                  }
                                }
                            
                                updateRelays();
                              }
                              else if (message.type == V_HVAC_SETPOINT_HEAT) {
                                if (message.sensor == (MAX_ATTACHED_DS18B20 + NUMBER_OF_RELAYS)) {
                                  targetTemp = message.getInt();
                                  DEBUG_PRINT(F("Zieltemp gesetzt auf "));
                                  DEBUG_PRINTLN(targetTemp);
                                  if (targetTemp > MAX_TEMP) targetTemp = START_TARGET_TEMP;
                                  if (targetTemp < 20) targetTemp = 20;
                                  send(msgTargetTemp.set(targetTemp));
                                }
                              }
                            }
                            
                            // This is called when a new time value was received
                            void receiveTime(unsigned long controllerTime) {
                              // Ok, set incoming time
                              DEBUG_PRINT(F("Time value received: "));
                              DEBUG_PRINTLN(controllerTime);
                            #ifndef NO_RTC
                              RTC.set(controllerTime);
                              else
                                setTime(controllerTime);
                            #endif
                              timeReceived = true;
                            }
                            
                            void sendTemp() {
                              static int lastSentTemperature[MAX_ATTACHED_DS18B20] = { -100, -100, -100 };
                              static unsigned long previousTempMillis[MAX_ATTACHED_DS18B20] = { 0, 0, 0 };
                            
                              for (int i = 0; i < MAX_ATTACHED_DS18B20 ; i++) {
                                if (lastTemperature[i] != -100) {
                                  bool bSend = false;
                                  if (previousTempMillis[i] == 0) {                               // noch nie gesendet
                                    bSend = true;
                                  }
                                  else if (abs(lastSentTemperature[i] - lastTemperature[i]) >= 2) { // Differenz von >= zwei Grad werden gemeldet
                                    bSend = true;
                                  }
                                  else if ((millis() - previousTempMillis[i]) > MIN_REPORT_INTERVAL) {
                                    bSend = true;
                                  }
                            
                                  if (bSend) {
                                    // TODO: Check if we want to look at the return value of send
                                    send(msgTemp.setSensor(i).set(lastTemperature[i], 1));
                                    previousTempMillis[i] = millis();
                                    lastSentTemperature[i] = lastTemperature[i];
                                  }
                                }
                              }
                            }
                            #endif
                            
                            #ifndef NO_AC_DETECT
                            void buderusSet() {
                              testStateBuderus = true;
                            }
                            #endif
                            
                            void reboot() {
                              wdt_enable(WDTO_30MS);
                              while (1) {};
                            }
                            
                            void readButtons() {
                            
                              byte buttons = ledModule.getButtons();
                            
                              if (lastButtonState != buttons) {
                                lastButtonState = buttons;
                                if (buttons > 0) {
                                  for (byte i = 0; i <= 7; i++) {
                                    if ((buttons >> i) & 1) {
                                      ledState[i] = !ledState[i];
                                      if (i < NUMBER_OF_RELAYS) relState[i] = ledState[i];
                                      updateRelays();
                                      if (ledState[i])
                                        ledModule.setLED(1, i);
                                      else
                                        ledModule.setLED(0, i);
                                      if (i == POWERLED) {
                                        powerOn = ledState[i];
                            #ifndef NO_MYS
                                        send(msgPower.set(powerOn));
                            #endif
                                        if (powerOn)
                                          EEPROM.write(EEPROM_POWERSTATE, 1);
                                        else
                                          EEPROM.write(EEPROM_POWERSTATE, 0);
                            
                                      }
                            
                                      if (i == TEMPDOWNLED) {
                                        targetTemp--;
                                        if (targetTemp < 30) targetTemp = 30;
                                        EEPROM.write(EEPROM_TARGET_TEMP, targetTemp);
                                      }
                                      if (i == TEMPUPLED) {
                                        targetTemp++;
                                        if (targetTemp > MAX_TEMP) targetTemp = MAX_TEMP;
                                        EEPROM.write(EEPROM_TARGET_TEMP, targetTemp);
                                      }
                                      DEBUG_PRINT(F("ButtonState changed "));
                                      DEBUG_PRINTLN(i);
                                    }
                                  }
                                }
                              }
                            }
                            
                            void readTemp() {
                              static float temp;
                              static int tempi;
                              static unsigned long lastReadTemp1 = -1;
                              static unsigned long lastReadTemp2 = -1;
                              static unsigned long lastReadTemp3 = -1;
                            
                              if (previousTempMillis == -1) {
                                // Dallas
                                sensors.requestTemperatures();
                                previousTempMillis = nowms;
                              }
                            
                              if ((millis() - previousTempMillis) >= conversionTime) {
                                temp = sensors.getTempC(Probe01);
                                if (temp != DEVICE_DISCONNECTED_C) {
                                  tempi = (int)(temp + 0.5);
                                  lastTemperature[VORLAUF] = tempi;
                                  lastReadTemp1 = nowms;
                                }
                            
                                if (temp != DEVICE_DISCONNECTED_C) {
                                  temp = sensors.getTempC(Probe02);
                                  tempi = (int)(temp + 0.5);
                                  lastTemperature[RUECKLAUF] = tempi;
                                  lastReadTemp2 = nowms;
                                }
                            
                                if (temp != DEVICE_DISCONNECTED_C) {
                                  temp = sensors.getTempC(Probe03);
                                  tempi = (int)(temp + 0.5);
                                  lastTemperature[ZULAUF] = tempi;
                                  lastReadTemp3 = nowms;
                                }
                            
                                if (nowms > 60000) {    // ersta nach einer minute prüfen
                                  unsigned long compare = nowms - 60000; // vor 1 Minute
                                  if ((lastReadTemp1 < compare) || (lastReadTemp2 < compare) || (lastReadTemp3 < compare)) {
                                    DEBUG_PRINTLN(F("Zu lange keine Temeratur -> reset"));
                                    lastReadTemp1 = -1;
                                    lastReadTemp2 = -1;
                                    lastReadTemp3 = -1;
                                    ledModule.setDisplayToString(F("ERR Reb"));
                                    delay(1000);
                                    reboot();
                                  }
                                }
                            
                                previousTempMillis = -1;
                              }
                            
                            #ifdef SIMULATE_VOR
                              lastTemperature[VORLAUF] = SIMULATE_VOR;
                              lastReadTemp1 = nowms;
                            #endif
                            
                            #ifdef SIMULATE_RUE
                              lastTemperature[RUECKLAUF] = SIMULATE_RUE;
                              lastReadTemp3 = nowms;
                            #endif
                            
                            #ifdef SIMULATE_ZU
                              lastTemperature[ZULAUF] = SIMULATE_ZU;
                              lastReadTemp3 = nowms;
                            #endif
                            }
                            
                            #ifndef NO_AC_DETECT
                            
                            void readAC() {
                              if ((millis() - lastResetBuderus) > 100) // bei 50 HZ sind das 25 Durchgänge...
                              {
                                noInterrupts();
                                if (testStateBuderus != powerOnBuderus ) {
                                  powerOnBuderus = testStateBuderus;
                                  testStateBuderus = false;
                                  interrupts();
                                  ledState[BUDERUSLED] = powerOnBuderus;
                            #ifndef NO_MYS
                                  send(msgPowerBuderus.set(powerOnBuderus));
                            #endif
                                }
                                lastResetBuderus = nowms;
                                testStateBuderus = false;
                              } else
                                interrupts();
                            }
                            #endif
                            
                            raptorjrR Offline
                            raptorjrR Offline
                            raptorjr
                            wrote on last edited by
                            #13

                            @FotoFieber

                            That was very advanced =) I don't have any high voltage involved. Only have a test setup on a breadboard.

                            I tried to move the sensors.begin to the setup, but then I don't get any temperature readings?

                            1 Reply Last reply
                            0
                            • gohanG Offline
                              gohanG Offline
                              gohan
                              Mod
                              wrote on last edited by
                              #14

                              Try post your code so we can take a look. Did you cross check the hw yet?

                              raptorjrR 1 Reply Last reply
                              0
                              • gohanG gohan

                                Try post your code so we can take a look. Did you cross check the hw yet?

                                raptorjrR Offline
                                raptorjrR Offline
                                raptorjr
                                wrote on last edited by
                                #15

                                @gohan

                                It is the same sketch as my second post.

                                Haven't done anything with the hardware yet. Was following Fabiens advice with using 2.1 on both sketch and gateway. And restart gateway with problem. And then test again and restart node when the problem occurs.

                                1 Reply Last reply
                                0
                                • Darren McInnesD Offline
                                  Darren McInnesD Offline
                                  Darren McInnes
                                  wrote on last edited by
                                  #16

                                  You may want to check which version of the onewire library you are running. I was having exactly the same issue and fixed it by upgrading the onewire library from 2.7.2 (I think?) To the latest version.

                                  It's been a few weeks now with no crashes.

                                  raptorjrR 1 Reply Last reply
                                  1
                                  • Darren McInnesD Darren McInnes

                                    You may want to check which version of the onewire library you are running. I was having exactly the same issue and fixed it by upgrading the onewire library from 2.7.2 (I think?) To the latest version.

                                    It's been a few weeks now with no crashes.

                                    raptorjrR Offline
                                    raptorjrR Offline
                                    raptorjr
                                    wrote on last edited by
                                    #17

                                    @Darren-McInnes said:

                                    You may want to check which version of the onewire library you are running. I was having exactly the same issue and fixed it by upgrading the onewire library from 2.7.2 (I think?) To the latest version.

                                    It's been a few weeks now with no crashes.

                                    In the Arduino IDE version 2.3.2 seems to be the latest. But is there a newer one that I can download and install?

                                    Maybe should figure out why I don't get any sensor readings when I have sensors.begin() in the setup. Maybe that is a problem also that I have it in the loop()?

                                    1 Reply Last reply
                                    0
                                    • Darren McInnesD Offline
                                      Darren McInnesD Offline
                                      Darren McInnes
                                      wrote on last edited by
                                      #18

                                      Sorry i meant the dallastemperature library!

                                      i'm running 3.7.5 now without issues but had problems after a day with 3.7.2

                                      my ide version is 1.6.9 and onewire version 2.3.2

                                      raptorjrR 1 Reply Last reply
                                      0
                                      • Darren McInnesD Darren McInnes

                                        Sorry i meant the dallastemperature library!

                                        i'm running 3.7.5 now without issues but had problems after a day with 3.7.2

                                        my ide version is 1.6.9 and onewire version 2.3.2

                                        raptorjrR Offline
                                        raptorjrR Offline
                                        raptorjr
                                        wrote on last edited by
                                        #19

                                        @Darren-McInnes

                                        I have 3.7.6 installed. On thing might just be updated libraries. I have been using Visual Studio for development with the plugin from Visual Micro. But then the libraries don't get updated. Had some problems with a update from Visual Micro so I went back to the Arduino IDE.
                                        Have been running since Monday now. Although it could take more than a week before any problem, but I'm keeping my fingers crossed.

                                        gohanG 1 Reply Last reply
                                        0
                                        • raptorjrR raptorjr

                                          @Darren-McInnes

                                          I have 3.7.6 installed. On thing might just be updated libraries. I have been using Visual Studio for development with the plugin from Visual Micro. But then the libraries don't get updated. Had some problems with a update from Visual Micro so I went back to the Arduino IDE.
                                          Have been running since Monday now. Although it could take more than a week before any problem, but I'm keeping my fingers crossed.

                                          gohanG Offline
                                          gohanG Offline
                                          gohan
                                          Mod
                                          wrote on last edited by
                                          #20

                                          @raptorjr
                                          I am also using visual studio but libraries and boards get updated through the arduino ide without problems

                                          raptorjrR 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          14

                                          Online

                                          11.7k

                                          Users

                                          11.2k

                                          Topics

                                          113.1k

                                          Posts


                                          Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • MySensors
                                          • OpenHardware.io
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular