Peltier PWM Temperature Control: Noise Blanking

The MOSFET tester I’m building controls the MOSFET’s gate voltage and drain current, while measuring the drain voltage. That, however, puts the drain terminal at a relatively high-impedance node between two current sources: the limiter and the MOSFET-under-test. When they’re both set to nearly the same value, the drain terminal picks up a generous helping of 32 kHz noise from the 3 A PWM Peltier module current. When either current source is set much larger than the other, the higher one serves as a relatively low impedance path that reduces the pickup.

I thought about grounding the thermal block, but that means adding an insulating washer under every MOSFET-under-test, which means an even greater thermal control problem. So the easiest solution is to just turn off the PWM during measurements:

Peltier Noise - VDS - PWM Shutdown

Peltier Noise - VDS - PWM Shutdown

The lower trace (at 5 V/div, not 500 mV as shown) is a digital output marking the duration of the three analog reads: temperature, drain voltage, and drain current. The upper trace shows the absolute worst case for the noise, which looks rather awful.

The Peltier PWM comes from Arduino digital output 10, which is lashed to hardware Timer 1. Turning off the PWM requires setting the corresponding clock prescaler to “no input”, then setting it back to select the appropriate clock input after the measurement.

Just on general principles, I average three successive analog inputs, so the Arduino source code for the analog reads looks like this:

#define TCCRxB                  0x01        // set prescaler to 1:1 for 32 kHz PWM
#define NUM_T_SAMPLES    3

float ReadAI(byte PinNum) {
word RawAverage;

    digitalWrite(PIN_SYNC,HIGH);                // scope sync
    TCCR1B = 0x00;                              // turn off Peltier module PWM

    RawAverage = analogRead(PinNum);            // prime the averaging pump

    for (int i=2; i <= NUM_T_SAMPLES; i++) {
        RawAverage += (word)analogRead(PinNum);

    TCCR1B = TCCRxB;                            // restart Peltier PWM

    RawAverage /= NUM_T_SAMPLES;

    return (float)RawAverage;

  1. #1 by Mark Wilson on 2012-03-14 - 16:37

    Some good ideas and tips coming along in this thread Ed. I do similar averaging on analog reads but with a slight variation at the end. To reduce the effects of truncation in the division, (i.e. to round the result to the nearest whole number) I do something like:
    – read and sum 4 (or some higher multiple of 2) samples
    – add a value of half the sample count to the sum, then divide
    e.g. RawAverage = (RawAverge +2) / 4

    RawAverage = (RawAverge +2) >>2 (i.e. right shift instead of divide)

    • #2 by Ed on 2012-03-14 - 16:51

      round the result to the nearest whole number

      That certainly seems reasonable, although those poor analog inputs see enough noise that their low-order of bits resemble the stock market: purely random!

      For completeness, I should also turn off the gate voltage and drain current outputs, too, which might shave off a bit or two of noise. The looong time constants on those PWM filters should hold their outputs over a few tens of cycles.

      Thanks for the reminder!

  2. #3 by Aki on 2012-03-15 - 11:17

    “the stock market: purely random!”

    “As Li himself said of his own model: “The most dangerous part is when people believe everything coming out of it.””