[SOLVED] Controlling a NeoPixel Ring

Hi, I’m trying to turn a NeoPixel Ring on and off, with a Spark Core.

I got it to turn off, but I can’t get it to turn back “on.” I know I’m leaving something out. Something’s missing.

Any help/ideas appreciated.

Here’s the Spark core code:

    #include "application.h"
#include "neopixel/neopixel.h" // use for Build IDE
// #include "neopixel.h" // use for local build

SYSTEM_MODE(AUTOMATIC);

// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D6
#define PIXEL_COUNT 24
#define PIXEL_TYPE WS2812B
int lights_on=0;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

// Prototypes for local build, ok to leave in for Build IDE
void rainbow(uint8_t wait);
uint32_t Wheel(byte WheelPos);

void setup()

{  
Particle.function("setlight", setlight);
  strip.begin();
  strip.setBrightness(128);
  strip.show(); // Initialize all pixels to 'off'
}
void loop()
{if (lights_on)
  rainbow(20);
  else{}
}
int setlight(String pstn) {
    lights_on = pstn.toInt();
    serv.write(pos);
    return pos;
}
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) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

And here’s what I’ve got on my webpage:

<form>
<p><input type="radio" value="off" onclick="showValue(this.value)" name="led" /> Off
<input type="radio" value="on" onchange="showValue(this.value)" name="led"/> On 

</p>
</form>

<script type="text/javascript">
    function showValue(newValue) {
    //  document.getElementById("range").innerHTML=newValue;
      var request = new XMLHttpRequest();
      var dev_id = '53ff6e065075535119361687';
      var access = '55124b3412345678972438e81e14213710e';
      var data = 'params='+newValue+'&access_token='+access;
      var url = 'https://api.particle.io/v1/devices/'+dev_id+'/led/';
      request.open('POST', url, true);
      request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
      request.send(data);
    }
    </script></p>

To eliminate the webpage from being the issue, could you try either of these options to trigger your function?
http://jordymoors.nl/interface
http://suda.github.io/particle-web-interface/
or the new Particle iOS app

1 Like

and try to call

Particle.process();

inside rainbow()'s blocking for-loop.

or use

SYSTEM_THREAD(ENABLED);

or un-block that blocking code!

1 Like

Thanks, these both look really helpful.

Are there any instructions/context available? They look pretty straightforward, but I’d be interested in reading any background info on them.

Thanks again!

DC

Thanks. I’ll give that a try. Always interested in advice from the Mill City. : )

DC

There’s not much to tell on either. Pick your function, enter an optional argument, and you should be good to go :smile:
Mine (the first) is made with the SparkJS library to test its (and my) capabilities. It ended up being useful, so I kept it around. The second one is made by @suda, presumably to be able to quickly call functions/variables as well :smile:

1 Like

for a fan of everything obsolete (giant brick garment mills and Wang word processors!)

void rainbow(uint8_t wait) 
{
	static int lastUpdateMillis = 0;
	static int direction = -1;
	static int pixelIndex = 0;
	
	if(millis() - lastUpdateMillis >= wait)
	{
		if(pixelIndex <= 0 or pixelIndex >=255)
		{
			direction *= -1;
		}
		pixelIndex += direction;
		for(int i = 0; i < strip.numPixels(); i++) 
		{
			strip.setPixelColor(uint16_t i, Wheel((i + pixelIndex) & 255));  // not sure about this...
		}
		strip.show();
                lastUpdateMillis = millis();  //  Whoopsie!!
	}
}

or something close to this :wink:

1 Like

Wow, thanks!

I can’t wait to dig into this.

And don’t forget Jack Kerouac!

Thanks again,

DC

yes… Old brick mills, Wang word processors (which there is likely no one on this forum that knows what the heck that is) and… Beatnicks, right!

1 Like

@BulldogLowell, are you kidding!!! Wang used to rock! What about Z80 computers running CPM/80, the TRS80 and the Cosmac VIP. :stuck_out_tongue:

