[SOLVED] Error sending switch command



  • Almost every time when I try to control my relay from Domoticz I get a "Error sending switch command, check device/hardware !" even though the relay turns on/off. There is maybe a 2-3 seconds delay between when I press the switch in Domoticz and when it reacts.

    Don't know if it is the mysGateway not communicating properly with Domoticz or some other problem? Since the command works it seems to me that my sensors is working and talking to each other.

    Any idea on what could be wrong or how to narrow down the problem?

    I was hoping for a logfile for the mysController but haven't found anything. If there is some error between the gateway and the sensor.

    However, watching the messages in MYScontroller I always see the same command sends two times (either on or off) every time when I get the error message in Domoticz. The few times when it works as it should, no error in Domoticz, on/off is only sent one time.

    Don't know if it is possible to configure some more time in Domoticz before it produces a error? Or if the gateway is not communication properly with Domoticz saying "wait a second, need to resend the command", and therefore Domoticz thinks there is a problem with the command? Because it seems to me that the gateway at least understands that it needs to send the command twice sometimes.

    I have capacitors on the NRF, so communication should be good.


  • Contest Winner

    @raptorjr There could be several different reasons:

    1. Communication problems
    2. Node is not able to handle incomming messages at the moment you send the command.
    3. Others I have not yet come accross

    Could you post your sketch?



  • @TheoL

    Sure, here is my 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
    
    //Temperatur sensor
    #define ONE_WIRE_BUS 4
    #define COMPARE_TEMP 0 // 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
    
    void setup(void)
    {
    	// start serial port
    	Serial.begin(115200);
    
    	pinMode(RELAY_PIN, OUTPUT);
    	digitalWrite(RELAY_PIN, RELAY_OFF);
    }
    
    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");
    }
    
    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 = sensors.getTempC(tempDeviceAddress);
    		//Serial.print("Temperature=");
    		//Serial.println(tempC); 
    #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;
    		}
       } 
    
    	delay(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) 
    	{
    		// Change relay state
    		digitalWrite(RELAY_PIN, message.getBool() ? RELAY_ON : RELAY_OFF);
    	}
    }
    

    Maybe a communication problem, but the command does work. Don't really see it as a problem that the gateway has to send the command twice sometimes, there is maybe a 0.5-1s delay because of it. But it is a problem that the controller screams error every time that occurs.

    Don't know how a controller and gateway communicates, but it feels like it should be the gateway that tells the controller that it have failed to send the command. And I can't think that it does that at the same time as it sends the command again to my relay?
    Or is it the controller that timeout to fast even though the gateway haven't reported the right status?


  • Contest Winner

    @raptorjr Try changing the delay in your loop to a wait statement.

     wait(SLEEP_TIME); // delay(SLEEP_TIME);
    

    When you use a delay the Arduino completely delays your sketch meaning no incomming events can be processed. When you use a MySensors wait. The Arduino doesn't delay your sketch and will be able to handle incomming messages.



  • @TheoL

    Thank you. That works perfect.


  • Contest Winner

    @raptorjr Glad that I could help you.



  • Hello @TheoL I am having the same problem with a slightly similar sketch. the delay didn't have much impart. One second its working fine and the next its breaking into errors. I couldn't find a .1uf Capacitor, so I used electrolytic 1uf instead. Worked fine in the Sprinkler Project, but I don't know if that's the problem here. My sketch is a follows:-

    // Example sketch showing how to control physical relays. 
    // This example will remember relay state even after power failure.
    
    // Enable debug prints
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    
    #define MY_NODE_ID 6  // Set this to fix your Radio ID or use AUTO or 1
    #define MY_REGISTRATION_FEATURE // Forece registration
    #define MY_REGISTRATION_RETRIES 5
    
    #include <Wire.h>
    #include <TimeLib.h>
    #include <SPI.h>
    #include <MySensors.h>
    #include <LCD.h>
    #include <LiquidCrystal.h>
    #include <LiquidCrystal_I2C.h>
    
    // For Debug
    #ifdef DEBUG_ON
    #define DEBUG_PRINT(x)   Serial.print(x)
    #define DEBUG_PRINTLN(x) Serial.println(x)
    #else
    #define DEBUG_PRINT(x)
    #define DEBUG_PRINTLN(x)
    #define SERIAL_START(x)
    #endif
    
    #define RELAY_PIN 2  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 4 // Total number of attached relays
    #define RELAY_ON 0  // GPIO value to write to turn on attached relay
    #define RELAY_OFF 1 // GPIO value to write to turn off attached relay
    #define SKETCH_NAME "Swimming Pool Node"
    #define SKETCH_VERSION "0.1.4"
    #define CHILD_ID 0
    
    MyMessage msg(1,V_LIGHT);
    unsigned long SLEEP_TIME = 5000;   // Sleep time inbetween reads in milliseconds
    void setup()
    {
      for (int sensor=1, pin=RELAY_PIN; 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, loadState(sensor)?RELAY_ON:RELAY_OFF);   // to remember last state
        digitalWrite(pin, loadState? 0 : 0);   // Keep everything off after power failure
      }
    }
    
    void presentation() { 
      sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
    
      // Fetch relay status
      for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
        // Register all sensors to gw (they will be created as child devices)
        present(sensor, S_BINARY);
        pinMode(pin, OUTPUT); // Then set relay pins in output mode  
    //    boolean savedState = loadState(sensor); // Set relay to last known state (using eeprom storage)
    //    digitalWrite(pin, savedState?RELAY_ON:RELAY_OFF);
    //    send(msg.set(savedState? 0 : 1));
      }
          DEBUG_PRINTLN(F("Sensor Presentation Complete"));
    }
    void loop() 
    {
    // Alway process incoming messages whenever possible
    // Sleep until interrupt comes in on motion sensor. Send update every two minute.
    //  sleep(digitalPinToInterrupt(msg.sensor-1+RELAY_PIN), CHANGE, SLEEP_TIME);
    wait(SLEEP_TIME);
    }
    void receive(const MyMessage &message){
    // Change relay state if message is receieved
    
       if (message.type == V_STATUS){
       digitalWrite(message.sensor-1+RELAY_PIN, message.getBool()?RELAY_ON:RELAY_OFF);
    // Store state in eeprom
       saveState(message.sensor-1+RELAY_PIN, message.getBool());
    // Write some debug info
       Serial.print("Incoming change for sensor ID: ");
       Serial.print(message.sensor);
       Serial.print(", New status: ");
       Serial.println(message.getBool());
        } 
      }
    

Log in to reply
 

Suggested Topics

25
Online

11.2k
Users

11.1k
Topics

112.5k
Posts