Bashでブレッドボードの絵を描く(SVG)

12-5.画像

bread6-001

電子工作記事でブレッドボードの絵を使うことがありますが、手描きはとても面倒です。ネットで良く見かけるブレッドボードの絵って何か特別なツール使ってるのでしょうけど、それを調べることすら面倒なので、コマンドラインでブレッドボードを作れるように、Bashプログラミングしてみます。

ブレッドボードの穴を空ける

まずは、30 x 10=300個の穴から。

~$ bread.sh
     1	a=`perl -e '
     2	foreach $n (0..299){
     3		$x = int($n / 30) * 20 + 85;
     4		$y = int($n % 30) * 20 + 25;
     5		print qq#<rect x="$x" y="$y" width="9" height="9" fill="glay"></rect>#;
     6	}
     7	'`
     8	
     9	cat <<EOL > /tmp/tmp.svg
    10	<svg width="384" height="650">
    11	<rect x="0" y="0" width="384" height="650" fill="white"></rect>
    12	$a
    13	</svg>
    14	EOL
    15	inkscape -z -e out.png /tmp/tmp.svg

bread-001
左右5列ずつで分かれているので、3行目を以下のように修正します。

     3		$x = int($n / 30) * 20 + 85 + ($n >= 150)*25;

bread-002
電源ラインの穴も作ります。

   7  foreach $n (0..99){
     8          $x = int($n / 25) * 20 + 15 + ($n >= 50)*285;
     9          $y = int($n % 25) * 20 + 30 + int(($n % 25) /5) * 20;
    10          print qq#<rect x="$x" y="$y" width="9" height="9" fill="glay"></
    11  }

bread-003
まあこれで十分な気もしますが、さらにいろいろ飾り付けます。

~$ cat -n bread.sh
     1	a=`perl -e '
     2	foreach(split / /, "0,60 62,125 197,125 324,60"){
     3		my($x,$w) = split /,/,$_;
     4		print qq#<rect x="$x" y="0" width="$w" height="650" stroke="black" fill="none"></rect>#;
     5	}
     6	foreach(split / /, "8:red 50:blue 334:red 376:blue"){
     7		my($x,$c) = split /:/,$_;
     8		print qq#<line x1="$x" y1="20" x2="$x" y2="620" stroke="$c" stroke-width="2"/>#;
     9	}
    10	foreach $n (0..99){
    11		$x = int($n / 25) * 20 + 15 + ($n >= 50)*285;
    12		$y = int($n % 25) * 20 + 30 + int(($n % 25) /5) * 20;
    13		print qq#<rect x="$x" y="$y" width="9" height="9" fill="glay"></rect>#;
    14	}
    15	foreach $n (0..59){
    16		$num=($n%30)+1;
    17		$x = int($n / 30) * 20 + 75 + ($n >= 30)*215;
    18		$y = int($n % 30) * 20 + 35;
    19		print qq#<text x="$x" y="$y" font-size="15" text-anchor="middle">$num</text>#;
    20	}
    21	$x=90;
    22	foreach $ch (split //,"abcdefghij"){
    23		print qq#<text x="$x" y="15" font-size="15" text-anchor="middle">$ch</text>#;
    24		print qq#<text x="$x" y="635" font-size="15" text-anchor="middle">$ch</text>#;
    25		$x += 20;
    26		$x += 25 if($ch eq "e");
    27	}
    28	foreach $n (0..299){
    29		$x = int($n / 30) * 20 + 85 + ($n >= 150)*25;
    30		$y = int($n % 30) * 20 + 25;
    31		print qq#<rect x="$x" y="$y" width="9" height="9" fill="glay"></rect>#;
    32	}
    33	'`
    34	
    35	cat <<EOL > /tmp/tmp.svg
    36	<svg width="384" height="650">
    37	<rect x="0" y="0" width="384" height="650" fill="white"></rect>
    38	$a
    39	</svg>
    40	EOL
    41	inkscape -z -e out.png /tmp/tmp.svg

