Please Help Me Converting Dotstar Code to FastLED Code

Hi, I'm trying to make a vu meter. I found the Adafuit LED Ampli-Tie project and got it working with my dotstar. I would like to use the FastLED library instead but I'm having trouble converting the code. Is this possible or do I have to start from scratch if I want to use fastLED library?

I've looked up other fastLED vu meter code on Github and the Ampli-Tie is still the options/features that I am looking for(mostly falling dot/ underlying color gradient or animations). If you have a better or cooler looking fastLED vu meter code please share it with me too.

I commented the original code and wrote what I think fastLED code should be underneath it. Please let me know what I'm doing wrong or if there is a way i can do it.

Thank you so much.

#include <FastLED.h>
#include <math.h>

#define N_PIXELS  72
#define MIC_PIN   A5
#define DATAPIN    6
#define CLOCKPIN   7
#define SAMPLE_WINDOW   2
#define PEAK_HANG 5
#define PEAK_FALL 1
#define INPUT_FLOOR 270
#define INPUT_CEILING 450


struct CRGB leds[N_PIXELS];  

byte peak = 16;
unsigned int sample;

byte dotCount = 0;
byte dotHangCount = 0;

void setup() 
{
  delay(1000);   
  FastLED.addLeds<DOTSTAR, DATAPIN, CLOCKPIN, BGR> (leds, N_PIXELS);

  FastLED.setBrightness(5);
  FastLED.show();

}

void loop() 
{
  unsigned long startMillis= millis();
  float peakToPeak = 0;

  unsigned int signalMax = 0;
  unsigned int signalMin = 1023;
  unsigned int c, y;

  while (millis() - startMillis < SAMPLE_WINDOW)
  {
    sample = analogRead(MIC_PIN);
    if (sample < 1024)
    {
      if (sample > signalMax)
      {
        signalMax = sample;
      }
      else if (sample < signalMin)
      {
        signalMin = sample;
      }
    }
  }
  peakToPeak = signalMax - signalMin;

//  for (int i=0;i<=strip.numPixels()-1;i++){
//    strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
//  }
    for (int i=0;i<=N_PIXELS -1;i++){
    leds[i] = CHSV(map(i,0,N_PIXELS-1, 30, 150));
    }

//  c = fscale(INPUT_FLOOR, INPUT_CEILING, strip.numPixels(), 0, peakToPeak, 2);
  c = fscale(INPUT_FLOOR, INPUT_CEILING, N_PIXELS, 0, peakToPeak, 2);

  if(c < peak) {
    peak = c;
    dotHangCount = 0;
  }

//  if (c <= strip.numPixels()) {
//    drawLine(strip.numPixels(), strip.numPixels()-c, strip.Color(0, 0, 0));
//  }
   if (c <= N_PIXELS) {
    drawLine(N_PIXELS, N_PIXELS - c, 0);
  }

//  y = strip.numPixels() - peak;
  y = N_PIXELS - peak;
  
  //strip.setPixelColor(y-1,Wheel(map(y,0,strip.numPixels()-1,30,150)));
  y-1 = CHSV(map(y,0,N_PIXELS - 1,30,150));

  FastLED.show();

  if(dotHangCount > PEAK_HANG) { 
    if(++dotCount >= PEAK_FALL) { 
      peak++;
      dotCount = 0;
    }
  } 
  else {
    dotHangCount++; 
  }
}

void drawLine(uint8_t from, uint8_t to, uint32_t c) {
  uint8_t fromTemp;
  if (from > to) {
    fromTemp = from;
    from = to;
    to = fromTemp;
  }

//  for(int i=from; i<=to; i++){
//    strip.setPixelColor(i, c);
//  }
  for(int i=from; i<=to; i++){
   leds[i] = c;
  }
}


