Scriptone Scriptone

【Rust】Raspberry Pi用の学習キットを利用してテーブルランプを作る

概要

Lチカの回路にボタンを追加して点灯させる動作をRustで記述します。前回と同様にFreenoveの題材を使用します。キットはamazonで購入できますが汎用的な部品なので任意の方法で調達をお願いいたします。

回路

使用する部品は下記の通りです。

  • 220Ωの抵抗x1
  • 10kΩの抵抗x2
  • タクトスイッチx1
  • LED

リンク先2.1.3. Circuitに配線および回路図がありますので図表に沿って回路を構築してください。

コード

cargoでrppalctrlcを追加してコードを記述します。

ButtonSwitch

無限ループを使ってGPIO18に電源が供給されいるかされていないかでGPI18のレベルがHIGHであるかLOWであるかを判別します。ボタンを押すとHIGHとLOWが切り替わり、それに併せてLEDピンをHIGH/LOWを制御する仕組みとなっています。

use rppal::gpio::{Gpio, Level};
use std::error::Error;

const LED_PIN: u8 = 17;
const BTN_PIN: u8 = 18;

fn main() -> Result<(), Box<dyn Error>> {
    println!("Program is starting...");
    let gpio = Gpio::new()?;
    let mut led_pin = gpio.get(LED_PIN)?.into_output();
    let btn_pin = gpio.get(BTN_PIN)?.into_input();
    // Ctrl+Cが押されたら終了
    let running = Arc::new(AtomicBool::new(true));
    let r = running.clone();
    ctrlc::set_handler(move || {
        r.store(false, Ordering::SeqCst);
    })?;
    loop {
        if btn_pin.is_low() {
            // led_pin.set_high();
            led_pin.write(Level::High);
            println!("Button is pressed, led turned on >>>");
        } else {
            // led_pin.set_low();
            led_pin.write(Level::Low);
            println!("Button is released, led turned off <<<");
        }
    }
}

TableLamp

ButtonSwitchではスイッチを押している間にのみ電源がつく仕様でしたが、TableLampではボタンを押すごとにON/OFFを切り替えるコードとなっています。btn_pin.poll_interrupt(true, Some(Duration::from_millis(1)))?でボタンが押されたかどうかを判別します。ボタンが押された場合にLEDのピンがLOWの状態であるか確認して、電源のON/OFFを制御します

use rppal::gpio::{Gpio, Level, Trigger};
use std::error::Error;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;

const LED_PIN: u8 = 17;
const BTN_PIN: u8 = 18;

fn main() -> Result<(), Box<dyn Error>> {
    println!("Program is starting...");
    let gpio = Gpio::new()?;
    let mut led_pin = gpio.get(LED_PIN)?.into_output();
    let mut btn_pin = gpio.get(BTN_PIN)?.into_input();
    led_pin.set_low();
    // ボタンの割り込み設定
    btn_pin.set_interrupt(Trigger::FallingEdge, None);
    // Ctrl+Cが押されたら終了
    let running = Arc::new(AtomicBool::new(true));
    let r = running.clone();
    ctrlc::set_handler(move || {
        r.store(false, Ordering::SeqCst);
    })?;
    println!("Waiting for button press...");
    while running.load(Ordering::SeqCst) {
        if let Some(_) = btn_pin.poll_interrupt(true, Some(Duration::from_millis(1)))? {
            // LEDの状態をトグル
            if led_pin.is_set_low() {
                led_pin.set_high();
                println!("Led turned on >>>");
            } else {
                led_pin.set_low();
                println!("Led turned off <<<");
            }
        }
    }
    println!("Program is finished.");
    btn_pin.clear_interrupt();
    led_pin.set_low();
    Ok(())
}

動作の様子

ButtonSwitchのみですが動作の様子をX(twitter)にアップロードしております。

まとめ

Lチカの回路にボタンによる電源の制御を加えました。GPIO18とスイッチを使うことで回路の状態を変えることができ、プログラムで状態をリアルタイムに読み取れることがわかったかと思います。また、プログラムの書き方により押している間のみ動作させたり、押すごとに動作を変えたりなどもでき、作りたい機能に合わせてプログラムを修正するだけで同じ回路でも動作が変わる点が大事なポイントだと思います。同じ回路であってもプログラムで動作のさせ方を変えられる点で調整がしやすいので、簡単な回路を組みつつソフトウェアの調整をいろいろ変えると学びが深まるのではないかと考えました。次回はLEDライトバーを使ったもう少し複雑なLEDの制御を実装します。

関連記事