bread-004
後は、これに部品が載せられるようにすれば良いですね。

ワイヤーを描く

スクリプトの引数で、ワイヤーの絵も描くように改造したいと思います。
座標は1始まりの数を使うことにしました。ブレッドボードに印刷されている数字が1始まりだからです。
bread2-001
以下のスクリプトになりました。
1始まりの数指定をするために、このサブルーチンの中では、-1して扱いやすくしています。
8行目で$yを0にしているのは、両端の4列分は穴が少ないので、穴数を超えた指定をされたら0に矯正するようにしています。

     1	sub get_board_xxyy{
     2	        my($x,$y) = @_;
     3	        $x-=1;
     4	        $y-=1;
     5	        if($x < 4){ 6 my $w = 20; 7 $xx = $x * $w + 15 + ($x >= 2)*285;
     8	                $y = 0 if($y >= 25);
     9	                $yy = $y * 20 + 35 + int($y /5) * 20;
    10	        }else{
    11	                my $w = 19;
    12	                $xx = $x * $w + 10 + ($x >= 9)*32;
    13	                $yy = $y * 20 + 30;
    14	        }
    15	        return ($xx,$yy);
    16	}

座標変換のサブルーチンができたので、せっかくなので、ブレッドボードの穴もこれを使って描くように書き直しました。

     1	for($x=1;$x<=14;$x++){
     2	        for($y=1;$y<=30;$y++){
     3	                my($xx,$yy) = get_board_xxyy($x,$y);
     4	                print qq#<rect x="$xx" y="$yy" width="9" height="9" fill="black"
     5	                if($x == 5 or $x == 14){
     6	                        $xx -=10 if($x == 5);
     7	                        $xx +=20 if($x == 14);;
     8	                        $yy +=10;
     9	                        print qq#<text x="$xx" y="$yy" font-size="13" text-ancho
    10	                }
    11	        }
    12	}

さて、ワイヤーを描くためのサブルーチンを作りますが、先に呼び出し方を決めておきます。

     1	put_wire("red",1,1, 5,1);

第1引数は色
第2,3は、始点x1,y1
第4,5は、終点x2,y2とします。

配線用として別途座標変換サブルーチンを別途つくりました。

     1	sub get_xxyy{
     2	        my($x,$y) = get_board_xxyy(@_);
     3	        return ($x+4,$y+4);
     4	}

ワイヤー処理です。

     1	sub put_wire{
     2	        my($color,$x1,$y1, $x2,$y2) = @_;
     3	        my($xx1,$yy1) = get_xxyy($x1,$y1);
     4	        my($xx2,$yy2) = get_xxyy($x2,$y2);
     5	        print qq#<circle cx="$xx1" cy="$yy1" r="3" fill="white" />#;
     6	        print qq#<circle cx="$xx2" cy="$yy2" r="3" fill="white" />#;
     7	        print qq#<line x1="$xx1" y1="$yy1" x2="$xx2" y2="$yy2" stroke="$color" s
     8	
     9	}

さっそく実行してみます。
bread2-002
さて、これをコマンドラインから指定して実行できるようにします。

     1	put_wire(split /,/,$ARGV[0]);
~$ . bread.sh 'red,1,9,6,10'

