TAA4100A T級デジタルICアンプ

TAA4100AというT級(D級デジタルとAB級特性を兼ね合わせたものという意味らしい)ICアンプが秋月電子で売っていた

4chものBTL出力、しかも100Wもの高出力とあるが、NET情報によればかなり良い音がするらしい。
データシートを見てみると、14.4V電源で4Ωスピーカーで10W出した場合、歪率は0.01%とある。ここらへんで使うのが良いのではないかな?

さて、TA2020で作った時のように、ユニバーサル基板で作っても良いのだが、何とICのピンが32もある。これは大変だ。しかも出力端子にダイオードやコイル、コンデンサを何種も付けなければならないので、この配線も面倒になりそうです。

しばらくNET情報をしらべていたら、何と「お気楽オーディオキット資料館」の藤原さんが基板関連を頒布しているではないですか。しかも詳しい製作記製作マニュアルも完備してます。何といっても、基板の他に入手し難いインダクタ・コイルやアンプICそのものもオプションで購入できるので願ったり叶ったりです。m(_ _)m
藤原さんは一度 基板頒布を中止されておられたのですが、いつ再開されたのか? DACを中心に多彩な活動をされているページです。

参考までに、このTAA4100Aを使ったキット基板を他でも売っていますが、何と1万円やそれ以上の価格です。藤原さんの基板ならばオプションを入れても3400円程度で入手できました。

というわけで、早速基板や関連パーツを頒布頂いて作ってみました。

【前から】
PowerTAA4100A_1.jpg

4chアンプなのですがとりあえず2chしか使っていません。もったいないですね。(SP端子が1個後家さんです)

【後ろから】
PowerTAA4100A_2.jpg

【IC周囲詳細】
PowerTAA4100A_3.jpg

タカチ・YM-150ケースに収納するため、ヒートシンクはケースで代用してます。放熱用シリコンを塗ってます。
ICの放熱金属部分はGND回路に繋がっています。

6畳の部屋で8cmスピーカーを使い小音量で使う環境ならば、ほんのりと温かくなる程度です。電源は15V1.6AのACアダプターを使ってます。流れる電流は平均で0.22A程度です。藤原さんの解説記事にも詳しく載ってましたが、私も外部電源を付けて電流を測りました。

藤原さんの基板では、SLEEPとMUTE制御を行うためPICマイコンを使っています。1秒後にSLEEPをONさせ、2秒後にMUTEをONさせ、更には3秒後には外部リレー出力をONさせるといった念が行ったつくりです。このマイコンは基板に添付されていますので楽ちんです。
(SLEEPは電源OFFじのコンデンサ放電のため、ONのままに変更しているかもしれません)

さて、肝心の音はどうでしょうか?

藤原さんも書かれていますが、意外に抜けの良い音という評があります。
私がTA2020やTDA1552Q ICアンプを比べてみると、このアンプの高域に張りがあるような気がします。低音もかなり出ます。

もう一度聴き比べてみると、音のバランス的にはTDA1552Qが最も良さそうですが、高域の張った感じが好きな人はこのアンプを選ぶのかもしれませんね。エージング効果がでるのかどうかわかりませんが、しばらく使ってみることにします。


4ch回路の使い道ですが、8年前に2.1chアンプシステムを作りました。家族に低音が出過ぎて不評だったので、アンプは捨ててしまいましたが、そういえばあのスパイラル・ダクト・ウーファーはテレビの裏で死蔵されていましたね。あれをもう一度再開しても良いかもです。







TA2020 & TDA1552Qステレオ・アンプ(原点回帰)

まもなく30万ヒットを迎えようとしている我がブログであるが、更新周期が伸びていることは、正直言って「ネタ切れ」の感が強い。
昨今はHPA製作ばかりに気を取られ、自分が何でこのブログを始めたのだったかな、を反芻してみました。

そこで気付いたことは、自分の部屋でゆっくりと聴ける良い音アンプから初めていたことでした。

さらに気付くと、私の部屋には中華製アンプやら、良く判らないメーカーの既成アンプやらが蔓延ってます。

以前、素晴らしい音に感動したアンプは何だったろうか・・・     原点回帰です。

【TA2020】
現在のようにディスクリートでアンプ回路が組めるようになった以前、そもそものオーディオ作りの最初は、「カーオーディオIC」を使ってアンプを作り始めたのでした。そして初めて作ったのが、TA2020を使ったこのアンプです。

TA2020-20

TA2020 ICです。この写真はICの足が切れてます。私の失敗一号作でショートしてしまい、あの世行きでした。

TA2020AMP.jpg

この時に作ったアンプを今も大事に持ってます。TA2020-20と印字されたICもまだ1個持ってました。TRIPATHというロゴ印字が見えると思います。製作記はこちらです。

今も珠に聴いていますが、とても澄んだ音色がする秀逸なアンプです。

【TDA1552Q】
TA2020が素晴らしい音色のアンプだったのですが、実はそれを上回るアンプICが登場しました(と言うより、見つけました)
TDA1552Qの音は、何と言ってもその煌びやかな音色に他ならないでしょう。それでいながらしっかりとした音色も奏でます。

その当時は12VDCのACアダプタで聴いていたのですが、様々な評価を見ていると、15Vが秀逸な音が出るらしい。
そこで今回15VDCのACアダプタで駆動してみました。

TDA1552Q_1.jpg

以前、統合アンプに組み込んでいたTDA1552Qアンプ基板(茶色のユニバーサル基板)を持ってきて、コモンモード・トランスに組み合わせました。昨今のACアダプタのノイズ削減対策です。(リレーは使ってません。RCを組み合わせてMUTE ONしてます)

いやいや、やはり素晴らしい音色で鳴ってくれます。見直しましたね。

…気が付いていなかったのですが、2009年5月にこのアンプの完成を記したブログには、何と!31 回もの拍手を頂いておりました。

TDA1552Qは相当以前にディスコンなのですが、唯一、共立エレショップには在庫しているようです。


さて、これらの素晴らしかったアンプを踏まえ、今度は何を作ろうかな・・・ 考え中です。


 

金田式もどき(改)バランス型ヘッドホンアンプ

・・・久々の記事です。

バランス型Lineアンプに使いたいということで、ヘッドホンアンプを昨年末に作りました。

金田式のヘッドホンアンプやパワーアンプの回路構成は、「対称型」と言うらしいが、この【対称】であるかどうかという諸説が色々あって私には良く判りません。
この回路はNPN-PNP素子組み合わせではなく、NPN-NPNやPNP-PNPの同じトランジスタを組み合わせることができるので、増幅度hFEの選別合わせが容易なので愛用しています。

この金田式の2番目以降の増幅回路をパラに組み合わせて、バランス型アンプを多々作っていますが、一番の難点は私の歪率計測器ではバランス型アンプの計測ができません。よって歪率を計測するのに、オペアンプで組んだバランスtoアンバランス変換回路を使っていたのですが、計測するアンプの出力電圧が上がってくると、この回路も使えない状況です。

バランス型のアンプは私の歪率計測道具では計測ができないという結論になったので、回路シミュレーションが頼りです。

今回のヘッドホンアンプも15VDC電圧(5Vのモバイルバッテリーを3個使う)をレールスプリッタ分圧で±7.5Vで使っているが、低出力域では何とか計測できるが、パワーを上げると計測アンプの波形が変形し歪率が急増してしまいます。バランス型アンプの出力は電圧が2倍出るのでそれがネックです。

【LTSpiceでシミュレーション】
HPA_kane_DC_BAL_4_7_2.jpg

この図では小さくて識別できませんが(拡大して見てください)、電圧や電流を確認するときに使う SPICE directive が左下で、中央下が歪率とパワーを計算するものです。

