Issue with interrupt

Hi all,

I am busy with a controller for my Philips Hue lights. I would like to place the Photon behind my wall switch to adjust brightness, switch off with timedelay and switch to default state. It is all working now, but some strange behaviour on the interrupt.

What I do is when i want to increase brightness, first check if the light is on, if not, swtich it on first.

When I attach the interupt to pin D1 with rising edge to a function where the getHue function is called. The Photon does not react anymore. The software seems to hang…

If I set a flag in the interrupt function, and in my main check if the flag is set, if so, call the function getHue(), and in this function, clear the flag. The getHue is called manytimes. I expect the function is called only during rising edge.

Below my code as it is right now, getHue is also called when no rising edge is detected.

    TCPClient client;

    const char hueHubIP[] = "192.168.1.100";  // Hue hub IP 
    const char hueUsername[] = "newdeveloper";  // Hue username 
    const int hueHubPort = 80; 

    /*PROTOTYPES*/
    void checkStatus(void);
    bool statusFlag = false;


    //  Hue variables  
    bool hueOn = false;  // on/off 
    int hueBri;  // brightness value 
    long hueHue;  // hue value 

    unsigned long buffer=0;  //buffer for received data storage 
    unsigned long addr; 

    int incPin = D1;
    int decPin = D0;
    int bt1Pin = D2;
    int bt2Pin = D3;
 
    unsigned int incState;
    unsigned int decState; 
    unsigned int bt1State;
    unsigned int bt2State;

    /* Structure to store the status of the hue lights*/
    struct hue_t {
	  bool On;
	  int Bri;
	  int Sat;
	  int Hue;
    } hue;


    void setup(){
       pinMode(incPin, INPUT_PULLDOWN);
      attachInterrupt(D1, getHueStatus, RISING);
      pinMode(decPin, INPUT_PULLDOWN);
      pinMode(bt1Pin, INPUT_PULLDOWN);
      pinMode(bt2Pin, INPUT_PULLDOWN);

      Serial.begin(9600);
      delay(100);
  
     Serial.print("Setup Done");
    }

    void getHueStatus(void){
        statusFlag = true;
    }

    void loop(){
    
    incState = digitalRead(incPin);
    decState = digitalRead(decPin);
    bt1State = digitalRead(bt1Pin);
    bt2State = digitalRead(bt2Pin);

    /*If the flag is set on rising edge, get Hue status*/
    if (statusFlag == true){
        getHue(1);
    }
    
    if ((incState == HIGH) && hueOn){
        delay(300); //Add delay 
        Serial.println("Increase with 25");
        String jsonData = "{\"bri_inc\": 25}";
        sendJSON(jsonData);
    }
    else if ((incState == HIGH) && !hueOn){
        //getHue(1);
        Serial.println("Light was off, switch it on!");
        String jsonData = "{\"on\": true}";
        sendJSON(jsonData);
    }
    else if (decState == HIGH){
        delay(300);
        Serial.println("Assume the lights are on, decrease brightness!");
        String jsonData = "{\"bri_inc\": -25}";
        sendJSON(jsonData);
    }
    else if (bt1State == HIGH){
        /*Switch ON the lights*/
        Serial.println("set to default scene");
        //String jsonData = "{\"scene\": Relax}";
        String jsonData = "{\"bri\": 229, \"sat\": 213, \"hue\": 13088}";
        sendJSON(jsonData);
    }
    else if (bt2State == HIGH){
        /*Call script that turn the lights off in 2 minutes*/
        getHue(1);
        if (hueOn == true){
            Serial.println("switch off with transition time of 2 minutes");
            String jsonData = "{\"on\": false, \"transitiontime\": 1200 }";
            sendJSON(jsonData);
            delay(500);
            }
        }
    }    

    /*
    * @brief; this function is called to get the light status
    * if we want to inc or dec the brightness, first we have to get the current brightness
    */

    boolean getHue(int lightNum){
      if (client.connect(hueHubIP, hueHubPort)){
        Serial.println("getHue Function");  
        client.print("GET /api/");
        client.print(hueUsername);
        client.print("/lights/");
        client.print(lightNum);  
        client.println(" HTTP/1.1");
        client.print("Host: ");
        client.println(hueHubIP);
        client.println("Content-type: application/json");
        client.println("keep-alive");
        client.println();
        while (client.connected()){
          if (client.available()){
            client.findUntil("\"on\":", "\0");
            hueOn = (client.readStringUntil(',') == "true");  // if light is on, set variable to true
 
            client.findUntil("\"bri\":", "\0");
            hueBri = client.readStringUntil(',').toInt();  // set variable to brightness value
 
            client.findUntil("\"hue\":", "\0");
            hueHue = client.readStringUntil(',').toInt();  // set variable to hue value
        
            Serial.println(hueOn);
            Serial.println(hueBri);
            Serial.println(hueHue);
        
            break;  // not capturing other light attributes yet
            statusFlag == false;
          }
        }
        client.stop();
        return true;  // captured on,bri,hue
      }
      else
        return false;  // error reading on,bri,hue
    }
 
      /* setHue() is our main command function, which needs to be passed a light number and a 
     * properly formatted command string in JSON format (basically a Javascript style array of variables
     * and values. It then makes a simple HTTP PUT request to the Bridge at the IP specified at thestart.
     */
     void sendJSON(String jsonData) {
        if (client.connect(hueHubIP, hueHubPort)) {
            if(client.connected()) {
                Serial.println("Connected");
                unsigned int jsonLen = jsonData.length(); //get length of JSON data
                client.println("PUT /api/newdeveloper/groups/1/action");
                //client.println("PUT /api/newdeveloper/lights/1/state");
               // client.print(hueUsername);
               client.println("Connection: keep-alive"); //
               client.println("Host: "); // 192.168.1.100"); //same as server 
               client.println(hueHubIP);
               client.println("Content-Type: text/plain;charset=UTF-8"); //
               client.print("Content-Length: "); //param 
               client.println(jsonLen); //brightness string + val length;
               client.println();  // blank line before body
               client.print(jsonData);
               delay(100); // slight delay IMPORTANT
           }
           client.stop();
       }  
   }

You need to declare your flag volatile bool statusFlag = false;
And I guess you should reset your flag after you’ve processed it (not only if your function succeedes).
This won’t help too

    if (...) {
      ...
      break;  // not capturing other light attributes yet
      statusFlag == false;
    }

Also what happens when you call getHue(1) without the interrupt attached?

How long does your code spend inside

  while(client.connected()) {
    ...
  }

Try adding a Serial.print() or LED blink to check.

1 Like

Hi ScruffR,

Thank you for your helpfull answer. This works better.
Now, I clear the flag after calling getHue();

if (statusFlag == true){
    getHue(1);
    statusFlag = false;
}

When I call getHue without the interrupt works also, but I want to call the function only on the rising edge of the brightness increment button.

it spend a long time in the function:

while(client.connected()) {
    ...
  }

I think about 600ms - 1s.

I will check it.

I noticed Serial.println("Host: "); where you meant just print()

You probably just need to debounce the button inputs. Otherwise you can get several rising edge interrupts from a press as well as a release.