bread2-003
複数指定できない回路になりませんから、複数指定できるようにしておきます。

     1	
     2	
     3	a=`perl -e '
     4	foreach(split / /, "0,60 62,125 197,125 324,60"){
     5		my($x,$w) = split /,/,$_;
     6		print qq#<rect x="$x" y="0" width="$w" height="650" stroke="black" fill="none"></rect>#;
     7	}
     8	foreach(split / /, "8:red 50:blue 334:red 376:blue"){
     9		my($x,$c) = split /:/,$_;
    10		print qq#<line x1="$x" y1="25" x2="$x" y2="620" stroke="$c" stroke-width="2"/>#;
    11	}
    12	
    13	$x=90;
    14	foreach $ch (split //,"abcdefghij"){
    15		print qq#<text x="$x" y="20" font-size="15" text-anchor="middle">$ch</text>#;
    16		print qq#<text x="$x" y="638" font-size="15" text-anchor="middle">$ch</text>#;
    17		$x += 20;
    18		$x += 25 if($ch eq "e");
    19	}
    20	
    21	for($x=1;$x<=14;$x++){
    22		for($y=1;$y<=30;$y++){
    23			my($xx,$yy) = get_board_xxyy($x,$y);
    24			print qq#<rect x="$xx" y="$yy" width="9" height="9" fill="black"></rect>#;
    25			if($x == 5 or $x == 14){
    26				$xx -=10 if($x == 5);
    27				$xx +=20 if($x == 14);;
    28				$yy +=10;
    29				print qq#<text x="$xx" y="$yy" font-size="13" text-anchor="middle">$y</text>#;
    30			}
    31		}
    32	}
    33	foreach(@ARGV){
    34		put_wire(split /,/,$_);
    35	}
    36	
    37	sub put_wire{
    38		my($color,$x1,$y1, $x2,$y2) = @_;
    39		my($xx1,$yy1) = get_xxyy($x1,$y1);
    40		my($xx2,$yy2) = get_xxyy($x2,$y2);
    41		print qq#<circle cx="$xx1" cy="$yy1" r="3" fill="white" />#;
    42		print qq#<circle cx="$xx2" cy="$yy2" r="3" fill="white" />#;
    43		print qq#<line x1="$xx1" y1="$yy1" x2="$xx2" y2="$yy2" stroke="$color" stroke-width="8"/>#;
    44	
    45	}
    46	
    47	sub get_xxyy{
    48		my($x,$y) = get_board_xxyy(@_);
    49		return ($x+4,$y+4);
    50	}
    51	
    52	sub get_board_xxyy{
    53		my($x,$y) = @_;
    54		$x-=1;
    55		$y-=1;
    56		if($x < 4){ 57 my $w = 20; 58 $xx = $x * $w + 15 + ($x >= 2)*285;
    59			$y = 0 if($y >= 25);
    60			$yy = $y * 20 + 35 + int($y /5) * 20;
    61		}else{
    62			my $w = 19;
    63			$xx = $x * $w + 10 + ($x >= 9)*32;
    64			$yy = $y * 20 + 30;
    65		}
    66		return ($xx,$yy);
    67	}
    68	' $@`
    69	
    70	
    71	cat <<EOL > /tmp/tmp.svg
    72	<svg width="384" height="650">
    73	<rect x="0" y="0" width="384" height="650" fill="white"></rect>
    74	$a
    75	</svg>
    76	EOL
    77	inkscape -z -e out.png /tmp/tmp.svg

行数がもう面倒なレベルになってきましたが、使ってみましょう。

~$ r(){
> perl -e '@col=("brown","red","orange","yellow","green","blue");
> printf"%s,%d,%d,%d,%d",@col[int rand(6)],
> 1+int rand(4),
> 1+int rand(25),
> 4+int rand(10),
> 1+int rand(30);'
> }
~$
~$ . bread.sh `r` `r` `r` `r` `r` `r` `r` `r` `r`

bread2-rand

抵抗を作る

では、ブレッドボードコマンドの続きを作って行きます。
抵抗のサブルーチン名はこのようにします。

put_resistor($x1,$x1,$x2,$y2,$ohm)

$x1 抵抗のワイヤーのX座標(穴座標)始点
$y1 抵抗のワイヤーのY座標(穴座標)始点
$x2 抵抗のワイヤーのX座標(穴座標)終点
$y2 抵抗のワイヤーのY座標(穴座標)終点
$ohmは抵抗値(1000を指定したら1kΩ)

穴座標x1,y1,x2,y2を、画像座標xx1,yy1,xx2,yy2に変換したら、ワイヤーの中間に抵抗を配置したいので、始点と終点の中間点を求めます。
bread3-001
中間点を求めるサブルーチンです。

