Increasing PWM frequency causes jittery movement

Hello,
I am using an Arduino Nano (ATmega328P) combined with a Pololu G2 motor driver to drive a DC motor. With the default PWM frequency of the Nano, there is a loud noise coming from the motor, so I wanted to increase the PWM Frequency to some frequency above 20kHz, to make it inaudible to the human ear.

I found this example code on how to increase the PWM frequency for the Nano on pin D9 to ~31kHz:
TCCR1B = TCCR1B & B11111000 | B00000001;

However, after adding this line, the motor movement is very jittery and the motor basically jumps around instead of smooth motion/acceleration.

The Pololu G2 Motor drivers can handle a PWM frequency of up to 100kHz and I have used them with a PWM frequency of 25kHz (controlled by a different microcontroller) before, which worked just fine. But I can not get a smooth motion with the Arduino Nano and the increased PWM frequncy.

What could be the problem? And is there another solution to get smooth motion without affecting millis() and without hearing the PWM frequncy through the motor?

Hi,
What are your motors and what is your powersupply?

Can you please post a circuit diagram and some images of your project.

Please do no use Fritzy, an image of a hand drawn circuit will be fine, please include power supplies and component names and pin labels.

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

The timer is busy with other functions and related code that affects the PWM generation.

Sorry for the late response.
I attached a simplified schematic from the PCB design.
the power supply for the moment is just a lab bench power supply which can provide more than enough current for the motor. With the normal PWM frequency everything works just fine - except the audible noise.

Could the use of millis() be the problem then? I was a bit worried, that increasing the PWM frequency in this way could affect the output of millis(), but when I use Serial.print to output the current time, the timing still seems right.
I don't use any additional libraries, so the code mostly consists of a bunch of if/else conditions.

At the end of the loop function, I have a 10ms delay - but the timer shouldn't be affected by the delay anyway, right?

But with the irregular and abrupt motor movement, I also guess, that there is a problem with the generation of the PWM signal.

There is something wrong with your motor, driver and supply. Get another motor and driver and check how these behave. Did you already check a different driver instead of the G2?

Significant motor noise is often a sign of poor quality construction, wear, etc.

Please comply with the request to post links to the motor and motor power supply.

Hello mvu, Good day.
Have you measured the 31kHz Pwm Signal with an Oszi if freq is matching to 31kHz?

I would suggest this register setting for 31kHz PWM.

// clear registers
TCCR1A = 0;
TCCR1B = 0;

// Set fast mode 9 bit          
TCCR1A |= (1 << WGM11);
TCCR1B |= (1 << WGM12);
// Set prescaler to 1
TCCR1B |= (1 << CS10);
//Set noninverting PWM
TCCR1A |= (1 << COM1A1);

// PWM Frequenz = 16.000.000 / (1 * 512) = 31.250 Hz
// Output pin is D9

Best regards Markus

Quote from data sheets:
The actual OC1x value will only be visible on the port pin if
the data direction for the port pin is set as output (DDR_OC1x).

Your sketch is missing the following line:

pinMode(9, OUTPUT);

Also, you need to set the duty cycle of the wave at some value with the help of OCR1A Register.

Hi @mvu46579

The Arduino Nano "Original" (not the newfangled ones) has 6 PWM pins that can be controlled with the analogWrite() function.

Those on digital pins 5 and 6 operate at a frequency of 980Hz. However, these pins use timer 0, which is also employed for the millis() and micros() timing functions, therefore this timer is best left alone.

Regarding the other PWM outputs, digital pins 9 and 10 use timer 1, while digital pins 3 and 11 function with timer 2. These all normally operate at a frequency of 490Hz.

Since timers 1 and 2 aren't used by the timing functions, it's possible to simply tweak their prescalers in order to generate a PWM output frequency of 31.25kHz (instead of 490Hz) and still control the duty cycle using the analogWrite() function as you would normally, (duty-cycle 0 to 255).

For timer 1 on digital pins 9 and 10, just add the following line to your sketch:

TCCR1B &= ~_BV(CS11);	// Increase the timer1 PWM frequency to 31.25kHz

For timer 2 on digital pins 3 and 11, just add these lines:

TCCR2B &= ~_BV(CS22);	// Increase the timer2 PWM frequency to 31.25kHz
TCCR2B |= _BV(CS20);
1 Like

Thank you for all the responses.

I tried using a different power supply, a different motor, a new motor driver (still a Pololu G2 but a spare one) and also tried a new Arduino Nano. Still the same behaviour.

I also tried the alternative methods of achieving the 31kHz, but the problem remains.

Measuring the output of the motor driver with an oscilloscope (both with, and without motor) also shows the irregularity of the output.

However, I noticed that changing the frequency somhehow messes with my code. With the default PWM frequency the code works just fine. With the increased frequency and a constant PWM value, it also seems to be working. Only when I use the increased frequency and ramp the speed up or down this problems seems to be occuring.
When I print the speed value (which is being sent to the analogWrite function) this value also fluctuates. So the problem seems to be software related.

I will go back a few steps and do some more testing with a simplified sketch and see at which point the increased PWM frequency starts to mess with the code.

Who generates the ramp? Changing the duty cycle is not always trivial.

Try with the following setup and sketch; where, you can change frequency by varying PotF and duty cycle by varying the PotD of Fig-1. Vary PotD slowly so that OCR1A remains below of ICR1.
pwmAPPosc
Figure-1:

Sketch:

//62.5 kHz 1 Hz PWM signal with 50% duty cycle using TCNT1 at DPin-9
#define OC1A 9

void setup()
{
  Serial.begin(9600);

  pinMode(OC1A, OUTPUT);  //PWM signal will appear on DPin-9
  TCCR1A = 0x00;   //reset
  TCCR1B = 0x00;   //TC1 reset and OFF
  //fOC1A (DPin-9) = clckSys/(N*(1+ICR1)); Mode-14 Fast PWM; OCR1A controls duty cycle

  TCCR1A = (1 << COM1A1) | (1 << WGM11); //non-inverting Dual Slope FPWM, Mode-14
  //ICR1 = 49999;  //changes frequnecy as ICR chnages
  //OCR1A = 25000;   //~= 50% duty cycle and practically chnages the duty cycle
  TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10); //Mode-14, /1; TC1 in ON
}

void loop()
{
  ICR1 = map(analogRead(A0), 0, 1023, 0, 65535); //changes frequency
  Serial.print("ICR1 = "); Serial.println(ICR1);
  Serial.print("Frequency is: "); Serial.print(16000000 / (1 + ICR1)); Serial.println(" Hz");
  Serial.println("------------------------------------");
  OCR1A = map(analogRead(A1), 0, 1023, 0, 65535); //changes duty cycle
  Serial.print("OCR1A = "); Serial.println(OCR1A);
  Serial.print("Duty cycle is: "); Serial.print((float)OCR1A/ICR1*100.0, 2); Serial.println(" %");
  Serial.println("================================");
  delay(1000);
}

Typical Output:

================================
ICR1 = 19795
Frequency is: 808 Hz
------------------------------------
OCR1A = 8456
Duty cycle is: 42.72 %
================================

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