float fscale( float originalMin, float originalMax, float newBegin, float
newEnd, float inputValue, float curve){

  float OriginalRange = 0;
  float NewRange = 0;
  float zeroRefCurVal = 0;
  float normalizedCurVal = 0;
  float rangedValue = 0;
  boolean invFlag = 0;

  if (curve > 10) curve = 10;
  if (curve < -10) curve = -10;

  curve = (curve * -.1) ; 
  curve = pow(10, curve);
  
  if (inputValue < originalMin) {
    inputValue = originalMin;
  }
  if (inputValue > originalMax) {
    inputValue = originalMax;
  }

  OriginalRange = originalMax - originalMin;

  if (newEnd > newBegin){ 
    NewRange = newEnd - newBegin;
  }
  else
  {
    NewRange = newBegin - newEnd; 
    invFlag = 1;
  }

  zeroRefCurVal = inputValue - originalMin;
  normalizedCurVal  =  zeroRefCurVal / OriginalRange;


  if (originalMin > originalMax ) {
    return 0;
  }

  if (invFlag == 0){
    rangedValue =  (pow(normalizedCurVal, curve) * NewRange) + newBegin;

  }
  else
  {   
    rangedValue =  newBegin - (pow(normalizedCurVal, curve) * NewRange); 
  }

  return rangedValue;
}

Just realized I uploaded the wrong code, here's my final... not that it makes much difference, still couldn't compile it...

#include <FastLED.h>
#include <math.h>

#define N_PIXELS  72
#define MIC_PIN   A5
#define DATAPIN    6
#define CLOCKPIN   7
#define SAMPLE_WINDOW   2
#define PEAK_HANG 5
#define PEAK_FALL 1
#define INPUT_FLOOR 270
#define INPUT_CEILING 450


struct CRGB leds[N_PIXELS];  

byte peak = 16;
unsigned int sample;

byte dotCount = 0;
byte dotHangCount = 0;

void setup() 
{
  delay(1000);   
  FastLED.addLeds<DOTSTAR, DATAPIN, CLOCKPIN, BGR> (leds, N_PIXELS);

  FastLED.setBrightness(5);
  FastLED.show();

}

void loop() 
{
  unsigned long startMillis= millis();
  float peakToPeak = 0;

  unsigned int signalMax = 0;
  unsigned int signalMin = 1023;
  unsigned int c, y;

  while (millis() - startMillis < SAMPLE_WINDOW)
  {
    sample = analogRead(MIC_PIN);
    if (sample < 1024)
    {
      if (sample > signalMax)
      {
        signalMax = sample;
      }
      else if (sample < signalMin)
      {
        signalMin = sample;
      }
    }
  }
  peakToPeak = signalMax - signalMin;

//  for (int i=0;i<=strip.numPixels()-1;i++){
//    strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
//  }
    for (int i=0;i<=N_PIXELS -1;i++){
    leds[i] = CHSV(map(i,0,N_PIXELS-1, 30, 150), 255, 255);
    }

//  c = fscale(INPUT_FLOOR, INPUT_CEILING, strip.numPixels(), 0, peakToPeak, 2);
  c = fscale(INPUT_FLOOR, INPUT_CEILING, N_PIXELS, 0, peakToPeak, 2);

  if(c < peak) {
    peak = c;
    dotHangCount = 0;
  }

//  if (c <= strip.numPixels()) {
//    drawLine(strip.numPixels(), strip.numPixels()-c, strip.Color(0, 0, 0));
//  }
   if (c <= N_PIXELS) {
    drawLine(N_PIXELS, N_PIXELS - c, FastLED.clear());
  }

//  y = strip.numPixels() - peak;
  y = N_PIXELS - peak;
  
  //strip.setPixelColor(y-1,Wheel(map(y,0,strip.numPixels()-1,30,150)));
  y-1 = CHSV(map(y,0,N_PIXELS - 1,30,150), 255, 255);

  FastLED.show();

  if(dotHangCount > PEAK_HANG) { 
    if(++dotCount >= PEAK_FALL) { 
      peak++;
      dotCount = 0;
    }
  } 
  else {
    dotHangCount++; 
  }
}

