Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
Azuolas
Published

Bluetooth RGB LED Controller for iPhone & Android

It is an engaging Arduino project that empowers users to control an RGB LED strip via Bluetooth using their iPhone or Android device.

IntermediateFull instructions provided245
Bluetooth RGB LED Controller for iPhone & Android

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
HM-10
×1
Power Supply 5V 8A
×1
WS2812 Addressable LED Strip
Digilent WS2812 Addressable LED Strip
2m, 60LED/1m, IP30
×1
Resistor 220 ohm
Resistor 220 ohm
×2
Resistor 100 ohm
Resistor 100 ohm
×1

Software apps and online services

Dabble
STEMpedia Dabble

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
3D Printer (generic)
3D Printer (generic)
(Highly optional)

Story

Read more

Custom parts and enclosures

Lid

Sketchfab still processing.

Box

Sketchfab still processing.

Latch

Sketchfab still processing.

Schematics

Schematic

Schematic

Code

Led Control

Arduino
This code enables you to use Dabble terminal to control the animations, colors and brightness of the led strip
#define CUSTOM_SETTINGS
#define INCLUDE_TERMINAL_MODULE
#include <Dabble.h>
#include <FastLED.h>

#define LED_PIN 6
#define NUM_LEDS 120
CRGB leds[NUM_LEDS];
uint8_t paletteIndex = 0;
uint8_t colorIndex[NUM_LEDS];
String currentAnimation = "";  // Keeps track of the active animation
uint8_t    numdots =   4;                                     // Number of dots in use.
uint8_t   thisfade =   2;                                     // How long should the trails be. Very low value = longer trails.
uint8_t   thisdiff =  16;                                     // Incremental change in hue between each dot.
uint8_t    thishue =   0;                                     // Starting hue.
uint8_t     curhue =   0;                                     // The current hue
uint8_t    thissat = 255;                                     // Saturation of the colour.
uint8_t thisbright = 255;                                     // How bright should the LED/display be.
uint8_t   thisbeat =   5;    
CRGBPalette16 currentPalette;                                 // Use palettes instead of direct CHSV or CRGB assignments
CRGBPalette16 targetPalette;                                  // Also support smooth palette transitioning
TBlendType    currentBlending;    
DEFINE_GRADIENT_PALETTE(club_gp) {
  0, 255, 0, 255,
  64, 186, 85, 211,
  128, 147, 112, 219,
  192, 123, 104, 238,
  255, 100, 76, 204,
};

CRGBPalette16 club = club_gp;


void setup() {
  Serial.begin(9600);
  Dabble.begin(9600);
  currentPalette  = CRGBPalette16(CRGB::Black);
  targetPalette   = club_gp;
  currentBlending = LINEARBLEND;  
  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.clear();
  FastLED.show();

  for (int i = 0; i < NUM_LEDS; i++) {
    colorIndex[i] = random8();
  }

  Serial.println("Setup complete. Waiting for commands...");
}
String readCommand() {
    String command = "";  
    while (Terminal.available()) {
        char c = Terminal.read();  
        if (c == '\n' || c == '\r') break;  
        command += c;  
    }
    return command;
}
void loop() {
  Dabble.processInput(); 

 
  if (Terminal.available()) {
    String command = readCommand();
    command.trim();
    processCommand(command);  
  }

 
 else if (currentAnimation == "PARTY") {
    animateParty();
  } else if (currentAnimation == "CYLON") {
    animateCylon();
  }
  else if (currentAnimation == "SEA") {
    animateSea();
  }
}
void processCommand(String cmd) {
    cmd.toUpperCase();  

 if (cmd == "PARTY") {
        currentAnimation = "PARTY"; 
    }    else if (cmd.startsWith("BRIGHTNESS")) {
   
        int spaceIndex = cmd.indexOf(' ');
        if (spaceIndex != -1) {
            String brightnessValue = cmd.substring(spaceIndex + 1);
            int brightness = brightnessValue.toInt();
            if (brightness >= 0 && brightness <= 255) {
                FastLED.setBrightness(brightness);
                FastLED.show();
            } 
        } 
        return;
    }else if (cmd == "CYLON") {
        currentAnimation = "CYLON";  
    } else if (cmd == "SEA") {
        currentAnimation = "SEA";  
    }  else if (cmd == "OFF") {
        currentAnimation = "";  
        setColor(CRGB::Black);
    } else if (cmd == "RED") {
        currentAnimation = "";
        setColor(CRGB::Red);
    } else if (cmd == "GREEN") {
        currentAnimation = "";
        setColor(CRGB::Green);
    } else if (cmd == "BLUE") {
        currentAnimation = "";
        setColor(CRGB::Blue);
    } else if (cmd == "YELLOW") {
        currentAnimation = "";
        setColor(CRGB::Yellow);
    } else if (cmd == "MAGENTA") {
        currentAnimation = "";
        setColor(CRGB::Magenta);
    }  else if (cmd == "WHITE") {
        currentAnimation = "";
        setColor(CRGB::White);
    } else if (cmd == "ORANGE") {
        currentAnimation = "";
        setColor(CRGB::Orange);
    } else if (cmd == "PURPLE") {
        currentAnimation = "";
        setColor(CRGB::Purple);
    } else if (cmd == "GOLD") {
        currentAnimation = "";
        setColor(CRGB::Gold);
    } else if (cmd == "SKYBLUE") {
        currentAnimation = "";
        setColor(CRGB::DeepSkyBlue);
    } else if (cmd == "KHAKI") {
        currentAnimation = "";
        setColor(CRGB::Khaki);
    } else if (cmd == "INDIGO") {
        currentAnimation = "";
        setColor(CRGB::Indigo);
    } else if (cmd == "VIOLET") {
        currentAnimation = "";
        setColor(CRGB::Violet);
    } else if (cmd == "CRIMSON") {
        currentAnimation = "";
        setColor(CRGB::Crimson);
    }  else if (cmd == "LIME") {
        currentAnimation = "";
        setColor(CRGB::Lime);
    } else if (cmd == "TEAL") {
        currentAnimation = "";
        setColor(CRGB::Teal);
    } else if (cmd == "MAROON") {
        currentAnimation = "";
        setColor(CRGB::Maroon);
    }  else if (cmd == "SPRINGGREEN") {
        currentAnimation = "";
        setColor(CRGB::SpringGreen);
    }   else if (cmd == "MIDNIGHTBLUE") {
        currentAnimation = "";
        setColor(CRGB::MidnightBlue);
    } else if (cmd == "FORESTGREEN") {
        currentAnimation = "";
        setColor(CRGB::ForestGreen);
    }  else if (cmd == "PERU") {
        currentAnimation = "";
        setColor(CRGB::Peru);
    }  else if (cmd == "ORCHID") {
        currentAnimation = "";
        setColor(CRGB::Orchid);
    }    else {
        Serial.println("Unknown command: " + cmd);
    }
}


