Create an IF loop

Hi

Excuse my newbie-ness. I’m learning slowly, but mainly just copy and paste code from other sources, and tweak as needed. :slight_smile:

I’m creating a Google Home voice controlled ESP8266 LED strip using the following void loop:

void loop()
{
  MQTT_connect();
  
  //Read from our subscription queue until we run out, or
  //wait up to 5 seconds for subscription to update
  Adafruit_MQTT_Subscribe * subscription;
  while ((subscription = mqtt.readSubscription(5000)))
  {
    //If we're in here, a subscription updated...
    if (subscription == &onoff)
    {
      //Print the new value to the serial monitor
      Serial.print("onoff: ");
      Serial.println((char*) onoff.lastread);
      
      //If the new value is  "ON", turn the light on.
      //Otherwise, turn it off.
      if (!strcmp((char*) onoff.lastread, "ON"))
      {
        for(int i=0;i<NUMPIXELS;i++)
        {
          rainbow(20); 
        }
      }
      else
      {
        for(int i=0;i<NUMPIXELS;i++)
        {
          pixels.setPixelColor(i, pixels.Color(0,0,0));
          pixels.show();
          delay(delayval);
        }
      }
    }
  }

  // ping the server to keep the mqtt connection alive
  if (!mqtt.ping())
  {
    mqtt.disconnect();
  }
}

As it stands, when I say “Lights On” the IF is triggered and the rainbow pattern repeats 20 times then stops on a static colour. How can I get it to repeat the rainbow in the IF command until the ELSE is triggered?

Thanks

D

Something is changing onoff.lastread such that !strcmp((char*) onoff.lastread, "ON") is no longer true. But I don't know that that is because that section of the program was not posted.

I've only posted the void loop, as that is where I need help. The whole sketch works as it should with the voice control, I just wanted to know a way of making the IF/ELSE section loop. As I understand it, an IF statement only runs once.

dazwell: I've only posted the void loop, as that is where I need help.

Perhaps the problem is another part of the program where you have not been looking for it?

In any case, it is much easier for someone to get a full understanding of a program when you post a complete program. We don't charge per line of code posted.

...R

Okay, here’s the full code…

#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

#include <Adafruit_NeoPixel.h>

#ifdef __AVR__
  #include <avr/power.h>
#endif


#define WIFI_SSID "xxxxxxxx"
#define WIFI_PASS "xxxxxxxx"

#define MQTT_SERV "io.adafruit.com"
#define MQTT_PORT 1883
#define MQTT_NAME "xxxxxxxx"
#define MQTT_PASS "xxxxxxxxx"

#define PIN D4
#define NUMPIXELS 12

//Set up MQTT and WiFi clients
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, MQTT_SERV, MQTT_PORT, MQTT_NAME, MQTT_PASS);

//Set up the feed you're subscribing to
Adafruit_MQTT_Subscribe onoff = Adafruit_MQTT_Subscribe(&mqtt, MQTT_NAME "/f/onoff");

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval = 5; // delay for half a second

void setup()
{

  pixels.begin(); // This initializes the NeoPixel library.
  pixels.show(); // Initialize all pixels to 'off'
  
  Serial.begin(9600);

  //Connect to WiFi
  Serial.print("\n\nConnecting Wifi... ");
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
  }

  Serial.println("OK!");

  //Subscribe to the onoff feed
  mqtt.subscribe(&onoff);
  
  

}

void loop()
{
  MQTT_connect();
  
  //Read from our subscription queue until we run out, or
  //wait up to 5 seconds for subscription to update
  Adafruit_MQTT_Subscribe * subscription;
  while ((subscription = mqtt.readSubscription(5000)))
  {
    //If we're in here, a subscription updated...
    if (subscription == &onoff)
    {
      //Print the new value to the serial monitor
      Serial.print("onoff: ");
      Serial.println((char*) onoff.lastread);
      
      //If the new value is  "ON", turn the light on.
      //Otherwise, turn it off.
      if (!strcmp((char*) onoff.lastread, "ON"))
      {
        for(int i=0;i<NUMPIXELS;i++)
        {
          rainbow(20); 
        }
      }
      else
      {
        for(int i=0;i<NUMPIXELS;i++)
        {
          pixels.setPixelColor(i, pixels.Color(0,0,0));
          pixels.show();
          delay(delayval);
        }
      }
    }
  }

  // ping the server to keep the mqtt connection alive
  if (!mqtt.ping())
  {
    mqtt.disconnect();
  }
}


/***************************************************
  Adafruit MQTT Library ESP8266 Example

  Must use ESP8266 Arduino from:
    https://github.com/esp8266/Arduino

  Works great with Adafruit's Huzzah ESP board & Feather
  ----> https://www.adafruit.com/product/2471
  ----> https://www.adafruit.com/products/2821

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Tony DiCola for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/

void MQTT_connect() 
{
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected()) 
  {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) // connect will return 0 for connected
  { 
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
       retries--;
       if (retries == 0) 
       {
         // basically die and wait for WDT to reset me
         while (1);
       }
  }
  Serial.println("MQTT Connected!");
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<pixels.numPixels(); i++) {
    pixels.setPixelColor(i, c);
    pixels.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<pixels.numPixels(); i++) {
      pixels.setPixelColor(i, Wheel((i+j) & 255));
    }
    pixels.show();
    delay(wait);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< pixels.numPixels(); i++) {
      pixels.setPixelColor(i, Wheel(((i * 256 / pixels.numPixels()) + j) & 255));
    }
    pixels.show();
    delay(wait);
  }
}



//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < pixels.numPixels(); i=i+3) {
        pixels.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
      }
      pixels.show();

      delay(wait);

      for (uint16_t i=0; i < pixels.numPixels(); i=i+3) {
        pixels.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Now that we can see where onoff is being set, we can also see that it is not something within this sketch that is changing the value.

Since I don't have the hardware to replicate your setup, I can only suggest the following troubleshooting steps.

If statement are not usually that difficult to troubleshoot unless there criteria is weird. Your is not and you have proved it works...once.

You have a while, then an if, then another if to get to the else statement. anyone of those three can prevent you from getting to the else statement. I suggest adding some addition debug statements between the while and the first if statement. There is already a debug line between the first and second if statements. On that note, what is the output of the debug serial print after the second if statement? If the program getting that far? You only mention it does one rainbow(20) loop then ends and you would like it to repeat. You have more information from that serial print just before the if. What does it tell you (us)?

dazwell:
How can I get it to repeat the rainbow in the IF command until the ELSE is triggered?

First thing is that IF is not a loop - it is is just a test for true or false.

In your code the rainbow repeats for 20 times because of the line for(int i=0;i<NUMPIXELS;i++)

If you want the rainbow feature to run for an indefinite time you need a very different approach. When the ON is detected you need to set a variable (let’s call it runRainbow) to true. And in your loop() you could then have something like

if (runRainbow == true) {
   rainbow(20);
}

…R