この回路ではオリジナルの金田式に比較して大きく変更したところが、バランス型改造以外に2か所あります。

1.初段J-FETの差動増幅の定電流が、FET+抵抗1本から、カレントミラーと半固定抵抗になり安定した調整と温度特性になりました。
2.上図の赤楕円部分にあった負荷抵抗1.2kを外し、2段目差動増幅からドライバー段増幅への接続が、「インバーテッド・ダーリントン接続の変形」になってます。これに変更することで大幅な歪率低下と安定した動作になりました。

金田式ヘッドフォン回路では以前から歪率が安定しないケースが散発していました。こちらの記事です。
http://higa284.blog20.fc2.com/blog-entry-272.html
その歪率グラフはこちらです。
金田式オリジナルのTrである、2SC959を使った時に、途中から歪率が持ち上がる現象が出ました。
今また、金田さんのヘッドホンアンプ製作記事を見直してみると、歪率が0.3%程度もあります。この負荷抵抗が問題だったように思われます。

このことは、同じ回路構成をしているパワーアンプでも同様のようです。

【計算結果】

HPA_kane_DC_BAL_4_8.jpg

1V入力の時、2.74Vrms=208mW(日本製ヘッドフォンの代表的インピーダンス36Ωで)出力、0.0146%の歪率です。

【基板】
HPA_kane_DC_BAL_4.jpg

両側に左右2chが並んでいます。中央はオペアンプで電圧中点をしっかり合わせる機能を有するレールスプリッタ電源です。動作テストに使った負荷抵抗が向こう側に見えています。この抵抗値をわざとアンバランスにして電圧中点がずれないかをチェックします。

【アンプケースに配置】
HPA_kane_DC_BAL_4_4.jpg

今回使ったケースはタカチ・HIT23518SS、両側に放熱フィンが付いています(今回は使いません)。パワーアンプの終段トランジスタを付けるにはGoodです。
バランス入力型なので4連ボリュームです。ぺるけさんから頒布いただきました。いつもありがとうございます。
入力はXLR3P端子2個から左右別々です。出力端子はXLR5Pが2個並列についていますので、2台のヘッドフォンが付けられます。
白くやや太めの配線は、立井マイクケーブルの芯線です。オーディオ信号ケーブルとして特性が良いと言われています。


【外観】
HPA_kane_DC_BAL_4_5.jpg  

アンプ上面に文字シールを作って印刷する前のサンプル紙が載っています。本番は透明シールになります。
左に見える箱は、5Vモバイルバッテリー3個を接続し、15VDCにするためのものです。

金田式もどきDCヘッドホンアンプ・アルミケースバージョンの頒布

金田式もどきDCヘッドホンアンプ・アルミケース バージョンを頒布します。

----- 8月6日 午後追記 -----
・製作マニュアルをアップしました。
・歪率と出力グラフと周波数特性グラフを追記しました。

---- 2016/ 8/23 ----
第2次 10台追加を30日から再開します。ご要望あればコメントに記載ください。

---- 2016/ 9/ 5 ----
基板を20枚追加しました。


製作記事は、
http://higa284.blog20.fc2.com/blog-entry-311.html と、
http://higa284.blog20.fc2.com/blog-entry-298.html です。


音が好評で数十台の頒布となりました前作プラスチックバージョン(こちら)に対し、変更点は以下の通りです。

・外部からの飛翔ノイズ対策でアルミケース化しました。

・定電流(アイドル電流)調整のピーキー特性と温度による不安定を改良するため、
 定電流回路にDualトランジスタによるカレントミラー回路を追加しました。

・内部スペースが拡大したので、電源コンデンサを2個から4個に増やし、高さ15mmまでのサイズまで装着できます。

【内部及び外観】
HPA_kane_DC_LCase_9.jpg

【回路図】
HPA_kane_DC_LCase_12.jpg

【金田式「もどき」としている本器の説明・特徴】

・金田式ヘッドホンアンプの特徴は
2段目にも差動回路を有し、この各々の出力をNPN-NPN構成の終段増幅に接続する、「対称型」と言われる回路です。即ち初段差動増幅から終段増幅まで、±である音楽信号に対し対称になるような回路構成です。

・本器の特徴は
ここでは細かな説明は省きますが、オリジナル回路の2段目差動回路には負荷抵抗があり電圧ロスがありました。本アンプではこの抵抗を取り去り、インバーテッド・ダーリントン接続の変形とも言える回路構成になり、シンプルながらも高性能になってます。
この回路の説明はこちらのブログに掲載してあります。

本来、金田式という呼称を付けるためには、回路構成は元より使う素子も金田さんと同じでなければならないということらしいのですが、殆どのトランジスタ素子類はとっくの昔にディスコンで、初段差動の2SK246BLだけは私の倉庫から出して使ってます。
なので「もどき」です(もう既に「もどき」とも言えないかもしれませんね)

金田式ヘッドホンアンプの電源はネネループ電池を4個+4個使い、公称±4.8V(実質±5.6V)ですが、本アンプでは単三型リチウムイオン電池を使って、同±3.7V(±4.0V)です。よって電圧が低い分だけ、先のインバーテッド・ダーリントン変形回路によって性能が同等になっています。

リチウムイオン電池を使うことで、充電回路を内蔵しスマホ充電器を利用した自己充電ができるようになってます。

【歪率と出力】
HPA_kane_DC_LCase_20.jpg

【周波数特性】
HPA_kane_DC_LCase_21.jpg

【パーツリスト】
部品番号部品名型番、値個数費用(円)
・表面実装部品付き基板 
 専用基板 1 5,000  
・トランジスタ 
Q101,103定電流、終段増幅
NPNデュアルTr
BC846DS4基板実装
Q201,203
Q1022段目差動
PNPデュアルTr
BCM856DS2
Q202
FET101,102
FET201,202
初段差動FET2SK246BL(金田式指定品)
Idss 0.1mA差選別品
4400 
FET103,203定電流 J-FET2SK208-O2基板実装
・初段、中段チップ部品  
R108,R109
R208,R209
チップ抵抗 2012差動負荷 1.5K4基板実装
R110,R210チップ抵抗 2012300Ω2
C113,C213チップコン 20121000P2
R111,R211チップ抵抗 2012120Ω2
R106,R107
R206,R207
チップ抵抗 2012定電流 110Ω4
C109,C110
C209,C210
チップコン 2012位相補償100P4
・電源コンデンサ 
C001,C002
C003,C004
表面実装コンデンサ1000uF4 520  
C004,C005チップコン 20120.1u2基板実装
・LEDチップ抵抗    
R001チップ抵抗 201227k1基板実装
・充電用パーツ   
IC1,IC2Li-ion電池Protecter 2基板実装
IC3,IC4充電用ICXC68022
C007,C008チップコン1uF or 10uF2
R002,R004チップ抵抗 201215k2
R003,R005チップ抵抗 20122k2
LED2,LED3チップLED青、16082
・入出力、負帰還 金属皮膜抵抗  
R112,R113
R212,R213
終段負荷
金属皮膜抵抗1/4W
10Ω
利久RO抵抗は終了
4 
400 
 
R102
R202
負帰還
金属皮膜抵抗1/4W
22k(利久RO抵抗)2
R103
R203
負帰還
金属皮膜抵抗1/4W
33k(利久RO抵抗)2
・機構部品    
ST_JACK1入出力
φ3.5ステレオジャック
AJ-17802180  
ST_JACK2
SW2系統スイッチ ON-OFF-ON 動作
 フジソク、CFT2-2PC4-AW
