Go Down

Topic: Sonómetro y tira de LEDs Neopixel (Read 155 times) previous topic - next topic

ESPITY

Feb 11, 2020, 02:16 am Last Edit: Feb 11, 2020, 02:19 am by ESPITY
Hola:
Estoy trabajando en la programación de un sonómetro pero estoy teniendo problemas con mi código (probablemente sea mi ignorancia), tengo que entregarlo el jueves y llevo una semana con este problema y no consigo resolverlo!

Uso este sensor para medir la amplitud y, posteriormente, calcular los decibelios, hasta ahí bien.

Después, muestra los decibelios en un display de segmentos de cuatro dígitos, esto funciona perfectamente, pero yo quería añadir una tira de LEDs Neopixel para que se ilumine en:
  • Rojo: cuando los dB superen los 120 (el umbral de dolor, aunque nunca llega a detectar sonidos así).
  • Amarillo: entre 65 y 120 dB
  • Verde: entre 30 y 65 dB.

Para programar la tira empleé la librería Neopixel de Adafruit, concretamente colorwipe pero, como usa un delay, afectaba al display de segmentos (como no muestran los dígitos a la vez sino de forma consecutiva pero tan rápido que no podemos verlo este delay aumentaba este tiempo considerablemente) así que traté de hacer que realizase el colorwipe empleando millis.

Al principio, se enciende verde correctamente (con el colorwipe) pero cuando cambia a amarillo en vez de comenzar en el primer LED y acabar en el último (37) comienza en uno aleatorio (cada vez) y ni siquiera enciende 37 LEDs a partir de ese, a veces incluso enciende unos amarillos hay un espacio de verdes y después amarillos.

Aquí muestro el primer código, en el que la tira de LEDs funcionaba correctamente (como me gustaría que hiciese ahora) pero se veía afectado el display de segmentos :

Code: [Select]
#include <Adafruit_NeoPixel.h>
#include <SevSeg.h>            // Display de segmentos

#define LED_PIN   24
#define LED_COUNT 37
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
SevSeg sevseg;

const int soundPin = 0;        // Pin envelope del sensor de sonido (Analógico)

//Variables del sonido
int sound;                     // Amplitud
float decibelsCalculated;
float dB;                      // Decibelios tras la operación (float --> decimal)

//Millis
unsigned long time;
unsigned long t = 0;
int dt = 1000;                 // Diferencia de tiempo


void setup() {

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)

  Serial.begin(9600);

  byte numDigits = 4;
  byte digitPins[] = {10, 11, 12, 13};
  byte segmentPins[] = {2, 3, 4, 5, 6, 7, 8, 9};
  bool resistorsOnSegments = true;
  byte hardwareConfig = COMMON_CATHODE;
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
  // sevseg.setBrightness(90);

}

void loop() {
  time = millis();
  if (time - t > dt) {
    t = time;
    sound = analogRead(soundPin);                 // Lee los datos y valores del pin Envelope del sensor de sonido

    decibelsCalculated = 20 * log10(sound / 1);   // Calcula los dB
    dB = decibelsCalculated + 30.15;

    Serial.println(dB);                            // Imprimimos en el puerto serial los dB
  }

  sevseg.setNumber(dB, 2);                        // Escribimos los dB en el display de segmentos
  sevseg.refreshDisplay();

  // Leds
  if (dB > 120) {                                   // Led ROJO --> A partir de 120 dB
    colorWipe(strip.Color(225,   0,   0), 20);
  }
  if (dB > 65 && dB < 120) {                        // Led AMARILLO --> Entre 65 y 120 dB
    colorWipe(strip.Color(225,   128,   0), 20);
  }
  if (dB > 30 && dB < 65) {                        // Led VERDE --> Entre 30 y 65 dB
    colorWipe(strip.Color(0,   225,   0), 20); // Red
  }

}

void colorWipe(uint32_t color, int wait) {
  for (int i = 0; i < strip.numPixels(); i++) { // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

Y aquí está el código empleando millis, en el que el display de segmentos funciona correctamente pero los LEDs son un caos:

Code: [Select]
#include <Adafruit_NeoPixel.h>
#include <SevSeg.h>            // Display de segmentos

#define LED_PIN   24
#define LED_COUNT 37
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
SevSeg sevseg;

const int soundPin = 0;        // Pin envelope del sensor de sonido (Analógico)

//Variables del sonido
int sound;                     // Amplitud
float decibelsCalculated;
float dB;                      // Decibelios tras la operación (float --> decimal)

//Millis
unsigned long time;
unsigned long t = 0;
int dt = 1000;                 // Diferencia de tiempo

unsigned long interval = 50; // the time we need to wait
unsigned long previousMillis = 0;

uint16_t currentPixel = 0;// what pixel are we operating on


void setup() {

  currentPixel = 0;
  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)

  Serial.begin(9600);

  byte numDigits = 4;
  byte digitPins[] = {10, 11, 12, 13};
  byte segmentPins[] = {2, 3, 4, 5, 6, 7, 8, 9};
  bool resistorsOnSegments = true;
  byte hardwareConfig = COMMON_CATHODE;
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
  // sevseg.setBrightness(90);

}

void loop() {
  time = millis();
  if (time - t > dt) {
    t = time;
    sound = analogRead(soundPin);                 // Lee los datos y valores del pin Envelope del sensor de sonido

    decibelsCalculated = 20 * log10(sound / 1);   // Calcula los dB
    dB = decibelsCalculated + 30.15;

    Serial.println(dB);                            // Imprimimos en el puerto serial los dB
  }

    sevseg.setNumber(dB, 2);                        // Escribimos los dB en el display de segmentos
    sevseg.refreshDisplay();

  // Leds
  if (dB > 120 && (unsigned long)(millis() - previousMillis) >= interval) {                                   // Led ROJO --> A partir de 120 dB
    previousMillis = millis();
    colorWipe(strip.Color(255, 0, 0));
  }
  if (dB > 65 && dB < 120 && (unsigned long)(millis() - previousMillis) >= interval) {                        // Led AMARILLO --> Entre 65 y 120 dB
    previousMillis = millis();
    colorWipe(strip.Color(255, 128, 0));
  }
  if (dB > 30 && dB < 65 && (unsigned long)(millis() - previousMillis) >= interval) {                        // Led VERDE --> Entre 30 y 65 dB
    previousMillis = millis();
    colorWipe(strip.Color(0, 255, 0));
  }
}

void colorWipe(uint32_t color) {
  strip.setPixelColor(currentPixel, color);
  strip.show();
  currentPixel++;
  if (currentPixel == LED_COUNT) {
    currentPixel = 0;
  }
}


También intenté emplear la librería FastLED (incluso conseguí que hiciese un colorwipe) pero al final desistí porque no entendía la mitad de las cosas.
Intentaré poner un vídeo o un gif del problema.

Gracias de antemano!

Go Up