Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Troubleshooting
  3. RGB Light, cancel loop?

RGB Light, cancel loop?

Scheduled Pinned Locked Moved Troubleshooting
11 Posts 6 Posters 4.1k Views 4 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    msebbe
    wrote on last edited by msebbe
    #1

    Hello, I have modified the RGB-3D example to run my Neopixel as a moodlight. I am trying to do so that When I press light switch ON, it will run a loop that slowly changes colour. When I press light switch OFF it will exit the loop and turn leds off.

    Turning it on works, but It seem that it gets stuck in the loop so that it cant turn off.. How can I fix this?

    #define SN   "Moodlight"
    #define SV   "v1.0"
    
    
    #include <Adafruit_NeoPixel.h>
    #ifdef __AVR__
      #include <avr/power.h>
    #endif
    #include <SPI.h>
    #include <MySensor.h>
    
    
    #define NEO_PIN      4 // NeoPixels input pin
    #define NUMPIXELS    16 // Number of nexpixels in ring/strip
    
    Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, NEO_PIN, NEO_GRB + NEO_KHZ800);
    
    MySensor gw;
    
    MyMessage rgbShowState(0, V_LIGHT);
    
    int isShow;
    
    void setup()
    {
      gw.begin(incomingMessage, AUTO, true);
    
      gw.sendSketchInfo(SN, SV);
    
      gw.present(0, S_LIGHT, "Moodlight", false);
    
       // Correct RGB show state for first start and load it (set to 'On' at first start)
      gw.saveState(0, constrain((int8_t)gw.loadState(0), 0, 1));
      isShow=gw.loadState(0);
           
      // Send RGB show state to controler (request ack back: true/false)
      gw.send( rgbShowState.set(isShow), false);
      
      if (isShow==1){Serial.println("RGB show running..."); }
      Serial.println("Ready to receive messages...");  
    
      strip.begin();
      strip.show();
      
    }
    
    void loop()
    {
      // Process incoming messages (like config and light state from controller)
      gw.process();    
          
      // Run RGB show if is set
      while (isShow==1)
      {
          rainbow(6000);
      }
      
    }
    
    void incomingMessage(const MyMessage &message)
    {
      if (message.isAck())
      {
         Serial.println("Got ack from gateway");
      }
      if (message.type == V_LIGHT)
      {
        // Incoming on/off command sent from controller ("1" or "0")
        int lightState = message.getString()[0] == '1';
      
        // if receive RGB Show On commands, start the show
        if (message.sensor==0 && lightState==1){ rgbShowOn(); }
        
            // if receive RGB Show Off commands, stop the show
        else if (message.sensor==0 && lightState==0){ rgbShowOff(); }
           
        
      }
    }
         
    void rgbShowOn()
    {
      // define show On
      isShow=1;
      // Write some debug info
      Serial.println("Show must go on");
    }
       
    void rgbShowOff()
    {
      // define show Off
      isShow=0;
      Serial.println("Stop the show");      
    }
    
    void rainbow(uint8_t wait) {
      uint16_t i, j;
    
      for(j=0; j<256; j++) {
        for(i=0; i<strip.numPixels(); i++) {
          strip.setPixelColor(i, Wheel((i+j) & 255));
        }
        strip.show();
        delay(wait);
       }
     }
    
    
    // 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 strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
      }
      if(WheelPos < 170) {
        WheelPos -= 85;
        return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
      WheelPos -= 170;
      return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
    }```
    1 Reply Last reply
    0
    • AWIA Offline
      AWIA Offline
      AWI
      Hero Member
      wrote on last edited by
      #2

      Put the gw.process inside your while (isShow==1) loop should help. You are not receiving anything when inside that loop...

      M 1 Reply Last reply
      1
      • AWIA AWI

        Put the gw.process inside your while (isShow==1) loop should help. You are not receiving anything when inside that loop...

        M Offline
        M Offline
        msebbe
        wrote on last edited by msebbe
        #3

        @AWI Hi, thanks for reply.

        I tried putting gw.process on a few different places now but it still seems like it gets stuck in the loop rainbow();

        If I remove rainbow(); from the main loop, everything seems to work according to the debug messages. Except for that there is no lights but.. Either I need to listen to messages from gw in the rainbow(); or this to be reworked in some way.

        1 Reply Last reply
        0
        • TD22057T Offline
          TD22057T Offline
          TD22057
          Hardware Contributor
          wrote on last edited by
          #4

          I think the issue is that you shouldn't be calling delay() basically anywhere. The main loop() needs to run at a reasonable rate (i.e. be called at least every millisecond). One option: make rainbow() just show one time (remove the outer loop and delay calls) and pass in the current j variable as an argument. Then in loop(), use a timer to test if enough time has passed to re-call rainbow(). Any arduino ellapsed time/timer libraries will work fine. Here is an example: http://playground.arduino.cc/Code/ElapsedMillis. In that example, change the ledState/digitalWrite lines to call the new rainbow() function.

          M 1 Reply Last reply
          0
          • TD22057T TD22057

            I think the issue is that you shouldn't be calling delay() basically anywhere. The main loop() needs to run at a reasonable rate (i.e. be called at least every millisecond). One option: make rainbow() just show one time (remove the outer loop and delay calls) and pass in the current j variable as an argument. Then in loop(), use a timer to test if enough time has passed to re-call rainbow(). Any arduino ellapsed time/timer libraries will work fine. Here is an example: http://playground.arduino.cc/Code/ElapsedMillis. In that example, change the ledState/digitalWrite lines to call the new rainbow() function.

            M Offline
            M Offline
            msebbe
            wrote on last edited by msebbe
            #5

            @TD22057 Okey, thank you. I will try with millis when I have time this weekend :+1:

            AWIA 1 Reply Last reply
            0
            • M msebbe

              @TD22057 Okey, thank you. I will try with millis when I have time this weekend :+1:

              AWIA Offline
              AWIA Offline
              AWI
              Hero Member
              wrote on last edited by
              #6

              @msebbe another option is to replace the delay( time ) with gw.wait( time ). This will allow for reception of messages and still use a simple "delay".

              1 Reply Last reply
              0
              • M Offline
                M Offline
                msebbe
                wrote on last edited by
                #7

                This is my attempt at millis... I can still not get it to stop. :sadface:

                #define SN   "Moodlight"
                #define SV   "v1.0"
                
                
                #include <Adafruit_NeoPixel.h>
                #ifdef __AVR__
                #include <avr/power.h>
                #endif
                #include <SPI.h>
                #include <MySensor.h>
                
                
                #define NEO_PIN 4 // NeoPixels input pin
                #define NUMPIXELS 16 // Number of nexpixels in ring/strip
                #define interval 50
                
                Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, NEO_PIN, NEO_GRB + NEO_KHZ800);
                
                long previousMillis = 0;
                int l = 0;
                int isShow;
                
                MySensor gw;
                MyMessage rgbShowState(0, V_LIGHT);
                
                void setup()
                {
                  gw.begin(incomingMessage, AUTO, true);
                
                  gw.sendSketchInfo(SN, SV);
                
                  gw.present(0, S_LIGHT, "Moodlight", false);
                
                   // Correct RGB show state for first start and load it (set to 'On' at first start)
                  gw.saveState(0, constrain((int8_t)gw.loadState(0), 0, 1));
                  isShow=gw.loadState(0);
                       
                  // Send RGB show state to controler (request ack back: true/false)
                  gw.send( rgbShowState.set(isShow), false);
                  
                  if (isShow==1){Serial.println("RGB show running..."); }
                  Serial.println("Ready to receive messages...");  
                
                  strip.begin();
                  strip.show();
                  
                }
                
                void loop()
                {
                  // Process incoming messages (like config and light state from controller)
                  gw.process();    
                      
                  // LEDs off if state 0
                  if (isShow == 0)
                  {
                    strip.Color(0,0,0);
                  }
                  // Run RGB show if state 1
                  if (isShow == 1)
                  {
                    
                    newRainbow();
                  }
                  
                  
                }
                
                void incomingMessage(const MyMessage &message)
                {
                  
                  if (message.type == V_LIGHT)
                  {
                    // Incoming on/off command sent from controller ("1" or "0")
                    int lightState = message.getString()[0] == '1';
                  
                    // if receive RGB Show On commands, start the show
                    if (message.sensor==0 && lightState==1){ rgbShowOn(); }
                    
                        // if receive RGB Show Off commands, stop the show
                    else if (message.sensor==0 && lightState==0){ rgbShowOff(); }
                       
                    
                  }
                }
                     
                void rgbShowOn()
                {
                  // define show On
                  isShow = 1;
                  // Write some debug info
                  Serial.println("Show must go on");
                }
                   
                void rgbShowOff()
                {
                  // define show Off
                  isShow = 0;
                  Serial.println("Stop the show");      
                }
                
                void newRainbow()
                {
                  if (millis() - previousMillis > interval * 2)
                  {
                    for (int h = 0; h < strip.numPixels(); h++)
                    {
                      strip.setPixelColor(h, Wheel((h + l) & 255));
                    }
                    l++;
                    if (l >= 256)
                      l = 0;
                    strip.show();
                    previousMillis = millis();
                  }
                }
                
                
                // 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 strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
                  }
                  if(WheelPos < 170) {
                    
                    WheelPos -= 85;
                    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
                  }
                  WheelPos -= 170;
                  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
                }
                
                1 Reply Last reply
                0
                • V Offline
                  V Offline
                  vil1driver
                  wrote on last edited by vil1driver
                  #8

                  hi,

                  what difference between what I had named rgbShow and your moodlight ?

                  M 1 Reply Last reply
                  0
                  • V vil1driver

                    hi,

                    what difference between what I had named rgbShow and your moodlight ?

                    M Offline
                    M Offline
                    msebbe
                    wrote on last edited by msebbe
                    #9

                    @vil1driver

                    I guess it is that neopixel cant run with your RGB-3D since it only has 3 pins - VCC, GND, DATA.

                    Edit : I figured it out! I will add some more functions to it and then share it.

                    Thx for help!

                    BulldogLowellB 1 Reply Last reply
                    0
                    • M msebbe

                      @vil1driver

                      I guess it is that neopixel cant run with your RGB-3D since it only has 3 pins - VCC, GND, DATA.

                      Edit : I figured it out! I will add some more functions to it and then share it.

                      Thx for help!

                      BulldogLowellB Offline
                      BulldogLowellB Offline
                      BulldogLowell
                      Contest Winner
                      wrote on last edited by
                      #10

                      @msebbe

                      an easy way would be a non-blocking function that breathes the LED... I did this for a recent project:

                      void breatheUpdate(const uint8_t * segment, const uint8_t numLeds, const uint32_t increment, const uint8_t step)
                      {
                        static uint32_t lastTimeChange = 0;
                        static uint8_t direction = 1;
                        const static uint8_t lowLimit = 50;
                        static uint8_t value = lowLimit;
                        if(millis() - lastTimeChange > increment)
                        {
                          value +=(direction * step);
                          value = constrain(value, lowLimit, 255);
                          if (value <= lowLimit || value >= 255)
                          {
                            direction = direction * -1;
                          }
                          for(uint8_t i = 0; i < numLeds; i++)
                          {
                            myPixels.setPixelColor(segment[i], myPixels.Color(0, 0, value));
                          }
                          myPixels.show();
                          lastTimeChange += increment;
                        }
                      }
                      

                      segment here is an array of leds, but you can convert the function to a single neopixel easily.

                      loop() would look like this:

                      void loop()
                      {
                        gw.process();
                        if (isShow)
                        {
                          breatheUpdate(mySegment, sizeof(mySegment), breatheRate, 1);
                        }
                      }
                      
                      1 Reply Last reply
                      1
                      • Y Offline
                        Y Offline
                        yugoos
                        wrote on last edited by
                        #11

                        I made a ws2812 (neopixel) sketch not to long ago, maybe you can use some or all of the code.
                        my loop only contains gw.process() for incomming messages (color, brightness, off).
                        I made no loops for color shows because i'm not interested in that but is should not be to difficult to adapt the code, there is however a short colorwhipe (chaser) when changing the strip color

                        #include <MySensor.h>
                        #include <SPI.h>
                        
                        #include "Adafruit_NeoPixel.h"
                        
                        #define NUMPIXELS 4   // Number of connected pixels on a single datapin
                        #define PIN 4         // Digital output pin
                        
                        #define NODE_ID AUTO  //254 for testing purpose
                        #define CHILD_ID 0  
                        
                        
                        Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
                        long RGB_values[3] = {0,0,0};
                        
                        MySensor gw;
                        
                        void setup()
                        {
                            gw.begin(incomingMessage, NODE_ID, false);
                            gw.sendSketchInfo("RGB Node", "1.0");
                            gw.present(CHILD_ID, S_RGB_LIGHT);
                            strip.begin();
                            strip.show(); // Update the strip, to start they are all 'off'
                        }
                        
                        
                        void loop()
                        {
                            gw.process();
                        }
                        
                        void incomingMessage(const MyMessage &message) {
                            if (message.type==V_RGB) {
                          // starting to process the hex code
                                String hexstring = message.getString(); //here goes the hex color code coming from through MySensors (like FF9A00)
                                long number = (long) strtol( &hexstring[0], NULL, 16);
                                RGB_values[0] = number >> 16;
                                RGB_values[1] = number >> 8 & 0xFF;
                                RGB_values[2] = number & 0xFF;
                        
                                colorWipe(Color(RGB_values[0],RGB_values[1],RGB_values[2]), 60);
                             }
                             
                            if (message.type==V_DIMMER) {
                              strip.setBrightness(round((2.55*message.getInt())));
                              strip.show();
                              }
                              
                            if (message.type==V_LIGHT) {
                               if (message.getInt() == 0) {
                                strip.clear();
                                strip.show();
                               }
                            }
                          
                        }
                         
                        void colorWipe(uint32_t c, uint8_t wait) {
                          int i;
                         
                          for (i=0; i < strip.numPixels(); i++) {
                              strip.setPixelColor(i, c);
                              strip.show();
                              delay(wait);
                          }
                        }
                        
                            /* Helper functions */
                        
                        // Create a 15 bit color value from R,G,B
                        uint32_t Color(byte r, byte g, byte b)
                        {
                          uint32_t c;
                          c = r;
                          c <<= 8;
                          c |= g;
                          c <<= 8;
                          c |= b;
                          return c;
                        }
                           
                        

                        It's not the cleanest code but it works for me...

                        have fun.

                        1 Reply Last reply
                        2
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        11

                        Online

                        11.7k

                        Users

                        11.2k

                        Topics

                        113.0k

                        Posts


                        Copyright 2019 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • MySensors
                        • OpenHardware.io
                        • Categories
                        • Recent
                        • Tags
                        • Popular