sub get_center{
        my($xx1,$yy1,$xx2,$yy2) = @_;

        my $xxc = $xx1 + ($xx2 - $xx1)/2;
        my $yyc = $yy1 + ($yy2 - $yy1)/2;
        return ($xxc,$yyc);
}

角度はアークタンジェントで求めます。
bread3-002
atan2の戻り値はラジアンなので、度に変換します。rad2degを使うためMath::Trigをuseします。

use Math::Trig;
sub get_rr{
        my($xx1,$yy1,$xx2,$yy2) = @_;
        my($ww, $hh) = ($xx2-$xx1, $yy2-$yy1);
        my $rr = rad2deg atan2($ww,$hh);

        return 90 - $rr;
}

全体はこうなりました。もう長すぎです。

~$ cat -n bread.sh
     1	a=`perl -e '
     2	use Math::Trig;
     3	@colors=("black","brown","red","orange","yellow","green","blue","purple","gray","white");
     4	foreach(split / /, "0,60 62,125 197,125 324,60"){
     5		my($x,$w) = split /,/,$_;
     6		print qq#<rect x="$x" y="0" width="$w" height="650" stroke="black" fill="none"></rect>#;
     7	}
     8	foreach(split / /, "8:red 50:blue 334:red 376:blue"){
     9		my($x,$c) = split /:/,$_;
    10		print qq#<line x1="$x" y1="25" x2="$x" y2="620" stroke="$c" stroke-width="2"/>#;
    11	}
    12	
    13	$x=90;
    14	foreach $ch (split //,"abcdefghij"){
    15		print qq#<text x="$x" y="20" font-size="15" text-anchor="middle">$ch</text>#;
    16		print qq#<text x="$x" y="638" font-size="15" text-anchor="middle">$ch</text>#;
    17		$x += 20;
    18		$x += 25 if($ch eq "e");
    19	}
    20	
    21	for($x=1;$x<=14;$x++){
    22		for($y=1;$y<=30;$y++){
    23			my($xx,$yy) = get_board_xxyy($x,$y);
    24			print qq#<rect x="$xx" y="$yy" width="9" height="9" fill="black"></rect>#;
    25			if($x == 5 or $x == 14){
    26				$xx -=10 if($x == 5);
    27				$xx +=20 if($x == 14);;
    28				$yy +=10;
    29				print qq#<text x="$xx" y="$yy" font-size="13" text-anchor="middle">$y</text>#;
    30			}
    31		}
    32	}
    33	
    34	foreach (@ARGV){
    35		put_resistor(split /,/,$_) if(/R$/);
    36		put_wire(split /,/,$_) if(/W$/);
    37	}
    38	
    39	sub put_wire{
    40		my($color,$x1,$y1, $x2,$y2) = @_;
    41		my($xx1,$yy1) = get_xxyy($x1,$y1);
    42		my($xx2,$yy2) = get_xxyy($x2,$y2);
    43		print qq#<circle cx="$xx1" cy="$yy1" r="3" fill="white" />#;
    44		print qq#<circle cx="$xx2" cy="$yy2" r="3" fill="white" />#;
    45		print qq#<line x1="$xx1" y1="$yy1" x2="$xx2" y2="$yy2" stroke="$color" stroke-width="8"/>#;
    46	
    47	}
    48	
    49	sub put_stripedwire{
    50		my($x1,$y1, $x2,$y2) = @_;
    51		my($xx1,$yy1) = get_xxyy($x1,$y1);
    52		my($xx2,$yy2) = get_xxyy($x2,$y2);
    53		my($xxc,$yyc) = get_center($xx1,$yy1,$xx2,$yy2);
    54		my($rr) = get_rr($xx1,$yy1,$xx2,$yy2);
    55		print qq#<circle cx="$xx1" cy="$yy1" r="3" fill="white" />#;
    56		print qq#<circle cx="$xx2" cy="$yy2" r="3" fill="white" />#;
    57		print qq#<line x1="$xx1" y1="$yy1" x2="$xx2" y2="$yy2" stroke="black" stroke-width="5"/>#;
    58		print qq#<line x1="$xx1" y1="$yy1" x2="$xx2" y2="$yy2" stroke="silver" stroke-width="4"/>#;
    59		return ($xxc,$yyc,$rr);
    60	}
    61	
    62	sub put_resistor{
    63		my $ohm = @_[4];
    64		my($xxc,$yyc,$rr) = put_stripedwire(@_);
    65		@resi = split //,$ohm;
    66	
    67		my ($xx1,$yy1) = ($xxc-20,$yyc-5);
    68		my ($xxb1,$yyb1,$cb1) = ($xxc-15,$yyc-5,$colors[$resi[0]]);
    69		my ($xxb2,$yyb2,$cb2) = ($xxc-7,$yyc-5,$colors[$resi[1]]);
    70		my ($xxb3,$yyb3,$cb3) = ($xxc+1,$yyc-5,$colors[$#resi]);
    71		my ($xxb4,$yyb4,$cb4) = ($xxc+11,$yyc-5,"gold");
    72	
    73		print qq#<rect x="$xx1" y="$yy1" width="40" height="10" stroke="black" fill="white" transform="rotate($rr,$xxc,$yyc)"></rect>#;
    74		print qq#<rect x="$xxb1" y="$yyb1" width="4" height="10" fill="$cb1" transform="rotate($rr,$xxc,$yyc)"></rect>#;
    75		print qq#<rect x="$xxb2" y="$yyb2" width="4" height="10" fill="$cb2" transform="rotate($rr,$xxc,$yyc)"></rect>#;
    76		print qq#<rect x="$xxb3" y="$yyb3" width="4" height="10" fill="$cb3" transform="rotate($rr,$xxc,$yyc)"></rect>#;
    77		print qq#<rect x="$xxb4" y="$yyb4" width="4" height="10" fill="$cb4" transform="rotate($rr,$xxc,$yyc)"></rect>#;
    78	}
    79	
    80	sub get_center{
    81		my($xx1,$yy1,$xx2,$yy2) = @_;
    82	
    83		my $xxc = $xx1 + ($xx2 - $xx1)/2;
    84		my $yyc = $yy1 + ($yy2 - $yy1)/2;
    85		return ($xxc,$yyc);
    86	}
    87	
    88	sub get_rr{
    89		my($xx1,$yy1,$xx2,$yy2) = @_;
    90		my($ww, $hh) = ($xx2-$xx1, $yy2-$yy1);
    91		my $rr = rad2deg atan2($ww,$hh);
    92	
    93		return 90 - $rr;
    94	}
    95	
    96	sub get_xxyy{
    97		my($xx,$yy) = get_board_xxyy(@_);
    98		return ($xx+4,$yy+4);
    99	}
   100	
   101	sub get_board_xxyy{
   102		my($x,$y) = @_;
   103		$x-=1;
   104		$y-=1;
   105		if($x < 4){ 106 my $w = 20; 107 $xx = $x * $w + 15 + ($x >= 2)*285;
   108			$y = 0 if($y >= 25);
   109			$yy = $y * 20 + 35 + int($y /5) * 20;
   110		}else{
   111			my $w = 19;
   112			$xx = $x * $w + 10 + ($x >= 9)*32;
   113			$yy = $y * 20 + 30;
   114		}
   115		return ($xx,$yy);
   116	}
   117	' $@`
   118	
   119	cat <<EOL > /tmp/tmp.svg
   120	<svg width="384" height="650">
   121	<rect x="0" y="0" width="384" height="650" fill="white"></rect>
   122	$a
   123	</svg>
   124	EOL
   125	inkscape -z -e out.png /tmp/tmp.svg -w 384 -h 600

使ってみます。例によってランダム実行。

~$ r(){
perl -e '
printf"%d,%d,%d,%d,%d,R",
1+int rand(4),
1+int rand(25),
4+int rand(10),
1+int rand(30),
1+int rand(100000);
'
}
~$ . bread.sh `r` `r` `r` `r` `r` `r` `r` `r` `r` `r` `r` `r` `r` 

bread3-003

LEDとICを配置する

ブレッドボード画像生成コマンドに、LEDとICを追加します。

まずはLED。
抵抗を作るときに作ったput_stripedwireを使います。ワイヤーの中間点が得られるので、そこに円を描くだけです。

sub put_led{
        my $color = shift;
        my($xxc,$yyc) = put_stripedwire(@_);
        print qq#<circle cx="$xxc" cy="$yyc" r="9" fill="$color" />#;
}

色を指定できるようにしました。

ついでに、座標の指定が難しいのでブレッドボードに記載してあるa〜iの文字でも座標指定できるようにしておきます。

foreach (@ARGV){
        s/a(\d+)/5,$1/g;
        s/b(\d+)/6,$1/g;
        s/c(\d+)/7,$1/g;
        s/d(\d+)/8,$1/g;
        s/e(\d+)/9,$1/g;
        s/f(\d+)/10,$1/g;
        s/g(\d+)/11,$1/g;
        s/h(\d+)/12,$1/g;
        s/i(\d+)/13,$1/g;
        s/j(\d+)/14,$1/g;
        put_resistor(split /,/,$_) if(/R$/);
        put_wire(split /,/,$_) if(/W$/);
        put_led(split /,/,$_) if(/L$/);
}

