raspberry PiとPerlで7セグメントLEDを光らせる。

ダイナミック点灯しようとすると上手くいかなかった。
ダイナミック点灯しようとすると上手くいかなかった。

ずっとやってみたかったRaspberry Piでの電子工作に挑戦してみました。ちなみに(環境上はんだごては部屋で使えない+不器用+それ以前に道具がないので)ハンダ付けはできないし電子部品とかもマジで何買っていいのかわかんないしそもそも電子回路もよくわかんない状態でのスタートだったので、「Raspberry Piをはじめよう」を読みながらぐーぐる先生で検索して何とかしました。
あと、物を全部揃えたつもりだったのに「えっこれもいるの?」「あれもない!」状態で秋月電子さんには実店舗に3回位行きました。事前にちゃんと買うもの確認しとけばよかったです。あまりによくわかってなくてかなり不安でしたが、なんとか光りました。ちなみにブザーもつけたりLEDも光らせたりしてるのですが、何に使うかは決めてません。

回路は下記の記事のものを、そっくりそのまま同じようにつなぎました。
Raspberry Life | Dynamic LED
たまたま秋月電子で同じLEDを買っていたので大変参考になりました。ありがとうございます。LEDのセグメントを制御&どのLEDを光らせるかを選択して光らせるんですね。
プログラムもRaspberry Lifeさんに掲載されているPythonのものをそのまま使えば問題なく光るのですが、Pythonは一行も書けないし、Perlと組み合わせできたほうが嬉しいのでPerlで書くことにしました。

Perlで書くのは下記の記事を参考にしました。(ちなみに使用しているOSはraspbianで、ドライバのインストール等は特に問題なく実行できたのでインストール方法については言及しません。)
彩実験室 – Raspberry PI と GPIOで7セグ

PythonのRPi.GPIOはPin NameでPinを指定するようなのですが、Device::BCM2835はPin Numberで指定するようなので、下記を参照しながら書き換えました。
RPi Low-level peripherals – eLinux.org

スクリプトが思った以上に長くなったので、続きに載せておきます。
(コード自体は彩実験室さんとRaspberry Lifeさんのものをだいぶ参考にしています。)

13のピン(GPIO27)はRev.1とRev.2で指定の方法が違うので、ここだけ光らなくて焦りました。「Raspberry Piをはじめよう」には「電子工作する前にRev.1かRev.2かどっちか確認しとけ」ってあったので確認はしてたのですが、指定の方法自体はDevice::BCM2835のdescriptionに書いてなかった気がします。どういうことなの…。ちなみに指定方法は以下のフォーラムに書いてありました。
Raspberry Pi • View topic – Perl Device::BCM2835 Pins fail: 3, 5, 13

use strict;
use warnings;
use utf8;

use Device::BCM2835;

Device::BCM2835::init()
|| die "Could not init library";

my $ledport = [8, 10, 12, 16];
my $segport = [7, 11, 13, 15, 19, 21, 23]; #dot = 26

my $digit = [
	[1, 1, 1, 1, 1, 1, 0],     # 0
	[0, 1, 1, 0, 0, 0, 0],     # 1
	[1, 1, 0, 1, 1, 0, 1],     # 2
	[1, 1, 1, 1, 0, 0, 1],     # 3
	[0, 1, 1, 0, 0, 1, 1],     # 4
	[1, 0, 1, 1, 0, 1, 1],     # 5
	[1, 0, 1, 1, 1, 1, 1],     # 6
	[1, 1, 1, 0, 0, 0, 0],     # 7
	[1, 1, 1, 1, 1, 1, 1],     # 8
	[1, 1, 1, 1, 0, 1, 1],     # 9
	[0, 0, 0, 0, 0, 0, 0],     # Blank
	[0, 0, 0, 0, 0, 0, 1]];    # Minus

sub set_output {
	my $pin = shift;

	my $device_name = sprintf("RPI_GPIO_P1_%02d", $pin);
	if($pin == 13) {
		$device_name = "RPI_V2_GPIO_P1_13";
	}
	Device::BCM2835::gpio_fsel(eval("&Device::BCM2835::$device_name"),
		&Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
}

sub gpio_write {
	my $pin = shift;
	my $onoff = shift;

	my $device_name = sprintf("RPI_GPIO_P1_%02d", $pin);
	if($pin == 13) {
		$device_name = "RPI_V2_GPIO_P1_13";
	}

	Device::BCM2835::gpio_write(eval("&Device::BCM2835::$device_name"), $onoff);
}

sub dynamic_led {
	my $num = shift;
	&gpio_write(26,0); #dot_off
	my $number = $digit->[$num];
	my $counter = 0;
	for my $i (@$number){
		&gpio_write($segport->[$counter], $i);
		$counter++;
	}
}

sub dot_on {
	&gpio_write(26,1); #dot
}

sub clear{
	for my $seg (@$segport){
		&gpio_write($seg,0);
	}
	for my $led (@$ledport){
		&gpio_write($led,1);
	}
	&gpio_write(26,0); #dot
}

sub select_port {
	my $port = shift;
	my $num = shift;
	&gpio_write($ledport->[$port], $num);
}

sub init {
	for my $seg (@$segport){
		&set_output($seg);
	}
	for my $led (@$ledport){
		&set_output($led);
	}
	&clear();
}

sub on_light {
	my $port = shift;
	my $num = shift;
	&gpio_write($ledport->[$port], 0);
	&dynamic_led($num);
}

sub on_delay {
	my $port = shift;
	Device::BCM2835::delay(200);
	&gpio_write($ledport->[$port], 1);
	Device::BCM2835::delay(5);
}

sub cancel {
	&clear();
	exit;
}

&init();

$SIG{'INT'} = 'cancel';

while(1){
	&on_light(0,1);
	&dot_on();
	&on_delay(0);

	&on_light(1,2);
	&on_delay(1);

	&on_light(2,3);
	&on_delay(2);

	&on_light(3,4);
	&dot_on();
	&on_delay(3);
}

「1. 2 3 4.」が順番に光るようになっています。
ダイナミック点灯させたかったのですが、ちらついたり上手く表示できなかったりで諦めました。多分工夫したらなんとかなると思うのでうまくいくまで頑張ってみようと思います。
それ以前にスクリプトがこれで正しいのかが不安なのですが。

5/25追記

スレッド立てて処理したりしてるんですがさっぱりうまくダイナミック点灯できる気配がないです…どうしたもんか…。