InfiniteLoop when trying to create a bilateral relationship

Moderators: adafruit_support_bill, adafruit

Forum rules
If you're posting code, please make sure your code does not include your Adafruit IO Active Key or WiFi network credentials.
Locked
User avatar
BrookeDot
 
Posts: 33
Joined: Sat Sep 05, 2015 12:34 pm

InfiniteLoop when trying to create a bilateral relationship

Post by BrookeDot »

Hi,

I am trying to create an LED control based on the basic example. This is my first Adafruit.IO project and I was pleased with how easily everything came together. I was able to modify the code for my microcontroller and LED Strip. (I don't think it's relevant but using an AnaviTechnology LED Controller that uses the ESP8266).

The basic sketch is working great, and so I decided to add brightness and power controls as well. I got those working fairly quickly, but now I'm trying to get "fancy" and have the UX respond nicely to user input. For example:

- If the switch of "off" then brightness should be "0"
- if brightness is above 0 then "on-off" should be "on"

The code below creates an infinite loop which got my user temporarily banned (oops, did I mention I'm new here?)

I know it has to do with setting the state of both each time, I likely need to add a flag to control that, but wanted to ask for input before trying anything else since I want to be respectful of the API limits and ensure that my bad programming isn't gonna get me in any more trouble.

Code: Select all

// Adafruit IO RGB LED Output Example
// Tutorial Link: https://learn.adafruit.com/adafruit-io-basics-color
//
// Adafruit invests time and resources providing this open source code.
// Please support Adafruit and open source hardware by purchasing
// products from Adafruit!
//
// Written by Todd Treece for Adafruit Industries
// Copyright (c) 2016-2017 Adafruit Industries
// Licensed under the MIT license.
//
// All text above must be included in any redistribution.

/************************** Configuration ***********************************/

// edit the config.h tab and enter your Adafruit IO credentials
// and any additional configuration needed for WiFi, cellular,
// or ethernet clients.
#include "config.h"

/************************ Example Starts Here *******************************/

// default PWM pins for ESP8266.
// you should change these to match PWM pins on other platforms.
#define RED_PIN   12
#define GREEN_PIN 13
#define BLUE_PIN  14

// set up the 'color' feed
AdafruitIO_Feed *color = io.feed("color");

// set up the 'on-off' feed
AdafruitIO_Feed *onOff = io.feed("on-off");

// set up the 'brightness' feed
AdafruitIO_Feed *brightness = io.feed("brightness");

uint8_t  lastRed   = 0;
uint8_t  lastGreen = 0;
uint8_t  lastBlue  = 0;

uint8_t  lastBrightness = 255;

void setup() {

  // start the serial connection
  Serial.begin(115200);

  // wait for serial monitor to open
  while(! Serial);
    pinMode(RED_PIN, OUTPUT);
    pinMode(GREEN_PIN, OUTPUT);
    pinMode(BLUE_PIN, OUTPUT);

  // connect to io.adafruit.com
  Serial.print("Connecting to Adafruit IO");
  io.connect();

  // set up a message handler for the 'color' feed.
  // the handleColor function (defined below)
  color->onMessage(handleColor);

  // set up a message handler for the 'on-off' feed.
  // the handleOnOff function (defined below)
  onOff->onMessage(handleOnOff);

// set up a message handler for the 'brightness' feed.
// the handleOnOff function (defined below)
  brightness->onMessage(handleBrightness);


  // wait for a connection
  while(io.status() < AIO_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  // we are connected
  Serial.println();
  Serial.println(io.statusText());
  color->get();

  // set analogWrite range for ESP8266
    analogWriteRange(255);

}

void loop() {

  // io.run(); is required for all sketches.
  // it should always be present at the top of your loop
  // function. it keeps the client connected to
  // io.adafruit.com, and processes any incoming data.
  io.run();

}

// this function is called whenever a 'brightness' message
// is received from Adafruit IO. it was attached to
// the brightness feed in the setup() function above.
void handleBrightness(AdafruitIO_Data *data) {

  float brightnessVaule = data->toFloat();
  float brightnessPercent = brightnessVaule * 0.01;

  // print RGB values and hex value
  Serial.println("Brightness Happening:");

//Don't do anything with brightness if the light is off
  if( brightnessVaule == 0.0 ) {
    if ( onOff->get() != 0){
      onOff->save(0);
    }
  }
  else{
      if (onOff->get() != 1) {
        onOff->save(1);
      }
    Serial.print("brightness: ");
    Serial.print(brightnessPercent);
    Serial.println("%");
    analogWrite(RED_PIN,  float( lastRed * brightnessPercent ));
    analogWrite(GREEN_PIN,float(lastGreen * brightnessPercent));
    analogWrite(BLUE_PIN, float(lastBlue * brightnessPercent ));
    lastBrightness = brightnessVaule;
  }
}


// this function is called whenever a 'on-off' message
// is received from Adafruit IO. it was attached to
// the on-off feed in the setup() function above.
void handleOnOff(AdafruitIO_Data *data) {

  // print RGB values and hex value
  Serial.println("Power button clicked:");

//turn light off if zero
  if( data->isFalse() ) {
    Serial.println("Turning Lights Off:");
    analogWrite(RED_PIN, 0);
    analogWrite(GREEN_PIN, 0);
    analogWrite(BLUE_PIN, 0);
    if( brightness->get() != 0 ){
      brightness->save(0);
    }
  }
  else{
    Serial.println("Turning Lights On to last color state:");
    float brightnessPercent = lastBrightness * 0.01;
    analogWrite(RED_PIN,  float( lastRed * brightnessPercent ));
    analogWrite(GREEN_PIN,float(lastGreen * brightnessPercent));
    analogWrite(BLUE_PIN, float(lastBlue * brightnessPercent ));
    if( brightness->get() !=lastBrightness ){
      brightness->save(lastBrightness);
    }
  }
}


// this function is called whenever a 'color' message
// is received from Adafruit IO. it was attached to
// the color feed in the setup() function above.
void handleColor(AdafruitIO_Data *data) {

  lastRed   = data->toRed();
  lastGreen = data->toGreen();
  lastBlue  = data->toBlue();

  float brightnessPercent = lastBrightness * 0.01;
  analogWrite(RED_PIN, float(data->toRed() * brightnessPercent));
  analogWrite(GREEN_PIN,float(data->toGreen() * brightnessPercent));
  analogWrite(BLUE_PIN, float(data->toBlue() * brightnessPercent));
  
}

User avatar
brubell
Learn User Page
 
Posts: 2010
Joined: Fri Jul 17, 2015 10:33 pm

Re: InfiniteLoop when trying to create a bilateral relationship

Post by brubell »

- If the switch of "off" then brightness should be "0"
- if brightness is above 0 then "on-off" should be "on"

The code below creates an infinite loop
Some pointers for this project...

1) Since MQTT callbacks are asynchronous, I'd remove code within the two callbacks (`handle...()`) that write to opposite feeds. The brightness callback function should only write to the brightness feed, same with on-off. You may want to only have a brightness slider and feed, instead of the switch.
2) Additionally, if you have a switch block on a dashboard, you may also connect to the brightness feed. From the switch block's settings, you can set the "on value" as 1 and "off value" as 0. It should work the same as it does in your code above, except only using one feed instead of 2

