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?
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?
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);
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.
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.
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 %
================================