BurningWreck

Bottango - Neopixel color changes

Dec 10th, 2025
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.05 KB | Software | 0 0
  1. // Bottango - Neopixel color changes
  2. // Controls colors of Neopixels via Color Event in Bottango
  3. // In Arduino IDE, replace BottangoArduinoCallbacks.cpp with this code
  4. // Tested with Bottango 0.7.1p7a
  5.  
  6. // Edit the following:
  7. // - Pin Neopixels are connected to
  8. // - Number of Neopixels you have
  9. //
  10. // In Arduino software, add FastLED library:
  11. // Library Manager > Search for "FastLED", and install
  12. //
  13. // Then upload to your controller with Arduino IDE.
  14. //
  15. // In Bottango desktop app, set up a Color Event:
  16. // Build tab > Create Part > Custom Events > Color
  17. // On right panel:
  18. // Rename to NeoPixels
  19. // Select Live On Project Launch
  20. // Set Identifier to a descriptive name - use "neoColor" to match this code
  21.  
  22. // NOTE: For more than 1 or 2 Neopixels you will need to power them with their own
  23. // power supply.  See the Adafruit Neopixel Guide for details.
  24. // An Arduino UNO or ESP32 can not run them on their own, too many will
  25. // brown out & reset the controller, and the Bottango desktop app will show an error that
  26. // says, "The hardware driver has been set to not live."
  27.  
  28. #include "BottangoArduinoCallbacks.h"
  29. #include "src/AbstractEffector.h"
  30. #include "src/Outgoing.h"
  31. #include "src/BottangoCore.h"
  32.  
  33. // FastLED setup
  34. #include "FastLED.h"
  35. #define DATA_PIN 14             // Edit this to match your setup
  36. #define LED_TYPE NEOPIXEL
  37. #define COLOR_ORDER GRB
  38. #define NUM_LEDS 8              // Edit this - How many LEDs?
  39. #define BRIGHTNESS 75
  40. CRGB leds[NUM_LEDS];
  41.  
  42.  
  43. namespace Callbacks {
  44. // !!!!!!!!!!!!!!! //
  45. // !! CONTROLLER LIFECYCLE CALLBACKS !! //
  46. // !!!!!!!!!!!!!!! //
  47.  
  48. // called AFTER a successful handshake with the Bottango application, signifying that this controller has started.
  49. // use for general case startup process
  50. // Effector registration will happen after this callback, in their own callback.
  51. // If you have effector registration specific needs, you should use onEffectorRegistered
  52. void onThisControllerStarted() {
  53.   FastLED.addLeds<LED_TYPE, DATA_PIN>(leds, NUM_LEDS);
  54.   FastLED.setBrightness(BRIGHTNESS);
  55. }
  56.  
  57. // called after the controller recieves a stop command. The controller will stop all movement, deregister all effectors
  58. // After which this call back is triggered.
  59. void onThisControllerStopped() {
  60. }
  61.  
  62. // called each loop cycle. If you have timing based code you'd like to utilize outside of the Bottango animation
  63. // This callback occurs BEFORE all effectors process their movement, at the end of the loop.
  64. void onEarlyLoop() {
  65.   // Example for triggering animations in your own logic, while in offline (save to code / SD card) mode
  66.   // if not playing anything, play animation index 2 (the third exported animation) and set it to looping
  67.  
  68.   // if (BottangoCore::commandStreamProvider->streamIsInProgress() == false)
  69.   // {
  70.   //     BottangoCore::commandStreamProvider->startCommandStream(2, true);
  71.   // }
  72.   //
  73.   // The following will stop an offline animation from playing if any
  74.   // BottangoCore::commandStreamProvider->stop();
  75. }
  76.  
  77. // called each loop cycle.
  78. // This callback occurs AFTER all effectors process their movement, at the end of the loop.
  79. void onLateLoop() {
  80.  
  81. }
  82.  
  83. // !!!!!!!!!!!!!!! //
  84. // !! EFFECTOR CALLBACKS !! //
  85. // !!!!!!!!!!!!!!! //
  86.  
  87. // 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.
  88. // for most effectors, it is the first pin in their set of pins
  89. // i2c effectors have the i2c address before the first pin
  90. // you query for an effector with a c string char array, instanitated at 9 characters (8 for the identifier, and a null terminating char)
  91.  
  92. // The below are called by built in effectors at various stages in their lifecycle
  93.  
  94. // called by an effector when registered, after registration is complete
  95. void onEffectorRegistered(AbstractEffector *effector) {
  96.   // example, turn on built in LED if effector registered with identifier "1";
  97.   // char effectorIdentifier[9];
  98.   // effector->getIdentifier(effectorIdentifier, 9);
  99.  
  100. }
  101.  
  102. // called by an effector when deregistered, before deregistration is complete
  103. void onEffectorDeregistered(AbstractEffector *effector) {
  104.   // example, turn off built in LED if effector registered with identifier "1";
  105.  
  106.   // char effectorIdentifier[9];
  107.   // effector->getIdentifier(effectorIdentifier, 9);
  108.  
  109.   // if (strcmp(effectorIdentifier, "1") == 0)
  110.   // {
  111.   //     pinMode(LED_BUILTIN, OUTPUT);
  112.   //     digitalWrite(LED_BUILTIN, LOW);
  113.   // }
  114. }
  115.  
  116. // called by effectors each loop with its current signal (example: servo PWM or stepper steps from home )
  117. // didChange is true if different from last update called
  118. void effectorSignalOnLoop(AbstractEffector *effector, int signal, bool didChange) {
  119.   // example, set built in led for effector with identifier "1" based on if signal is greater than 1500
  120.  
  121.   // char effectorIdentifier[9];
  122.   // effector->getIdentifier(effectorIdentifier, 9);
  123.  
  124.   // if (strcmp(effectorIdentifier, "1") == 0)
  125.   // {
  126.   //     pinMode(LED_BUILTIN, OUTPUT);
  127.   //     if (signal > 1500)
  128.   //     {
  129.   //         digitalWrite(LED_BUILTIN, HIGH);
  130.   //     }
  131.   //     else
  132.   //     {
  133.   //         digitalWrite(LED_BUILTIN, LOW);
  134.   //     }
  135.   // }
  136.  
  137.   // another example, drive a custom motor, which you have coded to have a setSignal function
  138.   // if (strcmp(effectorIdentifier, "myMotor") == 0)
  139.   // {
  140.   //      myMotor->setSignal(signal);
  141.   // }
  142. }
  143.  
  144. // !!!!!!!!!!!!!!!!!!! //
  145. // !! CUSTOM EVENTS !! //
  146. // !!!!!!!!!!!!!!!!!!! //
  147. // The below are called by custom events so you can provide your own behaviours
  148.  
  149. // 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)
  150. void onCurvedCustomEventMovementChanged(AbstractEffector *effector, float newMovement) {
  151.   // example, fade an led based on the new movement value
  152.   // char effectorIdentifier[9];
  153.   // effector->getIdentifier(effectorIdentifier, 9);
  154.  
  155.   // if (strcmp(effectorIdentifier, "myLight") == 0)
  156.   // {
  157.   //     pinMode(5, OUTPUT);
  158.   //     int brightness = 255 * newMovement;
  159.   //     analogWrite(5, brightness);
  160.   // }
  161. }
  162.  
  163. // called by a on off custom event any time the on off value is changed.
  164. void onOnOffCustomEventOnOffChanged(AbstractEffector *effector, bool on) {
  165.   // example, turn on built in led based on the on off value
  166.   // char effectorIdentifier[9];
  167.   // effector->getIdentifier(effectorIdentifier, 9);
  168.  
  169.   // if (strcmp(effectorIdentifier, "Cylon") == 0) {  // Edit the Identifier ("Cylon") to match On/Off event
  170.   //   Cylon_animating = !Cylon_animating;
  171.   // }
  172. }
  173.  
  174. // called by a trigger custom event any time the on event is triggered.
  175. void onTriggerCustomEventTriggered(AbstractEffector *effector) {
  176.   // example, set led to a random brightness each trigger
  177.   // char effectorIdentifier[9];
  178.   // effector->getIdentifier(effectorIdentifier, 9);
  179.  
  180.   // if (strcmp(effectorIdentifier, "myLight") == 0)
  181.   // {
  182.   //     pinMode(5, OUTPUT);
  183.   //     int brightness = random(0, 256);
  184.   //     analogWrite(5, brightness);
  185.   // }
  186. }
  187.  
  188. void onColorCustomEventColorChanged(AbstractEffector *effector, byte newRed, byte newGreen, byte newBlue) {
  189.   char effectorIdentifier[9];
  190.   effector->getIdentifier(effectorIdentifier, 9);
  191.  
  192.   if (strcmp(effectorIdentifier, "neoColor") == 0) {
  193.     fill_solid(leds, NUM_LEDS, CRGB(newRed, newGreen, newBlue));
  194.     FastLED.show();
  195.   }
  196. }
  197.  
  198. bool isEffectorAutoHomeComplete(AbstractEffector *effector, int &postAutoSyncMove, int autoSyncDirection) {
  199.   // return true if the given stepper is at home position
  200.   // else return false
  201.  
  202.   // example, end homing on stepper with step on pin 6, when pin 10 is read high
  203.  
  204.   // int autoSyncDirection is the direction (+1 or -1) of the auto sync movement
  205.  
  206.   // postAutoSyncMove is additional steps you'd like to take after auto home is complete
  207.   // as an example, if you want to hit a limit switch, then move 200 steps clockwise
  208.   // set postAutoSyncMove = 200 and return true when the limit switch is hit
  209.   // set postAutoSyncMove to a negative number to step counter clockwise
  210.  
  211.   // char effectorIdentifier[9];
  212.   // effector->getIdentifier(effectorIdentifier, 9);
  213.  
  214.   // if (strcmp(effectorIdentifier, "6") == 0)
  215.   // {
  216.   //     pinMode(10, INPUT);
  217.   //     if (digitalRead(10) == HIGH)
  218.   //     {
  219.   //         return true;
  220.   //     }
  221.   // }
  222.  
  223.   return false;
  224. }
  225.  
  226. void onEffectorPostAutoHomeSecondarySyncComplete(AbstractEffector *effector) {
  227.   // if moving a stepper after homing via the postAutoSyncMove int in isStepperAutoHomeComplete callback
  228.   // this callback is called after that additional move is complete
  229.  
  230.   // in this example, after doing the additional post limit switch steps
  231.   // if the effector has an identifer of "6", set pin 12 high
  232.  
  233.   // char effectorIdentifier[9];
  234.   // effector->getIdentifier(effectorIdentifier, 9);
  235.  
  236.   // if (strcmp(effectorIdentifier, "6") == 0)
  237.   // {
  238.   //      digitalWrite(12, HIGH);
  239.   // }
  240. }
  241.  
  242. void onEffectorHomeReset(AbstractEffector *effector) {
  243.   // callback when an effector is no longer considered homed, use for you own internal state tracking if needed.
  244. }
  245. }  // namespace Callbacks
Tags: #Bottango
Advertisement
Add Comment
Please, Sign In to add comment