I’m using a Baby O and Motordriver 18v15 to control speed and direction of a 6 V. Faulhaber motor.
It’s working, but after trying all different frequencies in Fast PWM and Phase Correct PWM I can’t get ridd of a high pitch sound. It’s worst at low rpm.
Here’s the code for the Phase corrrect PWM I’m using:
int main(void)
{
unsigned char i=0;
// Initial PORT Used
DDRD = 0b11111111; // Set PORTD: Output
PORTD = 0x00;
// Initial TIMER0 Phase Correct PWM
// Phase Correct Frequency = fclk / (N * 510), Where N is the Prescaler
// f_PWM = 20 000 000 / (8 * 510) = 4.9 kHz
TCCR0A = 0b10100001; // Phase Correct PWM 8 Bit, Clear OCA0/OCB0 on Compare Match, Set on TOP
TCCR0B = 0b00000010; // Used 8 Prescaler
For my application it’s crucial that I can minimize this sound.
Is there a solution to this problem, am I doing something wrong?
Typically, you’ll want “fast PWM” rather than “phase correct PWM.”
The key to removing PWM sound is to run the PWM at a high enough frequency that you don’t hear it. Aim for 20 kHz.
This assumes that your motor controller can keep up at that speed. If not, chances are you’ll blow it out.
The specification for the 18v15 driver says:
How can I get this PWM of 20 kHz.?
I’ve tried to use prescaler 1, this gives a lower wine at low rpm but makes the motor act erratic at higher rpm’s.
I also tried to change the clock frequency, but this doesn’t seem to have any effect.
I’m a newbie on this, so you have to lead me every step of the way…
Where did you get the code you are currently using? Do you understand it well enough to modify it?
One easy way to get to 20 kHz is to take the 5 kHz phase-correct PWM you have now and set the TOP to be 63 (a quarter of what it is now). Alternatively, you could use a fast PWM with a TOP value of 127 (keeping the timer 0 prescaler at 8).
Faulhaber uses up to 70 kHz. to run its motors. So I think I have to use the maximum of 40 kHz. that my motor driver can handle.
How can I change this TOP value?
That blog post you linked to has examples of how to set the TOP, but you might just want to look at the ATmega328p datasheet. I think you should be using timer 1 instead of timer 0, since the Baby Orangutan uses timer 0 for its own motor driver (are you using the Baby Orangutan motor driver outputs as inputs for your high power motor driver?). Also, I suggest you shoot for a PWM frequency of 20 kHz to minimize switching losses. 20 kHz will be just as quiet as 40 kHz. If there is something you don’t understand in the datasheet, please let me know.
Thank’s for your reply.
I’ve been looking both at the blog I send you and the datasheet. It’s hard to understand for me, but I’ve been trying the following code, where I changed from pin PD5 to PB1 and use different coding to set the registers:
int main (void)
{
unsigned char i=0;
DDRB |= _BV(PB1); //Set Pin PB1 as output
//Fast PWM, 8-bit, Prescaling (N = 8)
TCCR1A |= _BV(COM1A1) | _BV(WGM10); // Fast PWM Frequency = fclk / (N * 127), Where N is the Prescaler
TCCR1B |= _BV(CS11) | _BV(WGM12); // f_PWM = 20 000 000 / (8 * 127) = 19,7 kHz
ICR1H = 0x7FFF; //Set TOP to 127 (16 bit register)
ICR1L = 0x7FFF;
for(;;)
{
//Fade up
for(i=0; i<127;i++){
OCR1A = i; //Set new duty cycle value
delay(10); //delay a litle bit
}
//Fade down
for(i=127; i>0;i--)
{
OCR1A = i; //Set new duty cycle value
delay(10); //delay a litle bit
}
}
return 0; // Standard Return Code
}
I assume that if I lower the TOP to 127 that I have to lower “i” to 127 as well. This gives me only half the motor speed. It works well with “i” set to 255, so I’m not sure if the motor is running on 20 kHz.
There are a few problems with what you’re doing. As a first step, let’s figure out what you want. It sounds like you want to use a non-inverted fast PWM on timer 1 with a configurable top. If you look in the ATmega328P datasheet on pages 132-138, you can figure out what register values give you these settings:
non-inverted fast PWM on PB1 (OC1A): COM1A1 = 1, COM1A0 = 0
fast PWM with configurable top (ICR1): WGM13 = 1, WGM12 = 1, WGM11 = 1, WGM10 = 0
The frequency of a fast PWM is given by f = F_CPU/prescaler/(TOP + 1)
If we know we want a frequency of 20 kHz and F_CPU is 20 MHz, we get that:
TOP = 1000/prescaler - 1
Timer 1 is a 16-bit register, which means that 999 is an acceptable value and we can use a prescaler of 1 (the timer ticks at the full rate of 20 MHz). If we were using an 8-bit timer, we would pick a prescaler to get the biggest TOP value under 256.
prescaler of 1: CS12 = 0, CS11 = 0, CS10 = 1
So this means we want to set:
TCCR1A = _BV(COM1A1) | _BV(WGM11); // equivalent to 10000010, or 0x82
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // equivalent to 00011001, or 0x19
ICR1 = 999; // set TOP to 999 for a 20 kHz PWM
To control the duty cycle, you would set OCR1A. If you make OCR1A = 500, you will get a 50% duty cycle. This means that your ramp-up and ramp-down code will need to change to loop from 0 to 999 instead of 127, and you will probably want to decrease the length of your delay so that it still takes the same amount of time.