Download the Ada-remoteFXTrigger_NeoTrellis_FastLED_RX code below and upload it to your controller box.
// SPDX-FileCopyrightText: 2019 Erin St. Blaine for Adafruit Industries // SPDX-FileCopyrightText: 2019 John Edgar Park for Adafruit Industries // // SPDX-License-Identifier: MIT // //Ada_remoteFXTrigger_RX_NeoPixel //Remote Effects Trigger Box Receiver //by John Park & Erin St Blaine //for Adafruit Industries // // Button box receiver with NeoPixels using FastLED // // //MIT License #include <FastLED.h> #define LED_PIN 12 #define NUM_LEDS 20 #define LED_TYPE WS2812B #define COLOR_ORDER GRB CRGBArray<NUM_LEDS> leds; #include <SPI.h> #include <RH_RF69.h> #include <Wire.h> #define LED 13 /********** NeoPixel Setup *************/ #define UPDATES_PER_SECOND 100 CRGBPalette16 currentPalette( CRGB::Black); CRGBPalette16 targetPalette( PartyColors_p ); TBlendType currentBlending; int SPEEDO = 25; int STEPS = 20; int HUE = 200; // starting color int SATURATION = 255; int BRIGHTNESS = 200; int glitter = 0; /************ Radio Setup ***************/ // Change to 434.0 or other frequency, must match RX's freq! #define RF69_FREQ 915.0 #if defined (__AVR_ATmega32U4__) // Feather 32u4 w/Radio #define RFM69_CS 8 #define RFM69_INT 7 #define RFM69_RST 4 #endif #if defined(ARDUINO_SAMD_FEATHER_M0) // Feather M0 w/Radio #define RFM69_CS 8 #define RFM69_INT 3 #define RFM69_RST 4 #endif #if defined (__AVR_ATmega328P__) // Feather 328P w/wing #define RFM69_INT 3 // #define RFM69_CS 4 // #define RFM69_RST 2 // "A" #endif #if defined(ESP32) // ESP32 feather w/wing #define RFM69_RST 13 // same as LED #define RFM69_CS 33 // "B" #define RFM69_INT 27 // "A" #endif // Singleton instance of the radio driver RH_RF69 rf69(RFM69_CS, RFM69_INT); bool oldState = HIGH; void setup() { delay( 3000 ); // power-up safety delay FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip ); FastLED.setBrightness( BRIGHTNESS ); pinMode(LED, OUTPUT); pinMode(RFM69_RST, OUTPUT); digitalWrite(RFM69_RST, LOW); Serial.println("Feather RFM69 RX/TX Test!"); // manual reset digitalWrite(RFM69_RST, HIGH); delay(10); digitalWrite(RFM69_RST, LOW); delay(10); if (!rf69.init()) { Serial.println("RFM69 radio init failed"); while (1); } Serial.println("RFM69 radio init OK!"); // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module) // No encryption if (!rf69.setFrequency(RF69_FREQ)) { Serial.println("setFrequency failed"); } // If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the // ishighpowermodule flag set like this: rf69.setTxPower(14, true); // The encryption key has to be the same as the one in the server uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; rf69.setEncryptionKey(key); pinMode(LED, OUTPUT); Serial.print("RFM69 radio @"); Serial.print((int)RF69_FREQ); Serial.println(" MHz"); delay(500); Gradient(); //So the lights come un upon startup, even if the trigger box is off } void loop(){ if (rf69.waitAvailableTimeout(1000)) { // Should be a message for us now uint8_t buf[RH_RF69_MAX_MESSAGE_LEN]; uint8_t len = sizeof(buf); if (! rf69.recv(buf, &len)) { Serial.println("Receive failed"); return; } //digitalWrite(LED, HIGH); //rf69.printBuffer("Received: ", buf, len); //buf[len] = 0; //Serial.print("Got: "); Serial.println((char*)buf); //Serial.print("RSSI: "); Serial.println(rf69.lastRssi(), DEC); char radiopacket[20] = "Button #";//prep reply message to send if (buf[0]=='A'){ //the letter sent from the button ledMode(0); radiopacket[8] = 'A'; } else if (buf[0]=='B'){ //the letter sent from the button ledMode(1); radiopacket[8] = 'B'; } else if (buf[0]=='C'){ //the letter sent from the button ledMode(2); radiopacket[8] = 'C'; } else if (buf[0]=='D'){ //the letter sent from the button ledMode(3); radiopacket[8] = 'D'; } else if (buf[0]=='E'){ //the letter sent from the button ledMode(4); radiopacket[8] = 'E'; } else if (buf[0]=='F'){ //the letter sent from the button ledMode(5); radiopacket[8] = 'F'; } else if (buf[0]=='G'){ //the letter sent from the button ledMode(6); radiopacket[8] = 'G'; } else if (buf[0]=='H'){ //the letter sent from the button ledMode(7); radiopacket[8] = 'H'; } else if (buf[0]=='I'){ //the letter sent from the button ledMode(8); radiopacket[8] = 'I'; } else if (buf[0]=='J'){ //the letter sent from the button ledMode(9); radiopacket[8] = 'J'; } else if (buf[0]=='K'){ //the letter sent from the button ledMode(10); radiopacket[8] = 'K'; } else if (buf[0]=='L'){ //the letter sent from the button ledMode(11); radiopacket[8] = 'L'; } else if (buf[0]=='M'){ //the letter sent from the button ledMode(12); radiopacket[8] = 'M'; } else if (buf[0]=='N'){ //the letter sent from the button ledMode(13); radiopacket[8] = 'N'; } else if (buf[0]=='O'){ //the letter sent from the button ledMode(14); radiopacket[8] = 'O'; } else if (buf[0]=='P'){ //the letter sent from the button ledMode(15); radiopacket[8] = 'P'; } else if (buf[0]=='Q'){ //the letter sent from the button ledMode(16); radiopacket[8] = 'Q'; } else if (buf[0]=='R'){ //the letter sent from the button ledMode(17); radiopacket[8] = 'R'; } else if (buf[0]=='S'){ //the letter sent from the button ledMode(18); radiopacket[8] = 'S'; } else if (buf[0]=='T'){ //the letter sent from the button ledMode(19); radiopacket[8] = 'T'; } else if (buf[0]=='Z'){ //the letter sent from the button ledMode(20); radiopacket[8] = 'Z'; } /* radiopacket[9] = 0; Serial.print("Sending "); Serial.println(radiopacket); rf69.send((uint8_t *)radiopacket, strlen(radiopacket)); rf69.waitPacketSent(); */ digitalWrite(LED, LOW); } } void ledMode(int i) { switch(i){ case 0: HUE=0; SATURATION=255; BRIGHTNESS=200; Solid(); // red break; case 1: HUE=40; SATURATION=255; BRIGHTNESS=200; Solid(); // gold break; case 2: HUE=100; SATURATION=255; BRIGHTNESS=200; Solid(); // green break; case 3: HUE=140; SATURATION=255; BRIGHTNESS=200; Solid(); // Blue break; case 4: HUE=180; SATURATION=255; BRIGHTNESS=200; Solid(); // purple break; case 5: HUE=220; SATURATION=255; BRIGHTNESS=200; Solid(); // pink break; case 6: HUE=0; SATURATION=0; BRIGHTNESS=200; Solid(); // white break; case 7: HUE=0; BRIGHTNESS=0; Solid(); // off break; case 8: HUE=0; SATURATION=255; BRIGHTNESS=200; Gradient(); // red break; case 9: HUE=40; SATURATION=255; BRIGHTNESS=200; Gradient(); // gold break; case 10: HUE=100; SATURATION=255; BRIGHTNESS=200; Gradient(); // green break; case 11: HUE=140; SATURATION=255; BRIGHTNESS=200; Gradient(); // blue break; case 12:HUE=180; SATURATION=255; BRIGHTNESS=200; Gradient(); // purple break; case 13:HUE=220; SATURATION=255; BRIGHTNESS=200; Gradient(); // pink break; case 14:HUE=160; SATURATION=50; BRIGHTNESS=200; Gradient(); // white break; case 15:SATURATION=255; BRIGHTNESS=200; Rainbow_Fade(); // rainbow fade break; case 16:STEPS=4; SATURATION=255; BRIGHTNESS=200; Rainbow(); //rainbow 2 break; case 17:STEPS=20; BRIGHTNESS=200; SATURATION=255; Rainbow(); // rainbow 3 break; case 20:BRIGHTNESS=200; break; } } // GRADIENT -------------------------------------------------------------- void Gradient() { SetupGradientPalette(); static uint8_t startIndex = 0; startIndex = startIndex + 1; // motion speed FillLEDsFromPaletteColors( startIndex); FastLED.show(); FastLED.delay(SPEEDO); } // SOLID ---------------------------------------------------- void Solid() { fill_solid(leds, NUM_LEDS, CHSV(HUE, SATURATION, BRIGHTNESS)); FastLED.show(); delay(20); } // RAINBOW -------------------------------------------------- void Rainbow() { FastLED.setBrightness( BRIGHTNESS ); currentPalette = RainbowColors_p; static uint8_t startIndex = 0; startIndex = startIndex + 1; FillLEDsFromPaletteColors( startIndex); FastLED.show(); FastLED.delay(SPEEDO); } // RAINBOW FADE -------------------------------------------------- void Rainbow_Fade() { //-m2-FADE ALL LEDS THROUGH HSV RAINBOW HUE++; if (HUE > 255) {HUE = 0;} for(int idex = 0 ; idex < NUM_LEDS; idex++ ) { leds[idex] = CHSV(HUE, SATURATION, BRIGHTNESS); } LEDS.show(); delay(SPEEDO); } void SetupGradientPalette() { CRGB light = CHSV( HUE + 25, SATURATION - 20, BRIGHTNESS); CRGB dark = CHSV( HUE, SATURATION - 15, BRIGHTNESS); CRGB medium = CHSV ( HUE - 25, SATURATION, BRIGHTNESS); currentPalette = CRGBPalette16( light, light, light, light, medium, medium, medium, medium, dark, dark, dark, dark, medium, medium, medium, medium ); } void FillLEDsFromPaletteColors( uint8_t colorIndex) { uint8_t brightness = BRIGHTNESS; for( int i = 0; i < NUM_LEDS; i++) { leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending); colorIndex += STEPS; } }
Customizing
This code allows you to tell the LEDs what to do when the command is received from the control box. This example code matches the TX code in a number of ways. There are 21 different letters set up that can be received and each letter triggers a different LED mode.
A Note about Animations
FastLED is wonderful at producing buttery smooth animations. However, this setup works much better with very little LED motion or solid colors. Every time the signal is sent from the controller box, the animation is interrupted for just a moment. If we didn't interrupt the animation then most of your button presses would be missed while the animation was busy running, making it seem the controller box was not working or that the commands weren't being received. So I've made simple animations and solids the focus of this tutorial. For example, the Rainbow_Fade()
animation does fade through the rainbow but it does it very slowly due to being interrupted so much.
There are two sections of code to pay attention to. Look for this section:
if (buf[0]=='A'){ //the letter sent from the button ledMode(0); radiopacket[8] = 'A'; } else if (buf[0]=='B'){ //the letter sent from the button ledMode(1); radiopacket[8] = 'B'; }
The radio packet being sent (A
or B
in this case) will cause the ledMode
to change.
Further down, you'll find:
void ledMode(int i) { switch(i){ case 0: HUE=0; SATURATION=255; BRIGHTNESS=200; Solid(); // red break; case 1: HUE=40; SATURATION=255; BRIGHTNESS=200; Solid(); // gold break;
These are the different modes being triggered by each radio packet. Here is where you can change what happens on the LED strip when button 0 is pressed, sending A, and triggering LED mode 0.
Text editor powered by tinymce.