ラズパイ財団プロダクト同士でなんか作ってみようと思って、micro:bitをフロントエンドとしてmic入力とLED出力を使った、音声のレベル表示(一応LED25個で25レベルの表示ができます)をやってみた
macro:bit (p1) –> ラズピコADC1(平均化処理)-> PWM出力およそ22KHzをrcでローパス -> micro:bit(p2)という流れ
<micro:bit側のコード>
from microbit import *
def show_bar(level): # level: 0-25
display.clear()
height = level // 5 # 5段に分割
width = level % 5 # 各段の幅
# 下からバー積み上げ
for y in range(5):
if 4-y < height:
for x in range(5):
display.set_pixel(x, 4-y, 9)
elif 4-y == height:
for x in range(width):
display.set_pixel(x, 4-y, 9)
while True:
mic_level = microphone.sound_level()
pin1.write_analog(mic_level * 4)
control_level = pin2.read_analog()
# 0-25に変換
bar_level = min(control_level // 40, 25)
show_bar(bar_level)
sleep(10)
<ラズピコ側>
Cargo.toml
embedded-halの1.0系は0.2と互換なし、embeded-halはobject指向言語で言うところのinterfaceでrp-235x-halは実装、つまりプロセッサが変わっても共通だろうinterfaceをembedded-halはtraitの集合として持っている
[package]
edition = "2024"
name = "rust_starter"
version = "0.1.0"
license = "MIT or Apache-2.0"
[dependencies]
cortex-m = "0.7.7"
cortex-m-rt = "0.7.5"
rp235x-hal = "0.3"
embedded-hal = "0.2"
#embedded-hal = "1.0.0" does not support rp235x-hal yet
defmt = "1.0.1"
defmt-rtt = "1.0.1"
panic-probe = { version = "1.0", features = ["print-defmt"] }
[build-dependencies]
regex = "1.11.0"
[target.'cfg( target_arch = "arm" )'.dependencies]
panic-probe = { version = "1", features = ["print-defmt"] }
[target."thumbv8m.main-none-eabihf".dependencies]
rp235x-hal = { version = "0.3", features = ["rt", "critical-section-impl"] }<Rustコード>
Lチカコードを修正
#![no_std]
#![no_main]
use defmt_rtt as _;
use hal::pac;
use embedded_hal::adc::OneShot;
use embedded_hal::blocking::delay::DelayUs;
use embedded_hal::PwmPin;
#[cfg(target_arch = "riscv32")]
use panic_halt as _;
#[cfg(target_arch = "arm")]
use panic_probe as _;
// Alias for our HAL crate
use hal::entry;
#[cfg(rp2350)]
use rp235x_hal as hal;
#[cfg(rp2040)]
use rp2040_hal as hal;
// use bsp::entry;
// use bsp::hal;
// use rp_pico as bsp;
/// The linker will place this boot block at the start of our program image. We
/// need this to help the ROM bootloader get our code up and running.
/// Note: This boot block is not necessary when using a rp-hal based BSP
/// as the BSPs already perform this step.
#[unsafe(link_section = ".boot2")]
#[used]
#[cfg(rp2040)]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
/// Tell the Boot ROM about our application
#[unsafe(link_section = ".start_block")]
#[used]
#[cfg(rp2350)]
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
/// External high-speed crystal on the Raspberry Pi Pico 2 board is 12 MHz.
/// Adjust if your board has a different frequency
const XTAL_FREQ_HZ: u32 = 12_000_000u32;
const DELAY: u32 = 1000; // μs delay
const SAMPLES: u32 = 250;
/// Entry point to our bare-metal application.
///
/// The `#[hal::entry]` macro ensures the Cortex-M start-up code calls this function
/// as soon as all global variables and the spinlock are initialised.
///
/// The function configures the rp2040 and rp235x peripherals, then toggles a GPIO pin in
/// an infinite loop. If there is an LED connected to that pin, it will blink.
#[entry]
fn main() -> ! {
// 1. Peripherals取得
let mut pac = pac::Peripherals::take().unwrap();
// 2. クロック・ウォッチドッグ初期化
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
let clocks = hal::clocks::init_clocks_and_plls(
XTAL_FREQ_HZ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog,
)
.ok()
.unwrap();
// 3. GPIO初期化
let sio = hal::Sio::new(pac.SIO);
let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
let mut delay = hal::Timer::new_timer0(pac.TIMER0, &mut pac.RESETS, &clocks);
// 4. ADC設定
let mut adc = hal::Adc::new(pac.ADC, &mut pac.RESETS);
let mut adc_pin = hal::adc::AdcPin::new(pins.gpio26).unwrap();
// 5. PWM設定
let pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS);
let mut pwm = pwm_slices.pwm0;
pwm.set_ph_correct();
pwm.set_top(4095);
pwm.enable();
// GP0 = PWM Slice 0 Channel A(alomost 20KHz duty 99% @3.3v full scale)
let mut pwm_channel = pwm.channel_a;
let _pwm_pin = pins.gpio0.into_function::(); // GP0 as a PWM output
loop {
let mut sum: u32 = 0;
// measure "samples" time and make average
for _ in 0..SAMPLES {
let v: u16 = adc.read(&mut adc_pin).unwrap();
sum += v as u32;
}
let avg = (sum / SAMPLES) as u16;
pwm_channel.set_duty(avg);
delay.delay_us(DELAY);
}
}
/// Program metadata for `picotool info`
#[unsafe(link_section = ".bi_entries")]
#[used]
pub static PICOTOOL_ENTRIES: [hal::binary_info::EntryAddr; 5] = [
hal::binary_info::rp_cargo_bin_name!(),
hal::binary_info::rp_cargo_version!(),
hal::binary_info::rp_program_description!(c"Blinky Example"),
hal::binary_info::rp_cargo_homepage_url!(),
hal::binary_info::rp_program_build_attribute!(),
];
// End of file 動いてるところの動画は以下に、
まだ周辺回路サポートのcrateは途上ではあるけれども、組み込みでも普通に使えるようになってきたのは大きな進歩
admin
