Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Динамик MB2

На вашем MB2 есть встроенный динамик — большое чёрное квадратное устройство с надписью «SPEAKER» в центре обратной стороны платы.

Динамик работает так: он перемещает воздух в ответ на сигнал с GPIO-вывода. Когда вывод динамика в высоком уровне (3,3 В), внутренняя диафрагма — «конус динамика» — выдвигается полностью наружу; когда вывод в низком уровне (GND), конус втягивается полностью внутрь. Когда воздух выталкивается наружу и втягивается обратно, он проходит через маленькое прямоугольное отверстие — «порт динамика» — на боковой стороне устройства. Если делать это достаточно быстро, перепады давления создадут звук.

При правильной схеме управления этот конус динамика можно было бы переместить в любое положение в своём диапазоне с помощью соответствующего тока. Это позволило бы довольно хорошо воспроизводить любой звук, как у «обычного» динамика. К сожалению, ограничения аппаратуры MB2, управляющей динамиком, означают, что доступны только крайние положения — полностью внутрь и полностью наружу.

Давайте выталкивать конус динамика наружу и внутрь 220 раз в секунду. Это создаст «квадратную» волну давления с 220 циклами в секунду. Единица «циклов в секунду» — герц; мы получим тон 220 Гц (музыкальная нота «ля» малой октавы, A3), который на этом пронзительном динамике звучит неплохо.

Мы сделаем так, чтобы тон звучал пять секунд, а затем прекратился. Важно помнить, что наша программа хранится во флеш-памяти MB2: тон будет начинаться снова при каждом сбросе или даже включении MB2. Если позволить тону звучать вечно, такое поведение быстро станет очень раздражающим.

Вот код (examples/square-wave.rs).

#![no_main]
#![no_std]

use cortex_m::asm;
use cortex_m_rt::entry;
use embedded_hal::{delay::DelayNs, digital::OutputPin};
use panic_rtt_target as _;
use rtt_target::rtt_init_print;

use microbit::{
    hal::{gpio, timer},
    Board,
};

/// «Период» — это время одного цикла. Он равен
/// 1/f, где f — частота в Гц. В этом случае
/// время измеряем в миллисекундах.
const PERIOD: u32 = 1000 / 220;

/// Количество циклов для пяти секунд звучания.
const CYCLES: u32 = 5000 / PERIOD;

#[entry]
fn main() -> ! {
    rtt_init_print!();
    let board = Board::take().unwrap();
    let mut speaker_pin = board.speaker_pin.into_push_pull_output(gpio::Level::Low);
    let mut timer = timer::Timer::new(board.TIMER0);

    for _ in 0..CYCLES {
        speaker_pin.set_high().unwrap();
        timer.delay_ms(PERIOD / 2);
        speaker_pin.set_low().unwrap();
        timer.delay_ms(PERIOD / 2);
    }

    loop {
        asm::wfi();
    }
}