Function not declared in scope; FastLED GitHub code issues

Hi,

I have tried using the "DiscoStrobe" FastLED pattern in Arduino IDE 2.0.3 only to get the following compiler errors:

/private/var/folders/x9/813wvrzs4qn0mlv592nynbtr0000gn/T/.arduinoIDE-unsaved20221118-42360-13nlnt8.d5upg/sketch_dec18a/sketch_dec18a.ino: In function 'void discostrobe()':
/private/var/folders/x9/813wvrzs4qn0mlv592nynbtr0000gn/T/.arduinoIDE-unsaved20221118-42360-13nlnt8.d5upg/sketch_dec18a/sketch_dec18a.ino:128:5: error: 'discoWorker' was not declared in this scope
/private/var/folders/x9/813wvrzs4qn0mlv592nynbtr0000gn/T/.arduinoIDE-unsaved20221118-42360-13nlnt8.d5upg/sketch_dec18a/sketch_dec18a.ino:128:5: note: suggested alternative: 'discostrobe'
/private/var/folders/x9/813wvrzs4qn0mlv592nynbtr0000gn/T/.arduinoIDE-unsaved20221118-42360-13nlnt8.d5upg/sketch_dec18a/sketch_dec18a.ino: In function 'void discoWorker(uint8_t, uint8_t, int8_t, uint8_t, uint8_t)':
/private/var/folders/x9/813wvrzs4qn0mlv592nynbtr0000gn/T/.arduinoIDE-unsaved20221118-42360-13nlnt8.d5upg/sketch_dec18a/sketch_dec18a.ino:173:3: error: 'drawRainbowDashes' was not declared in this scope

exit status 1

Compilation error: 'discoWorker' was not declared in this scope

And code:

#include "FastLED.h"

// DiscoStrobe
// *Flashing* rainbow lights that zoom back and forth to a beat.
// See your doctor before using this code if you have certain neurological conditions.
//
// Mark Kriegsman, July 2015


#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif

#define DATA_PIN    3
//#define CLK_PIN   4
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS    200
CRGB leds[NUM_LEDS];


#define BRIGHTNESS          255
#define FRAMES_PER_SECOND   100

#define ZOOMING_BEATS_PER_MINUTE 122

void setup() {
  delay(3000); // 3 second delay for recovery
  
  // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip).setDither(BRIGHTNESS < 255);
  //FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip).setDither(BRIGHTNESS < 255);

  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);
}

  
void loop()
{
  // draw the light pattern into the 'leds' array
  discostrobe();
  
  // send the 'leds' array out to the actual LED strip
  FastLED.show();

  // delay just enough to keep a steady frame rate, e.g 100 FPS
  delayToSyncFrameRate( FRAMES_PER_SECOND);
}


