Interrupt conflict newremoteswitch and MySensors receive() function?



  • Hi all,

    I'm trying to make a node that functions as a dimmer for a LED strip as well as a RF receiver for nearby KlikAanKlikUit RF switches.
    Pressing a KaKu RF switch sets a MySensors switch to let the controller know the switch was flipped and execute some stuff in Domoticz.

    I've managed to combine everything codewise, but when I run the sketch it works initially but seizes up after a while.
    I'm pretty sure it has to do with the receiver() function and interrupts somehow, but I'm not experienced enough in C or the MySensors framework to fix this.
    Can one of you have a look at my code and help me fix the problem? (With interruptchain perhaps???)

    Here's the code:

    // Enable debug prints to serial monitor
    
    #include <NewRemoteReceiver.h>
    
    #define MY_DEBUG
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    #define MY_REPEATER_FEATURE
    
    #include <MySensors.h>
    #include <Bounce2.h>
    
    #define SN "DimmableLED"
    #define SV "1.1"
    
    #define PRIMARY_CHILD_ID 1
    #define SECONDARY_CHILD_ID 2
    
    #define LED_PIN 3      // Arduino pin attached to MOSFET Gate pin
    #define FADE_DELAY 10  // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
    
    static int16_t currentLevel = 0;  // Current dim level...
    static int16_t currentButtonState = 0;  // Current state for button 1
    static int16_t currentButton2State = 0;  // Current state for button 2
    int lastLevel;
    
    MyMessage dimmerMsg(0, V_DIMMER);
    MyMessage lightMsg(0, V_LIGHT);
    MyMessage buttonMsg(PRIMARY_CHILD_ID, V_LIGHT);
    MyMessage buttonMsg2(SECONDARY_CHILD_ID, V_LIGHT);
    
    /***
     * Dimmable LED initialization method
     */
    void setup()
    {
        // Pull the gateway's current dim level - restore light level upon sendor node power-up
        request( 0, V_DIMMER );
    
    	// Setup the RF receiver
    	NewRemoteReceiver::init(0, 2, showCode);
    }
    
    void presentation()
    {
        // Register the LED Dimmable Light with the gateway
        present( 0, S_DIMMER );
    	
    	// Register binary input sensor to sensor_node (they will be created as child devices)
    	// You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. 
    	// If S_LIGHT is used, remember to update variable type you send in. See "msg" above.
    	present(PRIMARY_CHILD_ID, S_LIGHT);
    	present(SECONDARY_CHILD_ID, S_LIGHT);
    
        sendSketchInfo(SN, SV);
    }
    
    /***
     *  Dimmable LED main processing loop
     */
    void loop()
    {
    
    }
    
    void receive(const MyMessage &message)
    {
        if ((message.type == V_LIGHT || message.type == V_DIMMER) && message.sensor == 0) {
    
            //  Retrieve the power or dim level from the incoming request message
            int requestedLevel = atoi( message.data );
    
            // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
            //requestedLevel *= ( message.type == V_LIGHT ? 100 : 1 );
    		// Als we van OFF naar ON gaan, dan laatst bekende niveau toepassen
    		requestedLevel *= (message.type == V_LIGHT ? lastLevel : 1);
    
            // Clip incoming level to valid range of 0 to 100
            requestedLevel = requestedLevel > 100 ? 100 : requestedLevel;
            requestedLevel = requestedLevel < 0   ? 0   : requestedLevel;
    
            Serial.print( "Changing level to " );
            Serial.print( requestedLevel );
            Serial.print( ", from " );
            Serial.println( currentLevel );
    
            fadeToLevel( requestedLevel );
    
            // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value...
            send(lightMsg.set(currentLevel > 0));
    
            // hek comment: Is this really nessesary?
            send( dimmerMsg.set(currentLevel) );
    		if (currentLevel != 0)
    		{
    			lastLevel = currentLevel;
    		}
    	}
    }
    
    /***
     *  This method provides a graceful fade up/down effect
     */
    void fadeToLevel( int toLevel )
    {
        int delta = ( toLevel - currentLevel ) < 0 ? -1 : 1;
    
        while ( currentLevel != toLevel ) {
            currentLevel += delta;
            analogWrite( LED_PIN, (int)(currentLevel / 100. * 255) );
            delay( FADE_DELAY );
        }
    }
    
    // Callback function is called only when a valid code is received.
    void showCode(NewRemoteCode receivedCode) {
    	// Note: interrupts are disabled. You can re-enable them if needed.
    
    	// Print the received code.
    	//Serial.print("Addr ");
    	//Serial.print(receivedCode.address);
    
    	//if (receivedCode.groupBit) {
    	//	Serial.print(" group");
    	//}
    	//else {
    	//	Serial.print(" unit ");
    	//	Serial.print(receivedCode.unit);
    	//}
    
    	//switch (receivedCode.switchType) {
    	//case NewRemoteCode::off:
    	//	Serial.print(" off");
    	//	break;
    	//case NewRemoteCode::on:
    	//	Serial.print(" on");
    	//	break;
    	//case NewRemoteCode::dim:
    	//	Serial.print(" dim");
    	//	break;
    	//}
    
    	//if (receivedCode.dimLevelPresent) {
    	//	Serial.print(", dim level: ");
    	//	Serial.print(receivedCode.dimLevel);
    	//}
    
    	//Serial.print(", period: ");
    	//Serial.print(receivedCode.period);
    	//Serial.println("us.");
    
    	String str(receivedCode.switchType);
    
    	if (receivedCode.unit == 10 && str == "1")
    	{
    		Serial.println("Send nr 1 ON");
    		send(buttonMsg.set(1));
    		Serial.println("Send nr 1 ON done");
    	}
    
    	if (receivedCode.unit == 10 && str == "0")
    	{
    		Serial.println("send nr 1 OFF");
    		send(buttonMsg.set(0));
    		Serial.println("send nr 1 OFF done");
    	}
    
    	if (receivedCode.unit == 11 && str == "1")
    	{
    		Serial.println("Send nr 2 ON");
    		send(buttonMsg2.set(1));
    		Serial.println("Send nr 2 ON done");
    	}
    
    	if (receivedCode.unit == 11 && str == "0")
    	{
    		Serial.println("Send nr 2 OFF");
    		send(buttonMsg2.set(0));
    		Serial.println("Send nr 2 OFF done");
    	}
    
    }
    

  • Admin

    In your code only NewRemoteReceiver will use interrupts. MySenosrs won't.

    Scanning the code, I would blame the use of the String-class. Not recommended.



  • Hi Hek,

    Thank you for the feedback! I'll get rid of the String class and have another go.



  • I also use newremoteswitch for KlikaanKlikuit on a MySensors node and it works great... So your problem is probably indeed something else.



  • @Alexander, does your node use the receive() function to receive commands from controller?



  • I don't think so.... but why should you or I? I get a switch command from the controller (Domoticz in my case) which is 'translated' to a newremoteswitch command to the 433 mhz transmitter. (Please feel free to let it go if I lack knowledge here and it is not helpfull for your problem 🙂 )



  • Ok sorry, I see the difference. I still use version 1.5.4


 

337
Online

8.0k
Users

8.8k
Topics

94.4k
Posts