LinkedIn YouTube Facebook
Szukaj

Newsletter

Proszę czekać.

Dziękujemy za zgłoszenie!

Wstecz
Artykuły

[PROJEKT] Wskaźnik wysterowania mikrofonu MEMS na panelu KAmodWS2812-8 + Arduino

Mając przygotowany i połączony sprzęt można przejść do oprogramowania Arduino (przygotowany program znajduje się w sekcji „Do pobrania”). W pierwszym kroku dołączana jest biblioteka do sterowania diodami, a także zdefiniowana jest: liczba diod, linia z której korzystają oraz liczba próbek, z której będziemy odtwarzać wartość szczytową.

#include "Adafruit_NeoPixel.h"
#define N 32
#define LICZBA_DIOD 16
#define PIN 6

Następnie deklarowane są zmienne globalne potrzebne w programie oraz następuje inicjalizacja biblioteki NeoPixel, za pomocą której sterowany jest łańcuch diod.

int peakL = 0, peakR = 0; // wartość szczytowa w buforze
int diodyL = 0; // liczba diod, które należy zapalic
int diodyR = 0;
int buforL[N], buforR[N]; // bufor w którym znajduje się poprzednie N próbek 
int i = 0, j = 0; // liczniki petli
const float offset=log(1.65); // zlogarytmowana skladowa stala napiecia na mikrofonie
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(LICZBA_DIOD, PIN, NEO_GRB + NEO_KHZ800); // inicjalizacja lancucha diod

W funkcji odbierzSygnal() pobierana jest z przetwornika ADC aktualna wartość dla obu mikrofonów: lewego i prawego. Następnie obie wartości są wprowadzane do buforów kołowych o długości N. Aktualne wartości są wpisywane na i-tą pozycję tablicy, gdzie zastępują próbkę najstarszą. Pętla for wyszukuje w całym buforze (który mieści próbkę aktualną i N-1 poprzednich) wartość najwyższą i wpisuje ją do zmiennej peak zarówno dla prawego, jak i lewego kanału.

void odbierzSygnal(void)
{
    peakL = 0;
    peakR = 0;
    buforL[i] = analogRead (A0);
    buforR[i] = analogRead (A1);
    (++i)%=N;
    for(j=0;j<N;j++)
    {
      if (peakL< buforL[j])
        peakL = buforL[j];
      if (peakR< buforR[j]);
        peakR=buforR[j];
    }
  }

Funkcja przeliczPoziom() działa jako konwerter wartości szczytowej sygnału na liczbę diod jaką należy wyświetlić. Najpierw wartość próbki jest przeliczana na wartość w woltach, następnie logarytmowana. Logarytm o podstawie 10 jest tu użyty, aby wskaźnik reagował także na cichsze dźwięki oraz ze względu na charakterystykę ludzkiego ucha. Dzięki temu układ wskazuje natężenie w przybliżeniu odpowiadające naturalnemu odczuwaniu głośności. Następnie odejmowana jest zlogarytmowana składowa stała, a całość dzielona przez 0,3 (ok. log10(2)). W ten sposób otrzymujemy wartość wyskalowaną od 0 do 1, a więc należy pomnożyć ją przez 8 i zaokrąglić, aby otrzymać liczbę diod, jaką należy zapalić. Przetwornik ADC w Arduino jest zasilany napięciem 5V i może przyjmować wartość napięcia aż do VCC. W związku z tym maksymalna liczba zapalonych diod dla kanału ograniczana jest do 8, gdyż w przeciwnym wypadku wskazanie będzie przenosić się na sąsiedni panel.

void przeliczPoziom(void)
{
    diodyL = round((log(peakL*(5.0/1023.0))-offset)/0.3*8.0);
    diodyR = round((log(peakR*(5.0/1023.0))-offset)/0.3*8.0);
    if (diodyL > 8)
      diodyL = 8;
   if (diodyR > 8)
     diodyR = 8;
}

Funkcja zaswiecDiody() steruje łańcuchami w zależności od wcześniej przeliczonej liczby diod do zapalenia. Należy mieć świadomość, że dla tak połączonego łańcucha dioda nr 8 jest diodą najwyższą w łańcuchu lewym, a dioda nr 15 – najniższą tamże. Oznacza to, że dla lewego kanału diody trzeba zapalać w odwrotnej kolejności. W bibliotece NeoPixel funkcja clear() wygasza cały łańcuch (niezbędne, aby diody nie zatrzaskiwały się po przekroczeniu pewnego poziomu), natomiast funkcja show() wysyła wprowadzone wartości do łańcucha.

void zaswiecDiody(void)
{
  pixels.clear();

  for(int ii=0; ii<diodyR; ii++)
  {
    pixels.setPixelColor(ii, 64, 0, 64);
  } 

  for(int jj=15; jj>15-diodyL; jj--)
  {
    pixels.setPixelColor(jj, 64, 64, 0);
  }

  pixels.show();
  delay(1);
}

W funkcji setup() inicjalizowane są tylko moduły WS2812-8:

void setup()
{
  pixels.begin();
}

W funkcji loop() wywoływane są po kolei wcześniej omówione funkcje:

void loop()
{
   odbierzSygnal();
   przeliczPoziom();
   zaswiecDiody();
}

Działanie programu zostało przedstawione w poniższym filmie: