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