Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "BottangoArduinoCallbacks.h"
- #include "src/AbstractEffector.h"
- #include "src/Outgoing.h"
- #include "src/BottangoCore.h"
- // FastLED setup
- #include "FastLED.h"
- #define DATA_PIN 14
- #define LED_TYPE NEOPIXEL
- #define COLOR_ORDER GRB
- #define NUM_LEDS 8 // 12 - ring. 36 - strip for Evil Pumpkin
- #define BRIGHTNESS 50
- //CRGB leds[NUM_LEDS];
- CRGBArray<NUM_LEDS> leds;
- CRGBSet eyeLEDS(leds(6, 7)); // Eyes are last two in strand
- CRGBSet allLEDs(leds(0, NUM_LEDS - 1)); // This covers the entire string (zero indexed)
- CRGBSet randomLeds(leds(0, 5));
- //CRGBSet randomLeds(leds(2, 7)); // Random LEDs at end of strand, eyes are first two
- // For random blinking effect
- #define NUM_RANDOM_LEDS 6
- // Define base timing values for random blinking
- #define CHECK_INTERVAL 50 // How often we check for updates
- #define MIN_BLINK_TIME 300 // Minimum time in milliseconds
- #define MAX_BLINK_TIME 2000 // Maximum time in milliseconds
- // Arrays to track state for each random blinking LED
- bool blinkState[NUM_RANDOM_LEDS];
- CRGB colors[NUM_RANDOM_LEDS];
- uint16_t nextChangeTime[NUM_RANDOM_LEDS]; // How many milliseconds until this LED changes state
- bool RBlinks_animating = false; // Controls FastLED effect on/off
- namespace Callbacks {
- // !!!!!!!!!!!!!!! //
- // !! CONTROLLER LIFECYCLE CALLBACKS !! //
- // !!!!!!!!!!!!!!! //
- // called AFTER a successful handshake with the Bottango application, signifying that this controller has started.
- // use for general case startup process
- // Effector registration will happen after this callback, in their own callback.
- // If you have effector registration specific needs, you should use onEffectorRegistered
- void onThisControllerStarted() {
- // pinMode(BUTTON_PIN, INPUT_PULLUP); // set the button pin to be read, no pullup with touch sensor
- FastLED.addLeds<LED_TYPE, DATA_PIN>(leds, NUM_LEDS);
- FastLED.setBrightness(BRIGHTNESS);
- // Initialize random seed
- random16_add_entropy(analogRead(35));
- // Initialize random blink timings, states, and colors
- for (int i = 0; i < NUM_RANDOM_LEDS; i++) {
- // Randomize initial states with variation to avoid clusters
- blinkState[i] = (random8(10) > 5 + i % 3) ? true : false;
- // Assign an initial delay before the first change
- nextChangeTime[i] = random16(MIN_BLINK_TIME, MAX_BLINK_TIME);
- // Generate a random color for each LED
- colors[i] = CHSV(random8(), random8(180, 255), random8(200, 255));
- }
- //leds(0, 1) = CRGB::Black; // Eyes are first two in strand
- leds(0, NUM_LEDS - 1) = CRGB::Black; // NUM_LEDS - all; 1 - just the first two for eyes
- }
- // called after the controller recieves a stop command. The controller will stop all movement, deregister all effectors
- // After which this call back is triggered.
- void onThisControllerStopped() {
- }
- // called each loop cycle. If you have timing based code you'd like to utilize outside of the Bottango animation
- // This callback occurs BEFORE all effectors process their movement, at the end of the loop.
- void onEarlyLoop() {
- // Example for triggering animations in your own logic, while in offline (save to code / SD card) mode
- // if not playing anything, play animation index 2 (the third exported animation) and set it to looping
- // if (BottangoCore::commandStreamProvider->streamIsInProgress() == false)
- // {
- // BottangoCore::commandStreamProvider->startCommandStream(2, true);
- // }
- //
- // The following will stop an offline animation from playing if any
- // BottangoCore::commandStreamProvider->stop();
- }
- // called each loop cycle.
- // This callback occurs AFTER all effectors process their movement, at the end of the loop.
- void onLateLoop() {
- if (RBlinks_animating == true) {
- EVERY_N_MILLISECONDS(CHECK_INTERVAL) {
- for (int i = 0; i < NUM_RANDOM_LEDS; i++) {
- // Decrease the time until next change
- if (nextChangeTime[i] > CHECK_INTERVAL) {
- nextChangeTime[i] -= CHECK_INTERVAL;
- } else {
- // Time to change this LED's state
- blinkState[i] = !blinkState[i];
- if (blinkState[i]) {
- // Generate a new random color when turning on
- colors[i] = CHSV(random8(), random8(180, 255), random8(200, 255));
- // Assign new time for how long to stay ON
- nextChangeTime[i] = random16(MIN_BLINK_TIME, MAX_BLINK_TIME);
- } else {
- // Assign new time for how long to stay OFF (slightly different range)
- nextChangeTime[i] = random16(MIN_BLINK_TIME + 100, MAX_BLINK_TIME - 200);
- }
- }
- // Set LED to either its color or black based on current state
- randomLeds[i] = blinkState[i] ? colors[i] : CRGB::Black;
- }
- }
- // Update the LED strip
- EVERY_N_MILLISECONDS(20) {
- FastLED.show();
- }
- }
- if (RBlinks_animating == false) {
- randomLeds = CRGB::Black; // Turn them off
- }
- FastLED.show();
- }
- // !!!!!!!!!!!!!!! //
- // !! EFFECTOR CALLBACKS !! //
- // !!!!!!!!!!!!!!! //
- // All effectors have an identifier. It is an 8 char or less string. Check Bottango to see the identifier for a given effector in app.
- // for most effectors, it is the first pin in their set of pins
- // i2c effectors have the i2c address before the first pin
- // you query for an effector with a c string char array, instanitated at 9 characters (8 for the identifier, and a null terminating char)
- // The below are called by built in effectors at various stages in their lifecycle
- // called by an effector when registered, after registration is complete
- void onEffectorRegistered(AbstractEffector *effector) {
- // example, turn on built in LED if effector registered with identifier "1";
- char effectorIdentifier[9];
- effector->getIdentifier(effectorIdentifier, 9);
- if (strcmp(effectorIdentifier, "eyeColor") == 0) {
- FastLED.addLeds<LED_TYPE, DATA_PIN>(leds, NUM_LEDS);
- FastLED.setBrightness(BRIGHTNESS);
- }
- }
- // called by an effector when deregistered, before deregistration is complete
- void onEffectorDeregistered(AbstractEffector *effector) {
- // example, turn off built in LED if effector registered with identifier "1";
- // char effectorIdentifier[9];
- // effector->getIdentifier(effectorIdentifier, 9);
- // if (strcmp(effectorIdentifier, "1") == 0)
- // {
- // pinMode(LED_BUILTIN, OUTPUT);
- // digitalWrite(LED_BUILTIN, LOW);
- // }
- }
- // called by effectors each loop with its current signal (example: servo PWM or stepper steps from home )
- // didChange is true if different from last update called
- void effectorSignalOnLoop(AbstractEffector *effector, int signal, bool didChange) {
- // example, set built in led for effector with identifier "1" based on if signal is greater than 1500
- // char effectorIdentifier[9];
- // effector->getIdentifier(effectorIdentifier, 9);
- // if (strcmp(effectorIdentifier, "1") == 0)
- // {
- // pinMode(LED_BUILTIN, OUTPUT);
- // if (signal > 1500)
- // {
- // digitalWrite(LED_BUILTIN, HIGH);
- // }
- // else
- // {
- // digitalWrite(LED_BUILTIN, LOW);
- // }
- // }
- // another example, drive a custom motor, which you have coded to have a setSignal function
- // if (strcmp(effectorIdentifier, "myMotor") == 0)
- // {
- // myMotor->setSignal(signal);
- // }
- }
- // !!!!!!!!!!!!!!!!!!! //
- // !! CUSTOM EVENTS !! //
- // !!!!!!!!!!!!!!!!!!! //
- // The below are called by custom events so you can provide your own behaviours
- // called by a curved custom event any time the movement value is changed during a curved movement. (Movement is a normalized float between 0.0 - 1.0)
- void onCurvedCustomEventMovementChanged(AbstractEffector *effector, float newMovement) {
- // example, fade an led based on the new movement value
- // char effectorIdentifier[9];
- // effector->getIdentifier(effectorIdentifier, 9);
- // if (strcmp(effectorIdentifier, "myLight") == 0)
- // {
- // pinMode(5, OUTPUT);
- // int brightness = 255 * newMovement;
- // analogWrite(5, brightness);
- // }
- }
- // called by a on off custom event any time the on off value is changed.
- void onOnOffCustomEventOnOffChanged(AbstractEffector *effector, bool on) {
- char effectorIdentifier[9];
- effector->getIdentifier(effectorIdentifier, 9);
- if (strcmp(effectorIdentifier, "RBlinks") == 0) { // Edit the Identifier ("RBlinks") to match On/Off event
- RBlinks_animating = !RBlinks_animating;
- }
- }
- // called by a trigger custom event any time the on event is triggered.
- void onTriggerCustomEventTriggered(AbstractEffector *effector) {
- // example, set led to a random brightness each trigger
- // char effectorIdentifier[9];
- // effector->getIdentifier(effectorIdentifier, 9);
- // if (strcmp(effectorIdentifier, "myLight") == 0)
- // {
- // pinMode(5, OUTPUT);
- // int brightness = random(0, 256);
- // analogWrite(5, brightness);
- // }
- }
- void onColorCustomEventColorChanged(AbstractEffector *effector, byte newRed, byte newGreen, byte newBlue) {
- char effectorIdentifier[9];
- effector->getIdentifier(effectorIdentifier, 9);
- if (strcmp(effectorIdentifier, "eyeColor") == 0) {
- fill_solid(eyeLEDS, 2, CRGB(newRed, newGreen, newBlue)); // The "2" is for the eyes.
- //fill_solid(allLEDs, 12, CRGB(newRed, newGreen, newBlue)); // 12 - ring; 36 - strip
- FastLED.show();
- }
- }
- bool isStepperAutoHomeComplete(AbstractEffector *effector, int &postAutoSyncMove) {
- // return true if the given stepper is at home position
- // else return false
- // example, end homing on stepper with step on pin 6, when pin 10 is read high
- // postAutoSyncMove is additional steps you'd like to take after auto home is complete
- // as an example, if you want to hit a limit switch, then move 200 steps clockwise
- // set postAutoSyncMove = 200 and return true when the limit switch is hit
- // set postAutoSyncMove to a negative number to step counter clockwise
- // char effectorIdentifier[9];
- // effector->getIdentifier(effectorIdentifier, 9);
- // if (strcmp(effectorIdentifier, "6") == 0)
- // {
- // pinMode(10, INPUT);
- // if (digitalRead(10) == HIGH)
- // {
- // return true;
- // }
- // }
- return false;
- }
- void onStepperPostAutoHomeSecondarySyncComplete(AbstractEffector *effector) {
- // if moving a stepper after homing via the postAutoSyncMove int in isStepperAutoHomeComplete callback
- // this callback is called after that additional move is complete
- // in this example, after doing the additional post limit switch steps
- // if the effector has an identifer of "6", set pin 12 high
- // char effectorIdentifier[9];
- // effector->getIdentifier(effectorIdentifier, 9);
- // if (strcmp(effectorIdentifier, "6") == 0)
- // {
- // digitalWrite(12, HIGH);
- // }
- }
- } // namespace Callbacks
Advertisement
Add Comment
Please, Sign In to add comment