sui77 / rc-switch

Arduino lib to operate 433/315Mhz devices like power outlet sockets.
1.94k stars 662 forks source link

NodeMCU ESP8266-12E Constantly transmitting when Protocol 6 is used #102

Open nordicblue opened 7 years ago

nordicblue commented 7 years ago

Hi guys. Hopefully someone could help me with a little issue I am experiencing. I have been scratching my head for hours and just not getting anywhere:(

I have built a NodeMCU to transmit 315Mhz on/off signals to a fan and a light via MQTT. The issue that I run into is that, as soon as I transmit on Protocol 6, the NodeMCU's light turns off and the transmitter starts broadcasting constantly. No errors are seen in the serial connection. This constant broadcast is then blocking other communications in my house, in the 315Mhz range, which I cannot have:)

This issue seems to only happen when Protocol 6 is used, as if I use the default protocol or even protocol 5, the issue does not happen.

I have another NodeMCU, configured in the 433 Mhz range, and that one works flawlessly on Protocol 1.

Are there any known issues with the NodeMCU ESP8266-12E and protocol 6 that I cannot find?

For reference, the code I use is below. Commenting out the "mySwitch.setProtocol(6);" corrects the issue of the constant transmission, but then I cannot control my fan or light any longer, as the default protocol does not work. The code also does continue to work, as in, even though it is constantly broadcasting, if I send it a MQTT message to turn the light on or off, it still sends the right signal and the light turns on or off.

So, I just need to find out what is causing the system to continue to broadcast after the signal is sent to it and it fires off the mySwitch.send.

#include <MQTTClient.h>
#include <ESP8266WiFi.h>
#include <RCSwitch.h>

const char* ssid = "SSIDHERE";
const char* wifiPassword = "WIFIPSWDHERE"; 

const char* subscribeTopic = "my/topic/#"; // subscribe to this topic; anything sent here will be passed into the messageReceived function
const char* server = "###.###.###.####"; // server or URL of MQTT broker
String clientName = "MyNodeMCU"; // just a name used to talk to MQTT broker - doesn't actually matter. 

unsigned long resetPeriod = 86400000; // 1 day - this is the period after which we restart the CPU, to deal with odd memory leak errors

WiFiClient wifiClient;
MQTTClient client;
#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup() {

  // Transmitter is connected to NodeMCU GPIO 2 / D4  
  mySwitch.enableTransmit(2);
  mySwitch.setPulseLength(605);
  mySwitch.setProtocol(6);

  Serial.begin(115200);

  client.begin(server,wifiClient);
  Serial.print("Connecting to ");
  Serial.println(ssid);  
  WiFi.mode(WIFI_STA); //disables the built-in "doitwifi" being broadcast. 
  WiFi.begin(ssid, wifiPassword);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  Serial.print("Connecting to ");
  Serial.print(server);
  Serial.print(" as ");
  Serial.println(clientName);

  if (client.connect((char*) clientName.c_str())) {
    Serial.println("Connected to MQTT broker");
    Serial.print("Subscribed to: ");
    Serial.println(subscribeTopic);
    client.subscribe(subscribeTopic);

  }
  else {
    Serial.println("MQTT connect failed");
    Serial.println("Will reset and try again...");
    abort();
  }

}

void loop() {

  client.loop();

  // reset after a day to avoid memory leaks 
  if(millis()>resetPeriod){
    ESP.restart();
  }
}

/* This is where the magic happens, and you'll need to modify this to support custom items. At the moment, it listens
 *   to (first bit derived from channel name set at start):
 *   livingroom/control/switch/x/y (with payload value of on or off)
 *   and
 *   livingroom/control/screen (with payload value of up or down)
 *   You should be able to modify below to easily add more commands if needed
 */

void messageReceived(String topic, String payload, char * bytes, unsigned int length) {
  Serial.print("incoming: ");
  Serial.print(topic);
  Serial.print(" - ");
  Serial.print(payload);
  Serial.println();

  if (topic.indexOf("fan") >=0){
    //switch control, parse out the channel and plug id 

    int invId = getValue(topic,'/',3).toInt();

    if (invId == 1){ 
      if(payload == "low"){
        mySwitch.send(#######,24);
        Serial.print("fan low");
        Serial.println();
        }
      else{
        mySwitch.send(7939606,24);
        Serial.print("fan off");
        Serial.println();
        }
      }
    }
  else if (topic.indexOf("light") >=0){
    //switch control, parse out the channel and plug id 

    int locId = getValue(topic,'/',3).toInt();

    if (locId == 1){ 
      if(payload == "on"){
        mySwitch.send(#######,24);
        Serial.print("fan light on");
        Serial.println();
        }
      else{
        mySwitch.send(#######,24);
        Serial.print("fan light off");
        Serial.println();
        }
      }
    }
}

// getValue function taken from http://arduino.stackexchange.com/questions/1013/how-do-i-split-an-incoming-string/1237
String getValue(String data, char separator, int index)
{
 int found = 0;
  int strIndex[] = {
0, -1  };
  int maxIndex = data.length()-1;
  for(int i=0; i<=maxIndex && found<=index; i++){
  if(data.charAt(i)==separator || i==maxIndex){
  found++;
  strIndex[0] = strIndex[1]+1;
  strIndex[1] = (i == maxIndex) ? i+1 : i;
  }
 }
  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
nordicblue commented 7 years ago

Add on to this. I setup another node to receive signals and the issue is not with the 315Mhz transmitting, as the only things I receive are the on and off signals I am sending. So, this issue may have something to do with the WiFi maybe? The blue light does turn off, but it is still connected to WiFi and will receive MQTT requests...

I was going to just do a restart of the ESP, but that doesn't clear the issue either. Only way to clear is to do a hard disconnect and reboot.

fingolfin commented 7 years ago

So which protocols did you try? the default (1), 5 and 6 -- what about 2,3,4?

A wild guess might be that you are running into some kind of timeout for message handlers (I am blindly guessing here) -- the sync duration of protocol 6 is much longer than that of 1 and 5. If that's the case, the protocol 3 should also break, because it has an even longer sync.

nordicblue commented 7 years ago

The way I fixed it was a hack for sure, but it works for now. I ended up moving the length and the protocol right above the send. Then, below the send, I would call the length and protocol again, this time with protocol 1, and then doing another send with a zero byte payload. This resets the unit and it starts behaving normally again.

I know it's a hack, but I couldn't come up with any other way to get it to stop whatever broadcast it was doing after sending a protocol 6 message.

6 is the only one that works with my fan, so I couldn't use the others