Increasing the PWM Frequency on a MEGA 2560

I'm building a kinetic sculpture and using a MEGA 2560 to adjust spinning motor speeds. I've got a great, simple little program that I'm using to adjust the speed on the fly. I'm using a motor control module and this part has all tested out great.

/*
  Mega analogWrite() test for controlling motor with Serial.
  This only works with Serial input values between 0 and 255. Don't type anything else, silly.

*/

// These constants won't change. They're used to give names to the pins used:
const int motorPin = 9;

// This is where the incoming serial integers will be stored:
int incomingInt = 0;
String incomingString = "0";


void setup() {
  // set pin as output:

    pinMode(motorPin, OUTPUT);
    Serial.begin(115200); // opens serial port, sets data rate

}

void loop() {

if ( Serial.available() > 0) {
    // read the incoming serial data.
    incomingString = Serial.readStringUntil('\n');
    incomingInt = incomingString.toInt();
    // say what you got:
    Serial.print("I received: ");
    Serial.println(incomingInt, DEC);
  }
  
  analogWrite(motorPin,incomingInt);

}

HOWEVER, when controlled this way, the motor gets noisy, and the environment for the sculpture will be very quiet. I tested it, and the motor runs noticeably noisier with the PWM signal than it does with the equivalent average voltage run as "straight" analog DC from a power supply.

So I had this great idea that if I can increase the frequency of the PWM outside the range of human hearing, I could still control the motor from the Arduino, but it wouldn't have the same noise produced by the audible 490Hz PWM signal going to the motor.

I'm equipped with a Digital Oscilloscope and DMM to check my work as I go. I know my wiring and setup is good because it all reads and acts as expected with the sketch above.

I found the below little snippet online to adjust the timer on the Mega, which seemed like a good approach. Except, when I inserted it into my setup section, it seems to affect the analogWrite function in an unintended way. With this modification, any number I enter into serial >= 4 gives 100% duty cycle output, and anything lower obviously won't drive the motor.

int myEraser = 7; // this is 111 in binary and is used as an eraser
TCCR2B &= ~myEraser; // this operation (AND plus NOT), set the three bits in TCCR2B to 0
int myPrescaler = 1; // this could be a number in [1 , 6]. In this case, 3 corresponds in binary to 011.
TCCR2B |= myPrescaler; //this operation (OR), replaces the last three bits in TCCR2B with our new value 011

I've also tried a couple libraries i.e. Timer1, Timer3, but even running their example sketches give me an always-on output (confirmed by my Oscilloscope) instead of a PWM signal for some reason.

Long post but hoping all the detail will help.... Thank you in advance :slight_smile:

Update - the issue seems to be with my motor controller. It works great at 480Hz but doesn't seem to understand the 25kHz signal. My oscilloscope is confirming that the correct frequency is coming out of the MEGA, but the motor controller is not responding as expected (behavior described in previous post).

Can anyone point me towards a dc brushed motor control breakout / module / shield that will place nicely with this higher frequency signal?

may get more help on the motors forum

Any MOSFET H-bridge should be able to handle this (check the datasheet of course), perhaps you existing motor driver is a slow one (Darlington outputs?)

Why don't you put the analogWrite() inside the if() statement so you only update the PWM when you have input? I don't know exactly what analogWrite does but writing to counters/CCx registers when the timers are running can produce glitchy waveforms and cause some "noise"

This is not typically a problem with registers controlling duty-cycle unless you update more than once per PWM waveform.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.