シェルスクリプトマガジン

特別企画 イノシシ撃退機を作る ソフト作成編(Vol.92記載)

著者:米田 聡

「Interface」「CQ ham radio」「トランジスタ技術」などの雑誌を出版するCQ出版社の電子部品セット「イノシシ撃退機部品セットVer.1」を組み立て、ソフトウエアに一工夫を加えてイノシシ撃退機を作ります。今回は完成したハードウエア向けにソフトウエアを作成します。

シェルスクリプトマガジン Vol.92は以下のリンク先でご購入できます。

図18 PWM機能の初期化

(略)
#define PWM_PIN 20
(略)
#define PWM_SLICE_NUM pwm_gpio_to_slice_num(PWM_PIN)
(略)
void pwm_gpio_init() {
(略)
    gpio_set_function(PWM_PIN, GPIO_FUNC_PWM);
    pwm_set_wrap(PWM_SLICE_NUM, 4095);
    pwm_set_clkdiv(PWM_SLICE_NUM, 2);
    pwm_set_irq_enabled(PWM_SLICE_NUM, true);

    irq_set_exclusive_handler(PWM_IRQ_WRAP, on_pwm_wrap);
    irq_set_enabled(PWM_IRQ_WRAP, true);
(略)
}
(略)

図20 割り込みハンドラ

void on_pwm_wrap() {
    pwm_clear_irq(PWM_SLICE_NUM);
(略)
    uint16_t duty = convert_flash_data_to_duty(spi_rx_buf[flash_data_index], spi_rx_buf[flash_data_index + 1]);
    pwm_set_chan_level(PWM_SLICE_NUM, PWM_CHAN_A, duty);
    flash_data_index += 2;
    if (flash_data_index >= 256) {
        flash_data_index = 0;
    }
(略)
}

図21 ダブルバッファを使用する修正

■34~37行目の修正コード
#ifdef FLASH_DATA_TO_DUTY
// ダブルバッファ化
uint8_t spi_rx_buf[2][256];
volatile uint32_t flash_data_index = 0;
#endif

■45~54行目の修正コード
// バッファ選択
volatile uint32_t buf_flip = 0;

void on_pwm_wrap() {
    pwm_clear_irq(PWM_SLICE_NUM);

    #ifdef FLASH_DATA_TO_DUTY
    uint16_t duty = convert_flash_data_to_duty(spi_rx_buf[buf_flip][flash_data_index], spi_rx_buf[buf_flip][flash_data_index + 1]);
    pwm_set_chan_level(PWM_SLICE_NUM, PWM_CHAN_A, duty);
    flash_data_index += 2;
    if (flash_data_index >= 256) {
        // バッファ切り替え
        buf_flip ^= 1;
        flash_data_index = 0;
    }
}

■87~105行目の修正コード
void play_sound() {
    // バッファ切り替え(ローカル)
    int flip = 0;

    flash_data_index = 0;
    buf_flip = 0;
    pwm_set_enabled(PWM_SLICE_NUM, true);	//mu0918

    for(uint32_t address = 0; address < FLASH_SIZE; address += 256) {
        gpio_put(PICO_DEFAULT_SPI_SSEL_PIN, 0);  // Set the CS pin to active LOW
        
        // Send the read command
        uint8_t spi_tx_buf[] = {0x03, (address >> 16) & 0xFF, (address >> 8) & 0xFF, address & 0xFF};
        spi_write_blocking(spi, spi_tx_buf, 4);

        // Read the data
        spi_read_blocking(spi, 0, spi_rx_buf[flip], 256);
        // バッファ切り替え
        flip ^= 1;
        
        gpio_put(PICO_DEFAULT_SPI_SSEL_PIN, 1);  // Set the CS pin to non-active HIGH
    }
    pwm_set_enabled(PWM_SLICE_NUM, false);	//mu0918
}