I am trying to follow Need help to set PWM frequency to 25kHz and generate the same 25khz on pin 8 of arduino mega which is controlled by TIMER 4; I dont see any success; could someone please help?
Given below is the code I have tried based on an answer by @EdgarBonet in the linked post and I tried on connecting fan pwm on each of the 3 pins 6, 7, 8 one by one and still cannot get the speed to change and the fan is just running at full speed;
void analogWrite25k(int value)
{
OCR4A = value;
OCR4B = value;
OCR4C = value;
}
void setup()
{
TCCR4A = 0;
TCCR4B = 0;
TCCR4C = 0;
TCNT4 = 0;
TCCR4A = _BV(COM4A1)
| _BV(COM4B1)
| _BV(COM4C1)
| _BV(WGM11);
TCCR4B = _BV(WGM13)
| _BV(CS10);
TCCR4C = _BV(WGM13)
| _BV(CS10);
ICR4 = 320;
// Set the PWM pins as output.
pinMode( 8, OUTPUT);
}
void loop()
{
analogWrite25k(10);
for (;;) ; // infinite loop
}
edit2:
Thanks for the hints by @dannyf; I read the datasheet again and below is what I am trying now but even this is not working and I am really unable to figure out if something is not right in this; I am trying to set value of OCR4C only in analogWrite25k method since fan pwm line is connected to digital pin 8 of my Mega;
TCCR4A = 0;
TCCR4B = 0;
TCNT4 = 0;
TCCR4A = _BV(COM4C1)
| _BV(WGM41);
TCCR4B = _BV(WGM43)
| _BV(CS40);
ICR4 = 320; // TOP = 320
-
Comments are not for extended discussion; this conversation has been moved to chat.Majenko– Majenko2017年09月16日 20:44:23 +00:00Commented Sep 16, 2017 at 20:44
2 Answers 2
easy.
find a copy of the datasheet for your mcu;
go to the section about your timer;
figure out a prescaler setting that yields the maximum roll-over count;
pick the timer mode that supports the roll-over count;
write your own analogWrite() function;
[optional] if you wish to reuse the stock analogWrite(), make sure that roll-over count calculated in 3) is a valid data type for the stock analogWrite(). If not, increase the prescaler in 3) until it is.
done.
edit: i decided to give it a try.
the following code:
void setup() {
// put your setup code here, to run once:
pwm1Set(TMR1_PS8x, F_CPU / F_PWM1 / 8); //ps = 8x, top = F_CPU / F_PWM / 8 = 80
analogWrite(9, 20); //dc = 20/80=25%
analogWrite(10, 40); //dc = 40/80=50%
}
void loop() {
// put your main code here, to run repeatedly:
}
produced the following output on an ATMega328p's TIMER1.
i'm reasonably sure that the output is indeed 25Khz.
the code itself however is capable of generating pwm at other frequencies.
edit2: the same code on mega2560 generating 25Khz pwm on pin6/7/8:
code used for that is as follows:
//ps = 8x, top = F_CPU / F_PWM / 8 = 80
//DC on Pin 6 = 20/80 = 25,
//DC on Pin 7 = 40/80 = 50,
//DC on Pin 8 = 60/80 = 75,
pwm4Set(TMR4_PS8x, F_CPU / F_PWM4 / 8); analogWrite(6, 20); analogWrite(7, 40); analogWrite(8, 60);
pwm4Set() is a copy of pwm1Set(). Both are simple enough: only 5 lines of code used.
-
thanks for the response but the question was specific to arduino mega 2560;techniche– techniche2017年09月15日 06:15:50 +00:00Commented Sep 15, 2017 at 6:15
-
1@dannyf - thanks for the edit and help on mega but I am not sure where to get the pwm1Set or pwm4Set functions; are they builtin functions or part of some additional library?techniche– techniche2017年09月15日 19:50:42 +00:00Commented Sep 15, 2017 at 19:50
Found a properly working answer for the question finally; Thanks to KIV's answer on Need help to set PWM frequency to 25kHz on pin 8 of Arduino Mega to control speed of a 4-wire cpu fan an additional usful thing he has added is to allow setting of duty cycle from serial monitor input for convenience while testing;
void analogWrite25k(int value)
{
OCR4C = value;
}
void setup()
{
TCCR4A = 0;
TCCR4B = 0;
TCNT4 = 0;
// Mode 10: phase correct PWM with ICR4 as Top (= F_CPU/2/25000)
// OC4C as Non-Inverted PWM output
ICR4 = (F_CPU/25000)/2;
OCR4C = ICR4/2; // default: about 50:50
TCCR4A = _BV(COM4C1) | _BV(WGM41);
TCCR4B = _BV(WGM43) | _BV(CS40);
Serial.begin(115200);
// Set the PWM pin as output.
pinMode( 8, OUTPUT);
}
void loop()
{
int w = Serial.parseInt();
if (w>0) {
analogWrite25k(w);
Serial.println(w);
}
}