HC-05 bluetooth module fails to light up LEDs on a strand

Hello, thank you for checking out my post. I recently bought an HC-05 Bluetooth module hoping to use it on a project that I am working on. I tested it using a simple program that lights up one led when it receives a signal from your phone. However, when I went to use the full strand it refuses to work. I am using WS2811 addressable LEDs with a 12v power source and they work fine with some of the example code. I am following tutorials for most of this because I am very new and would like to learn more about electronics. I think that the code I am using is having trouble converting characters to data values and lighting up the LEDs

Here is the code

/* 
 * Stranger Things Message Wall
 * Written by Zach Hipps 2017 for byte sized YouTube channel: https://www.youtube.com/c/bytesized
 * 
 * Build instructions can be found at https://www.bytesizedelectronics.com/projects/how-to-make-a-stranger-things-message-wall
 * Video can be found at https://youtu.be/tG8sQMoKrb0
 * 
 * How to use: 
 * -----------
 * Connect string of WS2811 LEDs (or equivient) to the arduino with the data signal going to pin 3. 
 * Be sure to use a separate power supply as the arduino's voltage regulator cannot supply enough current for all these LEDs.
 * Send serial data to the program either using the serial monitor, or some external serial device (like HC-05 bluetooth module) connected to RX and TX pins. 
 * 
 * Known issues:
 * ------------
 * Due to strict timing requirments from the WS2811 LEDs, the FastLED library has to disable interrupts when writing to the LEDs. This will cause some serial data to be lost. 
 * The practical result is that messages longer than 6 characters seem to get truncated. Some sort of software buffering could potentially fix this. See https://github.com/FastLED/FastLED/wiki/Interrupt-problems
 * 
 */



#include "FastLED.h" // This is the library that does all the work with the LEDs


#define NUM_LEDS 28 // The number of LEDs in the string
#define DATA_PIN 3 // The pin that connects to the data signal on the LEDs

CRGB leds[NUM_LEDS]; // Define array with NUM_LEDS elements
CRGB led_color[NUM_LEDS]= // Define array to store LED colors
{
  led_color[0] = CRGB::Red,
  led_color[1] = CRGB::Red,
  led_color[2] = CRGB::Red,
  led_color[3] = CRGB::Red,
  led_color[4] = CRGB::Red,
  led_color[5] = CRGB::Red,
  led_color[6] = CRGB::Red,
  led_color[7] = CRGB::Red,
  led_color[8] = CRGB::Red,
  led_color[9] = CRGB::Red,
  led_color[10] = CRGB::Red,
  led_color[11] = CRGB::Red,
  led_color[12] = CRGB::Red,
  led_color[13] = CRGB::Red,
  led_color[14] = CRGB::Red,
  led_color[15] = CRGB::Red,
  led_color[16] = CRGB::Red,
  led_color[17] = CRGB::Red,
  led_color[18] = CRGB::Red,
  led_color[19] = CRGB::Red,
  led_color[20] = CRGB::Red,
  led_color[21] = CRGB::Red,
  led_color[22] = CRGB::Red,
  led_color[23] = CRGB::Red,
  led_color[24] = CRGB::Red,
  led_color[25] = CRGB::Red,
  led_color[26] = CRGB::Red,
  led_color[27] = CRGB::Blue,
};

void setup() 
{
  Serial.begin(115200); // start serial peripheral
  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS); // instantiate LED library with our information
  FastLED.clear(); // clear the LED display before doing anything else
}

void loop() 
{
  if(Serial.available()) // If there is serial data waiting in the buffer
  { 
    ascii2ledIndex(Serial.read()); // read the data and convert each letter from ascii to the appropriate LED index in the string
  }
}


// Convert a letter from ascii to the appropriate LED index in the string
void ascii2ledIndex(int asciiLetter)
{
    //Serial.println(asciiLetter);
    int ledIndex = -1; // create variable to store led index
    int indexMap[]={20,21,22,23,24,25,26,27,18,17,16,15,14,13,12,11,10,0,1,2,3,4,5,6,7,8}; // When I hung the LED string on the wall the first letters in the string are R S T U V W X Y Z then it skips one LED and winds around to  Q P O N M L K J I then it skips one LED and winds to A B C D E F G H
    if(asciiLetter >= 97 && asciiLetter <= 122) // It's an ASCII Lowercase Letter
    {
      ledIndex = indexMap[asciiLetter - 97];
    }
    else if (asciiLetter >= 65 && asciiLetter <= 90) // It's an ASCII Uppercase Letter
    {
      ledIndex = indexMap[asciiLetter - 65];
    }
    Serial.println(ledIndex);
    if(ledIndex >= -1) // valid LED index converted from either uppercase or lowercase letter
    {
      leds[ledIndex] = led_color[ledIndex];
      FastLED.show();
      delay(3000);
      FastLED.clear();
      FastLED.show();
      delay(250);
    }
    else // invalid led index. display blank. this is useful for spaces and other punctuation. 
    {
      FastLED.clear();
      FastLED.show();
      delay(750);
    }
    
}


// Test function that displays one LED at a time. This appears like the LED is chasing down the string. 
void chase() 
{
  for(int dot = 0; dot < NUM_LEDS; dot++) 
  { 
      leds[dot] = led_color[dot]; 
      FastLED.show();
      // clear this led for the next time around the loop
      leds[dot] = CRGB::Black;
      delay(100);
  }
}

// Test function that blinks all the LEDs 
void RGB_Blink()
{
  // Set all the colors
  leds[0] = led_color[0]; 
  leds[1] = led_color[1]; 
  leds[2] = led_color[2]; 
  leds[3] = led_color[3]; 
  leds[4] = led_color[4]; 
  leds[5] = led_color[5]; 
  leds[6] = led_color[6]; 
  leds[7] = led_color[7]; 
  leds[8] = led_color[8]; 
  leds[9] = led_color[9]; 
  leds[10] = led_color[10]; 
  leds[11] = led_color[11]; 
  leds[12] = led_color[12]; 
  leds[13] = led_color[13]; 
  leds[14] = led_color[14]; 
  leds[15] = led_color[15]; 
  leds[16] = led_color[16]; 
  leds[17] = led_color[17]; 
  leds[18] = led_color[18]; 
  leds[19] = led_color[19]; 
  leds[20] = led_color[20]; 
  leds[21] = led_color[21]; 
  leds[22] = led_color[22]; 
  leds[23] = led_color[23]; 
  leds[24] = led_color[24]; 
  leds[25] = led_color[25]; 
  leds[26] = led_color[26];
  leds[27] = led_color[27];  
  FastLED.show();
  delay(750);
  // Now turn the LED off, then pause
  FastLED.clear();
  FastLED.show();
  delay(500);
}

I have searched through the build guide and tried all the fixes that he describes before the code yet it refuses to work. When a character goes through the program an led number is supposed to appear in the serial monitor. He says to use the TX and RX pins to transfer data but when I plug them In the only numbers that the monitor reads are “-1” repeatedly. However when TX and RX are not plugged in, it reads the numbers fine but still does not light up the LEDs. I know that TX and RX have to remain unplugged while the program uploads but still no luck. I think the problem is somewhere around here,

//Serial.println(asciiLetter);
    int ledIndex = -1; // create variable to store led index
    int indexMap[]={20,21,22,23,24,25,26,27,18,17,16,15,14,13,12,11,10,0,1,2,3,4,5,6,7,8}; // When I hung the LED string on the wall the first letters in the string are R S T U V W X Y Z then it skips one LED and winds around to  Q P O N M L K J I then it skips one LED and winds to A B C D E F G H
    if(asciiLetter >= 97 && asciiLetter <= 122) // It's an ASCII Lowercase Letter
    {
      ledIndex = indexMap[asciiLetter - 97];
    }
    else if (asciiLetter >= 65 && asciiLetter <= 90) // It's an ASCII Uppercase Letter
    {
      ledIndex = indexMap[asciiLetter - 65];
    }
    Serial.println(ledIndex);
    if(ledIndex >= -1) // valid LED index converted from either uppercase or lowercase letter
    {
      leds[ledIndex] = led_color[ledIndex];
      FastLED.show();
      delay(3000);
      FastLED.clear();
      FastLED.show();
      delay(250);
    }
 
}

because of the -1 in the led index. Please let me know if you can help, and thanks for stopping by.

I also used some code from MIT app inventor, could this be the issue?

Now that I think about it, this post might have been better off uploaded to the programming questions forum, could someone maybe report this and try to have it moved? If not that is fine :slight_smile:

However when TX and RX are not plugged in, it reads the numbers fine but still does not light up the LEDs. I know that TX and RX have to remain unplugged while the program uploads but still no luck.

You have two issues to sort out, and you need to work on them separately.

I would remove the HC05 and how you talk to it (BT terminal app or custom App Inventor ) and get the program working properly with Serial input. Once you have that, adding the blue tooth using the hardware serial inputs, software serial inputs, or an Arduino with multiple serial ports is going to be straightforward.

If you can receive a valid led index from serial, what debugging have you done to see why the lights don't function properly?

Hello, and thanks for stopping by!

I think that I am in a little bit over my head. I do not understand what to do to get the serial LEDs to light up. Its giving me data but it seems inconsistent and random and is still not lighting up, and I am clueless on what to do. I dont know how to get it working any better. I am sorry for being so helpless but I am very new so this is a learning process for me. I tried unplugging the HC-05 and using the code in the serial monitor but still, nothing. I am seriously stuck and I have been looking everywhere for a solution but cant find one.

. I tried unplugging the HC-05 and using the code in the serial monitor

Yes, this is the correct way to go.

Its giving me data but it seems inconsistent and random and is still not lighting up

What do you see for ledIndex with this after entry from the Serial monitor? What letter to you enter, and what does it report?

Serial.println(ledIndex);

I think for simplicity and clarity, it would be best to set the Serial monitor to no line ending. Do you see the pull down menu on the lower left to set the line ending from the monitor?

I am using WS2811 addressable LEDs with a 12v power source and they work fine with some of the example code.

Please post the example code which you use to operate the light string.

Thank you for the tips, putting no line ending on helped greatly. I did not understand that the code was putting a -1 at the end of each word, and I thought that it was trying to add another character. the code assigns the letters with numbers like these -