void drawLine(uint8_t from, uint8_t to, uint32_t c) {
  uint8_t fromTemp;
  if (from > to) {
    fromTemp = from;
    from = to;
    to = fromTemp;
  }

//  for(int i=from; i<=to; i++){
//    strip.setPixelColor(i, c);
//  }
  for(int i=from; i<=to; i++){
   leds[i] = c;
  }
}


float fscale( float originalMin, float originalMax, float newBegin, float
newEnd, float inputValue, float curve){

  float OriginalRange = 0;
  float NewRange = 0;
  float zeroRefCurVal = 0;
  float normalizedCurVal = 0;
  float rangedValue = 0;
  boolean invFlag = 0;

  if (curve > 10) curve = 10;
  if (curve < -10) curve = -10;

  curve = (curve * -.1) ; 
  curve = pow(10, curve);
  
  if (inputValue < originalMin) {
    inputValue = originalMin;
  }
  if (inputValue > originalMax) {
    inputValue = originalMax;
  }

  OriginalRange = originalMax - originalMin;

  if (newEnd > newBegin){ 
    NewRange = newEnd - newBegin;
  }
  else
  {
    NewRange = newBegin - newEnd; 
    invFlag = 1;
  }

  zeroRefCurVal = inputValue - originalMin;
  normalizedCurVal  =  zeroRefCurVal / OriginalRange;


  if (originalMin > originalMax ) {
    return 0;
  }

  if (invFlag == 0){
    rangedValue =  (pow(normalizedCurVal, curve) * NewRange) + newBegin;

  }
  else
  {   
    rangedValue =  newBegin - (pow(normalizedCurVal, curve) * NewRange); 
  }

  return rangedValue;
}

It would be awfully helpful if you told us what you want the code to do and how what it actually does is different than what you want.

A secondary question would be why doesn't the code do what you want as written and why do you think converting to FastLED will make it do what you want?

gfvalvo:
It would be awfully helpful if you told us what you want the code to do and how what it actually does is different than what you want.

A secondary question would be why doesn't the code do what you want as written and why do you think converting to FastLED will make it do what you want?

Thank you for replying. The Adafruit Ampli-Tie vu meter I mentioned is what I want the code to do. I'm trying to use the second code on this page but with fastLED, because I want to combine this vu meter with my other code that use fastLED.

The code I posted is my failed attempt to convert Neopixel/Dotstar code to fastLED code, it won't even compile.

To put it simpler, I'm trying to convert the following code to fastLED.

/*
LED VU meter for Arduino and Adafruit NeoPixel LEDs.
 
 Hardware requirements:
 - Most Arduino or Arduino-compatible boards (ATmega 328P or better).
 - Adafruit Electret Microphone Amplifier (ID: 1063)
 - Adafruit Flora RGB Smart Pixels (ID: 1260)
 OR
 - Adafruit NeoPixel Digital LED strip (ID: 1138)
 - Optional: battery for portable use (else power through USB or adapter)
 Software requirements:
 - Adafruit NeoPixel library
 
 Connections:
 - 3.3V to mic amp +
 - GND to mic amp -
 - Analog pin to microphone output (configurable below)
 - Digital pin to LED data input (configurable below)
 See notes in setup() regarding 5V vs. 3.3V boards - there may be an
 extra connection to make and one line of code to enable or disable.
 
 Written by Adafruit Industries.  Distributed under the BSD license.
 This paragraph must be included in any redistribution.
 
 fscale function:
 Floating Point Autoscale Function V0.1
 Written by Paul Badger 2007
 Modified from code by Greg Shakar
 
 */

#include <Adafruit_NeoPixel.h>
#include <math.h>

#define N_PIXELS  16  // Number of pixels in strand
#define MIC_PIN   A9  // Microphone is attached to this analog pin
#define LED_PIN    6  // NeoPixel LED strand is connected to this pin
#define SAMPLE_WINDOW   10  // Sample window for average level
#define PEAK_HANG 24 //Time of pause before peak dot falls
#define PEAK_FALL 4 //Rate of falling peak dot
#define INPUT_FLOOR 10 //Lower range of analogRead input
#define INPUT_CEILING 300 //Max range of analogRead input, the lower the value the more sensitive (1023 = max)



byte peak = 16;      // Peak level of column; used for falling dots
unsigned int sample;

byte dotCount = 0;  //Frame counter for peak dot
byte dotHangCount = 0; //Frame counter for holding peak dot

Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() 
{
  // This is only needed on 5V Arduinos (Uno, Leonardo, etc.).
  // Connect 3.3V to mic AND TO AREF ON ARDUINO and enable this
  // line.  Audio samples are 'cleaner' at 3.3V.
  // COMMENT OUT THIS LINE FOR 3.3V ARDUINOS (FLORA, ETC.):
  //  analogReference(EXTERNAL);

  // Serial.begin(9600);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

}

void loop() 
{
  unsigned long startMillis= millis();  // Start of sample window
  float peakToPeak = 0;   // peak-to-peak level

  unsigned int signalMax = 0;
  unsigned int signalMin = 1023;
  unsigned int c, y;


  // collect data for length of sample window (in mS)
  while (millis() - startMillis < SAMPLE_WINDOW)
  {
    sample = analogRead(MIC_PIN);
    if (sample < 1024)  // toss out spurious readings
    {
      if (sample > signalMax)
      {
        signalMax = sample;  // save just the max levels
      }
      else if (sample < signalMin)
      {
        signalMin = sample;  // save just the min levels
      }
    }
  }
  peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
 
  // Serial.println(peakToPeak);


  //Fill the strip with rainbow gradient
  for (int i=0;i<=strip.numPixels()-1;i++){
    strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
  }


  //Scale the input logarithmically instead of linearly
  c = fscale(INPUT_FLOOR, INPUT_CEILING, strip.numPixels(), 0, peakToPeak, 2);

  


  if(c < peak) {
    peak = c;        // Keep dot on top
    dotHangCount = 0;    // make the dot hang before falling
  }
  if (c <= strip.numPixels()) { // Fill partial column with off pixels
    drawLine(strip.numPixels(), strip.numPixels()-c, strip.Color(0, 0, 0));
  }

  // Set the peak dot to match the rainbow gradient
  y = strip.numPixels() - peak;
  
  strip.setPixelColor(y-1,Wheel(map(y,0,strip.numPixels()-1,30,150)));

  strip.show();

  // Frame based peak dot animation
  if(dotHangCount > PEAK_HANG) { //Peak pause length
    if(++dotCount >= PEAK_FALL) { //Fall rate 
      peak++;
      dotCount = 0;
    }
  } 
  else {
    dotHangCount++; 
  }
}

//Used to draw a line between two points of a given color
void drawLine(uint8_t from, uint8_t to, uint32_t c) {
  uint8_t fromTemp;
  if (from > to) {
    fromTemp = from;
    from = to;
    to = fromTemp;
  }
  for(int i=from; i<=to; i++){
    strip.setPixelColor(i, c);
  }
}


