element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
RoadTests & Reviews
  • Products
  • More
RoadTests & Reviews
Review Blogs GIGA VU Meter and Spectrum Analyzer
  • Blogs
  • RoadTest Forum
  • Documents
  • RoadTests
  • Reviews
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join RoadTests & Reviews to participate - click to join for free!
  • Share
  • More
  • Cancel
  • Author Author: dougw
  • Date Created: 26 Oct 2025 6:13 PM Date Created
  • Views 37 views
  • Likes 7 likes
  • Comments 2 comments
Related
Recommended
  • RoadTest
  • dougw
  • VU Meter
  • arduino giga r1
  • pdm microphone

GIGA VU Meter and Spectrum Analyzer

dougw
dougw
26 Oct 2025

Intro

The Arduino GIGA R1 kit I am road testing has a display with built in microphone. To test the microphone I am starting with using it to create a VU meter (volume unit meter). All the hardware necessary for this VU meter is included in this plug-and-play kit. It just needed a little adaptation of some example firmware.

image

Here is a short video demonstrating VU meter capability:

VU Meter Video

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

This demo used the LVGL library (light and versatile graphics library). Unfortunately this instance of the library would not accept larger fonts, so the label is pretty small.

VU Meter Firmware

/*
  VU Meter - Arduino GIGA Display - Microphone Demo
  Requires PDM, Arduino_H7_Video and lvgl libraries
  Code modified from code provided by Arduino
  By Doug Wong 2025
*/

// Include libraries
#include <PDM.h>
#include "Arduino_H7_Video.h"
#include "lvgl.h"

// Create display object
Arduino_H7_Video Display(800, 480, GigaDisplayShield);

// Slider
static void set_slider_val(void *bar, int32_t val) {
  lv_bar_set_value((lv_obj_t *)bar, val, LV_ANIM_ON);
}

// Default number of output channels
static const char channels = 1;

// Default PCM output frequency
static const int frequency = 16000;

// Buffer to read samples into, each sample is 16-bits
short sampleBuffer[512];

// Number of audio samples read
volatile int samplesRead;

lv_obj_t *obj;
lv_anim_t a;
int micValue;
long tot = 0;
float av;

void setup() {
  // Initialize Display
  Display.begin();

  // Setup callback
  PDM.onReceive(onPDMdata);

  // Start PDM
  if (!PDM.begin(channels, frequency)) {
    Serial.println("Failed to start PDM!");
    while (1)
      ;
  }

  // Create the bar
  obj = lv_bar_create(lv_scr_act());
  lv_obj_set_size(obj, 600, 50);
  lv_obj_center(obj);
  lv_bar_set_value(obj, 500, LV_ANIM_OFF);

  // Create the animation for the bar
  lv_anim_init(&a);
  lv_anim_set_exec_cb(&a, set_slider_val);
  lv_anim_set_time(&a, 300);
  lv_anim_set_playback_time(&a, 300);
  lv_anim_set_var(&a, obj);

// add title
  create_title(lv_scr_act());

}

void loop() {

  // Wait for samples to be read
  if (samplesRead > 256) {
    micValue = 0;
    for (int i = 0; i < 129; i++) {
      if (micValue < sampleBuffer[i]) micValue = sampleBuffer[i];
    }
      int dv = micValue / 4 - 20;
      if (dv > 0) {
        micValue = 20 + dv/4;
      } 
      else {
        micValue = 20 - 18 / micValue;
      }
      micValue = micValue;
      if (micValue > 500) {
        micValue = 500;
      }
      lv_anim_set_values(&a, 0, micValue);
      lv_anim_start(&a);

    // Clear the read count
    samplesRead = 0;
    delay(80);
  }
  lv_timer_handler();
}

// Callback function to process the data from the PDM microphone.

void onPDMdata() {
  // Query the number of available bytes
  int bytesAvailable = PDM.available();

  // Read into the sample buffer
  PDM.read(sampleBuffer, bytesAvailable);

  // 16-bit, 2 bytes per sample
  samplesRead = bytesAvailable / 2;
}

void create_title(lv_obj_t *parent) {
  // Create a label
  lv_obj_t *label = lv_label_create(parent);

  // Set the label text
  lv_label_set_text(label, "VU Meter");

  // Set a large font (make sure the font is available in your project)
  lv_obj_set_style_text_font(label, &lv_font_montserrat_14, LV_PART_MAIN);

  // Align the label to the top center of the screen
  lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 60); // 60 pixels from the top
}

Spectrum Analyzer

image

Another microphone application I want to demonstrate is an audio spectrum analyzer, because the kit has all the hardware as well as the computing horsepower needed.

Here is an even shorter video demonstrating a simple spectrum analyzer:

Spectrum Analyzer Demo Video

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

The green bars are showing up as white in the video. The software is a long way from good, but the objective is to show that the hardware is capable.

Spectrum Analyzer Firmware