使ってみます。

~$ . bread.sh red,d10,g10,L blue,d12,g12,L yellow,d14,g14,L green,d16,g16,L orange,d18,g18,L

bread4-001

次はICです。
四角を描くのは手間がかかるだけで、特に難しくありません。

sub put_ic{
        my($x1,$y1, $x2,$y2) = @_;
        my($xx1,$yy1) = get_xxyy($x1,$y1);
        my($xx2,$yy2) = get_xxyy($x2,$y2);
        $xx1 +=6;
        $xx2 -=5;
        $yy1 -=5;
        $yy2 +=5;
        $w = $xx2 - $xx1;
        $h = $yy2 - $yy1;
        print qq#<rect x="$xx1" y="$yy1" width="$w" height="$h" fill="black"></r

        for($i=$y1; $i<=$y2; $i++){
                my($ix,$iy) = get_xxyy($x1,$i);
                $iy-=4;
                print qq#<rect x="$ix" y="$iy" width="7" height="10" fill="silve
                my($ix,$tmp) = get_xxyy($x2,$i);
                $ix-=6;
                print qq#<rect x="$ix" y="$iy" width="7" height="10" fill="silve
        }

        $arc_xx2 = $xx1+$w/2;
        $arc_yy2 = $yy1+10;
        $arc_xx1 = $arc_xx2-10;
        $arc_yy1 = $yy1;
        $arc_xx3 = $arc_xx2+10;
        $arc_yy3 = $yy1;
        print qq#<path d="M $arc_xx1 $arc_yy1 Q $arc_xx1 $arc_yy2 $arc_xx2 $arc_
}

使ってみます。

~$ . bread.sh e1,f4,I e6,f12,I d14,h27,I

bread4-002

動作しそうな回路を組んでみます。

~$ . bread.sh e14,f17,I red,j14,3,12,W black,2,15,a17,W d15,d9,300,R red,c9,2,8,L 

何のICかは分かりませんが、いい感じになってきました。
bread4-003

ピンヘッダー

その他の部品として、Raspberry PI2のピンヘッダーを描いていきます。

ピンヘッダーは左側に配置しますが、座標ルールを合わせるため、get_board_xxyyを改造しました。
14行目〜が、ピンヘッダー用の座標決めのソースです。
7行目〜13行目までに$〜offsetとあるのは、ブレッドボードを横にずらすために入れています。

     1	sub get_board_xxyy{
     2	        my($x,$y) = @_;
     3	        $x-=1;
     4	        $y-=1;
     5	        if($x < 4){ 6 my $w = 20; 7 $xx = $x * $w + 15 + ($x >= 2)*285 + $xx_offset;
     8	                $y = 0 if($y >= 25);
     9	                $yy = $y * 20 + 35 + int($y /5) * 20 + $yy_offset;
    10	        }elsif($x < 20){ 11 my $w = 19; 12 $xx = $x * $w + 10 + ($x >= 9)*32 + $xx_offset;
    13	                $yy = $y * 20 + 30 + $yy_offset;
    14	        }else{
    15	                my $w = 20;
    16	                $xx = ($x-20) * $w + 60;
    17	                $yy = $y   * 20 + 60;
    18	        }
    19	        return ($xx,$yy);
    20	}

ピンヘッダの描画は、put_pinheaderです。
考えるのが面倒になると、どんどんソースが荒れてきますね。廃墟のようなソースになると、リファクタリングするのが楽しくなります。

     1	sub put_pinheader{
     2	        my($x1,$y1,$x2,$y2) = @_;
     3	        my($xx1,$yy1,$xx2,$yy2) = get_board_xxyy(@_);
     4	
     5	        my($p_xx1,$p_yy1) = ($xx1 - 7, $yy - 7);
     6	        print qq#<rect x="$p_xx1" y="$p_yy1" width="40" height="400" stroke="bla
     7	
     8	        for($i=$x1;$i<=$x2;$i++){
     9	                for($j=$y1;$j<=$y2;$j++){
    10	                        $p_xx = $p_xx1 + ($i-21)*20+1;
    11	                        $p_yy = $p_yy1 + ($j-1)*20+1;
    12	                        $c_xx = $p_xx + 9;
    13	                        $c_yy = $p_yy + 9;
    14	        print qq#<rect x="$p_xx" y="$p_yy" width="18" height="18" stroke="white"
    15	        print qq#<circle cx="$c_xx" cy="$c_yy" r="3" fill="gold" />#;
    16	                }
    17	        }
    18	}

ピン配ラベルをつけて完成

ブレッドボードの絵の作成、今回で最終回です。
最後はピン配のラベルをつけていきます。あと、コマンドの指定方法が空白区切りは使い勝手が悪いので、改行区切りも対応します。

このような指定方法を、

takk@takk:~/bread$ cat sample.sh
. bread.sh 21,1,22,20,P e14,f17,I red,j14,3,12,W black,2,15,a17,W d15,d9,300,R red,c9,2,8,L red,21,1,3,3,W black,21,20,2,18,W

このように変えます。やはり改行した方が見やすいです。

takk@takk:~/bread$ cat sample.sh
.  bread.sh '
21,1,22,20,P
e14,f17,I
red,j14,3,12,W
black,2,15,a17,W
d15,d9,300,R
red,c9,2,8,L
red,21,1,3,3,W
black,21,20,2,18,W
'
takk@takk:~/bread$ 

引数の処理も、改行も許容するように改造します。

takk@takk:~/bread$ grep -A16 ARGV bread.sh
foreach (@ARGV){
	s/a(\d+)/5,$1/g;
	s/b(\d+)/6,$1/g;
	s/c(\d+)/7,$1/g;
	s/d(\d+)/8,$1/g;
	s/e(\d+)/9,$1/g;
	s/f(\d+)/10,$1/g;
	s/g(\d+)/11,$1/g;
	s/h(\d+)/12,$1/g;
	s/i(\d+)/13,$1/g;
	s/j(\d+)/14,$1/g;
	put_resistor(split /,/,$_) if(/R$/);
	put_wire(split /,/,$_) if(/W$/);
	put_led(split /,/,$_) if(/L$/);
	put_ic(split /,/,$_) if(/I$/);
	put_pinheader(split /,/,$_) if(/P$/);
}
takk@takk:~/bread$ 

各引数中の改行を処理することにより、改行で読み取れるように修正しました。

foreach $arg (@ARGV){
foreach (split /\n/,$arg){
        s/a(\d+)/5,$1/g;
        s/b(\d+)/6,$1/g;
        s/c(\d+)/7,$1/g;
        s/d(\d+)/8,$1/g;
        s/e(\d+)/9,$1/g;
        s/f(\d+)/10,$1/g;
        s/g(\d+)/11,$1/g;
        s/h(\d+)/12,$1/g;
        s/i(\d+)/13,$1/g;
        s/j(\d+)/14,$1/g;
        put_resistor(split /,/,$_) if(/R$/);
        put_wire(split /,/,$_) if(/W$/);
        put_led(split /,/,$_) if(/L$/);
        put_ic(split /,/,$_) if(/I$/);
        put_pinheader(split /,/,$_) if(/P$/);
}
}

コマンドが改行された引数を受け付けるようになったので、もう少し見やすくしたいと思います。末尾にあったLやR等の部品の種別を先頭に持ってきて、かつ意味がわかる英単語に修正します。

takk@takk:~/bread$ cat sample.sh
.  bread.sh '
PIN,21,1,22,20
IC,e14,f17
WIRE,red,j14,3,12
WIRE,black,2,15,a17
RESISTOR,d15,d9,300
LED,red,c9,2,8
WIRE,red,21,1,3,3
WIRE,black,21,20,2,18
'

行末チェックから、

        put_resistor(split /,/,$_) if(/R$/);

このように行頭チェックに変更して、単語でチェックするようにします。

	put_resistor(split /,/,$_) if(/^RESISTOR\b/);

これに付随して、各サブルーチンの先頭で、第一引数を捨てる処理(shift)を入れました。

sub put_resistor{
        shift;
        my $ohm = @_[4];

今回のメインであるラベル処理を追加します。
ピンヘッダーの左側は、右寄せテキストにしたいので、text-anchorにend指定します。右側は、左寄せにしたいので、start指定です。

sub put_pinlabel{
        shift;
        my($color,$x,$y,$text) = @_;
        my($xx,$yy) = get_xxyy($x,$y);
        my $l_xx;
        my $l_yy = $yy + 5;
        if($x == 21){
                $l_xx = $xx - 20;
                print qq#<text x="$l_xx" y="$l_yy" font-size="15" text-anchor="end" stroke="$color" fill="none" >$text</text>#;
        }else{
                $l_xx = $xx + 20;
                print qq#<text x="$l_xx" y="$l_yy" font-size="15" text-anchor="start" stroke="$color" fill="none" >$text</text>#;
        }
}

追加するラベルは、コマンドで指定できるようにsample.shに追加しました。

takk@takk:~/bread$ cat sample.sh
(省略)
LABEL,orange,21,1,3.3V
LABEL,blue,21,2,GPIO2/SDA1
LABEL,blue,21,3,GPIO3/SCL1
LABEL,green,21,4,GPIO4/CLK0
LABEL,black,21,5,0V
LABEL,green,21,6,GPI17
LABEL,green,21,7,GPI27
LABEL,green,21,8,GPI22
LABEL,orange,21,9,3.3V
LABEL,purple,21,10,GPI10/MOSI
LABEL,purple,21,11,GPI9/MISO
(省略)

ワイヤーでラベルのテキストが見えなくなってしまうので、ラズパイからブレッドボードへ飛ばすワイヤーは、透かせます。stroke-opacityで0〜1の間で透明度を指定します。

sub put_pinwire{
        shift;
        my($color,$x1,$y1, $x2,$y2) = @_;
        my($xx1,$yy1) = get_xxyy($x1,$y1);
        my($xx2,$yy2) = get_xxyy($x2,$y2);
        print qq#<circle cx="$xx1" cy="$yy1" r="4" fill="white" />#;
        print qq#<circle cx="$xx2" cy="$yy2" r="4" fill="white" />#;
        print qq#<line x1="$xx1" y1="$yy1" x2="$xx2" y2="$yy2" stroke="$color" stroke-width="12" stroke-opacity="0.5" />#;
}

これでブレッドボードの絵を描くコマンドが完成しました

bread6-001

コメント

タイトルとURLをコピーしました