void discostrobe()
{
  // First, we black out all the LEDs
  fill_solid( leds, NUM_LEDS, CRGB::Black);

  // To achive the strobe effect, we actually only draw lit pixels
  // every Nth frame (e.g. every 4th frame).  
  // sStrobePhase is a counter that runs from zero to kStrobeCycleLength-1,
  // and then resets to zero.  
  const uint8_t kStrobeCycleLength = 4; // light every Nth frame
  static uint8_t sStrobePhase = 0;
  sStrobePhase = sStrobePhase + 1;
  if( sStrobePhase >= kStrobeCycleLength ) { 
    sStrobePhase = 0; 
  }

  // We only draw lit pixels when we're in strobe phase zero; 
  // in all the other phases we leave the LEDs all black.
  if( sStrobePhase == 0 ) {

    // The dash spacing cycles from 4 to 9 and back, 8x/min (about every 7.5 sec)
    uint8_t dashperiod= beatsin8( 8/*cycles per minute*/, 4,10);
    // The width of the dashes is a fraction of the dashperiod, with a minimum of one pixel
    uint8_t dashwidth = (dashperiod / 4) + 1;
    
    // The distance that the dashes move each cycles varies 
    // between 1 pixel/cycle and half-the-dashperiod/cycle.
    // At the maximum speed, it's impossible to visually distinguish
    // whether the dashes are moving left or right, and the code takes
    // advantage of that moment to reverse the direction of the dashes.
    // So it looks like they're speeding up faster and faster to the
    // right, and then they start slowing down, but as they do it becomes
    // visible that they're no longer moving right; they've been 
    // moving left.  Easier to see than t o explain.
    //
    // The dashes zoom back and forth at a speed that 'goes well' with
    // most dance music, a little faster than 120 Beats Per Minute.  You
    // can adjust this for faster or slower 'zooming' back and forth.
    uint8_t zoomBPM = ZOOMING_BEATS_PER_MINUTE;
    int8_t  dashmotionspeed = beatsin8( (zoomBPM /2), 1,dashperiod);
    // This is where we reverse the direction under cover of high speed
    // visual aliasing.
    if( dashmotionspeed >= (dashperiod/2)) { 
      dashmotionspeed = 0 - (dashperiod - dashmotionspeed );
    }

    
    // The hueShift controls how much the hue of each dash varies from 
    // the adjacent dash.  If hueShift is zero, all the dashes are the 
    // same color. If hueShift is 128, alterating dashes will be two
    // different colors.  And if hueShift is range of 10..40, the
    // dashes will make rainbows.
    // Initially, I just had hueShift cycle from 0..130 using beatsin8.
    // It looked great with very low values, and with high values, but
    // a bit 'busy' in the middle, which I didnt like.
    //   uint8_t hueShift = beatsin8(2,0,130);
    //
    // So instead I layered in a bunch of 'cubic easings'
    // (see http://easings.net/#easeInOutCubic )
    // so that the resultant wave cycle spends a great deal of time
    // "at the bottom" (solid color dashes), and at the top ("two
    // color stripes"), and makes quick transitions between them.
    uint8_t cycle = beat8(2); // two cycles per minute
    uint8_t easedcycle = ease8InOutCubic( ease8InOutCubic( cycle));
    uint8_t wavecycle = cubicwave8( easedcycle);
    uint8_t hueShift = scale8( wavecycle,130);


    // Each frame of the animation can be repeated multiple times.
    // This slows down the apparent motion, and gives a more static
    // strobe effect.  After experimentation, I set the default to 1.
    uint8_t strobesPerPosition = 1; // try 1..4


    // Now that all the parameters for this frame are calculated,
    // we call the 'worker' function that does the next part of the work.
    discoWorker( dashperiod, dashwidth, dashmotionspeed, strobesPerPosition, hueShift);
  }  
}


// discoWorker updates the positions of the dashes, and calls the draw function
//
void discoWorker( 
    uint8_t dashperiod, uint8_t dashwidth, int8_t  dashmotionspeed,
    uint8_t stroberepeats,
    uint8_t huedelta)
 {
  static uint8_t sRepeatCounter = 0;
  static int8_t sStartPosition = 0;
  static uint8_t sStartHue = 0;

  // Always keep the hue shifting a little
  sStartHue += 1;

  // Increment the strobe repeat counter, and
  // move the dash starting position when needed.
  sRepeatCounter = sRepeatCounter + 1;
  if( sRepeatCounter>= stroberepeats) {
    sRepeatCounter = 0;
    
    sStartPosition = sStartPosition + dashmotionspeed;
    
    // These adjustments take care of making sure that the
    // starting hue is adjusted to keep the apparent color of 
    // each dash the same, even when the state position wraps around.
    if( sStartPosition >= dashperiod ) {
      while( sStartPosition >= dashperiod) { sStartPosition -= dashperiod; }
      sStartHue  -= huedelta;
    } else if( sStartPosition < 0) {
      while( sStartPosition < 0) { sStartPosition += dashperiod; }
      sStartHue  += huedelta;
    }
  }

  // draw dashes with full brightness (value), and somewhat
  // desaturated (whitened) so that the LEDs actually throw more light.
  const uint8_t kSaturation = 208;
  const uint8_t kValue = 255;

  // call the function that actually just draws the dashes now
  drawRainbowDashes( sStartPosition, NUM_LEDS-1, 
                     dashperiod, dashwidth, 
                     sStartHue, huedelta, 
                     kSaturation, kValue);
}


// drawRainbowDashes - draw rainbow-colored 'dashes' of light along the led strip:
//   starting from 'startpos', up to and including 'lastpos'
//   with a given 'period' and 'width'
//   starting from a given hue, which changes for each successive dash by a 'huedelta'
//   at a given saturation and value.
//
//   period = 5, width = 2 would be  _ _ _ X X _ _ _ Y Y _ _ _ Z Z _ _ _ A A _ _ _ 
//                                   \-------/       \-/
//                                   period 5      width 2
//
static void drawRainbowDashes( 
  uint8_t startpos, uint16_t lastpos, uint8_t period, uint8_t width, 
  uint8_t huestart, uint8_t huedelta, uint8_t saturation, uint8_t value)
{
  uint8_t hue = huestart;
  for( uint16_t i = startpos; i <= lastpos; i += period) {
    CRGB color = CHSV( hue, saturation, value);
    
    // draw one dash
    uint16_t pos = i;
    for( uint8_t w = 0; w < width; w++) {
      leds[ pos ] = color;
      pos++;
      if( pos >= NUM_LEDS) {
        break;
      }
    }
    
    hue += huedelta;
  }
}


// delayToSyncFrameRate - delay how many milliseconds are needed
//   to maintain a stable frame rate.
static void delayToSyncFrameRate( uint8_t framesPerSecond)
{
  static uint32_t msprev = 0;
  uint32_t mscur = millis();
  uint16_t msdelta = mscur - msprev;
  uint16_t mstargetdelta = 1000 / framesPerSecond;
  if( msdelta < mstargetdelta) {
    delay( mstargetdelta - msdelta);
  }
  msprev = mscur;
}

I believe I've found a similar/if not the same issue on a forum post
here.

It looks like the problem was solved in Arduino IDE 1.8.5 (quite a while back I know), but I seem to be having the same problem again.

Does anyone know how to resolve this/if I'm missing something stupid?

Thanks,
Adam

Your topic was MOVED to its current forum category which is more appropriate than the original as it has nothing to do with Installation and Troubleshooting of the IDE

The code compiles for me with no error using 1.8.19 with a Nano as the target

I suppose it's possible that the issue has come back again in later versions? I'm currently using an Uno but can't imagine the hardware would be the problem.

Just tried using 1.8.19 with the Uno, works fine. Must be an issue with 2.0.3.

It compiles OK using 2.0.3 if you put function prototypes for discoWorker() and drawRainbowDashes() at the start of the sketch

I also suspect that it would work if the function definitions came before calls to the functions in the IDE

What do you mean by this? Not familiar with the term.

C and C++ require that the existence and parameters for a function are known by the compiler before the actual functions are used. This requirement is hidden from you when using the Arduino IDE because the compilation process creates them for you behind the scenes. However, this process is not perfect and when it fails you get symptoms such as those that you report

Either add

void discoWorker(
  uint8_t dashperiod, uint8_t dashwidth, int8_t  dashmotionspeed,
  uint8_t stroberepeats,
  uint8_t huedelta);

static void drawRainbowDashes(
  uint8_t startpos, uint16_t lastpos, uint8_t period, uint8_t width,
  uint8_t huestart, uint8_t huedelta, uint8_t saturation, uint8_t value);

before setup() or move the definitions of the functions before setup()

Thank you all working now, appreciate it :slight_smile:

That's good news. Which option did you use ?

By the way, there is no harm in using function prototypes even if they are not strictly needed

This worked for me...

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.