float fscale( float originalMin, float originalMax, float newBegin, float
newEnd, float inputValue, float curve){

  float OriginalRange = 0;
  float NewRange = 0;
  float zeroRefCurVal = 0;
  float normalizedCurVal = 0;
  float rangedValue = 0;
  boolean invFlag = 0;


  // condition curve parameter
  // limit range

  if (curve > 10) curve = 10;
  if (curve < -10) curve = -10;

  curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output 
  curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function

  /*
   Serial.println(curve * 100, DEC);   // multply by 100 to preserve resolution  
   Serial.println(); 
   */

  // Check for out of range inputValues
  if (inputValue < originalMin) {
    inputValue = originalMin;
  }
  if (inputValue > originalMax) {
    inputValue = originalMax;
  }

  // Zero Refference the values
  OriginalRange = originalMax - originalMin;

  if (newEnd > newBegin){ 
    NewRange = newEnd - newBegin;
  }
  else
  {
    NewRange = newBegin - newEnd; 
    invFlag = 1;
  }

  zeroRefCurVal = inputValue - originalMin;
  normalizedCurVal  =  zeroRefCurVal / OriginalRange;   // normalize to 0 - 1 float

  // Check for originalMin > originalMax  - the math for all other cases i.e. negative numbers seems to work out fine 
  if (originalMin > originalMax ) {
    return 0;
  }

  if (invFlag == 0){
    rangedValue =  (pow(normalizedCurVal, curve) * NewRange) + newBegin;

  }
  else     // invert the ranges
  {   
    rangedValue =  newBegin - (pow(normalizedCurVal, curve) * NewRange); 
  }

  return rangedValue;
}


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } 
  else if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } 
  else {
    WheelPos -= 170;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

This might be more specific, these are the original code with neopixel/dotstar and what I wrote with fastLED.

original

for (int i=0;i<=strip.numPixels()-1;i++){
    strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
  }

me

    for (int i=0;i<=N_PIXELS -1;i++){
    leds[i] = CHSV(map(i,0,N_PIXELS-1, 30, 150), 255, 255);
    }

original

  c = fscale(INPUT_FLOOR, INPUT_CEILING, strip.numPixels(), 0, peakToPeak, 2);

me

  c = fscale(INPUT_FLOOR, INPUT_CEILING, N_PIXELS, 0, peakToPeak, 2);

original

  if (c <= strip.numPixels()) {
    drawLine(strip.numPixels(), strip.numPixels()-c, strip.Color(0, 0, 0));
  }

me

   if (c <= N_PIXELS) {
    drawLine(N_PIXELS, N_PIXELS - c, FastLED.clear());
  }

original

    y = strip.numPixels() - peak;
    strip.setPixelColor(y-1,Wheel(map(y,0,strip.numPixels()-1,30,150)));

me

  y = N_PIXELS - peak;
  y-1 = CHSV(map(y,0,N_PIXELS - 1,30,150), 255, 255);

original

  for(int i=from; i<=to; i++){
    strip.setPixelColor(i, c);
  }

me

  for(int i=from; i<=to; i++){
   leds[i] = c;
  }

On Line 78 your code is calling the 'drawLine() function:

drawLine(N_PIXELS, N_PIXELS - c, FastLED.clear());

That function (later in your code) expects the third argument to be a 'uint32_t'. You're trying to pass it a pointer to a function.

Line 85 shows this:

y - 1 = CHSV(map(y, 0, N_PIXELS - 1, 30, 150), 255, 255);

You can't put an expression on the left hand side of an assignment statement.

Fix those two things and it will compile. I can't tell you if it will "work".

gfvalvo:
On Line 78 your code is calling the 'drawLine() function:

drawLine(N_PIXELS, N_PIXELS - c, FastLED.clear());

That function (later in your code) expects the third argument to be a 'uint32_t'. You're trying to pass it a pointer to a function.

Looking at it again, I see that you're trying to pass the return value from 'FastLED.clear()' as the third argument to 'drawLine()' -- not a pointer, my mistake. Trouble is, 'FastLED.clear()' doesn't return a value (aka returns 'void').

gfvalvo:
Looking at it again, I see that you're trying to pass the return value from 'FastLED.clear()' as the third argument to 'drawLine()' -- not a pointer, my mistake. Trouble is, 'FastLED.clear()' doesn't return a value (aka returns 'void').

I changed them to

drawLine(N_PIXELS, N_PIXELS - c, CRGB::Black);
leds[y - 1] = CHSV(map(y, 0, N_PIXELS - 1, 30, 150), 255, 255);

Now they compile and work. Thank you for the explanation.

gfvalvo:
Looking at it again, I see that you're trying to pass the return value from 'FastLED.clear()' as the third argument to 'drawLine()' -- not a pointer, my mistake. Trouble is, 'FastLED.clear()' doesn't return a value (aka returns 'void').

Hi sorry to bother you again, I have a follow up question.

I'm having 2 strips of Dotstar to both be vu meters in one of my modes, I can't mirror them in the setup because I want them to do different things in other modes.

I'm having trouble with this part

   if (c <= NUM_LEDS) {
    drawLine(NUM_LEDS, NUM_LEDS - c, CRGB::Black);
  }

if I keep it as is, only the first strip will work properly, I tried to change it to the bottom so that I can address both strips.

   if (c <= NUM_LEDS) {
    drawLine(NUM_LEDS, NUM_LEDS - c, fill_solid(DOT, NUM_LEDS, CRGB::Black));
    drawLine(NUM_LEDS, NUM_LEDS - c, fill_solid(DOT2, NUM_LEDS, CRGB::Black));
  }

But the arduino says it's invalid use of void expression, I couldn't find any other way to replace it, can you please tell my what the correct language is for this part? Thank you.

I’m guessing that the problem is in the part of the complete code that you didn’t post. Or, maybe there’s a clue in the part of the complete error message that you didn’t post.

gfvalvo:
I’m guessing that the problem is in the part of the complete code that you didn’t post. Or, maybe there’s a clue in the part of the complete error message that you didn’t post.

I attached the full code, the vu meters are in mode 3 on the bottom.

The error message is

Arduino: 1.8.4 (Windows 10), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

In file included from C:\Users\Niki\Desktop\code\2dotstar_led_1_button_3_modes\2dotstar_led_1_button_3_modes.ino:13:0:

C:\Users\Niki\Documents\Arduino\libraries\FastLED/FastLED.h:17:21: note: #pragma message: FastLED version 3.001.006

 #    pragma message "FastLED version 3.001.006"

                     ^

C:\Users\Niki\Desktop\code\2dotstar_led_1_button_3_modes\2dotstar_led_1_button_3_modes.ino: In function 'void VU()':

2dotstar_led_1_button_3_modes:407: error: invalid use of void expression

     drawLine(NUM_LEDS, NUM_LEDS - c, fill_solid(DOT, NUM_LEDS, CRGB::Black));

                                                                            ^

2dotstar_led_1_button_3_modes:408: error: invalid use of void expression

     drawLine(NUM_LEDS, NUM_LEDS - c, fill_solid(DOT2, NUM_LEDS, CRGB::Black));

                                                                             ^

exit status 1
invalid use of void expression

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

2dotstar_led_1_button_3_modes.ino (11.2 KB)

You’re trying to pass the return result of the ‘fill_solid()’ function as the third parameter to the function ‘drawLine()’. However, ‘fill_solid()’ does not return a value, what makes you think it does?

Just so you know, you are not trying to convert Dotstar code, you are trying to convert Neopixel code. The two are not the same. They use different libraries and different code due to the Dotstars being APA102 strips with clock and data pins. I actually found your thread because I'm trying to convert Dotstar code to work with Neopixel so I thought I'd comment to advise you that when asking for help in forums, it's very important to provide clear and accurate information to support your question. People will find it difficult to help you if the information you provide is vague or incorrect, it will also hinder people like me who are searching forums for info relating to their issue.
Please don't think I'm trying to be a smartass, the main reason I'm highlighting this error is to save a bit of time for anyone else searching this topic, I spent quite a while trying to relate this thread to the context of my own issue before I noticed that your code references the Neopixel library and not the dotstar one :slight_smile: