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

左右5列ずつで分かれているので、3行目を以下のように修正します。
3 $x = int($n / 30) * 20 + 85 + ($n >= 150)*25;

電源ラインの穴も作ります。
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 }

まあこれで十分な気もしますが、さらにいろいろ飾り付けます。
~$ 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

後は、これに部品が載せられるようにすれば良いですね。
ワイヤーを描く
スクリプトの引数で、ワイヤーの絵も描くように改造したいと思います。
座標は1始まりの数を使うことにしました。ブレッドボードに印刷されている数字が1始まりだからです。
以下のスクリプトになりました。
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 }
さっそく実行してみます。
さて、これをコマンドラインから指定して実行できるようにします。
1 put_wire(split /,/,$ARGV[0]);
~$ . bread.sh 'red,1,9,6,10'

複数指定できない回路になりませんから、複数指定できるようにしておきます。
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`

抵抗を作る
では、ブレッドボードコマンドの続きを作って行きます。
抵抗のサブルーチン名はこのようにします。
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に変換したら、ワイヤーの中間に抵抗を配置したいので、始点と終点の中間点を求めます。
中間点を求めるサブルーチンです。
sub get_center{
my($xx1,$yy1,$xx2,$yy2) = @_;
my $xxc = $xx1 + ($xx2 - $xx1)/2;
my $yyc = $yy1 + ($yy2 - $yy1)/2;
return ($xxc,$yyc);
}
角度はアークタンジェントで求めます。
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`

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

次は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

動作しそうな回路を組んでみます。
~$ . 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かは分かりませんが、いい感じになってきました。
ピンヘッダー
その他の部品として、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" />#;
}
これでブレッドボードの絵を描くコマンドが完成しました



コメント