A - 20
B - 21
C - 22
D - 23
E - 24
F - 25
G - 26
H - 27
I - 18
J - 17
K - 16
L - 15
M - 14
N - 13
O - 12
P - 11
Q - 10
R - 0
S - 1
T - 2
U - 3
V - 4
W - 5
X - 6
Y - 7
Z - 8

That seems fine to me, but the LEDs do not respond when their number is typed in. However, the 22 LEDs that the program is not looking at are still lighting up from this example code.

#include <FastLED.h>

#define LED_PIN     5
#define NUM_LEDS    50
#define BRIGHTNESS  64
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

#define UPDATES_PER_SECOND 100

// This example shows several ways to set up and use 'palettes' of colors
// with FastLED.
//
// These compact palettes provide an easy way to re-colorize your
// animation on the fly, quickly, easily, and with low overhead.
//
// USING palettes is MUCH simpler in practice than in theory, so first just
// run this sketch, and watch the pretty lights as you then read through
// the code.  Although this sketch has eight (or more) different color schemes,
// the entire sketch compiles down to about 6.5K on AVR.
//
// FastLED provides a few pre-configured color palettes, and makes it
// extremely easy to make up your own color schemes with palettes.
//
// Some notes on the more abstract 'theory and practice' of
// FastLED compact palettes are at the bottom of this file.



CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;


void setup() {
    delay( 3000 ); // power-up safety delay
    FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.setBrightness(  BRIGHTNESS );
    
    currentPalette = RainbowColors_p;
    currentBlending = LINEARBLEND;
}


void loop()
{
    ChangePalettePeriodically();
    
    static uint8_t startIndex = 0;
    startIndex = startIndex + 1; /* motion speed */
    
    FillLEDsFromPaletteColors( startIndex);
    
    FastLED.show();
    FastLED.delay(1000 / UPDATES_PER_SECOND);
}

void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
    uint8_t brightness = 255;
    
    for( int i = 0; i < NUM_LEDS; i++) {
        leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
        colorIndex += 3;
    }
}


// There are several different palettes of colors demonstrated here.
//
// FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p,
// OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p.
//
// Additionally, you can manually define your own color palettes, or you can write
// code that creates color palettes on the fly.  All are shown here.

void ChangePalettePeriodically()
{
    uint8_t secondHand = (millis() / 1000) % 60;
    static uint8_t lastSecond = 99;
    
    if( lastSecond != secondHand) {
        lastSecond = secondHand;
        if( secondHand ==  0)  { currentPalette = RainbowColors_p;         currentBlending = LINEARBLEND; }
        if( secondHand == 10)  { currentPalette = RainbowStripeColors_p;   currentBlending = NOBLEND;  }
        if( secondHand == 15)  { currentPalette = RainbowStripeColors_p;   currentBlending = LINEARBLEND; }
        if( secondHand == 20)  { SetupPurpleAndGreenPalette();             currentBlending = LINEARBLEND; }
        if( secondHand == 25)  { SetupTotallyRandomPalette();              currentBlending = LINEARBLEND; }
        if( secondHand == 30)  { SetupBlackAndWhiteStripedPalette();       currentBlending = NOBLEND; }
        if( secondHand == 35)  { SetupBlackAndWhiteStripedPalette();       currentBlending = LINEARBLEND; }
        if( secondHand == 40)  { currentPalette = CloudColors_p;           currentBlending = LINEARBLEND; }
        if( secondHand == 45)  { currentPalette = PartyColors_p;           currentBlending = LINEARBLEND; }
        if( secondHand == 50)  { currentPalette = myRedWhiteBluePalette_p; currentBlending = NOBLEND;  }
        if( secondHand == 55)  { currentPalette = myRedWhiteBluePalette_p; currentBlending = LINEARBLEND; }
    }
}

// This function fills the palette with totally random colors.
void SetupTotallyRandomPalette()
{
    for( int i = 0; i < 16; i++) {
        currentPalette[i] = CHSV( random8(), 255, random8());
    }
}

// This function sets up a palette of black and white stripes,
// using code.  Since the palette is effectively an array of
// sixteen CRGB colors, the various fill_* functions can be used
// to set them up.
void SetupBlackAndWhiteStripedPalette()
{
    // 'black out' all 16 palette entries...
    fill_solid( currentPalette, 16, CRGB::Black);
    // and set every fourth one to white.
    currentPalette[0] = CRGB::White;
    currentPalette[4] = CRGB::White;
    currentPalette[8] = CRGB::White;
    currentPalette[12] = CRGB::White;
    
}

// This function sets up a palette of purple and green stripes.
void SetupPurpleAndGreenPalette()
{
    CRGB purple = CHSV( HUE_PURPLE, 255, 255);
    CRGB green  = CHSV( HUE_GREEN, 255, 255);
    CRGB black  = CRGB::Black;
    
    currentPalette = CRGBPalette16(
                                   green,  green,  black,  black,
                                   purple, purple, black,  black,
                                   green,  green,  black,  black,
                                   purple, purple, black,  black );
}


