Go Down

Topic: Second Strip of VU meter Has 1 LED Stay On (video included) (Read 514 times) previous topic - next topic

ratherwok

I am using an Arduino Mega and 2 strips of Dotstar leds. I'm trying to make 2 matching vu meters. I can't just mirror the strips because I will later add in modes and have the 2 strips do different animations in other modes.

The original code is from Adafruit Ampli-Tie project, I changed it to use FastLED library and It worked. But when I added a second strip, its last led will stay on constantly, I have tested both strips by themselves and they were fine. I switched pins and strips around and it's always the second strip in the code having this problem.

Here's a video https://youtu.be/wF5uJ8-aC6U, and here's the code

Code: [Select]
#include <FastLED.h>

#define NUM_LEDS 5
#define DATA_PIN 4
#define CLOCK_PIN 5
#define DATA_PIN2 6
#define CLOCK_PIN2 7

CRGB DOT[NUM_LEDS];
CRGB DOT2[NUM_LEDS];

#define MIC_PIN A5
#define SAMPLE_WINDOW   2
#define PEAK_HANG 5
#define PEAK_FALL 1
#define INPUT_FLOOR 100
#define INPUT_CEILING 450

byte peak = 16;
unsigned int sample;

byte dotCount = 0;
byte dotHangCount = 0;

void setup() {
  FastLED.addLeds<DOTSTAR, DATA_PIN, CLOCK_PIN, BGR> (DOT, NUM_LEDS);
  FastLED.addLeds<DOTSTAR, DATA_PIN2, CLOCK_PIN2, BGR> (DOT2, NUM_LEDS);
  FastLED.setBrightness(5);
}

void loop() {
  VU();
  FastLED.show();
}

void VU() {

  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<=NUM_LEDS -1;i++){
    DOT[i] = CHSV(map(i,0,NUM_LEDS-1, 30, 150), 255, 255);
    DOT2[i] = CHSV(map(i,0,NUM_LEDS-1, 30, 150), 255, 255);
    }

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

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

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

  y = NUM_LEDS - peak;
 
  DOT[y-1] = CHSV(map(y,0,NUM_LEDS - 1,30,150), 255, 255);
  DOT2[y-1] = CHSV(map(y,0,NUM_LEDS - 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++){
   DOT[i] = c;
   DOT2[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;
}

Grumpy_Mike

This is an odd way of writing a for loop:-
Code: [Select]

for (int i=0;i<=NUM_LEDS -1;i++)

why not
Code: [Select]
for (int i=0; i<NUM_LEDS;i++)

Note that with a 5 led array, you only have an array index from 0 to 4. It looks like you are over running your array.

Does anything change when you change this:-
Code: [Select]

CRGB DOT[NUM_LEDS];
CRGB DOT2[NUM_LEDS];

to this?
Code: [Select]

CRGB DOT2[NUM_LEDS];
CRGB DOT[NUM_LEDS];

ratherwok

This is an odd way of writing a for loop:-
Code: [Select]

for (int i=0;i<=NUM_LEDS -1;i++)

why not
Code: [Select]
for (int i=0; i<NUM_LEDS;i++)

Note that with a 5 led array, you only have an array index from 0 to 4. It looks like you are over running your array.

Does anything change when you change this:-
Code: [Select]

CRGB DOT[NUM_LEDS];
CRGB DOT2[NUM_LEDS];

to this?
Code: [Select]

CRGB DOT2[NUM_LEDS];
CRGB DOT[NUM_LEDS];

The code I used was originally intended for a longer strip, I'll change that part.

Changing the order of these doesn't change anything. If I change
Code: [Select]
#define DATA_PIN 4
#define CLOCK_PIN 5
#define DATA_PIN2 6
#define CLOCK_PIN2 7


to

Code: [Select]
#define DATA_PIN 6
#define CLOCK_PIN 7
#define DATA_PIN2 4
#define CLOCK_PIN2 5


The dot staying on will go from the strip on 6&7 to the one on 4&5, it's always the second strip having this problem.

I've tried to write the 2 vu meters seperately and not sharing any variables, that doesn't change anything either.

Grumpy_Mike

Quote
The dot staying on will go from the strip on 6&7 to the one on 4&5, it's always the second strip having this problem.
Altering the order of the #define will actual have no effect at all because it is a precompiler instruction, it does not change the code.

Reversing the order of the two I told you defines arrays at different addresses and if an array is being over run you will see a difference.

Go Up