1 Like

@dcdenison are you able to get the Ring to turn on and off now successfully?

Hi Kyle, Thanks for following up. I’m working on the project at Cambridge (MA) Hackspace, usually Tuesday nights, so I will definitely tackle it then, if I don’t get a chance before. I will report on my progress.

Since the Ring is Particle-specific, it makes sense to close the loop and add it to the knowledgebase here.

DC

1 Like

Nobody knows what this is?! Old wang, with the twinax? Or, the twinax ISA card for the PC so you could switch in and out of it from DOS?? Yes… sadly I had to support that from about 1987 'till 1994, when it was ME that left that job… not the Wang… :smile:

Thanks Moors7 and BulldogLowell. Worked on this last night at the Cambridge Hackspace Open House, and impressed the regulars. :open_mouth:

Those webpages were great to check the functions.

And BulldogLowell’s code worked great.

“off” = static, unanimated pixels on; “on” = rainbow animation on.

Now I have to try to make it work so that there’s a value to turn the NeoPixel black: so it can be controlled to go from “off/black” to “on” to “animated” and back to “off/black.”

I started working on it this morning, and it looks like I’ve introduced an error. Now it’s not verifying. Let me know if it’s anything super obvious. Otherwise I’ll try to debug it next week.

Thanks again Moors7 and BulldogLowell: you really gave me some momentum. I’ll post the whole thing, with the Javascript, once I get it all working together.

DC

Oh yeah, here’s the latest sketch, with errors :worried:

    #include "application.h"
    #include "neopixel/neopixel.h" // use for Build IDE
    // #include "neopixel.h" // use for local build
    
    SYSTEM_MODE(AUTOMATIC);
    
    // IMPORTANT: Set pixel COUNT, PIN and TYPE
    #define PIXEL_PIN D6
    #define PIXEL_COUNT 24
    #define PIXEL_TYPE WS2812B
    // this is a variable, an integer
    int lights_on=0;
    
    Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
    
    // Prototypes for local build, ok to leave in for Build IDE
    void rainbow(uint8_t wait);
    uint32_t Wheel(byte WheelPos);
    
    //this is a function
    void setup()
    
    {  
    Particle.function("setlight", setlight);
      strip.begin();
      strip.setBrightness(128);
      strip.show(); // Initialize all pixels to 'off'
    }
    
    //a function
    
    
    void loop()
    {Particle.process();
    if (lights_on)
      rainbow(20);
      else{
    // this is where I have to create something so that all the colors of the NeoPixel are black. This is a copy of the code below. 
    //  void rainbow(uint8_t wait) 
    //{Particle.function("lightsoff", lightsoff);
    //	static int lastUpdateMillis = 0;
    //	static int direction = -1;
    //	static int pixelIndex = 0;
    	
    //	if(millis() - lastUpdateMillis >= wait)
    //*	{
    //		if(pixelIndex <= 0 or pixelIndex >=255)
    //		{
    //			direction *= -1;
    //		}
    //		pixelIndex += direction;
    //		for(int i = 0; i < strip.numPixels(); i++) 
    //		{
    //			strip.setPixelColor( i, Wheel((i + pixelIndex) & 255));  // not sure about this...
    //		}
    //		strip.show();
    //                lastUpdateMillis = millis();  //  Whoopsie!!
    //	}
    //}    
    //      
     }
    }
    
    //a variable
    int setlight(String pstn) {
        lights_on = pstn.toInt();
      // serv.write(pos);
        return lights_on;
    }
    
    void rainbow(uint8_t wait) 
    {
    	static int lastUpdateMillis = 0;
    	static int direction = -1;
    	static int pixelIndex = 0;
    	
    	if(millis() - lastUpdateMillis >= wait)
    	{
    		if(pixelIndex <= 0 or pixelIndex >=255)
    		{
    			direction *= -1;
    		}
    		pixelIndex += direction;
    		for(int i = 0; i < strip.numPixels(); i++) 
    		{
    			strip.setPixelColor( i, Wheel((i + pixelIndex) & 255));  // not sure about this...
    		}
    		strip.show();
                    lastUpdateMillis = millis();  //  Whoopsie!!
    	}
    }
    //This is my old code
    // 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) {
      if(WheelPos < 85) {
       return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
      } else if(WheelPos < 170) {
       WheelPos -= 85;
       return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
      } else {
       WheelPos -= 170;
       return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
    }

Could you also post the error messages - that’d help a lot!

Doh! Of course.

32+0 records in
32+0 records out
32 bytes (32 B) copied, 7.2037e-05 s, 444 kB/s
4+0 records in
4+0 records out
4 bytes (4 B) copied, 0.0431554 s, 0.1 kB/s
a-rainbow2.cpp:7:14: error: 'String' was not declared in this scope
 int setlight(String pstn);
              ^

a-rainbow2.cpp:5:6: error: previous declaration of 'void setup()' with 'C++' linkage
 void setup();
      ^

In file included from ../wiring/inc/spark_wiring_system.h:36:0,
                 from ../wiring/inc/spark_wiring.h:47,
                 from ./inc/application.h:36,
                 from a-rainbow2.cpp:3:
../system/inc/system_user.h:28:12: error: conflicts with new declaration with 'C' linkage
 void setup();
            ^

a-rainbow2.cpp:6:6: error: previous declaration of 'void loop()' with 'C++' linkage
 void loop();
      ^

In file included from ../wiring/inc/spark_wiring_system.h:36:0,
                 from ../wiring/inc/spark_wiring.h:47,
                 from ./inc/application.h:36,
                 from a-rainbow2.cpp:3:
../system/inc/system_user.h:29:11: error: conflicts with new declaration with 'C' linkage
 void loop();
           ^

a-rainbow2.cpp: In function 'int setlight(String)':
a-rainbow2.cpp:67:25: error: 'int setlight(String)' redeclared as different kind of symbol
 //}    
                         ^

a-rainbow2.cpp:7:5: error: previous declaration of 'int setlight'
 int setlight(String pstn);
     ^

In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from a-rainbow2.cpp:3:
../wiring/inc/spark_wiring_cloud.h: In instantiation of 'static bool CloudClass::function(const T&, Types ...) [with T = char [9]; Types = {int}]':
a-rainbow2.cpp:26:39:   required from here
../wiring/inc/spark_wiring_cloud.h:191:39: error: invalid conversion from 'int' to 'int (*)(String)' [-fpermissive]
         return _function(name, args...);
                                       ^

../wiring/inc/spark_wiring_cloud.h:194:17: error:   initializing argument 2 of 'static bool CloudClass::_function(const char*, int (*)(String))' [-fpermissive]
     static bool _function(const char *funcKey, user_function_int_str_t* func)
                 ^

make[2]: *** [../build/target/user/platform-0-la-rainbow2.o] Error 1
make[1]: *** [user] Error 2
make: *** [main] Error 2

What way are you building?

Have you got multiple project files (with setup() & loop()) in your peoject folder?
Or have you got any .c files? Change them to .cpp.
Or if this is an .ino file you’d need to remove the function prototypes or add
#pragma SPARK_NO_PREPEOCESSOR
to prevent the preprocessor from adding them again.
But then you’d need to add prototypes for all your functions.

And you are building for a Spark Core, right?

Now, I haven’t test this but I was working on a project similar so I hacked this together for you.

It allows you to traverse through a set of LED effects (I was using the technique for an LCD display). I adapted the method for you and it compiles, but I cannot test it.

Take a look and let me know if it is what you were looking for.

Sending a 0, 1 or 2 to the function should switch to the LED effect you want to shortcut to. Sending a number outside the range (i.e. -1) would “index” you through the led effects.

Here is what I cobbled together for you:


#define LOCAL_BUILD

#define PIXEL_PIN D6 // IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_COUNT 24
#define PIXEL_TYPE WS2812B

#include "application.h"
#ifdef LOCAL_BUILD
#include "neopixel.h"
#else
#include "neopixel/neopixel.h"
#endif

SYSTEM_MODE(AUTOMATIC);

enum EffectsMode {
  RAINBOW_MODE = 0,
  CHASE_MODE,  // you could just add other effects modes above BLACK_MODE
  BLACK_MODE,
  MODES_MAX // <<<<< you will see where we are going with this later in the code...
};

EffectsMode effectsMode = RAINBOW_MODE;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

void setup()
{
  Particle.function("setlight", setlight);
  strip.begin();
  strip.setBrightness(128);
  strip.show();
}

void loop()
{
  switch (effectsMode)
  {
    case RAINBOW_MODE:
      rainbow(40);
      break;
    case CHASE_MODE:
      chase(100);
      break;
    case BLACK_MODE:
      setBlack();
      break;
  }
}

int setlight(String command)
{
  int newMode = command.toInt();
  if (newMode < static_cast<int>(MODES_MAX) && newMode >= 0) // within the range of options
  {
    effectsMode = static_cast<EffectsMode>(newMode);
  }
  else
  {
    int incrementMode = static_cast<int>(effectsMode);  // outside the range of options
    effectsMode = static_cast<EffectsMode>(++incrementMode % MODES_MAX);
  }
  return static_cast<int>(effectsMode);
}

void setBlack(void)
{
  for (int i = 0; i < strip.numPixels(); i++)
  {
    strip.setPixelColor( i, 0, 0, 0);
  }
  strip.show();
}

void rainbow(uint8_t wait)
{
  static int lastUpdateMillis = 0;
  static int direction = -1;
  static int pixelIndex = 0;

  if (millis() - lastUpdateMillis >= wait)
  {
    if (pixelIndex <= 0 or pixelIndex >= 255)
    {
      direction *= -1;
    }
    pixelIndex += direction;
    for (int i = 0; i < strip.numPixels(); i++)
    {
      strip.setPixelColor( i, Wheel((i + pixelIndex) & 255));  // not sure about this...
    }
    strip.show();
    lastUpdateMillis = millis();  //  Whoopsie!!
  }
}

void chase(uint8_t wait)
{
  static int lastUpdateMillis = 0;
  static int direction = -1;
  static int pixelIndex = 0;
  if (millis() - lastUpdateMillis >= wait)
  {
    if (pixelIndex <= 0 or pixelIndex >= 255)
    {
      direction *= -1;
    }
    pixelIndex += direction;
    for (int i = 0; i < strip.numPixels(); i++)
    {
      if (pixelIndex = i)
      {
        strip.setPixelColor(i, 255, 255, 255);
      }
      else
      {
        strip.setPixelColor(i, 0, 0, 0);
      }
    }
    strip.show();
    lastUpdateMillis = millis();
  }
}

uint32_t Wheel(byte WheelPos) {
  if (WheelPos < 85)
  {
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
  else if (WheelPos < 170)
  {
    WheelPos -= 85;
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  else
  {
    WheelPos -= 170;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

copiles, not tested
With a little cleanup… :wink:

Thanks, looking forward to checking this out… as soon as I get back from Maker Faire New York.

Anyone else going?

I know that Zach Crockett, Particle CTO will be giving a talk.

1 Like

Thanks for taking a look at this. I’m embarrassed to say that I don’t know the answers to many of these questions. But I should, and I’ll work through them with some of the much more sophisticated technologists who usually share a worktable with me at my local hackspace.

I am working with a Spark Core. I’m assuming that I can transition it to a Photon at a future date.

Thanks again for you thoughts, and provocative questions.

DC