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"); } }
-
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