Skip to content

Instantly share code, notes, and snippets.

@arnemileswinter
Created January 16, 2023 23:04
Show Gist options
  • Save arnemileswinter/c6635afa93f92fde73d818f55d616d70 to your computer and use it in GitHub Desktop.
Save arnemileswinter/c6635afa93f92fde73d818f55d616d70 to your computer and use it in GitHub Desktop.
Rust snippet using avr-hal: Manual PWM to pull a digital output pin on an arduino to specified Hertz frequency. Useful to operate buzzers.
use arduino_hal::{clock::Clock,port::{mode::Output, Pin, PinOps}};
/// Pull an arduino's output pin to specified Hertz for microseconds duration.
/// This is essentially manual PWM, without avr-hal's clock prescaling.
/// Useful to make buzzers oscillate at 440 hertz.
/// This is not measured to be precise but works well enough.
///
/// example:
/// let dp = arduino_hal::Peripherals::take().unwrap();
/// let pins = arduino_hal::pins!(dp);
/// let mut buzzer_pin = pins.d2.into_output()
/// pin_to_hz_for_duration_us(&mut buzzer_pin, 440, 2 * 10_u32.pow(6)) // pin d2 buzzes at 440hz for 2 seconds.
fn pin_to_hz_for_duration_us<P: PinOps> (pin: &mut Pin<Output, P>, frequency_hz: u32, duration_us: u32) {
if frequency_hz == 0 {
// can't meaningfully wait
arduino_hal::delay_us(duration_us);
return;
}
const CLOCK_SPEED_HZ: u32 = arduino_hal::DefaultClock::FREQ;
let wait_time = (CLOCK_SPEED_HZ / frequency_hz) / 100;
let mut acc = 0;
while acc < duration_us {
pin.set_high();
arduino_hal::delay_us(wait_time / 2);
pin.set_low();
arduino_hal::delay_us(wait_time / 2);
acc += wait_time;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment