aide néopixel [RESOLU]

Salut,

après avoir trouvé ce qu'il me fallait, ou presque pour réaliser un vumètre, j'aurais besoin de comprendre une chose dans ce programme à base de neopixel.

Le programme fonctionne très bien mais je voudrais modifier quelque chose.

en fait sur un ruban 144 leds le point de départ se situe au milieu, et je voudrais savoir sur quel paramètre agir pour que le point de départ soit soit à la led 1 soit 144.

quelqu'un pourrait m'éclairer ?

merci

PS : je trouve que ce programme gère exceptionnellement bien les basses, contrairement au programme de cine lights qui je trouve ne varie pas bien en fonction de la musique (juste un constat de ma part)

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

#define N_PIXELS  144  // Number of pixels in strand
#define MIC_PIN   A4  // 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 10 //Time of pause before peak dot falls
#define PEAK_FALL 4 //Rate of falling peak dot
#define INPUT_FLOOR 50 //Lower range of analogRead input
#define INPUT_CEILING 500 //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'

}

// FIXME:
// * left end works fine, right end doesn't blank


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)));
    }
  */

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

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

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

  // Set the peak dot to match the rainbow gradient
  y = strip.numPixels() / 2 - peak;

  // left - okay
  strip.setPixelColor(strip.numPixels() / 2 - (y - 1), Wheel(map(y, 0, strip.numPixels() / 2, 30, 150)));
  // right - maybe fixme
  strip.setPixelColor(strip.numPixels() / 2 + y - 1, Wheel(map(y, 0, strip.numPixels() / 2, 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);
  }
}

Ce n'est pas possible, la led numéro un est la plus proche du connecteur. Si tu veux utiliser une numérotation différente, c'est à toi de le faire mais il faudra en final la convertir pour respecter la numérotation utilisée par les bibliothèque

ok donc il faudrait que j'utilise une autre bibliothèque ? ou plutôt une autre fonction ?

Pas forcément. Ton problème je suppose est que tu veux que ton vu mètre affiche des valeurs positives et des valeurs négatives. Disons que la première led correspond à la valeur 'xmin' qui est négative, et que la led 144 correspond à la valeur 'xmax' qui est positive. Pour une valeur donnée 'x' tu cherches à allumer les leds de la valeur 0 à la valeur 'x', vers la gauche si x est négatif et vers la droite si x est positif ?
La valeur 0 devrait entre les leds numéro 72 et 73. Déjà, pour fonctionner comme je l'imagine, il te faudrait un nombre de leds impair. Disons que la led 144 ne sera jamais utilisée, ok ? Alors la valeur 0 correspond à la led 72.
Il te reste à savoir à quelle led correspond la valeur x'. Pour cela tu peux utiliser la fonction map.
Ensuite, il te reste à allumer les leds entre ce numéro et la 72...

j'ai dû mal m'expliquer ...

actuellement, avec ce code, le vu-metre a comme "début" de centre de la bande, c'est à dire que les leds s'allument identiquement vers la droite et vers la gauche.

moi je souhaiterais partir d'un bout pour le début et arriver à l'autre bout pour ...

rien de mieux qu'un exemple
sur la vidéo, je cherche à avoir le résultat du début de la vidéo jusqu'à la seconde 40
actuellement moi j'ai justement ce qu'il y a à partir de la 40ème seconde ..

Je pense que ce que tu cherches est déjà là :

  /*
    //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)));
    }
  */

Il suffit de le dé-commenter (enlever les :* et */) et de trouver ce qui fait l'animation actuelle pour le commenter (un peu plus dur). Je dirais qu'il faut commenter ces lignes (mettre /* juste avant et */ juste après) :

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

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

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

  // Set the peak dot to match the rainbow gradient
  y = strip.numPixels() / 2 - peak;

  // left - okay
  strip.setPixelColor(strip.numPixels() / 2 - (y - 1), Wheel(map(y, 0, strip.numPixels() / 2, 30, 150)));
  // right - maybe fixme
  strip.setPixelColor(strip.numPixels() / 2 + y - 1, Wheel(map(y, 0, strip.numPixels() / 2, 30, 150)));

j'ai réussi à avancer, mais je me retrouve avec le défilement de haut en bas .... je voudrais de bas en haut !!

je mets ce que j'ai modifié, peut-e^tre saurais tu comment inverser !!

 //Fill the strip with rainbow gradient
  for (int i = 0; i <= strip.numPixels() -i ; i++) {
    // left - works
    strip.setPixelColor(strip.numPixels() -i, Wheel(map(i, 0, strip.numPixels() -1, 30, 150)));
    // right - maybe fixme
   // strip.setPixelColor(i + strip.numPixels() / 2, Wheel(map(i, 0, strip.numPixels() / 2, 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
    // left - okay
    drawLine(0, c, strip.Color(0, 0, 0));
    // right - maybe fixed?
   // drawLine(strip.numPixels() - c, strip.numPixels(), strip.Color(0, 0, 0));
  }

  // Set the peak dot to match the rainbow gradient
  y = strip.numPixels()  - peak;

  // left - okay
  strip.setPixelColor(strip.numPixels()  - (y - 1), Wheel(map(y, 0, strip.numPixels() , 30, 150)));
  // right - maybe fixme
 // strip.setPixelColor(strip.numPixels() / 2 + y - 1, Wheel(map(y, 0, strip.numPixels() / 2, 30, 150)));

  strip.show();

Dans le principe c'est simple, tu retournes le ruban..
Sinon tu modifies les numéros de leds, comme ceci. Lorsqu'une instruction allume la led numéro n, il suffit de lui dire d'allumer la led strip.numPixels() - n

Donc tu changes la ligne

 strip.setPixelColor(i, Wheel(map(i, 0, strip.numPixels() - 1, 30, 150)));

En

 strip.setPixelColor(strip.numPixels() - i, Wheel(map(i, 0,strip.numPixels() -  1, 30, 150)));

Ou bien

 strip.setPixelColor(strip.numPixels() - i, Wheel(map(strip.numPixels() -i, 0,strip.numPixels() -  1, 30, 150)));

Voilà ça fonctionne !!

merci beaucoup pour ton aide !!

pour ceux qui veulent, le code !

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

#define N_PIXELS  144  // Number of pixels in strand
#define MIC_PIN   A4  // 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 10 //Time of pause before peak dot falls
#define PEAK_FALL 1 //Rate of falling peak dot
#define INPUT_FLOOR 70 //Lower range of analogRead input
#define INPUT_CEILING 500 //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

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

  //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() - c, strip.numPixels(), strip.Color(0, 0, 0));
  }

  // Set the peak dot to match the rainbow gradient
  y =  peak;

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

 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);
  }
}