need help, start to finish

looking for help with what i believe to be a fairly basic project… guess ill do my best to describe what I’m looking for and someone who’s interested in helping will contact me? lol heres hoping!

parts

arduino uno
1 rgb 5050smd strip split in two pieces (12v)
1 ws2812b rgb5050smd individually addressable(5v)
a few momentary pushbuttons
parallax sound impact sensor

basically i have led strips in 3 different areas…id like to be able to turn on/off each of the 3 groups of lights individually with three momentary pushbuttons and then cycle them through a series of cool light sequences… i also want to be able to have the light react to bass on one or all strips. lastly id like a button to toggle the first strip thats split in two pieces…

i have been trying to self teach myself but its not going very well… i don’t understand programming at all :frowning: … iv been able to hook up my ws2812b strip and run adrafruits strand test but adding my own light effects and the push botton toggle i cant figure out… also have no idea how i would run that program along side the program that would run the 2 other strips…

below is the music reactive code for the first strand but i haven’t been able to find one for the addressable strand

//Van der Stappen ©

#define REDPIN 5
#define GREENPIN 6
#define BLUEPIN 3

int redNow;
int blueNow;
int greenNow;
int redNew;
int blueNew;
int greenNew;

void setup()
{
pinMode(7,INPUT); //SIG of the Parallax Sound Impact Sensor connected to Digital Pin 7
pinMode(REDPIN, OUTPUT);
pinMode(GREENPIN, OUTPUT);
pinMode(BLUEPIN, OUTPUT);
redNow = random(255);
blueNow = random(255);
greenNow = random(255);
redNew = redNow;
blueNew = blueNow;
greenNew = greenNow;

}

#define fade(x,y) if (x>y) x–; else if (x<y) x++;

void loop()
{
boolean soundstate = digitalRead(7);
if (soundstate == 1) {
analogWrite(BLUEPIN, blueNow);
analogWrite(REDPIN, redNow);
analogWrite(GREENPIN, greenNow);
redNew = random(255);
blueNew = random(255);
greenNew = random(255);
// fade to new colors
while ((redNow != redNew) ||
(blueNow != blueNew) ||
(greenNow != greenNew))
{
fade(redNow,redNew)
fade(blueNow,blueNew)
fade(greenNow,greenNew)
analogWrite(BLUEPIN, blueNow);
analogWrite(REDPIN, redNow);
analogWrite(GREENPIN, greenNow);
delay(1);
}
}
else{
digitalWrite(REDPIN,0);
digitalWrite(GREENPIN,0);
digitalWrite(BLUEPIN,0);
}
}

Ok, you seem to be having trouble defining what you want the thing to do. It's all just ideas a this stage.

basically i have led strips in 3 different areas...id like to be able to turn on/off each of the 3 groups of lights individually with three momentary pushbuttons and then cycle them through a series of cool light sequences.... i also want to be able to have the light react to bass on one or all strips. lastly id like a button to toggle the first strip thats split in two pieces...

So, when you hit a bushbutton, the light goes on? Then off? Then it cycles though some cool effects? How can the arduino tell the difference between when you want the light to go on and when you want the light to do the cool stuff? I mean - it's all do-able. You can have long clicks, short clicks, double clicks and so on. But your first problem is defining what the sketch will do, and this has to be done with some degree of detail. Apart from anything else, long,short, and double click are a trifle fiddly, although they have the advantage that you are only using one pin.

And that's before you have worked out what these cool effects of yours do, and how they interact with the bass. The Adafruit library comes with a bunch of samples, of course, so you'd probably start by modifying them.

An issue is just how much I/O you are going to need. I could be the case that a 16MHz arduino just doesn't have the thoughput to do four strands of very dynamic flashy bass-driven adafruit strips.

thanks for the reply.... i think the trouble comes from the fact that i don't know enough about programming to know whats possible and what my limitations are... the idea of long clicks sounds good!

as i said, i have 3 led strips ( 2 actually but one is cut in half)... i want to have 3 pushbuttons ... each push button will be linked to a single strand of lights... 1 click on, additional clicks would cycle to new light scenes and a long click would turn the stand off. my hope is that whomever is able to help me would already have a library of predone light scenes and perhaps i could do a strand test and see which ones i liked? the bass light effect would just be accessed by clicking continuously until that setting is reached.....