// This example shows how to set up a static color palette
// which is stored in PROGMEM (flash), which is almost always more
// plentiful than RAM.  A static PROGMEM palette like this
// takes up 64 bytes of flash.
const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM =
{
    CRGB::Red,
    CRGB::Gray, // 'white' is too bright compared to red and blue
    CRGB::Blue,
    CRGB::Black,
    
    CRGB::Red,
    CRGB::Gray,
    CRGB::Blue,
    CRGB::Black,
    
    CRGB::Red,
    CRGB::Red,
    CRGB::Gray,
    CRGB::Gray,
    CRGB::Blue,
    CRGB::Blue,
    CRGB::Black,
    CRGB::Black
};



// Additional notes on FastLED compact palettes:
//
// Normally, in computer graphics, the palette (or "color lookup table")
// has 256 entries, each containing a specific 24-bit RGB color.  You can then
// index into the color palette using a simple 8-bit (one byte) value.
// A 256-entry color palette takes up 768 bytes of RAM, which on Arduino
// is quite possibly "too many" bytes.
//
// FastLED does offer traditional 256-element palettes, for setups that
// can afford the 768-byte cost in RAM.
//
// However, FastLED also offers a compact alternative.  FastLED offers
// palettes that store 16 distinct entries, but can be accessed AS IF
// they actually have 256 entries; this is accomplished by interpolating
// between the 16 explicit entries to create fifteen intermediate palette
// entries between each pair.
//
// So for example, if you set the first two explicit entries of a compact 
// palette to Green (0,255,0) and Blue (0,0,255), and then retrieved 
// the first sixteen entries from the virtual palette (of 256), you'd get
// Green, followed by a smooth gradient from green-to-blue, and then Blue.

Is this a problem? This has never happened to me before while testing the code.

That seems fine to me, but the LEDs do not respond when their number is typed in.

Good progress on the Serial front. In the code from the project there are two test functions for the light string. chase() and blink(). Have you tried to run them? I would certainly be trying a more simple test sketch than the ColorPalette.

However, the 22 LEDs that the program is not looking at are still lighting up from this example code.
Is this a problem? This has never happened to me before while testing the code.

It's possible that the new code is not being loaded. Are you certain that the HC05 is disconnected from the serial pins 0 and 1?

One thing I notice is that the palette test sketch is using pin 5 as the data pin , but the message wall sketch is using pin 3.

If you can get all the lights to work in the chase() sequence and you can get the Serial to read a letter, you will be most of the way to your goal. The bluetooth will be easy.

I tried using the test code for the chase() code but I am having trouble finding where to put it. Do I put it in setup or loop? Or is it an independent function? It is giving me a lot of errors. However, when I unplugged the HC-05 last night I just disconnected the jumper wires so that I would remember where they go, but now I unplugged them fully. I think my main problem with the test code is just figuring out what to define and where. Thanks for your patience!

Or is it an independent function?

Yes. chase() is a function which can be called in either setup() or loop(). It will run once in set up and repeat if called in loop.

Ok, I tried again without #including or #defining anything and it has gotten farther along the test code but still gives me an error,