1 350  
VOL2連ボリュームA50k(またはA20k),LINKMAN、RD925G1 300  
R102,R202定電流半固定VOL500Ω2 100  
R101,R201バランス半固定VOL100Ω2 100  
 ボリュームノブ銀φ61 380  
LED1LED青色φ31 20  
 収納ケース
(デザイン・ロゴシール付き)
タカチ,MXA2-8-9SS1 1,500  
 電池端子タカチ,IT-3SP,-3SM各2 100  
U_USBmicroUSBジャックZX62R1基板実装
・キット合計(オプション含まず)9,350  

【オプション部品 及び 作業】
内容パーツ数量費用(円)
電源コンデンサ差額導電性個体コンデンサ(OSコン)6.3V/1500uF4800  
リチウムイオン電池14500 (900mAh) 保護回路無し (保護回路は基板に実装)21,500  
ケース蓋加工アルミ蓋(表・裏)の加工1式1,000  

【完成後外観】
HPA_kane_DC_LCase_14.jpg
(初めてのアルミ加工でout端子回りに加工ミスがあります)

【頒布手順】

・とりあえず10セット限定で頒布します(第1次 10台が完了し、第2次を準備中です)


・頒布は上記の部品表に準じます。

 費用でくくっている単位で頒布いたしますが、
 この部品は手持ちがあるので不用、というご要望も可能です。

・自作が不得手だが聴いてみたいという方には完成品を頒布します。
 オプションコンデンサ付きですが、リチウムイオン電池がオプションです。
 頒布費用は、17,000円です(送料含む)。

・ご希望の方は、このブログのコメント欄に匿名で記載願います(匿名でなくともOKですが)
 メルアドの記載漏れ、ミスコピーにお気をつけください。
 当方からメールで連絡いたします。

・送付は私の都合で、ヤマト宅配便コンパクトになります。
 セットでの送料は下記URLの金額-35円(持ち込み-100円、箱+65円)になります。
 http://www.kuronekoyamato.co.jp/compact/


*ご注意:頒布部品が欠品する場合もあります。既にオーダー頂いている方はお待ちいただくことになります。オーダー前の方は頒布が中止になる場合もあります。よろしくお願いいたします。

【その他】

・製作マニュアルはこちらです。



金田式もどきDCヘッドホンアンプ・アルミケースバージョンの製作

---- 2016/ 8/ 10 初段2SK246BL の選別問題を追記 -----

この3月から準備してきた、金田式もどきDCヘッドホンアンプのアルミケースバージョンを製作しました。

【基板に表面実装部品を装着します】
HPA_kane_DC_LCase_8.jpg

これまでのプラスチックケースに代わり、アルミケースに収納するため基板サイズがかなり大きくなりました。部品配置もかなり楽々で、電源コンデンサも±に2個ずつ置きました。
リチウムイオン電池も基板上に設けた電池端子に取り付けます。

【完成状態の全容です】
HPA_kane_DC_LCase_9.jpg

HPA_kane_DC_LCase_14.jpg

ケース色はアルミ地のシルバーです。
全面と背面プレートもアルミタイプのケースを用いたので、透明のレタリング・シートで装飾できました。
(初めての加工だったのでout端子穴に加工ミスがあります)

全面の端子類配列はプラスチック・バージョンと同じで、左から3方向電源スイッチで、charge-OFF-ON になります。隣が青色LED、入力ジャック、ボリューム、出力ジャックとなります。

HPA_kane_DC_LCase_11.jpg

microUSB端子を使った充電端子は後面です。チャージの際は両側のLEDが明るく点灯します(但し、チャージが終わっても照度が落ちるだけで消灯しません。LEDの感度が上がったので充電終了時の微量な電流μAでも点灯してしまいます  -_-;)

【回路図】
HPA_kane_DC_LCase_12.jpg

前作のプラスチック・バージョンに対して大きく変わったのは初段差動増幅の定電流回路です。金田式のオリジナル回路ではFETと可変抵抗によるものでしたが、その調整のピーキーさと温度変化、特に温度上昇時に異常な発熱に至る問題がありました。
本作ではFETと調整用可変抵抗回路にDualトランジスタを使ったカレントミラー回路を組み合わせ、調整の容易化と温度安定度を考慮しました。

【基板図】
HPA_kane_DC_LCase_13.jpg

リチウムイオン電池の充電回路や保護ICは電池を置く上方にまとめました。保護ICは裏面に付けています。
電源コンデンサはSTDには表面実装の物を使いますが、通常の差し込み足タイプの物も使えます。取り付けの高さがぎりぎり15mmありますので、お好きなコンデンサの取り付けを可能にしています。

【アルミケースの加工について】

今回使ったアルミケースMXA2-8-9SSですが、タカチには前後パネルがプラスチックのMXシリーズもあるのですが、今回選定した80mmx90mmというちょうど良いサイズがMXシリーズにはありませんでした。よって加工をアルミ材に行うことになります。しかも3mmの板厚なので、手動ツールや手持ちドリルではしっかりとした加工ができない恐れがありました。

そこで新たにドリルスタンドを購入しました。

HPA_kane_DC_LCase_16.jpg

REXSON 小型ボール盤 200W の DP2250R というものです。超お買い得の12,900円です。
写真のようにバイス台までセットされており、速度調整も電気的な調整で可能なものですが、3,200rpmが最小回転なので高すぎでした。
そこで速度調整用に電圧調整ができる可変トランスを入れました。

HPA_kane_DC_LCase_18.jpg

機器の速度調整をするために昔使われていた、スライド式の電圧調整器です。今では周波数変換のインバーターに切り替わり、捨てられる直前の物をストックしていました。300VA容量なので200Wのボール盤にはちょうど良いサイズです。

バイス台回り
HPA_kane_DC_LCase_19.jpg

傷つきやすいアルミ板をバイスで固定するため、ラバーを介して挟み込み、下側に木を入れます。

寸法出し
HPA_kane_DC_LCase_17.jpg
CADを使ってアルミケース蓋の裏面側に加工位置を記した等倍図面を作ります。
このシートを透明フィルムに印刷し、中心位置をアルミケース蓋にポンチします。

でも、200Wのボール盤ではφ3.2が加工できる上限でした。それ以上はトルクが足りず止まってしまいます。
それでも、φ1で下穴を開け、φ2、φ3もしくはφ3.2 にサイズアップしていけば綺麗に加工ができます。

φ5.5、φ7 は仕方がないのでハンドリーマでこつことと広げます(笑い泣き)
out 端子穴が加工ミスしたのは、ボール盤加工をトライして失敗したものです。

ロゴ・シール
HPA_kane_DC_LCase_15.jpg

蓋の表面にはこのようなロゴシールをプロ印刷に依頼して作りました。
CADで穴加工位置やボリューム弧を描き、pdf印刷をしておきます。それをイラストレーターCS2で読み込みます。
ロゴ部分の作成や、ボリューム部分の塗りつぶしをイラストレーターで行い、全体をアウトライン化します。

約A4サイズに8シール並べられ、それを5枚作って約4,000円でした。1台当たりのコストは100円なので安いですよね。


【歪と出力、周波数特性】
・・・・歪率を計測する機器をしまい込んでしまったので、これから引っ張り出し、整備して特性計測をやってみようを思ってます。

ごそごそと引っ張り出した機材に、いつも使っているUSB DACを歪率計測に使う専用ノートPCに繋ぎ、WAVE Spectra で計測します。
その結果をExcelで作図させてます。

HPA_kane_DC_LCase_20.jpg

低歪のフラット部分が少なく、徐々に持ち上がっていく特性です。

このパターンによって、そのアンプの音色が変わっていくようなのです。
しかし、これがどのような音色であるかは波形から類推できないところにアンプ作りの面白さがあります。

HPA_kane_DC_LCase_21.jpg

周波数特性はいつもながら立派と言う他ないですね。

いつも、金田式に対して思うのですが、極低域のフラットさは秀逸と言う他ありませんね。


【出音】
・・・・電源を入れて10時間程度はやけに高音がきつい音感でしたが、やっと安定した音色の領域に入って来たようです。そろそろ金田式の妖艶な音色に近づいて来ました。

・・・・いつもの試聴ではHPAにかかる負荷は微小です。特性を計測する時には、そのアンプに最大パワーを出す入力をするので、使っている素子にとても大きいパワーがかかります。

というこで、特性計測後の音を試聴します。

再生している曲は、1978年、サーカスのミスター・サマータイムです(YouTube)。
昨日も同じ曲を聴いたが、痛い高音は消え、浮き上るような高音系のシャウト感があります。

---- 2016/ 8/ 10 初段2SK246BL の選別問題を追記 -----

2SK246BLの選別に問題があったので改良しました

2SK246BLの選別は7年前に自作した選別器で行っていたのですが、ぺるけ式の2SK170BLは問題なかったが、約0.9V以上のVgs計測ができない仕様だったので Idssで選別していました。
ところがこのIdss計測は発熱と共に変化する特性があるので計測誤差問題を抱えていたのです。
結果的にペア選別したものがバラツキがあり、調整トリマー一杯になる懸念が生じました。

そこで急きょ高い電圧のVgs計測ができるマニュアル計測型のツールを作りました。
HPA_kane_DC_LCase_22.jpg

急いで半日で作ったのでバラックです。デジタルテスターには、Vgs -2.409Vが表示されています。

これのベースはぺるけさんの改良型回路をそのまま頂きました。Vgsを計測するためのId が温度ドリフトしない仕様です。
ツェナーダイオード定数がオリジナルの5.6Vに対して5.1Vしか持っていなかったので、Id 調整抵抗を調整しました。
オリジナルはこの抵抗をロータリーSW切り替えで、Id を 0.75mA,1mA,2mAとするものですが、私は通常の2回路スイッチを使いたかったので、2mA固定とボリュームによる0.05mA~5mA可変が使えるようにしました。

非常に安定したVgs計測ができています。テスターの数値は1mV部分が若干動く程度です。

【2SK246BLのVgsペアとDC調整範囲】
この機器で計測したVgsでペアを数種類組み合わせてDC調整可能な範囲を調査しました
HPA_kane_DC_LCase_23.jpg
Vgs差が40mV以内であればDC調整ができます。
この結果はぺるけさんが頒布している2SK30A FETでの基準値と略同等かと思います。
Vgs差と無調整時のDC値がほぼ直線なのも、計測したVgsが正確である裏付けと思います。


これで安心して頒布ができます。やれやれです ^_^;





2Win 差動式 低電圧バランス型 DC HPA の電源改造

久しぶりにオーディオ記事に戻ります。

私の自作オーディオを気に入って頂けて方から、2Win 差動式 低電圧バランス型 DC HPAを、「長時間使える外部電池電源で駆動できるようにできないか」との打診がありました。

種々考えた末、市販されているUSB接続の 5V 電源を使ったらどうだろうかの結論に達しました。
・市販で簡単に入手できる
・価格が安い
・リチウムイオン電池の物も多く、充電器も添付されている、もしくは市販されているので安心して使える。

【内部】
HPA_v7_BAL_44.jpg

電池スペースに、microUSB端子から給電できる端子と、この5V電圧を±2.5Vに分圧する回路を設けました。
オペアンプで偏差電圧を補正する回路(サーボ回路)を有します。

【参照した電源回路図】
HPA_v7_BAL_46.jpg

miniAmpで使った分圧回路です。この回路では電源が15Vですが今回は5Vです。よってopAmpは5V動作するものを使う必要があります。今回は4580を使ってます。電解コンデンサは本体側に付いているので電源からは削除してます。トランジスタは消費電流が少ないので2SC1815/2SA1015で十分です。

【電源回路拡大】
HPA_v7_BAL_45.jpg

左側はHPA v6-2 までで使っていた microUSB端子を付ける基板をカットしてます。
右側にユニバーサル基板を使ったサーボ機能を有する分圧回路です。各々をエポキシ接着剤で接合してます。

------- 音の感触
電圧が±1.5Vから±2.5Vに変わったことで、かなりのパワーアップを感じます。
特に、ボリュームを上げた際に、しっかりとして追従してくれるような安心感があります。
気のせいか、高音系もしっかり感が増えたように思えます。

やはり、電圧を上げることがアンプにとっては最大の朗報なのですね。






ArduinoでCAN通信(その10:CCP通信・SD読み込み)

CCP通信を行うには対象となるECUのデータアドレス(ECUの品番毎に異なる)を都度Arduinoに与える必要があるので、これにはSDカードのテキストデータを経由することにしました。

【microSDカードを取り付け】
Arduino_CAN_ccp7.jpg

SDカードは3.3Vで動作しているため、SPIの信号もArduinoの5Vから3.3Vに落とす必要があります。
当初はmicroSDを取り付ける別基板を考えていましたが、省力のためArduinoのSPI端子に差し込めるように、ユニバーサル基板を使って変換させました。

回路的にはこちらで考えていた抵抗分圧でドロップさせます。

Arduino_CAN_28_sch.jpg

左上に見えるのが秋月のmicroSDカードをDIPに変換する基板が差し込まれるピンです。
この図では680Ωと360Ω抵抗を使う予定でしたが、手持ちの都合で1kと680Ωを使いました。
3.3Vのところが計算上は約3Vになりますが動作しました。

microSDカードのテキストデータは以下のようなものです。

//--- microSDカードのCCP_Set.txtの中身 (注:これはダミーデータです。またECU品番によって大きく異なります)
CPP_Set_Data
NE
0xFFFF9C8C
VS
0xFFFFC27C
QFIN
0xFFFFA440
PATM
0xFFFFC10C
THEX1
0xFFFFC044
THEX2
0xFFFFC06C
QP
0xFFFFA4B0
DPFMOD
0xFFFFB08C

先頭にCPP通信用データという意味の文字を書いてます(これは何でもよい)
次に計測名称とECUアドレスをセットにして2行ずつ8セット記載します。

これをArduinoのmicroSDで読み込ませるのですが、SD読み込みにはArduino標準添付のSD.hを使います。

しかし、ここでちょっと面倒なことが、なんとArduinoのSD.hには、「1行読み込み」機能がありません。
1.「1文字読み込み」機能があるので、これを使って行末の 0x0A 文字を使ってデータ区切りをします。

しかし、またここでちょっとハマりました。例の、「c言語が不得意な文字処理」です。私も不得意です。
2.・・・何だかんだと回り道(以前学んだことを忘れてる)で、strcat関数に繋がりました。

そして次にハマったことは、0xFFFF8C9C 等の文字データを、long形式の数値に変換することです。
3.当初、strtol関数がオーバーフローしていることに気が付かず、「何で皆同じ数値?」などと悩んでましたが、
  正解は、strtoul関数を使うことでした。

では、備忘録を1~3の順に記載します。

1.SDの読み込み

// ----
#include <SPI.h>        // SPIでSDカードを操作する
#include <SD.h>         // SDコントロール
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

File dataFile;      // SDカードのファイル

