Can anyone tell me how to get very close to 10 kHz (can be off a few hz) on Digital Pin 9 on a nano? I looked at the prescalars and they don't allow me to get close to that number but doing some research it appears to be possible through other means. I get confused with heavy amounts of C++ code though so if someone can post the most dummy-proof syntax to set and then unset pin 9 to 10kHz I would be immensely grateful. As a last resort, if I can't decipher the code, I'd like to be able to simply copy/paste a code block into my sketch. Thank you.
Here's one way, blink without delay style.
Adjust duration for the period you want.
byte triggerOut = 2; // port D, bit 2 on Arduino
unsigned long currentMicros;
unsigned long nextMicros;
unsigned long duration = 25UL; // flip every 50uS = 20KHz pulse
unsigned long elapsedMicros;
void setup() {
pinMode (triggerOut, OUTPUT);
nextMicros = micros();
}
void loop() {
currentMicros = micros();
elapsedMicros = currentMicros - nextMicros;
if (elapsedMicros >= duration) {
nextMicros = nextMicros + duration;
PIND = PIND | 0b00000100; // toggle D2 output by writing to input port.
}
// do other stuff while time goes by
// ...
// end of other stuff, go check time again at top of loop
}
Correct me if I'm wrong but this would seem to generate a constant 20khz square wave. I should have specified that I actually need the duty cycle functionality of the PWM so I'm looking for a means of easily manipulating the duty cycle using the conventional means (such as analogWrite(9, 128)) but instead of running at 490 Hz, running at 10khz. I just reviewed my code again and I believe the scope of my function means that I would only need to change the frequency once and not worry about flipping it back. Is there a way to permanently alter the PWM freq such that I can continue to use analogWrite as normal to control duty? Sorry if I've misunderstood.
I found this line of code:
TCCR1B = TCCR1B & B11111000 | B00000001;
which apparently changes the prescaler register for timer 1 which, as I understand it, controls pins 9 and 10.
Therefore, is it a correct assumption that if I stick that 1 line of code at the beginning of my function, I can proceed to use the PWM on pin 9 as normal using analogWrite(9, X), where X is my duty out of 255? Will there be a loss of resolution or will I still get 8 bits of duty? Thank you.
Use the Timer1 library too do this.
#include <TimerOne.h>
void setup()
{
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
Timer1.initialize(100);
Timer1.pwm(9, 512);
Timer1.pwm(10, 255);
}
void loop()
{
}
.
Cool. I think I have enough code space to add an extra library. Thanks.
"Correct me if I'm wrong but this would seem to generate a constant 20khz square wave."
Yes, just change the value here for other frequencies. Thought the comment would make that obvious:
unsigned long duration = 25UL; // flip every 50uS = 20KHz pulse
You can enter a new value via Serial monitor, reading switches, or other means if you need to change it on the fly.
Gahhhrrrlic:
Cool. I think I have enough code space to add an extra library. Thanks.
Note: you get a range of 0-1023 to control duty cycle using the TimerOne library.
Also:
Timer1.pwm(9, 512); <-----<<< gives 50% on pin D9
Timer1.initialize(100); <-----<<< is 100 micro seconds = 10KHz
.