概要
前回から引き続き、ラズパイ入門キット「SunFounder Da Vinci Kit for Raspberry Pi」に入っている機器をRaspberr Pi Pico + Zephyr OSで動かしてみた。
今回は、Segment Displayを試した。
環境
74HC595と7セグメントディスプレイを使用する。
Raspberr Pi Picoとを以下のように接続する。接続方法はSunFounderのチュートリアルを参考にした。
74HC595を使用する方法については以下のサイトを参考にした。
Arduinoからシフトレジスタ 74HC595へ SPIでデータを送る | meyon's STUDY
使用方法
前回と同様に作成したソースコードを以下に格納したので、これを使用する。
GitHub - aimdevel/my-zephyr-applications
Zephyrの開発環境構築については公式ドキュメントを参照。
Getting Started Guide — Zephyr Project Documentation
環境をセットアップ
前の記事と同様。
west init -m https://github.com/aimdevel/my-zephyr-applications.git --mr main my-workspace
cd my-workspace/
west update
この手順はこのリポジトリを利用するときに1回だけ実施すればよい。
ビルド
west build -b rpi_pico apps/apps/segment_display/
別のアプリのビルド結果が残っている場合、buildディレクトリを削除してから上記のコマンドを実行すること。
基板に焼いて動作確認
時間経過でディスプレイの表示が変化することを確認する。
作成したdevicetree
作成したdevicetreeは以下。
https://github.com/aimdevel/my-zephyr-applications/blob/main/apps/segment_display/boards/rpi_pico.overlay
全体は以下のようになっている。
&spi0 {
status="okay";
cs-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
gpio_expander_0: gpio_expander0@0 {
reg = <0>;
compatible = "ti,sn74hc595";
reset-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
ngpios = <0x8>;
spi-max-frequency = <2000000>;
#gpio-cells = <0x2>;
gpio-controller;
};
};
ドキュメントがあるのでそれに従って記述した。
ti,sn74hc595 (on spi bus) — Zephyr Project Documentation
cs-gpios
spiのチップセレクトの指定。
cs-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
ここで設定したGPIOが通信の際にACTIVE(=LOW)になる指定。
reset-gpios
リセットに使用するピンの指定。
ngpios
74HC595で制御できるGPIOの数。8で固定。
spi-max-frequency
周波数。適当な値でOKなはず。
このdevicetreeを記述していて気が付いたのだが、Zephyrではdevicetreeの定義を「dts/bindings/~~」にyamlファイルとして格納しておくと、その定義に合わない設定がされたときはコンパイルエラーになるようだ。
例えば、必須の設定がされていない場合や、statusに指定する値がokayやdisabled以外になっている場合などは、コンパイルに失敗する。
Linux のdevicetreeのコンパイル時には、最低限の文法に従っていればエラーが出ず、typoに気づきづらかった記憶があるので、これはありがたい。
devicetreeの関連個所
自分で作成したわけではないが、devicetreeで関係のある個所を説明する。
関係するのは以下のファイルの、spi0_default。
https://github.com/zephyrproject-rtos/zephyr/blob/main/boards/arm/rpi_pico/rpi_pico-pinctrl.dtsi
spi_defaultは以下のように設定されている。
spi0_default: spi0_default {
group1 {
pinmux = <SPI0_CSN_P17>, <SPI0_SCK_P18>, <SPI0_TX_P19>;
};
group2 {
pinmux = <SPI0_RX_P16>;
input-enable;
};
};
GPIOの17~19をそれぞれSPI0で使用する設定になっている。
Raspberry Pi PicoのPinoutを見ると、確かにGPIO17~19はSPI0で使用できるようになっている。
また、0~3、4~7でもSPI0を使用できそうだ。
使用したコードは以下。
https://github.com/aimdevel/my-zephyr-applications/blob/main/apps/segment_display/src/main.c
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/spi.h>
#define MAX_GPIOS 1<<7 - 1
static const struct device *const gpio_ex =
DEVICE_DT_GET(DT_NODELABEL(gpio_expander_0));
int main(void)
{
printk("start!\n");
if (!device_is_ready(gpio_ex)) {
return 0;
}
printk("device is ready!\n");
for (int i=0;i<8;i++) {
printk("gpio configure loop\n");
int ret = gpio_pin_configure(gpio_ex, i, GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW);
}
k_msleep(10000);
int gpio_n = 0;
while (1) {
printk("loop gpio_n=%d!\n",gpio_n);
gpio_port_set_masked_raw(gpio_ex, 0x7f, gpio_n);
//gpio_port_set_bits_raw(gpio_ex, gpio_n);
k_msleep(1000);
gpio_n++;
if (gpio_n > MAX_GPIOS) {
gpio_port_clear_bits_raw(gpio_ex, 0x7f);
gpio_n = 0;
}
}
return 0;
}
デバイスドライバの仕様に従ってgpio APIを使用した。
static const struct device *const gpio_ex =
DEVICE_DT_GET(DT_NODELABEL(gpio_expander_0));
- ピンの設定
ドライバの実装的にこの設定は意味がないかも。
for (int i=0;i<8;i++) {
printk("gpio configure loop\n");
int ret = gpio_pin_configure(gpio_ex, i, GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW);
}
- 出力の制御
74HC595の出力を制御する。gpio_port_set_masked_rawを使用する。
gpio_port_set_masked_raw(gpio_ex, 0x7f, gpio_n);
使用方法は、
- 第一引数に、deviceの構造体を渡す。
- 第二引数に、使用できるピンを表すmaskを渡す。
8bit分の各ビットがそれぞれのピンに対応する。今回は7セグメントディスプレイのため、
01111111
を指定している。
- 第三引数に、highにするピンの情報を渡す。
第二引数と同様に8bit分のデータを渡す。ここを変化させることでディスプレイの表示を変更できる。
device driver
使用したデバイスドライバは以下。
gpio APIを使用できるデバイスとして74HC595を制御できるようになっている。
zephyr/drivers/gpio/gpio_sn74hc595.c at main · zephyrproject-rtos/zephyr · GitHub
まとめ
Raspberry Pi Pico + Zephyr OSで、74HC595を使ってセグメントディスプレイを制御した。
74HC595にはドライバが用意されており、devicetreeを書けば簡単に使用できることが分かった。
devicetreeを触っていると、Linuxで使用しているdevicetreeとの差異が見えてきて面白い。Zephyrの方にはコンパイル時のdevicetreeチェックなどがあり、これは便利だと感じたのでLinuxの方にも実装してほしい。
記事の本題とは関係ないが、Hatena Blogの機能で、AIアシスタントが記事のタイトルを考えてくれるようになったので、使ってみた。
それっぽいタイトルをつけてくれるので、これは活用していきたい。
参考
GitHub - zephyrproject-rtos/zephyr: Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
Arduinoからシフトレジスタ 74HC595へ SPIでデータを送る | meyon's STUDY
1.1.4 7セグメントディスプレイ — SunFounder davinci-kit-for-raspberry-pi ドキュメント
Zephyr Project Documentation — Zephyr Project Documentation