hopefully this clarifies things a little more?

hopefully this clarifies things a little more?

Yep, totally.

I would address this with C++ classes.

Tell you what - I have some free time. I'll write a sketch with three buttons and three LEDs - so, not a strand ... WAIT A MOMENT! I totally have some neopixels! I have four little neopixel rings! And as a bonus, they are different lengths, so my sketch has to cope with that.

Well, I have found my project for this evening :) . I think I might have a double-click turn the strand off, and a really long-click turn ALL the strands off. Heck, maybe even have a long-click turn all the strands on back to where they were when you turned 'em off.

Seeing as this is gigs and collaborations, you wanna pay me? I take PayPal. Hundred bucks just for this evening (I'm in timezone +10), if what I produce is good for you. Honour system, of course, as I will be posting the sketch here publically too for educational purposes. (normally I'm $100 and hour, and this is going to take more than a couple of hours, so it's a very good deal, I promise.)

Honestly, I'm going to charge ahead and do this anyway, so it really won't make a difference.

Ok, I have built a thingy for you.

Demo at Youtube

Project at GITHUB

I use my debounce code. This is included in the github project, or you can add it to your environment as a library.

I’ll copy/paste the code, but it won’t compile without the debounce gear:

/*
 *  For Bigbroncodiver at http://forum.arduino.cc/index.php?topic=393102.0
 * 
 * 
   Copyright (c) Paul Murray, 2016. Released into the public domain
   under the unlicense http://unlicense.org .
*/


#include <Adafruit_NeoPixel.h>

#include "DebounceInput.h"

// a Button is constructed on a pin. I knows about clinks=, double clicks, and long clicks.

class Button : DebouncedInput {

    const unsigned long LONG_CLICK_ms = 500;
    const unsigned long DCLICK_ms = 250;

    unsigned long down;
    int clickcount;
    boolean clickfired;

  public:
    Button(int pin) : DebouncedInput(pin)  {}

    virtual void onClick(int) {}
    virtual void onLongClick(int) {}

    void loop() {
      read();

      if (falling()) {
        if (millis() - down > DCLICK_ms) clickcount = 0;
        clickcount ++;
        clickfired = false;
        down = millis();
      }
      else if (rising()) {
        if (!clickfired) {
          onClick(clickcount);
          clickfired = true;
        }
      }
      else if (low() && !clickfired && millis() - down > LONG_CLICK_ms) {
        onLongClick(clickcount);
        clickfired = true;
      }
    }
};

class StrandController;
class Effect;


int nEffects;
Effect *effects[20]; // this needs to be big enbough for the effect singletons
void register_effect(Effect *e) {
  effects[nEffects++] = e;
}


class Effect
{
  public:
    Effect() {
      register_effect(this);
    }
    virtual void start(StrandController *controller) {}
    virtual void loop(StrandController *controller) {}
    virtual void stop(StrandController *controller) {}


    // 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(Adafruit_NeoPixel &strip, 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);
    }
};


class StrandController {

  public:
    Adafruit_NeoPixel strand;
    int currentEffect = 0;

    // these variables are a scratchpad area for the various effects. HOw they are used
    // is defined by the effect. prev_ms and ms are maintained by the loop method here, but are
    // available to the effects

    unsigned long prev_ms, ms;
    unsigned long time[10];
    unsigned n[10];
    float f[10];
    boolean isOn = false;

    StrandController(int strandSize, int strandPin) :
      strand(strandSize, strandPin, NEO_GRB + NEO_KHZ800) {
    }

    void setup() {
      strand.begin();
      on();
    }

    void loop() {
      if (!isOn) return;
      ms = millis();
      effects[currentEffect]->loop(this);
      prev_ms = ms;
    }

    void off() {
      if (!isOn) return;
      ms = prev_ms = millis();
      effects[currentEffect]->stop(this);
      isOn = false;
      strand.clear();
      strand.show();
    }

    void on() {
      if (isOn) return;
      ms = prev_ms = millis();
      effects[currentEffect]->start(this);
      isOn = true;
    }

    void next() {
      if (isOn) {
        effects[currentEffect]->stop(this);
      }
      if (++currentEffect >= nEffects) {
        currentEffect = 0;
      }
      strand.clear();
      strand.show();
      if (isOn) {
        effects[currentEffect]->start(this);
      }
      prev_ms = ms = millis();
    }

};

class StrandControllerButton: Button {
    StrandController &controller;
  public :
    StrandControllerButton(StrandController &controller, int pin) :
      Button(pin), controller(controller) {
    }

    void loop() {
      Button::loop();
    }

    void onClick(int) {
      controller.next();
    }

    void onLongClick(int) {
      if (controller.isOn) {
        controller.off();
      }
      else {
        controller.on();
      }
    }
};

class Point : Effect {
  public:
    void start(StrandController *controller) {}
    void stop(StrandController *controller) {}

    // an extremely simple effect that moves the led along by one every 10th of a second.
    void loop(StrandController *controller) {
      int a = (controller->prev_ms / 100) % controller->strand.numPixels();
      int b = (controller->ms / 100) % controller->strand.numPixels();

      if (a != b) {
        controller->strand.setPixelColor(a, 0);
        controller->strand.setPixelColor(b, controller->strand.Color(255, 255, 255));
        controller->strand.show();
      }
    }

} point;

class Rainbow : Effect {
  public:
    void start(StrandController *controller) {}
    void stop(StrandController *controller) {}

    void loop(StrandController *controller) {
      int t =  (controller->ms ) & 255;

      for(int i = 0; i<controller->strand.numPixels(); i++) {
        controller->strand.setPixelColor(i, wheel(controller->strand,  ( (i*256/controller->strand.numPixels())+t) & 255));
      }

      controller->strand.show();
    }

} rainbow;

// atttach my four neopixel rings to pins 12-9. Two of my rings are 24-led, and two are 16 led

StrandController s12(24, 12), s11(24, 11), s10(16, 10), s9(16, 9);

// attach my three buttons. I will run strips 11 and 10 both off button 5.

StrandControllerButton b12(s12, 4), b11(s11, 5), b10(s10, 5), b9(s9, 6);

void setup() {
  // put your setup code here, to run once:

  s12.setup();
  s11.setup();
  s10.setup();
  s9.setup();

}

void loop() {
  // put your main code here, to run repeatedly:

  s12.loop();
  s11.loop();
  s10.loop();
  s9.loop();

  b12.loop();
  b11.loop();
  b10.loop();
  b9.loop();

}

To add your own effects, create a class extending Effect, create the start, stop, and loop methods, and create one instance of it. You can do other things too - make multiple instances with slightly different constructor arguments and so on.

You’ll need some control buttons, and some NeoPixel strings with data lines attached to the right pins. I’m not using the canShow() method to determine if the neopixel can be written to, and this could be a problem if your strips are quite long. I dont have long strips, so am unable to test this at the moment.

I think that if this is a problem, then something like updating StrandController.loop() to this might fix it:

    void loop() {
      if (!isOn) return;
      if(!strand.canShow()) return;
      ms = millis();
      effects[currentEffect]->loop(this);
      prev_ms = ms;
    }

paul! i cant thank you enough:) not a bad surprise to wake up to.....im definitely willing to compensate you but as it stands its still quite far away from working for me.... i wish all of my strands were addressable like your neopixels but but only one of mine is.... i have a strand of 150addressable and i have two groups of simple rgb lights (approx.150) can your script be made to operate non addressable strips? also, do you have a schematic for your demo? the schematic i was planning on using for the non addressable is this one here.

https://dl.dropboxusercontent.com/u/10830255/Arduino%20RGB%20on-beat%20leds%20Project/Scematics%20on-beat%20RGB%20strip.pdf

with 6 pwm capable pins on the arduino i figured it should be able to run the two strands separately and as far as I'm aware i don't need a pwm capable pin for the addressable.

According to your schematic, you are putting 12V into the Vin … well, I suppose the arduino will handle it. The voltage regulator might get a little warm, tho. I'm sure the guys over on the electronics subforum have designs for a "capacitative dropper" power supply that will get the voltage down to a more polite level for the arduino.

The setup for the video was: three normally-open switches between the switch input pins and ground - standard for wiring a control switch to an arduino, and ground and +5v to the pixel rings (the blue and red wires) and four data lines from the arduino to the neopixels. If your addressible strip is not a neopixel, well, obviously the plug-innable stuff needs to change a bit.

A UNO does have six PWM outputs, which is enough to drive two RGB leds, and it has five more pins - enough to handle two outputs and three buttons. Another plan is to use the analog inputs for the controller. It means turfing my gorgeous debounce library, but meh.

The result is that we have two 'effect' classes, one to drive a strip, and one to drive a single LED. This means we need two arrays for the different kinds of effect … code code code.

I'll have a look at it. The modifications I have to make to the existing code might themselves be instructive.

i could get another arduino and link it if that would make things easier? or maybe harder...

Alternatively..... I do have one of these aswell.... Would this be more suitable?

SunFounder Mega 2560 R3 ATmega2560-16AU Board

Fiddling around at home - may be able to do more tonight. I have separated out a few things to abstract away the notion of a "controller" as opposed to "a controller for an adafruit strand'. Changes are in github. The sketch as it stands should work the same as the previous one, but I'll have to set up the neopixel rings again. Might wire them together as a single long strand of 80 pixels, to more closely match your setup.

Todo:

flesh out RBG controller wire up an rgb led (I have one - one will have to do) write sample RGB effects (a colour cycle and just a on/off flash, I think) Add bass-thumper

As I understand it, the bass thumper can be modelled just as a button that I press in time with some imaginary music. I could rig up the effects so that when bass is thump, the leds go bright. That should be enough for proof of concept.

I have a cool idea for an effect driven by bass thump ... but that's for my own amusement and I may not get around to it.

Ok. I now have strip and RGB led controllers hapenning. Two effects for each: rainbow and moving dot for the strip and colour wheel and R/G/B/Off cycle for the LED.

My RGB LED is common anode, and on top of that it is a bit crap. The blue component has gone weird. The comon anode means that in this sketch, the analog out 255 is off and 0 is on.

Pinout:

control button 8 to ground.
control button 9 to ground.
common-anode LED on 3,5,6 (w/220R resistors).
24-element neopixel strip on 11. Neopixel needs power also (ground and +5v)

This is controlled by the pinout code:

StrandController s12(24, 11);
RGBController led1(3,5,6);
ControllerButton<StrandEffect> analog_0_button(s12, 8);
ControllerButton<RGBEffect> analog_1_button(led1, 9);

hold control button down to turn on/of, click button to change effect.

Todo: bass thumper input, maybe get myself a nice new common cathode RGB led, do another vid.

Board won’t let me post the code (too long). Code at github: GitHub - PaulMurrayCbr/arduino_forum_393102: http://forum.arduino.cc/index.php?topic=393102.

'Nite.

looking really great paul:) did we go away from the 3rd button though?

Bigbroncodriver:
looking really great paul:) did we go away from the 3rd button though?

Only have one RGB LED, so only two buttons. I’ll head over to Jaycar at some point in the not-to-distant future and get myself a couple of common cathode RGB LEDs for the parts bin. The point being: using objects with constructors to do the wiring-up makes reconfiguring the hardware very easy.

My UNO is running out of pins. six for the LEDs, one for the strip, and three buttons makes 10. You don’t want to use pins 0 and 1 unless you have to, because putting anything on those pins screws up the serial connection which makes uploading sketches a bit of a pain.

Still … there should be enough. Oh: and one for the bass thumper. I might use pin 13 as an input, if you can do that. Or use it as the output for the strip - the on-board LED will suck some juice, but hopefully there’ll be enough left over for the neopixels.

Tried using an analog in for the control buttons. This involves an external pull-down resistor, and I was getting all kinds of weird crap happening. I believe reading an analog in actually chews up cycles because ADC and capacitance or some such nonsense. It’s bad enough that I abandoned the attempt.

Anyway. With this sketch done, you will only have a couple of fairly crappy effects. Making cooler effects will require some programming, of course, but you can do that yourself or get someone else to do it. Not sure I’d be into it at this stage, and anyway, this sketch is also an experiment in using OO programming to make something that it’s easy for other people to build on.

Learning all about how crap C++ templates are compared to java generics. In Java, you can easily (well, kinda easily) say:

There are two kinds of effect: RGB and strip, and two kinds of controller: RGB and strip. A controller has a list of effects that it knows about, and RGB controllers, specifically, use lists of RGB effects. An effect has a ‘do the thing’ method which is passed a controller. An RGB effect must/will always be passed an RGB controller, and a strip effect must/will always be passed a strip controller".

And it’s all type-safe and good and the compiler understands what you are doing and will correct you if you screw it up.

C++? Feh. I’m right on the edge of using void pointers for everything and just casting them. Oh, and arduino has two flavours of pointer: PROGMEM and data. So you can’t use a void pointer for a function pointer without getting all sorts of bullshit messages from the compiler.

Dislike my design for effects. The five functions (set_up, start, loop, stop, tear_down) ought to be done with virtual inheritance, but I am having all sorts of trouble making it go. I’m finding that overrides aren’t getting overridden as they should when a call is made to the superclass method.

Maybe I need to google … oh. here we go:

To create a pure virtual function, rather than define a body for the function, we simply assign the function the value 0.

class Base

{
public:
    const char* SayHi() { return “Hi”; } // a normal non-virtual function   
    virtual const char* GetName() { return “Base”; } // a normal virtual function
    virtual int GetValue() = 0; // a pure virtual function
};

You “simply” assign it a value of zero. So simple! How could I not have though of that!

Well, tonight is D&D night, and then after D&D it transmogrifies into go-out-and-get-drunk night. I might have a look at this Saturday, do the run to the store then.

You know, dude, I’d be happier knowing that you had actually given this a bash - put the sketch in your arduino, plugged your lights (or a test LED) into the pins. There’s many a slip betwixt cup and lip.

Ok. As before, sketch is too big to post here, available on github.

New video showing the functionality is at YouTube. It’s a bit rushed because I was short of phone memory, but it demos the various functions.

We have two common-anode LEDs, separately controllable, and two sample effects: a not-very-good colour wheel and a red/green/blue flash. The flashes and wheels move in synchrony because both are driven of millis(), which of course reads the same for both at any particular time.

We have a 48-LED neopixel strip (two 24-LED rings hooked together), and two sample effects, a rainbow and a moving dot. Note that the moving dot draws two dots 24 pixels apart, which is why it looks like the two rings are showing the same thing.

We have a bass-thumper, which in this instance is just an INPUT_PULLUP pin. When the bass thumps, the three colour sketches flash the LEDs brighter.

The moving dot has some code so that when the bass thumps, the dot moves faster. When the thumper goes off, the speed bleeds away over half a second or so. So when the thumper is thumping, the dot sort of moves in a series of jumps. Should look way better on a long strip.

I’d like to clean up the code a little more, but the functionality you were after is there as far as I can tell. You will want more effects, better effects, artistic efects, but getting those coded up is a separate issue from doing this framework into which effects can be slotted. Likewise, if your addressable strip is not neopixels, well, I don’t have whatever you are using and you’ll need to modify the code.

PM me re moneys, if you want to do that. Paypal is best.

Update: finally got virtual inheritance working. Effects are way cleaner - you just override the methods rather than passing function pointers all over the shop. This means that the effect methods have access to the effect object, and so you can put parameters in the constructor. So our led flasher comes in two flavours: slow and fast, which is done with constructor arguments.

Ok!

I have added changes as requested.

1 - the leds and the neopixel strip now have a selection of solid colours that can react to the bass trigger. colours are StrandColor(255, 0, 0), //red StrandColor(255 - 8 - 32, 8, 32), // pink StrandColor(192, 64, 0), //orange StrandColor(128, 128, 0), //yellow StrandColor(64, 192, 0), //yelow green StrandColor(0, 128, 128), //cyan StrandColor(0, 0, 255), //blue StrandColor(128, 0, 128), //magenta StrandColor(64, 0, 192), //purple

2 - the bass trigger and be turned on and off for each individual effect. To do this, hold down the bassControlPin (12, at the moment) while clicking the control button. Instead of the control button advancing the effect selection, it will turn bass sensitivity on and off.

3 - I have left the rainbow effect on the strip as well as having the colours there

As before, new code is at github https://github.com/PaulMurrayCbr/arduino_forum_393102

Demo video available at https://youtu.be/VbrCmPspA50.

An issue is that I may have the bass thing around the wrong way: it's making the lights bright when the signal is LOW, possibly should be the other way around.