“exit status 1
a function-definition is not allowed here before ‘{’ token”

I did some research and I think it’s a problem with my curly brackets but I can’t figure out where to add/remove them.

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

{  for(int dot = 0; dot < NUM_LEDS; dot++) 
  { 
      leds[dot] = led_color[dot]; 
      FastLED.show();
      // clear this led for the next time around the loop
      leds[dot] = CRGB::Black;
      delay(100);
  }

}

I know that this is a very basic error message and I’m sorry to bother you, but thank you so much for helping me out!

You are confused between the declaration/definition of a function and when it is called in the code.

The function needs to be declared outside any other function, so “chase()” can go either above or below the “loop()” or “setup()” function.

The function definition is called the prototype, and is presented outside of other functions. For chase() it is

void chase() // function prototype defines the function

{  
  for(int dot = 0; dot < NUM_LEDS; dot++)
  {
      leds[dot] = led_color[dot];
      FastLED.show();
      // clear this led for the next time around the loop
      leds[dot] = CRGB::Black;
      delay(100);
  }

}

setup() or loop() can call the function, but the function definition/prototype should be outside of any other function. Structurally it might look like this

void setup() 
{
  
  chase(); //call chase function

}

void loop ()
{}

void chase() //function prototype define chase function
{
   
  for(int dot = 0; dot < NUM_LEDS; dot++)
  {
      leds[dot] = led_color[dot];
      FastLED.show();
      // clear this led for the next time around the loop
      leds[dot] = CRGB::Black;
      delay(100);
  }
}

The chase() code uploads without error! I fixed my code a little bit and it no longer gives me errors. However, the lights still dont light up. They light up with other example code thought, so maybe I need to add something to the code? Anyways, here is the code. Thank you for your help and patience! :slight_smile:

#include "FastLED.h" // This is the library that does all the work with the LEDs


#define NUM_LEDS 50 // The number of LEDs in the string
#define DATA_PIN 3 // The pin that connects to the data signal on the LEDs
#define BRIGHTNESS 64
CRGB leds[NUM_LEDS]; // Define array with NUM_LEDS elements
CRGB led_color[NUM_LEDS];

void setup()

 {
 
 void chase();

}

void loop ()
{}

void chase()
{
   
  for(int dot = 0; dot < NUM_LEDS; dot++)
  {
      leds[dot] = led_color[dot];
      FastLED.show();
      // clear this led for the next time around the loop
      leds[dot] = CRGB::Black;
      delay(100);
  }
}

I made an error which I corrected in my previous post about how to call the function. Do not use the word void when you call it. I apologize. :frowning:

void setup()

 {
 
  //void chase();
   chase();

}

Do you have some simple example code other than the palette code which does run the lights?

I’m unclear if the led/data pin is pin 3 or pin 5 as you have it wired. Previously, the working example was pin 5 but the current code uses pin 3.

I also think you need to go back the the original code from the website with all the full setup() but call chase() in that code.

/*
 * Stranger Things Message Wall
 * Written by Zach Hipps 2017 for byte sized YouTube channel: https://www.youtube.com/c/bytesized
 *
 * Build instructions can be found at https://www.bytesizedelectronics.com/projects/how-to-make-a-stranger-things-message-wall
 * Video can be found at https://youtu.be/tG8sQMoKrb0
 *
 * How to use:
 * -----------
 * Connect string of WS2811 LEDs (or equivient) to the arduino with the data signal going to pin 3.
 * Be sure to use a separate power supply as the arduino's voltage regulator cannot supply enough current for all these LEDs.
 * Send serial data to the program either using the serial monitor, or some external serial device (like HC-05 bluetooth module) connected to RX and TX pins.
 *
 * Known issues:
 * ------------
 * Due to strict timing requirments from the WS2811 LEDs, the FastLED library has to disable interrupts when writing to the LEDs. This will cause some serial data to be lost.
 * The practical result is that messages longer than 6 characters seem to get truncated. Some sort of software buffering could potentially fix this. See https://github.com/FastLED/FastLED/wiki/Interrupt-problems
 *
 */



#include "FastLED.h" // This is the library that does all the work with the LEDs


#define NUM_LEDS 28 // The number of LEDs in the string
#define DATA_PIN 3 // The pin that connects to the data signal on the LEDs

CRGB leds[NUM_LEDS]; // Define array with NUM_LEDS elements
CRGB led_color[NUM_LEDS]= // Define array to store LED colors
{
  led_color[0] = CRGB::Red,
  led_color[1] = CRGB::Red,
  led_color[2] = CRGB::Red,
  led_color[3] = CRGB::Red,
  led_color[4] = CRGB::Red,
  led_color[5] = CRGB::Red,
  led_color[6] = CRGB::Red,
  led_color[7] = CRGB::Red,
  led_color[8] = CRGB::Red,
  led_color[9] = CRGB::Red,
  led_color[10] = CRGB::Red,
  led_color[11] = CRGB::Red,
  led_color[12] = CRGB::Red,
  led_color[13] = CRGB::Red,
  led_color[14] = CRGB::Red,
  led_color[15] = CRGB::Red,
  led_color[16] = CRGB::Red,
  led_color[17] = CRGB::Red,
  led_color[18] = CRGB::Red,
  led_color[19] = CRGB::Red,
  led_color[20] = CRGB::Red,
  led_color[21] = CRGB::Red,
  led_color[22] = CRGB::Red,
  led_color[23] = CRGB::Red,
  led_color[24] = CRGB::Red,
  led_color[25] = CRGB::Red,
  led_color[26] = CRGB::Red,
  led_color[27] = CRGB::Blue,
};

void setup()
{
  Serial.begin(115200); // start serial peripheral
  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS); // instantiate LED library with our information
  FastLED.clear(); // clear the LED display before doing anything else

  chase();//try call chase() here

}

void loop()
{
  if(Serial.available()) // If there is serial data waiting in the buffer
  {
    ascii2ledIndex(Serial.read()); // read the data and convert each letter from ascii to the appropriate LED index in the string
  }
}


// Convert a letter from ascii to the appropriate LED index in the string
void ascii2ledIndex(int asciiLetter)
{
    //Serial.println(asciiLetter);
    int ledIndex = -1; // create variable to store led index
    int indexMap[]={20,21,22,23,24,25,26,27,18,17,16,15,14,13,12,11,10,0,1,2,3,4,5,6,7,8}; // When I hung the LED string on the wall the first letters in the string are R S T U V W X Y Z then it skips one LED and winds around to  Q P O N M L K J I then it skips one LED and winds to A B C D E F G H
    if(asciiLetter >= 97 && asciiLetter <= 122) // It's an ASCII Lowercase Letter
    {
      ledIndex = indexMap[asciiLetter - 97];
    }
    else if (asciiLetter >= 65 && asciiLetter <= 90) // It's an ASCII Uppercase Letter
    {
      ledIndex = indexMap[asciiLetter - 65];
    }
    Serial.println(ledIndex);
    if(ledIndex >= -1) // valid LED index converted from either uppercase or lowercase letter
    {
      leds[ledIndex] = led_color[ledIndex];
      FastLED.show();
      delay(3000);
      FastLED.clear();
      FastLED.show();
      delay(250);
    }
    else // invalid led index. display blank. this is useful for spaces and other punctuation.
    {
      FastLED.clear();
      FastLED.show();
      delay(750);
    }
   
}


// Test function that displays one LED at a time. This appears like the LED is chasing down the string.
void chase()
{
  for(int dot = 0; dot < NUM_LEDS; dot++)
  {
      leds[dot] = led_color[dot];
      FastLED.show();
      // clear this led for the next time around the loop
      leds[dot] = CRGB::Black;
      delay(100);
  }
}