/*
	Example of an audio spectrum analyzer display using the Arduino Giga Display and its microphone
  by Doug Wong 2025
  This program uses th FFT library by Enrique Condes
*/

#include "Arduino_GigaDisplay.h"
#include "arduinoFFT.h"
#include "Arduino_GigaDisplay_GFX.h"
#include <PDM.h>

GigaDisplay_GFX display; // Create the display object

#define SAMPLES 128           // Number of audio samples
#define BARS 16               // Number of spectrum bars
#define SAMPLING_FREQUENCY 16000  // Hz
#define GREEN 0x07E0
#define BLACK 0x0000
#define BLUE 0x001E

/*
These values can be changed in order to evaluate the functions
*/
const uint16_t samples = 128; //This value MUST ALWAYS be a power of 2
const double signalFrequency = 1000;
const double sampleFrequency = 16000;
static const int frequency = 16000;
static const char channels = 1;
const uint8_t amplitude = 100;
// static const int channels = 1;

short sampleBuffer[samples];

double vReal[samples];      //audio samples array
double vImag[samples];      //spectrum amplitudes
int iBar = SAMPLES / BARS;  //number of data points per bar
int barWidth = 2 * display.width() / BARS;  //number of pixels per bar
int barHeight;
int BarAmp;

int bytesAvailable = 128;   //in microphone buffer

/* Create FFT object */
ArduinoFFT<double> FFT = ArduinoFFT<double>(vReal, vImag, samples, sampleFrequency);

#define SCL_INDEX 0x00
#define SCL_TIME 0x01
#define SCL_FREQUENCY 0x02
#define SCL_PLOT 0x03

void setup()
{
  delay (400);
 // Serial.begin(115200);
  display.begin();
  display.setRotation(1);
  PDM.setBufferSize(samples);
  delay (400);
  display.fillScreen(BLACK);
  PDM.onReceive(onPDMdata);
    // Start PDM microphone
  if (!PDM.begin(channels, frequency)) {
    //Serial.println("Failed to start PDM!");
    while (1)
      ;
  }
}

void loop()
{
//  PDM.read(sampleBuffer, bytesAvailable);
  for (int i = 0; i < SAMPLES; i++) {
    vReal[i] = sampleBuffer[i];
    vImag[i] = 0.0;
  }

  FFT.windowing(vReal, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);	/* Weigh data */
  FFT.compute(vReal, vImag, SAMPLES, FFT_FORWARD); /* Compute FFT */
  FFT.complexToMagnitude(vReal, vImag, SAMPLES); /* Compute magnitudes */

// Draw spectrum bars
  for (int i = 0; i < BARS; i++) {
    BarAmp = 0;
    for(int j = 0; j < iBar; j++) {
//       if (BarAmp < vImag[i * BARS + j]) BarAmp = vImag[i * BARS + j];
      BarAmp = BarAmp + vImag[i * BARS + j];    // total amplitude in each bar
    }
    if (i == 8) BarAmp = BarAmp / 20;           // to reduce an anomolously high bar
    BarAmp =  BarAmp / BARS;                    // average amplitube in this bar
    barHeight = BarAmp / 16;                    // adjustment for overall volume
    if (barHeight > display.height()) barHeight = display.height(); 
    display.fillRect(i * barWidth, 0, barWidth - 2, display.height() - barHeight, BLACK);
    display.fillRect(i * barWidth, display.height() - barHeight, barWidth - 2, barHeight, GREEN);
  }
  delay(80);
}

void onPDMdata() {
  // query the number of bytes available
  int bytesAvailable = PDM.available();

  // read into the sample buffer
  int bytesRead = PDM.read(sampleBuffer, bytesAvailable);

  // 16-bit, 2 bytes per sample
  int samplesRead = bytesRead / 2;
}

Discussion

The Arduino Giga  kit has so many features these applications can be implemented with no extra hardware. The VU meter uses the MCU, the PDM microphone and the Giga Display. The Spectrum analyzer uses the same set of hardware but also uses the arduinoFFT library. This GIGA and display kit not only allows an extensive array of applications to be implemented with little or no extra hardware, the fact that so many features are built-in allows standard demo software to be developed that does all the heavy lifting in making features work together. This kit by itself could be the basis for an extensive course on microcontrollers.

Links:

Unboxing and display demo

Touch Screen and USB memory demo

GIGA display of an Arducam video camera

GIGA VU Meter and Spectrum Analyzer

Giga R1 Road Test page

  • Sign in to reply
  • dougw
    dougw 16 hours ago in reply to beacon_dave

    The phone speaker was very close to the Giga mic, so it generates a large signal.

    My camera mic, which is picking up the audio track for the video, is on me - much further from the phone. The MCU has lots of horsepower to do things like compress the amplitude or make it logarythmic or flash an overload LED, if someone wants to add a cool factor.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • beacon_dave
    beacon_dave 17 hours ago

    Looking good.

    Perhaps need to find the equivalent of 'wrapping the needle around the end stop' though  Slight smile

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube