analog microphone/Reading it/07. Resting level and swing
Reading it · 07 of 10

Resting level and swing

Two measurements turn this block into a number. At start-up, average a quiet second to find the resting level. Then, every 50 ms, take the highest reading minus the lowest: the peak-to-peak swing. The swing grows with loudness, the resting level cancels out of it, and a clap reads hundreds of millivolts where talking reads a few.

Two numbers, not one

The first reading showed the problem: one reading is one instant of the wave. So the sketch measures two things instead.

The resting level, once. At start-up it averages every reading taken over one quiet second. Averaging cancels the wave, if there is one, and what is left is where SIGNAL sits in silence on this board. It is printed so you know it; nothing later depends on it.

The swing, every 50 ms. The sketch reads as fast as it can for 50 ms, keeps the highest and the lowest reading, and prints the difference. That is the peak-to-peak swing. The resting level is in both the highest and the lowest, so it cancels out of the difference, and the same sketch works on a board that rests at 1.6 V and on one that rests at 4 V.

What a sound looks like

Resting level and swing
Sound
Resting level
2868 mV
Peak to peak
1486 mV
On an Uno
304 counts
Over 50 ms the highest point is 3609 mV and the lowest 2124 mV, either side of the resting level at 2868 mV. The difference, about 1486 mV or 304 counts on an Uno, is the number that grows with loudness. Neither the highest nor the lowest alone does, and the resting level cancels out of it.

Pick a sound. The figure draws 50 ms of SIGNAL from 5V, with the resting level dashed and the highest and lowest point marked. Talking a metre away swings it by about 15 mV, three counts on an Uno. A raised voice close by makes about 150 mV. A clap at arm's length makes well over a volt.

The sizes are a picture, not a measurement. The capsule's own sensitivity is not published anywhere we could find, so the figure borrows one from a comparable capsule of the same size. Your numbers will differ; the order will not.

Where it stops growing

Pick Clap, close. The wave wants to swing further than the board allows. Upwards SIGNAL stops at VCC, where the transistor turns fully off; downwards it stops a few tenths of a volt above 0, where it turns fully on. The tops and bottoms are cut flat and the swing stops growing. A clap close up and a clap a little further away can then read the same.

That is fine for a switch, which only has to know loud from quiet. It is why the numbers this sketch prints are not decibels: they rise with loudness, not in proportion to it, and not at all once the wave clips.

The window

Fifty milliseconds is several cycles of the lowest sound the block passes, about 75 Hz, so the window catches the wave's real highest and lowest points. An Uno's analogRead takes about a tenth of a millisecond, so it reads a few hundred times in each window. Anything much shorter than 50 ms can miss a low sound's peaks; much longer and the sketch answers late, with a clap and its echo in the same window.

The code

Reads millivolts: calibrated on an ESP32, scaled from the count on an Uno or a Pico. setup measures the resting level over a quiet second; loop prints the swing, highest minus lowest, for every 50 ms window.

mic_swing.ino
/*
  Analog Microphone - resting level and swing           TK27 / /p/tk27

  Wiring. Count from the square pad on the TinkerBlock board, parts
  up, header at the bottom:

    GND    -> GND
    VCC    -> 5V on an Uno; 3V3 on an ESP32, ESP32-S3 or Pico
    NC     -> nothing   (unconnected on the board)
    SIGNAL -> A0 on an Uno, GPIO 34 on an ESP32, GPIO 4 on an
              ESP32-S3, GP26 on a Raspberry Pi Pico

  Arduino IDE
    Tools > Board                 your board, e.g. Arduino Uno
    Tools > Port                  the one that appears when you plug in
    Tools > USB CDC On Boot       Enabled   (ESP32-S3 only)
    No library needed.
*/

// The analog pin SIGNAL is wired to.
// Uno: A0. ESP32: 34. ESP32-S3: 4. Pico: 26.
const int MIC_PIN = A0;

// Uno and Pico only: the ADC's full scale, in mV.
// Uno: 5000. Pico: 3300.
const float FULL_SCALE_MV = 5000.0;
// Several cycles of the lowest sound the block passes.
const unsigned long WINDOW_MS = 50;
const unsigned long CALIBRATE_MS = 1000;

float readMilliVolts() {
#if defined(ARDUINO_ARCH_ESP32)
  return analogReadMilliVolts(MIC_PIN);   // calibrated in the chip
#else
  return analogRead(MIC_PIN) * FULL_SCALE_MV / 1023.0;
#endif
}

void setup() {
  Serial.begin(115200);
  delay(500);
  Serial.println("Measuring the resting level. Keep quiet...");

  float sum = 0;
  long n = 0;
  unsigned long start = millis();
  while (millis() - start < CALIBRATE_MS) {
    sum += readMilliVolts();
    n++;
  }
  Serial.print("Resting level ");
  Serial.print(sum / n, 0);
  Serial.println(" mV");
}

void loop() {
  // The highest and lowest reading in one window.
  float lo = 100000;
  float hi = -1;
  unsigned long start = millis();
  while (millis() - start < WINDOW_MS) {
    float mv = readMilliVolts();
    if (mv < lo) lo = mv;
    if (mv > hi) hi = mv;
  }

  Serial.print("swing ");
  Serial.print(hi - lo, 0);   // peak to peak: louder, bigger
  Serial.println(" mV");
}

The resting level is printed once and not used again: the swing is measured from each window's own highest and lowest reading, so a resting level that drifts as the board warms changes nothing. On an Uno, set FULL_SCALE_MV to the 5V pin's real voltage for exact millivolts.

When it does not work

The swing is never 0, even in silence.

Every ADC's readings wander by a count or two, more on an ESP32, so the highest and lowest reading in any window differ a little. That is the quiet swing, and a sketch should measure it before it trusts any threshold. The ESP32 article does exactly that.

The resting level it prints is not what the plotter showed.

The sketch prints millivolts, not counts. On an Uno one count is about 4.9 mV, so a line at 600 in the plotter is about 2930 mV here. If it is further off than that, the room was not quiet while it measured: press reset and keep still for the first second.

Clapping closer stops making the number bigger.

Close up, a clap swings SIGNAL further than it can go: up to VCC on one side and down near 0 V on the other, and both are cut flat. Past that point the swing stops growing, however close you clap. This block tells loud from quiet reliably, not how loud once it clips.

Why 50 ms and not 10?

The block passes sounds down to about 75 Hz, and one cycle of 75 Hz lasts over 13 ms. A 50 ms window holds several cycles of the lowest sound it hears, so the highest and lowest reading in it are the wave's real peaks. A 10 ms window can miss them.

Where this goes next

Finer steps, more noise, and why every sketch should measure the quiet swing first.

Reading it on an ESP32

Edit this page — content/books/analog-microphone/resting-level-and-swing.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

Analog Microphone

Loading discussions…

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse Modules and blocks on the forum