User avatar
BrookeDot
 
Posts: 33
Joined: Sat Sep 05, 2015 12:34 pm

Re: InfiniteLoop when trying to create a bilateral relationship

Post by BrookeDot »

Thanks for your input:
1) Since MQTT callbacks are asynchronous, I'd remove code within the two callbacks (`handle...()`) that write to opposite feeds. The brightness callback function should only write to the brightness feed, same with on-off. You may want to only have a brightness slider and feed, instead of the switch.
We're on the same page with this! The problems all started when I added the "fancy" code so removing it make sense.
2) Additionally, if you have a switch block on a dashboard, you may also connect to the brightness feed. From the switch block's settings, you can set the "on value" as 1 and "off value" as 0. It should work the same as it does in your code above, except only using one feed instead of 2
I think that will work but it will set the brightness to "1" (not very bright) when the switch is first turned on. I could maybe do something like set the brightness feed from 2-100 and if it's 1 set it to the last value? but that won't work because the goal is to have it be for "off".

Any thoughts on how to to get around that to set the brightness to the last known brightness when the switch is first clicked on? could let it never get to 1 or something.

User avatar
BrookeDot
 
Posts: 33
Joined: Sat Sep 05, 2015 12:34 pm

Re: InfiniteLoop when trying to create a bilateral relationship

Post by BrookeDot »

I just realized I can set the "on" value for the switch to "100" and "off" value to "0" which should be a good work around! ya!

User avatar
BrookeDot
 
Posts: 33
Joined: Sat Sep 05, 2015 12:34 pm

Re: InfiniteLoop when trying to create a bilateral relationship

Post by BrookeDot »

That ALMOST works but the switch is only on when the brightness is exactly the "on value" of 85:
photo_2023-02-16_05-12-46.jpg
photo_2023-02-16_05-12-46.jpg (23.7 KiB) Viewed 167 times
Is there a way to set it to `>=1`?

User avatar
brubell
Learn User Page
 
Posts: 2010
Joined: Fri Jul 17, 2015 10:33 pm

Re: InfiniteLoop when trying to create a bilateral relationship

Post by brubell »

You could try using an Adafruit IO Action

User avatar
BrookeDot
 
Posts: 33
Joined: Sat Sep 05, 2015 12:34 pm

Re: InfiniteLoop when trying to create a bilateral relationship

Post by BrookeDot »

You could try using an Adafruit IO Action
Success! I added a feed back for the On/Off Switch and then setup an action where if the value of Brightness was greater or equal to 1, then set the switch to "on".

Then in my Arduino Code I added back on On-Off function.

I also added Arduino OTA updates and things are working great! Thanks for your help.

User avatar
brubell
Learn User Page
 
Posts: 2010
Joined: Fri Jul 17, 2015 10:33 pm

Re: InfiniteLoop when trying to create a bilateral relationship

Post by brubell »

Great to hear!

Locked
Forum rules
If you're posting code, please make sure your code does not include your Adafruit IO Active Key or WiFi network credentials.

Return to “Internet of Things: Adafruit IO and Wippersnapper”