void animateSea() {
    static uint32_t lastUpdate = 0;
    static uint8_t waveIndex = 0;  

  
    CRGBPalette16 seaPalette = CRGBPalette16(
        CRGB::DeepSkyBlue,   
        CRGB::Aqua,          
        CRGB::Aquamarine,         
        CRGB::Blue           
    );


    if (millis() - lastUpdate > 50) {
        lastUpdate = millis();

        for (int i = 0; i < NUM_LEDS; i++) {
            uint8_t colorIndex = sin8(waveIndex + (i * 10)); 
            leds[i] = ColorFromPalette(seaPalette, colorIndex, 255, LINEARBLEND);
        }

        waveIndex += 4;  
        FastLED.show();
    }
}

void animateCylon() {
    static uint32_t lastUpdate = 0;

   
    if (millis() - lastUpdate > 50) {
        lastUpdate = millis();

     
        if (currentAnimation != "CYLON") {
            return; 
        }

     
        EVERY_N_MILLISECONDS(100) { 
            uint8_t maxChanges = 24;
            nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges);
        }

        ChangeMe();
        juggle_pal();
        FastLED.show();  
    }
}

void animateParty() {
  static uint32_t lastUpdate = 0;
  if (millis() - lastUpdate > 50) { 
    lastUpdate = millis();
    leds[random8(0, NUM_LEDS)] = ColorFromPalette(club, random8(), 255, LINEARBLEND);
    fadeToBlackBy(leds, NUM_LEDS, 1);
    FastLED.show();
  }
}

void setColor(CRGB color) {
  fill_solid(leds, NUM_LEDS, color);
  FastLED.show();
}
void juggle_pal() {                                           
  
  curhue = thishue;                                           
  fadeToBlackBy(leds, NUM_LEDS, thisfade);
  
  for( int i = 0; i < numdots; i++) {
    leds[beatsin16(thisbeat+i+numdots,0,NUM_LEDS)] += ColorFromPalette(currentPalette, curhue , thisbright, currentBlending);    // Munge the values and pick a colour from the palette
    curhue += thisdiff;
  }
  
}



void ChangeMe() {                                             // A time (rather than loop) based demo sequencer. This gives us full control over the length of each sequence.
  
  uint8_t secondHand = (millis() / 1000) % 30;                // IMPORTANT!!! Change '30' to a different value to change duration of the loop.
  static uint8_t lastSecond = 99;                             // Static variable, means it's only defined once. This is our 'debounce' variable.
  
  if (lastSecond != secondHand) {                             // Debounce to make sure we're not repeating an assignment.
    lastSecond = secondHand;
    switch(secondHand) {
      case  0: numdots = 1; thisbeat = 20; thisdiff = 16; thisfade = 2; thishue = 0; break;                  // You can change values here, one at a time , or altogether.
      case 10: numdots = 4; thisbeat = 10; thisdiff = 16; thisfade = 8; thishue = 128; break;
      case 20: numdots = 8; thisbeat =  3; thisdiff =  0; thisfade = 8; thishue=random8(); break;           // Only gets called once, and not continuously for the next several seconds. Therefore, no rainbows.
      case 30: break;
    }
  }
  
}

Credits

Azuolas
1 project • 0 followers
I am a first-year Automation and Control student at KTU, interested in Arduino projects and striving to optimize my environment!
Contact

Comments

Please log in or sign up to comment.