PWM Servo Feedback (ADC) icon PWM Servo Feedback (ADC) Add ADC positional feedback to hobby PWM servos via minor mod to EZ-B/Arduino; enables real-time position readout, calibration and puppet mirroring Try it →
Asked
Smoothing Frequency Detector servo

Smoothing Frequency Detector Servo

I’m driving a standard 180 servo on D1 of an EZ-B v4 (Wi-Fi client mode) using the Frequency Detector skill to follow pitch. Windows default recording device is a Blue Snowball USB mic about 20 cm from a tone source (phone app sine and also an actual piano). In Frequency Detector I set Min Freq = 200 Hz, Max Freq = 800 Hz and mapped the servo range to 30-150. I also configured the skill to write the detected value to a variable named $fd_freq. The waveform shows clean input, but the Frequency Output bounces: when I play A4 (440 Hz), it jumps between ~430-470 and sometimes halves to ~220 or doubles to ~880. The servo then chatters as ARC keeps sending new positions.

What I’ve tried so far:

  • Reduced Windows mic gain and disabled AGC/noise suppression; tried 44.1 kHz and 48 kHz sample rates.
  • Moved mic closer and isolated it from the robot’s speaker to cut feedback.
  • Narrowed the min/max range to 350-500 Hz to focus on the fundamental.
  • Ticked the Pause checkboxes to confirm the jitter is coming from the detected value (it is), but that just stops motion.

Questions:

  • Is there a built-in smoothing or hysteresis setting in Frequency Detector (e.g., averaging window or update interval) that I’m missing?
  • If I set ServoSpeed for D1 in ARC, will that apply to movements generated by the Frequency Detector’s servo mapping, or do I need to script my own rate limit based on $fd_freq?
  • Any best practices to lock onto the fundamental to avoid the (1/2x, 1x, 2x) harmonic jumps when controlling an EZ-B v4 servo from this skill?

What’s the recommended way in ARC to stabilize this setup so the servo tracks pitch smoothly without twitching?



Related Hardware (view all EZB hardware)
EZ-B V4 by EZ-Robot
EZ-B v4/2 robot controller: dual Cortex ARM, Wi-Fi, audio/video, 24 servo/digital ports, I2C/UART, camera and Synthiam ARC control for custom robots
Wi-Fi / USB
Servos 24
Camera
Audio
UART 3
I2C
ADC 8
Digital 24

Related Robot Skills (view all robot skills)
Detect audio frequencies via PC microphone (FFT), output a variable and drive servos within configurable min/max ranges with waveform feedback.
Servo Speed by Synthiam
Adjust servo/PWM speed (0-20) between two positions to quickly experiment and tune motion; select board/port; settings aren't saved.

ARC Pro

Upgrade to ARC Pro

Don't limit your robot's potential – subscribe to ARC Pro and transform it into a dynamic, intelligent machine.

Author Avatar
PRO
Canada
Twitter YouTube GitHub
#1  

Yes - what you’re seeing is typical pitch-tracking jitter from FFT-based detection, especially when a tone has strong harmonics or the detector briefly "locks" to 1/2x or 2x of the fundamental.

Short answers

1) Built-in smoothing / hysteresis?

The Frequency Detector skill does not provide a user-facing smoothing window or hysteresis control for the detected frequency output.
So if the output is bouncing, the usual fix is to smooth the value yourself before driving the servo.

2) Will ServoSpeed help?

Yes, if the servo is being moved by ARC’s servo position updates, ServoSpeed can help reduce chatter by slowing how fast the servo responds to rapid position changes.

However, for best results, I’d still recommend rate limiting / filtering the frequency in a script before mapping it to the servo. That gives you control over:

  • smoothing
  • deadband / hysteresis
  • update rate
  • ignoring octave jumps

3) How to stabilize pitch tracking?

Best practice is usually a combination of:

  • average the detected frequency
  • ignore small changes with a deadband
  • reject octave errors by clamping changes that are roughly half or double the previous value
  • update the servo at a fixed interval instead of reacting to every fluctuation

Instead of sending the detected value straight to the servo skill, use the $fd_freq variable in a script and smooth it first.

Simple smoothing example in JavaScript

This example:

  • reads $fd_freq
  • applies a simple moving average
  • ignores tiny changes
  • maps the result to servo positions on D1
var alpha = 0.2; // lower = smoother, higher = more responsive
var deadbandHz = 8;
var filtered = 0;
var lastServoPos = 90;
var lastFreq = 0;

while (true) {
  var raw = parseFloat(getVar("$fd_freq", "0"));

  if (raw > 0) {
    if (filtered == 0) {
      filtered = raw;
    } else {
      filtered = filtered + alpha * (raw - filtered);
    }

    // Ignore tiny changes
    if (Math.abs(filtered - lastFreq) >= deadbandHz) {
      lastFreq = filtered;

      // Map 200-800 Hz to 30-150 degrees
      var pos = Math.round(Utility.map(filtered, 200, 800, 30, 150));

      // Clamp position
      if (pos < 30) pos = 30;
      if (pos > 150) pos = 150;

      // Only move if it actually changed enough
      if (Math.abs(pos - lastServoPos) >= 2) {
        Servo.setPosition(d1, pos);
        lastServoPos = pos;
      }
    }
  }

  sleep(50);
}

Add ServoSpeed too

If you want the servo itself to move more gracefully, set its speed as well:

Servo.setSpeed(d1, 5);

You can do that once in an initialization script or at project start.

A moderate value like 4-6 is usually a good starting point.


Reducing octave jumps

Those ~220 Hz / ~880 Hz jumps are harmonic-lock issues. To reduce them:

Option A: constrain the expected octave

If you know the note should be around 440 Hz, only accept values near that range.

Example logic:

  • if last stable frequency was around 440
  • ignore values below ~330 or above ~550 unless they persist

Option B: compare to last good value

If the new frequency is about:

  • half of the last value, or
  • double the last value

then reject it unless it stays there for several samples.

Option C: use a stronger fundamental source

A piano can be tricky because the overtone content is strong. A pure sine tone is much easier for the detector than piano. Your phone sine app is the better test source.


Practical tuning tips

Try this progression:

  1. Start with a sine tone
  2. Set Frequency Detector to a narrower range, like 380-520 Hz
  3. Add script-side smoothing
  4. Add deadband of 5-10 Hz
  5. Set ServoSpeed to 4-6
  6. Increase the script update interval to 50-100 ms

That usually gives a much calmer servo response.


Best ARC setup recommendation

For a stable pitch-following servo:

  • Use Frequency Detector only to detect pitch
  • Use a JavaScript loop to filter the detected frequency
  • Then call Servo.setPosition(d1, pos)
  • Optionally set Servo.setSpeed(d1, 4-6)

That’s generally better than relying on direct skill-to-servo mapping when you need smooth behavior.


If you want, I can help you build one of these:

  1. A simple low-pass filter script
  2. A median filter to suppress octave jumps
  3. A full pitch-tracking script with deadband + octave rejection + servo smoothing

If you’d like, I can write a version specifically for your D1 servo and your 200-800 Hz range.

I am a customer support AI and still learning. Please verify important answers in our support documentation. For advanced AI features, use the AI Script Agent built into ARC.