const int chipSelect = 10;    // SPI でSDカードをコントロールするCSピンに 10ピン を使う
char cTop[16];     // ファイルの最初行文字列用
char cName[8][16];      // 計測名称の文字列 2次元配列
char cAddress[8][16];  // アドレスの文字列(同上)
char tmp[5];      // SDカードから読み込んだ文字列バッファ
char StrBuf[32];    // シリアル出力用文字列バッファ
char *endptr;    // strtoul関数用

  // SSピン(Unoは10番、Megaは53番)は使わない場合でも出力にする必要があります。
  // そうしないと、SPIがスレーブモードに移行し、SDライブラリが動作しなくなります。
  pinMode(SS, OUTPUT);

  // SDライブラリを初期化
  if (!SD.begin(chipSelect)) {
    Serial.println(F("Card failed, or not present"));
    // 失敗、何もしない
    while(1);
  }
  Serial.println(F("ok."));

  //設定データファイルを開く
  dataFile = SD.open("CCP_Set.txt", FILE_READ);

// -----  ここまででSDカード上の、CCP_Set.txt ファイルのオープン処理ができました。

2.1文字毎、読み込んだデータを計測名称文字列、アドレス文字列に結合する

// ----- ここから
  //ファイルが開けたら設定値を読み込む
  if (dataFile) {
    // read from the file until there's nothing else in it:
    while (dataFile.available()) {    // ファイルにデータだある場合は継続する
      tmp[0] = dataFile.read();         // 1文字読み込む
      //Serial.write(tmp[0]);               // 正常に読み込んだかのデバック
      if(tmp[0] == '\n'){                // 読み込んだ文字が 0x0A だった場合
        switch(cnt){          // cnt はデータの行番号に対応します
          case 0:
            strcat(cTop,&tmp[0]);    // 結合する先の文字列 cTop に読み込んだ文字 tmp を結合する。
                    // strcat 関数の結合元 tmp は定数文字が指定なので、& を付与する。
            cnt++;       // 0x0Aだったのはファイル文字列の最終だったので、行番号 cnt を1つアップする。
            break;
          case 1:
            strcat(cName[0],&tmp[0]);
            cnt++;
            break;
          case 2:
            strcat(cAddress[0],&tmp[0]);
            cnt++;
            break;
          case 3:
            strcat(cName[1],&tmp[0]);
            cnt++;
            break;
          case 4:
            strcat(cAddress[1],&tmp[0]);
            cnt++;
            break;
          case 5:
            ・・・・・
            ・・・・・
            ・・・・・
          case 16:
            strcat(cAddress[7],&tmp[0]);
            cnt++;
            break;
        }  //switch
      }else{                // 以降は 0x0A ではない文字の処理
        switch(cnt){
          case 0:
            strcat(cTop,&tmp[0]);
            break;
          case 1:
            strcat(cName[0],&tmp[0]);
            break;
          case 2:
            strcat(cAddress[0],&tmp[0]);
            break;
          case 3:
            strcat(cName[1],&tmp[0]);
            break;
          case 4:
            strcat(cAddress[1],&tmp[0]);
            break;
          case 5:
            ・・・・・
            ・・・・・
            ・・・・・
          case 16:
            strcat(cAddress[7],&tmp[0]);
            break;
        }  //switch
      }  //if(tmp[0]
    } //while
   
    // close the file:
    dataFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening CCP_Set.txt");
  }
// ----- ここまで

3.入力し結合された文字列の表示確認と、アドレス文字をアドレス数値に変換・表示する

  //SDから読み込んだ値を表示
  //行頭文字
  sprintf(StrBuf,"cTop=%s",cTop);
  Serial.println(StrBuf);

  for(int i=0;i<=7;i++){
    //文字データを表示
    sprintf(StrBuf,"cName[%d]=%s",i,cName[i]);
    Serial.print(StrBuf);
    sprintf(StrBuf,"cAddress[%d]=%s",i,cAddress[i]);
    Serial.print(StrBuf);

    //アドレスの文字データをlong形式のlAddress[]に変換する
    lAddress[i] = strtoul(cAddress[i],&endptr,16);
    sprintf(StrBuf,"lAddress[%d]=%lu\n",i,lAddress[i]);
    Serial.println(StrBuf);
  }  //for

このソースを動作させたシリアルモニタ表示

cTop=CPP_Set_Data

cName[0]=NE
cAddress[0]=0xFFFF9C8C
lAddress[0]=4294941836

cName[1]=VS
cAddress[1]=0xFFFFC27C
lAddress[1]=4294951548

cName[2]=QFIN
cAddress[2]=0xFFFFA440
lAddress[2]=4294943808

cName[3]=PATM
cAddress[3]=0xFFFFC10C
lAddress[3]=4294951180

cName[4]=THEX1
cAddress[4]=0xFFFFC044
lAddress[4]=4294950980

cName[5]=THEX2
cAddress[5]=0xFFFFC06C
lAddress[5]=4294951020

cName[6]=QP
cAddress[6]=0xFFFFA4B0
lAddress[6]=4294943920

cName[7]=DPFMOD
cAddress[7]=0xFFFFB08C
lAddress[7]=4294946956

【備忘録のまとめ】
・ArduinoのSD.hでのテキストファイル読み込みは、1文字ずつしか読み取れない。
・これを1行ごとの文字列にするには、結合先の文字列 char[ ] に、strcat で結合する。
・数値文字列 0xFFFF9C8C 等のように 16bit 長を超えるものを数値化するには、strtol 関数ではなく、strtoul 関数を使う。

// -----  6月23日 追記
// ----- SDカードのデータを1文字ずつ読み込み、cName[ ] 、cAddress[ ] に振り分けて収納する部分のコードを少し短くしてみました。
/// -----  6月28日 修正:0xC,0xA(CR,LF)をデータに付加しないように変更

  //設定データファイルを開く
  dataFile = SD.open("CCP_Set.txt", FILE_READ);

  //ファイルが開けたら設定値を読み込む
  if (dataFile) {
    Serial.println("CCP_Set.txt open success.\n");

    // read from the file until there's nothing else in it:
    while (dataFile.available()) {

      //データを1文字読み取る
      tmp[0] = dataFile.read();

      //cntが0ならば0xAが来るまでcTopにstrcatする
      /// if((cnt == 0)&&(tmp[0] != '\n')){     /// これは止めて

      /// cntが0で、tmp[0]が0xC,0xA以外ならば cTopにstrcatする
      if((cnt == 0)&&((tmp[0] != '\n')&&(tmp[0] != '\r'))){

        strcat(cTop,&tmp[0]);
      /// cntが0で0xAが来たらstrcat後、cnt++する
      /// }else if((cnt == 0)&&(tmp[0] == '\n')){  /// ここも修正する

      /// cntが0で、tmp[0]が0xAならば cnt++する
      }else if((cnt == 0)&&(tmp[0] == '\n')){
        /// strcat(cTop,&tmp[0]);
        cnt++;
        flg = 1; //cntが初めて1になるときのフラグ
      }

      // cntが1以上ならばcName[],cAddress[]への処理をする
      // 2行前でcnt++ としているので、このままではcName処理に入ってしまう
      // よって flgがゼロになる場合だけの処理にする(最下段でゼロにしている)
      if((cnt > 0)&&(flg == 0)){
        // cName[ ] 処理と cAddres[ ] 処理を切り分ける chkを算出
        if(cnt % 2){  // cnt が奇数ならば
          chk = 0;
        }else{
          chk = 1;
        }
        // 変数 cName[ ] または cAddress[ ] の [ ] 内番号 iiを cnt と chk から算出する
        ii = (cnt / 2) - chk;   // cnt を 2で割った商から cnk を引けば ii となる
        //cName[]またはcAddress[]へstrcatする
        /// if(chk == 1){   /// ここも修正する
        if((chk == 1)&&((tmp[0] != '\r')&&(tmp[0] != '\n'))){  // CR,LF以外をstrcat する
          strcat(cAddress[ii],&tmp[0]);
        ///  }else if(chk == 0){   /// ここも修正する
        }else if((chk == 0)&&((tmp[0] != '\r')&&(tmp[0] != '\n'))){  // CR.LF以外をstrcat する
          strcat(cName[ii],&tmp[0]);
        }  //if(chk
        if(tmp[0] == '\n'){
          cnt++;  // 0xAが来れば cnt を加算する
        }
      }  //if(cnt
      flg = 0;

    } //while
    // close the file:
    dataFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening CCP_Set.txt");
  }








ArduinoでCAN通信(その9:CCP通信・再テスト)

前回までのccp通信テストでは、CANツールである07E2アドレスへのECUからの応答があったので、「テストOK」としていたのですが、返ってくるデータを実数変換してみると、変な値になっています。特にATM(大気圧)の値が99hPa程度であるはずが、変な値を示す場合があることに気が付きました。

【前出の記事での値】 (?は実数値の表示変換ミスで解決済み)
NE   :   0
VS   :?
Q    :?
ATM  :  32
THEX1:  31
THEX2:  96
QP   :?
MOD  : 90


色々と考えた末、もしかしたらECU側に問題が無いかをチェックするため、以前プロに作ってもらったツールを引っ張り出して通信テストを試みました。

【プロ仕様のCPP通信器】
Arduino_CAN_ccp6.jpg

ECUと銘打ったDsub9コネクタに電源とCAN信号が入ります。
本論とは関係ありませんが、GPSと書かれた端子が外部GPSアンテナを接続するもので、車がどこを走行したかを記録できます。

計測した結果がこれです(csvファイルの部分)

日時 時刻 NE VS PATM THAEX1 THAEX2 QFIN
2016/6/13 20:46:56 0 0 0 0 0 0
2016/6/13 20:46:56 0 0 98.47772 -20 -20 -50
2016/6/13 20:46:56 0 0 98.47772 -20 -20 -50
2016/6/13 20:46:57 0 0 98.47772 -20 -20 -50
2016/6/13 20:46:57 0 0 98.47772 -20 -20 -50
2016/6/13 20:46:58 0 0 98.5184 -20 -20 -50
2016/6/13 20:46:58 0 0 98.52095 -20 -20 -50
2016/6/13 20:46:58 0 0 98.48788 -20 -20 -50
2016/6/13 20:46:59 0 0 98.47958 -20 -20 -50
2016/6/13 20:46:59 0 0 98.47802 -20 -20 -50
2016/6/13 20:47:00 0 0 98.47774 -20 -20 -50
2016/6/13 20:47:00 0 0 98.47772 -20 -20 -50

PATMと書かれた列が大気圧で正常に受信できています。

即ち、うまくCPP通信ができていないのは、私が作ったArduino_CANに問題があります。

・・・何日もその原因を考え、
CCP通信をしているArduino_CANの通信状態を、もう一台のArduino_CANで横から覗いてみました。

すると、プログラム通りにCCP起動の送信しているはずの送信文に欠けが多々生じてます。
これは変です。Arduinoの受信処理スピードに問題は無いので、これは送信に問題がありそうです。

送信手順のプログラムを辿りました。

   CAN.sendMsgBuf(0x0000****, 0, 8, stmp);

これはstmpに格納された8Byteデータを0000****というIDで送信する部分です。
本プログラムでは次のコードの中で70回以上連続して送信しています。

    //ccp通信設定
    transmitDataFirst();
    transmitData(0x0C, cID, 0x80, 0, 0, 0, 0, 0, 0xFE, 0x39);
    transmitData(0x14, cID, 0, 0, 0, 0, 0x07, 0xE2, 7, 0);

    transmitFloat32(0, cID, lAddress[0]);
    transmitFloat32(1, cID, lAddress[1]);
    transmitFloat32(2, cID, lAddress[2]);
    transmitFloat32(3, cID, lAddress[3]);
    transmitFloat32(4, cID, lAddress[4]);
    transmitFloat32(5, cID, lAddress[5]);
    transmitFloat32(6, cID, lAddress[6]);

    transmitUbyte(6, cID, lAddress[7]);

    transmitData(0x0C, cID, 0x81, 0, 0, 0, 0, 0, 7, 0);
    transmitData(0x06, cID, 2, 0, 6, 0, 0, 1, 7, 0);
    transmitData(0x08, cID, 1, 0, 0, 0, 0, 0, 7, 0);

この処理がうまくできていないということは「送信タイムアウト」が考えられます。
mcp_can.cppを見てみると、送信バッファが空くのを50サイクルまで待ち、それでも空かなかったらタイムアウトとしています。即ち、CANコントローラMCP2515の送信処理があるサイクル内で終わらなかったらタイムアウトするようです。

//--- 抜粋
INT8U MCP_CAN::sendMsg()
{
    INT8U res, res1, txbuf_n;
    uint16_t uiTimeOut = 0;

    do {
        res = mcp2515_getNextFreeTXBuf(&txbuf_n);                       /* info = addr.                 */
        uiTimeOut++;
    } while (res == MCP_ALLTXBUSY && (uiTimeOut < TIMEOUTVALUE));

    if(uiTimeOut == TIMEOUTVALUE)
    {  
        return CAN_GETTXBFTIMEOUT;                                      /* get tx buff time out         */
    }
//--- 抜粋終わり

そこで少々手荒なのですが、送信する部分の間に delay(10) を挿入してみました。

・・・はい、やっとうまく動作しました。

NE   :    0
VS   : 0.0
Q    :3276754.3
ATM :99.0
THEX1:1310702
THEX2:1310702
QP   : 0.0
MOD: 90

ATMがECU内蔵センサで計測している気圧です。
その他はセンサ類を付けていないので正常な値ではありません。


やれやれ、やっとのことで正常動作したようです。

実はテストに使ったECUは大分古いバージョンなので、最近のECUでも通信が可能かをテストするようです。






ArduinoでCAN通信(その8:CCP通信・テスト)

諸々の準備ができたので、やっとCCP通信をトライします。

【ECUと通信準備ができたArduino】
Arduino_CAN_ccp5.jpg

24Vという大きな印字があるアルミの箱がECUです。これでエンジンや関連機器を制御してます。
今回はCCP通信テストだけなので、24V電源(赤が+B、右カプラにGNDあり)とCAN通信線(右コネクタ)だけです。

Arduinoは先のseeedのCAN-BUSソースに合わせたSPI.h仕様品です。

【ソフトウエア構成・概略内容です】
Arduino_CAN_ccp2.jpg

何から何まで最初から作るのは大変なので、昔プロに依頼して作ったVB6ソースを移植します。
流石、プロが作ったソフトは整然と作ってあります。複雑な通信手順を4種の関数にまとめ、表に見えるのは上図の14行で通信手順が完了します。整然としてます。(注意:この作りはあるECUでのケースです。CCP通信の標準手順であるかは未確認です)

この通信手順で最も特殊なのが、最初の行の、transmitDataFirst() 関数です。これはこのECU独自のスタートアップ手順のようで、これが無いとCCP通信が起動しません。(内容は割愛します)

次の2行はCCP通信の起動手順のようです。

次に続く7行が、ECUアドレスを指定して、そこのデータを送信してもらう手順です。Flort32という関数名称が示すように、IEEE形式の32Bitsバイナリでデータ転送されます。この部分はそのECU固有の値ですので省略します。番号は0から6まで7個指定できます。

続くのはByteタイプのデータ指定です。番号は7で1個指定できます(能力的にはかなり可能なはずですが)
続く3行がCCP通信手続きの終了部分です。

(関数内部の処理は秘匿性が高い部分なので割愛します)

【動作結果】
Arduino_CAN_ccp4.jpg

参考までに
CAN通信の状況を表示する赤いLEDは、上から送信、受信、受信割り込みです。
この写真では R という受信ランプが光って見えます。ECUが内部アドレスの値を返してきてます。
実は、受信割り込みの I というLEDも同様に光り、更に シリアル通信タイミング大きく光るのですが写真ではそれが映っていません。


先のccp通信起動をECUに流すと、ECUから継続的に、指定したECUアドレスデータが転送されてきます。

Arduino_CAN_ccp3.jpg

ECUから送られて来たデータをシリアル・モニタで表示したところです。

何と10mSec未満の間隔で送られてきますので、8ビットArduino で処理するのは大変そうです。
CANトランシーバは能力があるので、受信したデータをそのままArduinoに送って来たのをそのままシリアル・モニタに横流ししたのが上図です。これを少し解説すると、

・最初の数字:01から06は、関数 transmitFloat32()で指定したECUアドレスから返された値が、続く7Byteに収録されています。IEEE32バイナリフォーマットです。
・Byte指定した 7 のデータが返って無いように見えますが、06の最終 Byte 部分に格納されています。

これらのデータは転送されたまま収録バッファにしまい込んで置き、使用したい間隔(0.1秒とか0.5秒間隔)で抽出し、IEEE32バイナリを通常の float や int 形式に演算・キャストして使えば良いと思える。

忘備録的ですが、IEEE32 フォーマットデータを Float にキャストする資料を記載します。

【IEEE32 フォーマットについて】
こちらの記事がとても良く書いていると思います。英語ですが。

【私のプログラミング(やや冗長)】

void transFloat(){
  INT8U i,j,pE;
  INT32U pF;
  INT16U pS;

  for(i=0;i<6;i++){
    pE = i_dat[i][1];
    pF = (INT32U)(((i_dat[i][2] % 0x80)) * 0x10000) + (INT32U)((i_dat[i][3]) * 0x100) +
     (INT32U)((i_dat[i][4]) + 0x800000);
    if((pE / 0x80) == 0){
      pS = 1;
    }else{
      pS = -1;
    }
    pE = (pE % 0x80) * 2 + (INT8U)(i_dat[i][2] / 0x80);
    f_dat[i] = (float)(pS * (float)(pF / pow(2,(0x96-pE)))); 
  }
補足:i_dat[ i ] [ 1..4] に ECU から転送されてきた IEEE32 データが格納されています。
    演算処理後、 f_dat[ i ] にFloat が収納されます。

実はこの使用したい間隔に、以前と同じ MsTimer2 を使おうと思ったのですが、何故か seeed の CAN-BUS Sheild ソフトとぶつかるようです。よって今回は、 timer1 で発生させているカウンター値をポーリングし、そこで演算処理しました(この方法は良くないので、当初のタイマー割り込みで演算処理する方式に変える予定です)

【演算処理した結果】MS P ゴシックなので表示桁がずれてます

----- 5月28日の記事の結果

TIME :01m01.56s
00 00 00 00 00 04 46 - 01m02. 0s
01 00 00 00 00 04 46 - 01m02. 0s
02 C2 00 00 00 04 46 - 01m02. 1s
03 C2 00 36 00 04 46 - 01m02. 1s
04 C2 00 36 00 04 46 - 01m02. 2s
05 00 00 36 00 04 46 - 01m02. 3s

NE   :   0
VS   :   0
Q    :   0
ATM  :  98
THEX1:  98
THEX2:   0
QP   :   0
MOD  :  90

外部信号が全く入っていないECUなので、唯一動作している、大気圧 ATM が 98 という値を表示しています(実際は float なので分解能はもっと高いです)。これは 98 kPaという意味で、基準大気圧 101.325kPa よりも低い状態にあるということです。

THEX1 は不定状態にあるので、ATM の値を引いてしまっているのかもしれません。(Arduino 内部の問題かもしてませんが、真相は不明です)

注:上記通信データリストには、06 が抜けています。小生のコペピ作業ミスのようです。

----- 5月29日 再テスト結果を追記

00 00 00 00 00 04 46 - 12m26. 0s
01 00 00 C2 00 04 46 - 12m26. 0s
02 42 00 00 08 04 46 - 12m26. 1s
03 42 00 00 A0 04 46 - 12m26. 2s
04 42 00 C1 A0 04 46 - 12m26. 2s
05 42 C2 C1 48 04 46 - 12m26. 3s
06 00 00 C1 00 04 46 - 12m26. 4s
NE   :   0
VS   :?
Q    :?
ATM  :  32
THEX1:  31
THEX2:  96
QP   :?
MOD  : 90
TIME :12m26. 7s
00 00 00 00 00 04 46 - 12m26.50s
01 00 00 C2 00 04 46 - 12m26.50s
02 42 00 00 02 04 46 - 12m26.51s
03 42 00 00 A0 04 46 - 12m26.52s
04 42 00 C1 A0 04 46 - 12m26.53s
05 42 C2 C1 48 04 46 - 12m26.53s
06 00 00 C1 00 04 46 - 12m26.54s
NE   :   0
VS   :?
Q    :?
ATM  :  32
THEX1:  31
THEX2:  96
QP   :?
MOD  : 90
TIME :12m26.57s

気になったことが3点あったので再テストしました。

・06 と書かれた行が抜けていたこと:コピペミスではなく、私のソフトミスでした。
 0 から 6 までを、for 文でネストする際はVBでは、for i = 0 to 6 と記述します。
 これを、c言語では、for(i=0;i<=6;i++)か、for(i=0;i<7;i++)と書かねばならないのですが、for(i=0;i<6;i++)でした。
 つまり 6 が抜けてしまってました。

・例えば500mSec毎に数値化処理し、シリアル転送する処理時間はどの程度か?
 追加した結果リストはシリアル転送したものですが、*.00secか、*.05sec 毎にこの処理subを呼び出すのですが、リスト最初行の時間 12m26. 0s が示すように、シリアル送出直前にある演算処理はほとんど時間がかかっていません(10mSec以下)。しかしシリアル送出には15行で70mSec程度かかるようです。この部分は必要最小限にすべきのようです(500mSec間隔ならば全く余裕があります)

・floatデータをシリアル送出するには
 ?が付いている部分が浮動小数点数値を、sprintf の%f 指定した部分ですが、Arduino UNO 系IDE ではNGのようです。ここは数値を文字列に事前に変換するようです。

 --- 本件に関してさらに追記 ---

 Arduino UNO系 IDE では dtostrf() 関数を使用するとありました。
 dtostrf(実数, 全桁数, 少数以下桁数, 代入先文字変数)
 今回の例では、sprint 関数内に入れました。
 sprintf(StrBuf, "NE   :%s", dtostrf(f_dat[0], 5, 0, sstr));
 このように記述すると、sprintf 関数は dtostrf 関数の格納先 sstr を %s に格納してくれるようです。
 (注:c言語で格納という表現は正しくないのかもしれませんが)

----- 追記はここまで

----- 6月5日に追記します

更に何度か通信テストを続けて行く内に、ccp通信が確立されない場合が発生することがありました。

その原因は
「ECUが外部機器との通信を試みるため、拡張IDによる特定IDでの通信出力を頻繁にするため、Arduinoが起動直後だけでccp通信要求を出しているので失敗する場合がある」ということが判りました。

対応策
1)特定IDへのECUからの通信出力が10回以上連続で検出されたら、ccp通信要求を再発行する。
2)特定IDへのECUからの通信要求は続く場合もあるので、受信IDを見てデータ処理有無を分岐する。
//------ コード例
   if(id == 0x********){       //特定ID、これは都合により割愛します
      icount++;
      if(icount > 10){
         // sprintf(StrBuf, "Restart ccp");   // この2行はデバック用
         // Serial.println(StrBuf);
         transmitDataStart();   // ccp通信要求
         icount =0;
      }
         break;
      }else if(id == 0x7E2){       // 0x7E2 が通信ツールのIDです。このIDは一般に使われるIDです。
         icount = 0;
    //以下データ処理へ続く

// ------ コードここまで

// ------ 追記ここまで

以上で、Arduino が 8ビットマイコンの入門器ながらも、プロ・ユースのCPP通信にも十分使えるメドが立ちました。
今は汎用機器の組み合わせなので2階建てですが、専用基板を起こせばコンパクトで且つパワフルなCAN通信器ができる可能性があります。

用途:

・CAN通信の勉強ツール:送信や受信のArduino ソースが使用できるハード環境を提供

・CAN通信を使った実用ツール
 ・ホビーユースで車両からのCAN信号取得する→BlueToothで外部機器に伝送→用途に即したデータ処理
 ・実務ユースでCCP通信などのツール構築→BlueToothで外部機器に伝送→CANデータを様々な用途に使用

考えらえることは様々にあります。使い方はアイデア次第でしょうね。

専用基板製作のキックオフになりそうです。

【構想中のArduino 一体 CAN-BUS 基板】
Arduino_CAN_27_brd_3.jpg   






ArduinoでCAN通信(その7:CCP通信準備・続き)

いつものArduinoのサンプル・ソフト(この書籍で紹介されている)でCCP通信の準備を開始して気が付いたことがある。

Arduino_CAN_6.jpg

それはこの本に記載されてはいるが、Arduinoのサンプル・ソフトではサポートされていない、「CAN送信のエラー処理」ルーチンである。
送信エラーには2つのパターンがあるそうです・

「自分が出したメッセージが(自機?)内で喪失する場合(送信していない)」
「送信はしたが、CANバスエラーが発生した」

ECUにデータを送ってもらう要求送信時にこんなエラーが出た場合は、確実にエラー処理する必要があります。
本にはエラー処理部分の一部コードが載っているだけで、なかなか理解が進みません。

ここの記載では「Txpend0」というフラグをチェックした後、送信バッファのTxBnCTL.TXREQが1(未送信)、0(送信済み)であるかを判定するようになっていますが、Txpend0 が皆目謎です。
この本、元々はPICマイコン用に作った機器をベースに記載しているので、本家サポートを尋ねましたが長期メンテナンスで閉鎖されています。

推測するに Txpend0 はこの本独自ソフトで用意した送信終了チェック・ルーチンで、それがNGの場合にTxBnCTL.TXREQビットを調べるということのようですが、ここらへんを自分で実装すべきか悩みます。全くゼロから始めて、CAN通信の細かな手順をプログラミングするという目的ならば、自分でソフトを構築すべきなのですが、 【ArduinoでCCP通信する機器を作る】 目的には、かなり回り道になりそうです。

・・・悩んだ結果、ベースとするArduinoソースを切り替えることにしました。
これまでに何度もお世話になっている、

/CAN_BUS_Shield

です。URLは、こちらです。

以前も書きましたが、基幹となっているファイルが、*.cppという拡張子ですので、c++で記載されているようです。
私には更に敷居が高くなってくる思いがしますが、仕方ありません(笑)

【Seeed-Studio のExsample を使うための変更】
先の本ではSPIを若いデジタルピンに割り付け、自前のSPI送受信をやってましたが、SeeedではArduinoオリジナルのSPIポートを使います。SDカードSPIと重なりますが、同時に動作させる機能上の必要が無いので、CSピンで切り分けて使用できます。

Arduino_CANBUS2_2_sch.jpg  

ピンアサインを変更した回路です。MCP2515のSPIはSDカードと共有のArduino標準SPIポートに接続されてます。
デジタルピン9に CAN_CS を割り付け、デジタルピン 10 にはSD_CSを配置してます。

【テスト環境】
上図はシステム構築した後の実用回路(予定)なので、テスト環境が必要です。
とりあえずSDは無しでもCCP通信テストはできるので今使っている送信側のSPI接続を変えます。

Arduino_CAN_31.jpg

なんやらどちゃごちゃの↑部分がArduino純正SPI位置に変更した配線です。
回路図で示すとこんなです。

Arduino_CANBUS2_2_sch.jpg  

SD_***となっている端子がArduino純正SPI端子で、CANトランシーバとSDが共用します。CAN用CS端子をデジタルピン9に割り付けますが、今はまだピン10を使ってます。
また、本番品も同じですが、Seeed の CAN_BUS_Sheild と同様に、MCP2515 コントローラの受信割り込み INT ピンが Arduino のデジタルピン 2 に接続されているので、ハードウエア受信割り込みが使用できます。

seeed の CAN_BUS_Sheild の Exsample に send.ino という簡単なArduino ソースが載っています。
このフォルダ内ファイル構成を少々替え、send.ino と同じ場所に他のファイルも置きます。

Arduino_CAN_32.jpg

このようにしておけば、Arduino IDE で send.ino を開いた時に他のファイルも参照したり編集したりするのが容易になります。

Arduino_CAN_34.jpg
(seeedのExsample、send.inoをロードした画面、一部送信データ部分をマスクしてあります。ご容赦)

以下の部分が少しいじった個所です
    // send data:  id = 0x00,       standrad frame=0, data len = 8, stmp: data buf
    // send data:  id = 0x18F00400, Extend   frame=1, data len = 8, stmp: data buf
    CAN.sendMsgBuf(0x18F00400, 1, 8, stmp);

CAN.sendMsgBuf() 関数で簡単に CAN 送信ができます。スタンダードフレームか、拡張フレームかもここで指定できます。

sendMsgBuf() の実体は mcp_can.cpp に記載されています。これを辿って処理内容を見てみると、CAN送信に必要不可欠な処理がしっかりとフォローされています(例:先に苦労して作った 送信バッファ ID レジスタ処理、送信バッファコントロールレジスタ処理、3個ある送信バッファ選択処理、送信処理状態チェック 等です)

これは何としっかりとしたサンプルでしょうか。CAN_BUS_Sheild を売っていた(いる?)ので、実用ベースになるソフトを作っているのだと推測します。私には大変ありがたいことです。seeed さま、ありがとうございます。

先のテスト環境で送信させ、受信器のシリアル・モニタで得た結果です。

・・・・途中から

RPM:1999(r/min)-00m10.39s
RPM:1999(r/min)-00m10.49s
RPM:1999(r/min)-00m10.59s
RPM:1999(r/min)-00m10.69s
RPM:1999(r/min)-00m10.79s
RPM:1999(r/min)-00m10.89s
RPM:1999(r/min)-00m10.99s
RPM:1999(r/min)-00m11. 9s
RPM:1999(r/min)-00m11.19s
RPM:1999(r/min)-00m11.29s

・・・・途中まで

100mSec毎に送信した拡張IDによる送信結果が受信されています。(回転数1999というデータです)

以上でやっとCCP通信ソフトを作る準備ができました。





プロフィール

haiga

Author:haiga
私のブログへようこそ!
電気オンチが始めた自作オーディオです
2010/3/17 電子工作をプラスしました。

自作オーディオの楽しみ共有のため、私が作ったパーツ提供をしてます。質問や要望を遠慮なくコメント欄に書き込んでください。

FC2カウンター
その日1回目にアクセスいただいた方の総カウントです
最新記事
最新コメント
最新トラックバック
カテゴリ
月別アーカイブ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード