MacでVSCodeのPHPバージョンが変わらない件の解決方法

Macで、PHP 8をbrewでインストールしたにもかかわらず、VSCodeからPHPを実行するとインストールしたPHP 8ではなくMac標準のPHPが使われてしまう現象に出くわした。

phpinfo()
PHP Version => 7.3.24-(to be removed in future macOS)

PHP 8へのPATHはもちろん通してある。

ググってみるとsettings.jsonphp.validate.executablePathを指定する解決方法がヒットしたのでやってみたが、反映されなかった。

解決方法

launch.jsonにruntimeExecutableの設定を追加したところ、解決した。

"runtimeExecutable": "{PHP実行ファイルのパス}"
phpinfo()
PHP Version => 8.0.10

Zohoで管理者のパスワードが必要になった場合

Google/Yahoo/FacebookのアカウントでZohoに管理者ログインしているときに、各種設定画面で管理者パスワードの入力を要求されることがある。

「管理者パスワード? そんなの設定してないぞ?」

 

解決方法:以下のURLからパスワードのリセットを行うことで管理者パスワードを作成できる。

https://accounts.zoho.com/password

 

参考:Zohoのヘルプ

www.zoho.com

 

TA2020アンプキットを改造した

実験も終わったとこで、若松通商のTA2020キットをいよいよ改造。

改造内容

参考にさせていただいた主なサイトはこちら:

出力フィルタのコンデンサを交換

使用部品:コンデンサ Panasonic ECQE2 250V 0.22μF×6

C14・C15・C16・C18・C19・C20のコンデンサ。かんすぴのスピーカーユニット「FF85WK」のインピーダンスは8Ω、ということで、TA2020のデータシートに従って、6個のコンデンサをの容量を0.47μFから0.22μFに変更。

カップリングコンデンサを交換

使用部品:コンデンサ Panasonic ECQE2 250V 2.2μF×2、Panasonic ECQE2 250V 0.1μF×2

C9・C12のコンデンサ。2.2μFと0.1μFをパラで接続すると歪みが減るという記事があったので、真似してみた。

2.2μFのフィルムコンデンサが届いたときはそのデカさにびっくり。基板にはIN1・IN2の穴も使ってやや強引に取り付けた。

電源平滑コンデンサを追加

使用部品:コンデンサ MUSE FW 16V 3300μF×3

12V電源のノイズを除去するためのコンデンサMUSE FWがよく使われているようだったので、これを採用。

3つパラで並べて合計9900μF。キットに元々付いているものも加えれば、9900+(220+0.1)×2=10340.2μF(で合ってるかな?)になる。

突入電流対策は特になし。

+5Vの別電源化

使用部品:三端子レギュレータ 5V1A NJM7805FA、Panasonic ECQE2 250V 0.1μF×2、ダイオード 1000V1A 1N4007、OS-CON 16V 100μF、放熱器、放熱シート

三端子レギュレータはセオリー通り、保護ダイオードとノイズ除去用のコンデンサと組み合わせて用いる。念のため放熱器も付けておいた。

TA2020の30ピンをニッパーでカットし、三端子レギュレータで作った+5Vを5VGENに接続。

+5V部分のコンデンサも交換した。C1・C3のコンデンサを取り外し、C1の方のみOS-CONを取り付けた(C3の方は何も付けない)。熱に弱いらしいのでヒートクリップを使って慎重に半田付けした。

DCオフセット回路の追加

使用部品:抵抗 1MΩ×2、半固定ボリューム 20kΩ×2、コンデンサ Panasonic ECQE2 250V 0.1μF×2

参考サイトの通りに、オフセット調整回路を設置。

半固定ボリュームは50kΩを買おうと思ったが、売り切れだったので20kΩにした。20kΩでも調整は問題無く行えた。

うまく調整して、オフセットを0.3mV以下にまで減らすことができた。

ポップ音の除去

使用部品:トグルスイッチ 2回路2接点

リレーで遅延回路を作る作例が多く見つかるが、電源が入っている間(少量とはいえ)リレーに常に電流が流れ続けるのはちょっと気になるし、遅延時間の計算は難しいし、部品の設置スペースもそんなに余裕があるわけじゃない。

そこで、もっと簡単な方法は無いかと考えてたどり着いたのが、「手動でスピーカー接続をON/OFFすれば良くね?」という手抜きな方法であった。

改造箇所は、OUT1の+/-の間、OUT2の+/-の間にスイッチを1個追加するだけ。

あとはアンプを使うときに、電源をONにした後、3~4秒経ってからそのスイッチをONにするようにすればOK。手順が1つ増えるけどまぁこれぐらいはね。

ヒューズを追加

使用部品:ヒューズ、ヒューズホルダ

作業は自分なりにキッチリ行っているつもりだが、なにせ素人なので、ハンダ付けの不良とかがあるかも知れないし、使っているうちに部品が外れたり変なところに接触したりして万一のことがあっては大変。というわけでヒューズを追加。

容量は試行錯誤で決めた。何種類かの容量のヒューズを買ってきて、容量の小さいものから順にセットして試したところ、500mAでは切れたが1Aでは切れなかった。従って1Aのヒューズを使用することにした。

部品の取り付けはユニバーサル基板に

電子部品は小さいユニバーサル基板に半田付けし、基板同士はケーブルを直接半田付けしてつないだ。

サイズが大きい電源平滑コンデンサは、寝かせて接着剤で固定するといった方法もあるようだが、なんとなく抵抗があったのでこれも基板にキッチリ取り付けることにした。

ケースを交換

使用部品:タカチ YM-180

キットのケースは小さくて明らかに入りきらないので、一回り大きいケースを購入。

ホームセンターでレンタルした電動ドリルで穴を開け、リーマーで穴を広げ、ヤスリできれいに削った。粉を吸い込むと体に良く無さそうなのでマスクを着用。穴開けはキットを組み立てたときもやったけど、正直これが作業の中で一番大変だった。

基板の固定は、秋月で売っていた「貼り付けボス ASR-6」を使った。基板に穴を開けてネジで止めるのが通常のやり方っぽいけど、穴を開けるのが面倒なので簡単な方法が無いかと探していたところに見つけたのがこれで、裏側がシールになっていて基板にぺたっと貼り付けられる。これならケースに穴を開けなくて済むし、貼り付ける位置も自由に決められる。まさに「こういうものが欲しかった」と思えるものだった。

しかし大きさがちょっと大きかったので、カッターで切って少し小さくして使った。

またシャーシアースは、ケースにネジを1本つけてラグ端子で固定した。

ぐちゃぐちゃなアンプ内部

完成!

幸い1発で動いた。

2時間ほど音楽を再生した時点で、すでに改造前より音質が良くなっているのが分かる。ほっと一安心。

改造前の音がこもった感じはすっかり無くなり、音が非常にクリアになった。

そして1ヶ月後

音の響きはかなり効いている。エージング中はやたら高音が強くなったりして「本当にこのままで大丈夫なのか?」と不安になったが、それもだいぶ落ち着いてきてなかなか良い感じに。でもまだちょっと高音が強いような気がするので、後日測定してみる予定。

それでも、小さなかんすぴからこれだけの音が出るんだから満足度は高い。改造は全部一気に行ったので、どれが一番効果があったのかは不明だけど。

客観的に良い音なのかどうかも正直よく分からないけど、偶然できたオリジナルのこの音を楽しむのもそれはそれで悪くない。

ポップ音は手動スイッチを使えば全く鳴らない。なお手動スイッチを使わなくても、DCオフセット調整が効いているのか、改造前よりもポップ音はだいぶ小さくなっている。改造前は「ボンッ」と鳴っていたのが、改造後は小さく「プツッ」と鳴る程度。これぐらいなら手動スイッチを使わなくても大丈夫かも知れない(せっかく付けたけど)。

後になって1つ思ったのが、フィルムコンデンサPanasonic ECQE2ばかり使ったが、他の種類も混ぜるべきだったかも知れない。同じ種類のものばかり使うとその特性が強く出すぎるとのことなので。

アンプの電源ノイズを格安オシロスコープで測定してみる

この間買った若松通商TA2020キットを改造して音質UPするべく、ネットでいろいろ調べ、必要な部品を購入。

いざ制作…の前に、まず実験を行ってみる。

音に与える影響が大きいと言われる電源のノイズ。これを、(1)電源平滑コンデンサの追加、(2)三端子レギュレータによる5V給電 の2つの対策により、どれだけ減らすことができるのかを測定した。

 

測定にはオシロスコープを使用。下記のブログで紹介されていたQuimatの格安オシロスコープを購入した。お値段なんと3,649円。プローブと合わせても5,000円ぐらい。

tanukijima.at.webry.info

ホビー用途には十分。

オシロスコープなんて大学の実験で1・2回使ったことがあるだけなので、うまく使えるかどうか不安だったが、実際には問題無く直感的に使うことができた。

ちなみにこのオシロスコープ、以前はACアダプタが付属していなかったようだけど、現在は付属するようになったとのこと。

ノイズ対策前

まずは、若松通商TA2020キットに付属のノイズフィルター付きスイッチングACアダプタにノイズがどれだけあるのかを測定してみる。

こんな感じにLEDと抵抗、スイッチ、 それに秋月で買ったブレッドボード用DCジャックDIP化キットでACアダプタをつないで見てみると…

見えた。

20μsに設定すると、周波数60kHz程度、6mV〜8mV程度のノイズを観測できた。スイッチングノイズだ。

これでも、ノイズフィルターの無いACアダプタに比べればノイズは少ない。

リップルノイズも観測できないかと思い、いろいろ設定を切り替えて見たが、なかなかうまくいかない。

10msに設定したら↑のような波形が表れたが、これは何だろう? 周波数も時間によって40Hzぐらいになったり150Hzぐらいになったりと安定しない。リップルノイズであれば多分60Hz(西日本の場合)になるはず。エイリアシングというやつだろうか? 正体がはっきりしないため、リップルノイズの観測はひとまず置いておくことにした。

電源平滑コンデンサを追加する

MUSE FW 3300μF×3を回路に追加し、測定した。

結果は…

対策前に6mV〜8mVあったスイッチングノイズは、完全に無くなってはいないものの、1mV程度になり、かなり減少したのが分かる。なかなか嬉しい。

三端子レギュレータで5Vを出力する

こんな感じに三端子レギュレータNJM7805FA、保護ダイオード、LED、抵抗を接続。発振防止用の0.1μF×2は一旦あえてつけずに、5V出力の波形を測ってみる。

予想通り、発振する様子が観測できた。振幅は20mV前後が出ている。

発振防止用の0.1μF×2を追加し、改めて計測する。

発振は綺麗さっぱり無くなった。

 

素人なりの実験ではあったが、ちゃんと期待通りの結果が得られると嬉しいものだ。

これからいよいよ制作へ。

かんすぴ購入。TA2020アンプにつないで使用中

スピーカー自作キット「かんすぴ」を購入し、組み立てた。

スピーカーボックス:P800-E

スピーカーユニット:FF85WK

音がこもり気味だった、以前の5,000円のPCスピーカーと比べれば、遥かに良い音が出ている。

この写真を撮った後、10円玉をインシュレータ代わりにしたところ、やや高音が強い感じはするが、音の広がりはかなり増した。

しかしまだ、音質改善の余地はあるように感じる。

 

アンプは2月頃に買って組み立てた、若松通商のTA2020-020キット。今のところ無改造。電源ON時に盛大にポップ音が鳴る。

ポップ音の除去は必要だし、音質改善のためにできることはまだ多くあるようなので、これから順に試すつもり。

Flexコンポーネントのページを作成

ずっと前に作った、2つのFlexコンポーネント

せっかく作ったし、いつまでもページなしというのもあれなので、いまさらですがページを作成しました。

ちなみに2つとも、最新のソースコードCodeReposにあります。


そういえば、Flex4のベータ版が出たみたいですね。あとで試してみよう。

RTMFP, Stratusを試してみた

UDPベースのP2P通信のためのプロトコルRTMFPと、それをサポートするサービス「Stratus」。
Adobe Labs - Stratus

通信部分はきれいに隠蔽されていて、ActionScriptから使いやすくなっています。
勉強がてら、文字列のメッセージを1対1で送受信する簡単なプログラムを書いてみました。

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="creationCompleteHandler(event);">
	<mx:Script>
	<![CDATA[
		import flash.events.NetStatusEvent;
		import flash.net.NetConnection;
		import flash.net.NetStream;
		
		private const URL_CONNECT:String = "[StratusのURL]";
		private const PUBLISH_NAME:String = "rtmfp_test";

		private const STATE_NOT_CONNECT:int = 0;
		private const STATE_CONNECT:int = 1;
		
		[Bindable]
		private var state:int = STATE_NOT_CONNECT;

		private var netConnection:NetConnection = null;
		private var sendStream:NetStream = null;
		private var recvStream:NetStream = null;
		
		private function creationCompleteHandler(event:Event):void {
			netConnection = new NetConnection();
			netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnectionHandler);
			netConnection.connect(URL_CONNECT);
		}
		
		private function netConnectionHandler(event:NetStatusEvent):void {
			logText.text += "NetConnection event: " + event.info.code + "\n";
			
			switch (event.info.code) {
				case "NetConnection.Connect.Success":
					logText.text += "my ID: " + netConnection.nearID + "\n";
					createSendStream(netConnection.nearID);
					break;
				case "NetConnection.Connect.Closed":
					state = STATE_NOT_CONNECT;
					break;
				case "NetConnection.Connect.Failed":
					state = STATE_NOT_CONNECT;
					break;
				case "NetStream.Connect.Success":
					state = STATE_CONNECT;
					break;
				case "NetStream.Connect.Closed":
					hangUp();
					state = STATE_NOT_CONNECT;
					break;
			}
		}
		
		private function hangUp():void {
			if (recvStream) {
				recvStream.close();
				recvStream.removeEventListener(NetStatusEvent.NET_STATUS, recvStreamHandler);
				recvStream = null;
			}
		}
		
		private function createSendStream(myID:String):void {
			sendStream = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS);
			sendStream.addEventListener(NetStatusEvent.NET_STATUS, sendStreamHandler);
			sendStream.publish(PUBLISH_NAME);
			var c:Object = new Object;
			c.onPeerConnect = function(caller:NetStream):Boolean {
				logText.text += "onPeerConnect: " + caller.farID + "\n";
				if (!recvStream) {
					createRecvStream(caller.farID);
				}
				return true;
			}
			sendStream.client = c;
		}
		
		private function createRecvStream(farID:String):void {
			recvStream = new NetStream(netConnection, farID);
			recvStream.addEventListener(NetStatusEvent.NET_STATUS, recvStreamHandler);
			recvStream.play(PUBLISH_NAME);
			var o:Object = new Object();
			o.onIm = function(msg:String):Boolean {
				logText.text += msg + "\n";
				return true; 
			}
			recvStream.client = o;		
		}

		private function sendStreamHandler(event:NetStatusEvent):void {
			logText.text += "sendStreamHandler event: " + event.info.code + "\n";
		}
		
		private function recvStreamHandler(event:NetStatusEvent):void {
			logText.text += "recvStreamHandler event: " + event.info.code + "\n";
		}

		private function callButtonClickHandler(event:Event):void {
			createRecvStream(targetUserID.text);
		}
		
		private function sendButtonClickHandler(event:Event):void {
			logText.text += msg.text + "\n";
			sendStream.send("onIm", msg.text);

			msg.text = "";
		}
		
	]]>
	</mx:Script>
	
	<mx:ViewStack selectedIndex="{state}" resizeToContent="true">
		<mx:HBox>
			<mx:Label text="Target ID:"/>
			<mx:TextInput id="targetUserID" width="400" />
			<mx:Button id="callButton" label="call" click="callButtonClickHandler(event);" />
		</mx:HBox>
		<mx:HBox>
			<mx:Label text="Message:"/>
			<mx:TextInput id="msg" width="400"/>
			<mx:Button id="sendButton" label="send" click="sendButtonClickHandler(event);" />
		</mx:HBox>
	</mx:ViewStack>

	<mx:TextInput id="logText" width="500" height="300" />
</mx:Application>

※2/16 AM1:03 切断処理を追加


以下のようにして動作を確認できます。

  1. ブラウザで2つ開く
  2. 一方の「my ID」の値を、もう一方の「Target ID」にコピペして「call」をクリック。これでP2P接続ができる
  3. 一方の「Message」に適当な文字列を入れて「send」をクリックし、文字列メッセージを送信。するともう一方で文字列メッセージを受信する。

パケットロス対策とかパケットの届く順番とかは、どうなっているんだろう。次はそのあたりを調べてみないと。