Wemos D1 i Arduino

Moduł Wemos D1 jest mały i to jest (moim zdaniem jego zaleta), do różnego rodzaju testów nie potrzeba budować ogromnej machiny z kabli na wielkie płytce stykowej.

Tym razem na małej płytce stykowej umieściłem moduł Wemos D1 mini (Wemos D1 mini v3.1.0 ESP8266 WiFi Python NodeMCU tak brzmi jego pełna nazwa), moduł mikrofonu KY-038 oraz moduł wyświetlacza graficznego OLED SSD1306 dispaly (128×64). Dlaczego właśnie te elementy? Bo je kupiłem z myślą o przetestowaniu i sprawdzeniu jak je używać w aplikacji miernika poziomu natężenia dźwięku.

Połączenie wszystkiego jest banalnie proste. Napięcie 3,3V z wyjścia Wemos idzie na wejście „+” modułu mikrofonu i Vcc wyświetlacza OLED. Masa zasilania z wyjścia GND Wemos na GND wyświetlacza OLED i wejście „G” mikrofonu. Wyjście analogowe mikrofonu „A0” do wejścia pomiarowego A0 modułu Wemos. Wyjścia SDA i SCL należy podłączyć do odpowiednich wejść SDA i SCL modułu Wemos (D2 – SDA, D1-SCL).

No to bazę sprzętową przedstawiłem a teraz oprogramowanie. Inaczej, niż poprzednio postanowiłem do programowania Wemos D1 mini wykorzystać Arduino. Wemos to po prawdzie ESP8266 z „opakowaniem” więc w Arduino da się zaprogramować.

W „menadżerze płytek” jeśli nie macie „esp8266 by ESP community” to musicie ją zainstalować. Wybieracie następnie odpowiednią płytkę – u mnie to „LOLIN(Wemos) D1 R2& mini”.

W edytorze Arduino należy wpisać program:

/*******************************************
 * Decybelometr - test wersion
 * 
 * Test project for KY-038 microphone and Wemos D1
 * with OLED SSD1306 dispaly (128x64)
 *******************************************
 * last change: 2020-09-23
 *******************************************/

#include <ESP8266WiFi.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
 
#define SCREEN_WIDTH 128    // OLED display width, in pixels
#define SCREEN_HEIGHT 64    // OLED display height, in pixels
#define OLED_RESET -1       // Reset pin # (or -1 if sharing Arduino reset pin)

#define SENSOR_PIN A0                                     // pin for measurement
#define UART_SPEED 115200                                 // set UART speed

  Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &amp;Wire, OLED_RESET);

  const int sampleWindow = 100;            // Sample window width in mS (100 mS = 10Hz)
  unsigned int sample;
  
  int rawVal = 0;

  const String SSID = "***"; // wifi network name
  const String PASS = "***"; // password for access to wifi network

  int step = 0;

void setup() {
  pinMode (SENSOR_PIN, INPUT); // Set the signal pin as input
   
  Serial.begin(UART_SPEED);                                 // set UART speed to 115200

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);                // OLED display start
  display.display();                                        // show buffer
  display.clearDisplay();                                   // clear buffer
  display.setTextSize(1);                                   // Set text size to 1 (1-6)
  display.setTextColor(WHITE);                  // Set text color to BLUE in my display
  display.setCursor(0,0);                       // cursor to upper left corner
  display.println("2020 - Decybelometr");                   // write title
  
  display.setCursor(20,50);
  display.println("rafalrebacz.pl");
  
  display.display();                                        // show title
  delay(1000);                                              // wait 1 seconds  

  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(0,0);
  display.println("Connecting to WiFi");
  display.display();

  WiFi.begin(SSID,PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    display.print(".");
    display.display();
    Serial.print(".");    
  }
  Serial.print("\nWiFi CONNECTED!");
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());

  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0,0);
  display.println("WiFi CONNECTED!\n");
  display.print("IP: ");
  display.println(WiFi.localIP());
  display.display();
  delay(3000);
}

void loop() {

  unsigned long startMillis= millis();                      // Start of sample window
  float peakToPeak = 0;                                     // peak-to-peak level
 
  unsigned int signalMax = 0;                               // minimum value
  unsigned int signalMin = 1024;                            // maximum value

  float rms = 0;
  float sumSquare = 0;
  int licznik = 0;
                                                            
   while (millis() - startMillis < sampleWindow)         // collect data for 100 mS
   {
      sample = analogRead(SENSOR_PIN);                   // get reading from microphone

      sumSquare += sample * sample;
      licznik +=1;
      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
         }
      }
   }
 
  rms = sqrt(sumSquare/licznik);
 
   peakToPeak = signalMax - signalMin;             // max - min = peak-peak amplitude
   
   float db = map(peakToPeak,20,900,49.5,90);      // calibrate for deciBels 
                                       //(it's not correct, but it works as a sample!)

  double volts = (peakToPeak * 3.3) / 1024;
  
   display.setCursor(0,0);                               // cursor to upper left corner
   display.setTextSize(3);                               // set text size to 2
   display.print(db,1);                                  // write calibrated deciBels
   display.print(" dB");     
  
   display.drawRect(0,32,128,10, WHITE);                 // draw outline of bar graph
   
   int r = map(db,0,120,1,128);                          // set bar graph for width of screen

   display.fillRect(1,32,r,8,WHITE);      // draw rectangle bar graph with a width of r

   display.setTextSize(2);                // Set text size to 1 (1-6)
   display.setTextColor(WHITE);           // Set text color to WHITE (no choice)   

  if (db < 55) {
    display.setCursor(45,50);
    display.print("GOOD"); 
  } else if (db < 65) {
    display.setCursor(10,50);
    display.print("NOT GOOD");   
  } else {
    display.setCursor(40,50);
    display.print("ALARM");   
  }

  // heartbit drawing - small rotating lines in left bottom corner
    switch (step) {
      case 0:
        display.drawLine(0,59,5,64,WHITE);
        break;
      case 1:
        display.drawLine(3,59,3,64,WHITE);
        break;
      case 2:
        display.drawLine(5,59,0,64,WHITE);
        break;
      case 3:
        display.drawLine(0,61,5,61,WHITE);
        break;
    }

      if (step < 3) {
        step += 1;
      } else {
        step = 0;
      }

   display.display();                           // show all that we just wrote &amp; drew
   display.clearDisplay();                      // clear the display


  // print values via UART
  
  Serial.print(millis());
//  Serial.print("RMS: ");
  Serial.print("\t");
  Serial.print(rms,1); 
//  Serial.print("\twynik dB: ");
  Serial.print("\t");
  Serial.print(db);
//  Serial.print("\tnapiecie: ");
  Serial.print("\t");
  Serial.println(volts);
}

Zasada działania jest prosta. Moduł mikrofonu wzmacnia sygnał jaki do niego dociera i wystawia na wejście A0 modułu Wemos D1. Na tym wejściu dokonywane jest n pomiarów w założonym czasie i uśredniane.

Wartość ta jest skalowana na dB (niepoprawnie 🙂 od razu zaznaczam) i służy do wyświetlania na ekranie wyświetlacza OLED oraz wystawiana jest na port UART. W oparciu o progi (dowolnie ustawione/wybrane) wyświetlana jest na ekranie informacja „GOOD”, „NOT GOOD”, „ALARM” – to w innej wersji „miernika” posłuży do wyświetlania „koloru” na kolorowym wyświetlaczu z diodami WS2812B.

W programie jest też dodany mały wskaźnik „heartbit” w lewym dolnym narożniku wyświetlacza w postaci kręcącej się linii – ot taki „ficzer” ;).

Avatar

Autor: gervee

Pełnoetatowy ojciec małej gromadki, programista(?), "amator" fotograf, "dłubacz" lubiący DIY, miłośnik chmielonego napitku. "Żartowniś" bez poczucia humoru ;).

Dodaj komentarz