// Test function that blinks all the LEDs
void RGB_Blink()
{
  // Set all the colors
  leds[0] = led_color[0];
  leds[1] = led_color[1];
  leds[2] = led_color[2];
  leds[3] = led_color[3];
  leds[4] = led_color[4];
  leds[5] = led_color[5];
  leds[6] = led_color[6];
  leds[7] = led_color[7];
  leds[8] = led_color[8];
  leds[9] = led_color[9];
  leds[10] = led_color[10];
  leds[11] = led_color[11];
  leds[12] = led_color[12];
  leds[13] = led_color[13];
  leds[14] = led_color[14];
  leds[15] = led_color[15];
  leds[16] = led_color[16];
  leds[17] = led_color[17];
  leds[18] = led_color[18];
  leds[19] = led_color[19];
  leds[20] = led_color[20];
  leds[21] = led_color[21];
  leds[22] = led_color[22];
  leds[23] = led_color[23];
  leds[24] = led_color[24];
  leds[25] = led_color[25];
  leds[26] = led_color[26];
  leds[27] = led_color[27]; 
  FastLED.show();
  delay(750);
  // Now turn the LED off, then pause
  FastLED.clear();
  FastLED.show();
  delay(500);
}

I made made sure that I had the correct data pin every time I tested it, so I don’t think that’s the problem. I found some more example code in the FastLED library that is essentially just the chase() function and it works fine. I am clueless why this one works but the other one doesn’t.

#include <FastLED.h>

///////////////////////////////////////////////////////////////////////////////////////////
//
// Move a white dot along the strip of leds.  This program simply shows how to configure the leds,
// and then how to turn a single pixel white and then off, moving down the line of pixels.
// 

// How many leds are in the strip?
#define NUM_LEDS 50

// For led chips like WS2812, which have a data line, ground, and power, you just
// need to define DATA_PIN.  For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
// Clock pin only needed for SPI based chipsets when not using hardware SPI
#define DATA_PIN 3
#define CLOCK_PIN 13

// This is an array of leds.  One item for each led in your strip.
CRGB leds[NUM_LEDS];

// This function sets up the ledsand tells the controller about them
void setup() {
	// sanity check delay - allows reprogramming if accidently blowing power w/leds
   	delay(2000);

   
    FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
   
}

// This function runs over and over, and is where you do the magic to light
// your leds.
void loop() {
   // Move a single white led 
   for(int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed = whiteLed + 1) {
      // Turn our current led on to white, then show the leds
      leds[whiteLed] = CRGB::White;

      // Show the leds (only one of which is set to white, from above)
      FastLED.show();

      // Wait a little bit
      delay(100);

      // Turn our current led back to black for the next loop around
      leds[whiteLed] = CRGB::Black;
   }
}

I found some more example code in the FastLED library that is essentially just the chase() function and it works fine. I am clueless why this one works but the other one doesn’t.

Good job getting a more simple example to work, now we can go through the differences in detail.

There are a couple of details I want to clear up first.

First, can you please confirm that the working chase example will still work if you remove the #define CLOCK_PIN 13 It should not be necessary with the 2811 string.

Second, can you try the working sketch with #define NUM_LEDS 28 like with the message wall sketch.

In the working sketch can you change the working color from white to red like in the message wall.

void loop() {
   // Move a single white led
   for(int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed = whiteLed + 1) {
      // Turn our current led on to white, then show the leds
      //leds[whiteLed] = CRGB::White;
       
       leds[whiteLed] = CRGB::Red;

      // Show the leds (only one of which is set to white, from above)
      FastLED.show();

      // Wait a little bit
      delay(100);

      // Turn our current led back to black for the next loop around
      leds[whiteLed] = CRGB::Black;
   }

Let me know ff everything is still working with these changes and then we can see about getting the message wall sketch to run.

The first things to try with the message wall sketch is to change the library include to be like the working example.

//#include "FastLED.h"
#include <FastLED.h>

Put chase() in loop() instead of setup()

Finally change the location of the delay in chase() to be like the working example

void chase()
{
  for(int dot = 0; dot < NUM_LEDS; dot++)
  {
      leds[dot] = led_color[dot];
      FastLED.show();
      
      delay(100);

      // clear this led for the next time around the loop
      leds[dot] = CRGB::Black;
      //delay(100);
  }
}

I got all the fixes that you suggested working on the example code, however the message board chase() code still does not work. I tried using the

//#include “FastLED.h”
#include <FastLED.h>

to start the code, but I can’t figure out where to put the chase() function. Does it need to go inside the parenthesis in loop()? Because I tried putting it there and it kept giving me error messages. Also, when I went to upload the chase() code, I had been running the example code in the background and the led that it was on just froze and wouldn’t turn off until I unplugged it.

I got all the fixes that you suggested working on the example code

Good news, Its not the number of leds or the color which is a problem for the message board.

The # include for the library should not have made a difference and it didn’t.

Try this version of the message board code. I have modified chase() to use the delay() configuration of the working example code.

Without any serial input it should run chase(). If that works, then comment out the call to chase and see if you can light the letters with serial input.

/*
 * Stranger Things Message Wall
 * Written by Zach Hipps 2017 for byte sized YouTube channel: https://www.youtube.com/c/bytesized
 *
 * Build instructions can be found at https://www.bytesizedelectronics.com/projects/how-to-make-a-stranger-things-message-wall
 * Video can be found at https://youtu.be/tG8sQMoKrb0
 *
 * How to use:
 * -----------
 * Connect string of WS2811 LEDs (or equivient) to the arduino with the data signal going to pin 3.
 * Be sure to use a separate power supply as the arduino's voltage regulator cannot supply enough current for all these LEDs.
 * Send serial data to the program either using the serial monitor, or some external serial device (like HC-05 bluetooth module) connected to RX and TX pins.
 *
 * Known issues:
 * ------------
 * Due to strict timing requirments from the WS2811 LEDs, the FastLED library has to disable interrupts when writing to the LEDs. This will cause some serial data to be lost.
 * The practical result is that messages longer than 6 characters seem to get truncated. Some sort of software buffering could potentially fix this. See https://github.com/FastLED/FastLED/wiki/Interrupt-problems
 *
 */



//#include "FastLED.h" // This is the library that does all the work with the LEDs
#include <FastLED.h>

#define NUM_LEDS 28 // The number of LEDs in the string
#define DATA_PIN 3 // The pin that connects to the data signal on the LEDs

CRGB leds[NUM_LEDS]; // Define array with NUM_LEDS elements
CRGB led_color[NUM_LEDS]= // Define array to store LED colors
{
  led_color[0] = CRGB::Red,
  led_color[1] = CRGB::Red,
  led_color[2] = CRGB::Red,
  led_color[3] = CRGB::Red,
  led_color[4] = CRGB::Red,
  led_color[5] = CRGB::Red,
  led_color[6] = CRGB::Red,
  led_color[7] = CRGB::Red,
  led_color[8] = CRGB::Red,
  led_color[9] = CRGB::Red,
  led_color[10] = CRGB::Red,
  led_color[11] = CRGB::Red,
  led_color[12] = CRGB::Red,
  led_color[13] = CRGB::Red,
  led_color[14] = CRGB::Red,
  led_color[15] = CRGB::Red,
  led_color[16] = CRGB::Red,
  led_color[17] = CRGB::Red,
  led_color[18] = CRGB::Red,
  led_color[19] = CRGB::Red,
  led_color[20] = CRGB::Red,
  led_color[21] = CRGB::Red,
  led_color[22] = CRGB::Red,
  led_color[23] = CRGB::Red,
  led_color[24] = CRGB::Red,
  led_color[25] = CRGB::Red,
  led_color[26] = CRGB::Red,
  led_color[27] = CRGB::Blue,
};

void setup()
{
  Serial.begin(115200); // start serial peripheral
  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS); // instantiate LED library with our information
  FastLED.clear(); // clear the LED display before doing anything else
}

void loop()
{
  if(Serial.available()) // If there is serial data waiting in the buffer
  {
    ascii2ledIndex(Serial.read()); // read the data and convert each letter from ascii to the appropriate LED index in the string
  }
 
  chase(); //call chase from loop() comment it out if it works

}


// Convert a letter from ascii to the appropriate LED index in the string
void ascii2ledIndex(int asciiLetter)
{
    //Serial.println(asciiLetter);
    int ledIndex = -1; // create variable to store led index
    int indexMap[]={20,21,22,23,24,25,26,27,18,17,16,15,14,13,12,11,10,0,1,2,3,4,5,6,7,8}; // When I hung the LED string on the wall the first letters in the string are R S T U V W X Y Z then it skips one LED and winds around to  Q P O N M L K J I then it skips one LED and winds to A B C D E F G H
    if(asciiLetter >= 97 && asciiLetter <= 122) // It's an ASCII Lowercase Letter
    {
      ledIndex = indexMap[asciiLetter - 97];
    }
    else if (asciiLetter >= 65 && asciiLetter <= 90) // It's an ASCII Uppercase Letter
    {
      ledIndex = indexMap[asciiLetter - 65];
    }
    Serial.println(ledIndex);
    if(ledIndex >= -1) // valid LED index converted from either uppercase or lowercase letter
    {
      leds[ledIndex] = led_color[ledIndex];
      FastLED.show();
      delay(3000);
      FastLED.clear();
      FastLED.show();
      delay(250);
    }
    else // invalid led index. display blank. this is useful for spaces and other punctuation.
    {
      FastLED.clear();
      FastLED.show();
      delay(750);
    }
   
}


// Test function that displays one LED at a time. This appears like the LED is chasing down the string.
void chase()
{
  for(int dot = 0; dot < NUM_LEDS; dot++)
  {
      leds[dot] = led_color[dot];
      FastLED.show();
      delay(100);
      // clear this led for the next time around the loop
      leds[dot] = CRGB::Black;
      //delay(100);
  }
}

// Test function that blinks all the LEDs
void RGB_Blink()
{
  // Set all the colors
  leds[0] = led_color[0];
  leds[1] = led_color[1];
  leds[2] = led_color[2];
  leds[3] = led_color[3];
  leds[4] = led_color[4];
  leds[5] = led_color[5];
  leds[6] = led_color[6];
  leds[7] = led_color[7];
  leds[8] = led_color[8];
  leds[9] = led_color[9];
  leds[10] = led_color[10];
  leds[11] = led_color[11];
  leds[12] = led_color[12];
  leds[13] = led_color[13];
  leds[14] = led_color[14];
  leds[15] = led_color[15];
  leds[16] = led_color[16];
  leds[17] = led_color[17];
  leds[18] = led_color[18];
  leds[19] = led_color[19];
  leds[20] = led_color[20];
  leds[21] = led_color[21];
  leds[22] = led_color[22];
  leds[23] = led_color[23];
  leds[24] = led_color[24];
  leds[25] = led_color[25];
  leds[26] = led_color[26];
  leds[27] = led_color[27];
  FastLED.show();
  delay(750);
  // Now turn the LED off, then pause
  FastLED.clear();
  FastLED.show();
  delay(500);
}

Just tried this out, yet It still doesn't work. Could it be that the program needs something else #defined? Like Brightness or something? I don't know if that would make a difference but I noticed it on the working code.

Could it be that the program needs something else #defined? Like Brightness or something? I don’t know if that would make a difference but I noticed it on the working code.

I don’t see anything like that in the code which successfully runs a chase(). It was to have been slightly modified to run 28 leds with RED, no clock pin.

#include <FastLED.h>

///////////////////////////////////////////////////////////////////////////////////////////
//
// Move a white dot along the strip of leds.  This program simply shows how to configure the leds,
// and then how to turn a single pixel white and then off, moving down the line of pixels.
//

// How many leds are in the strip?
#define NUM_LEDS  28 //50

// For led chips like WS2812, which have a data line, ground, and power, you just
// need to define DATA_PIN.  For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
// Clock pin only needed for SPI based chipsets when not using hardware SPI
#define DATA_PIN 3
//#define CLOCK_PIN 13

// This is an array of leds.  One item for each led in your strip.
CRGB leds[NUM_LEDS];

// This function sets up the leds and tells the controller about them
void setup() {
	// sanity check delay - allows reprogramming if accidently blowing power w/leds
   	delay(2000);

   
    FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
   
}

// This function runs over and over, and is where you do the magic to light
// your leds.
void loop() {
   // Move a single white led
   for(int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed = whiteLed + 1) {
      // Turn our current led on to red, then show the leds
      leds[whiteLed] =  CRGB::Red;  // CRGB::White;

      // Show the leds (only one of which is set to white, from above)
      FastLED.show();

      // Wait a little bit
      delay(100);

      // Turn our current led back to black for the next loop around
      leds[whiteLed] = CRGB::Black;
   }
}

I think it is best to start adding the different pieces of the wall code to this base, and see when it breaks, rather than try to modify the wall code to look more like this does. Confirm that the code above works, and then change it to look like this with the addition of the Serial input and elimination of the color array from the wall sketch.

#include <FastLED.h>
#define NUM_LEDS  28 //50
#define DATA_PIN 3
//#define CLOCK_PIN 13

// This is an array of leds.  One item for each led in your strip.
CRGB leds[NUM_LEDS];

// This function sets up the leds and tells the controller about them
void setup() {
  // sanity check delay - allows reprogramming if accidently blowing power w/leds
    Serial.begin(115200);
    delay(2000);  
    FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);  
}

// This function runs over and over, and is where you do the magic to light
// your leds.
void loop() { 

    if(Serial.available()) // If there is serial data waiting in the buffer
  {
    ascii2ledIndex(Serial.read()); // read the data and convert each letter from ascii to the appropriate LED index in the string
  }
   // Move a single white led
   for(int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed = whiteLed + 1) {
      // Turn our current led on to red, then show the leds
      leds[whiteLed] =  CRGB::Red;  // CRGB::White;
      // Show the leds (only one of which is set to white, from above)
      FastLED.show();
      // Wait a little bit
      delay(100);
      // Turn our current led back to black for the next loop around
      leds[whiteLed] = CRGB::Black;
   }
}

// Convert a letter from ascii to the appropriate LED index in the string
void ascii2ledIndex(int asciiLetter)
{
    //Serial.println(asciiLetter);
    int ledIndex = -1; // create variable to store led index
    int indexMap[]={20,21,22,23,24,25,26,27,18,17,16,15,14,13,12,11,10,0,1,2,3,4,5,6,7,8}; // When I hung the LED string on the wall the first letters in the string are R S T U V W X Y Z then it skips one LED and winds around to  Q P O N M L K J I then it skips one LED and winds to A B C D E F G H
    if(asciiLetter >= 97 && asciiLetter <= 122) // It's an ASCII Lowercase Letter
    {
      ledIndex = indexMap[asciiLetter - 97];
    }
    else if (asciiLetter >= 65 && asciiLetter <= 90) // It's an ASCII Uppercase Letter
    {
      ledIndex = indexMap[asciiLetter - 65];
    }
    Serial.println(ledIndex);
    if(ledIndex >= -1) // valid LED index converted from either uppercase or lowercase letter
    {
      leds[ledIndex] = CRGB::Red;  //led_color[ledIndex];
      FastLED.show();
      delay(3000);
      FastLED.clear();
      FastLED.show();
      delay(250);
    }
    else // invalid led index. display blank. this is useful for spaces and other punctuation.
    {
      FastLED.clear();
      FastLED.show();
      delay(750);
    }   
}