CPU

AD変換の精度をよくする方法

ルネサスのWEBセミナーでAD変換の精度を良くする方法のセミナーがあったので、内容をちょっとご紹介。

といっても、さほどトリッキーな話はでてこないので、普段から設計している人なら「なーんだそんなこと」かもしれません。

それでも一応紹介します。

 

1,サンプル時間を長くする

2,外付け抵抗を小さくする

 

adc01

 

マイコンのAD変換回路の前段にサンプルホールド回路という物が内蔵されています。

中身は単純で、スイッチとコンデンサがセットになった物。

外部の電圧をいったんコンデンサにチャージしてからAD変換にかけます。

つまり、外部の電圧とこのコンデンサの電圧をきっちりあわせないと正確なAD変換になりません。

 

この電圧をきっちりあわせる一つ目の方法はサンプル時間を長くすること。

サンプル時間を長くすると言うのは、スイッチを入れておく時間を長くして時間をかけてチャージをかけると言うこと。

マイコンによって調整できたりできなかったりします。

チャージする時間が短すぎると内部コンデンサの電圧が上がりきるor下がりきる前にスイッチが切れてしまうので、変な値になってしまいます。

 

次に外付け抵抗R1を小さくすること。
ここで「外付け抵抗」と言っていますが、実際にはマイコンのADポートから見たものなので、目に見える抵抗がなくてもセンサーの内部抵抗も外付け抵抗と同じになります。
アナログセンサーだと内部抵抗が大きい部品も結構ありますからね。

ルネサスでは以下の式を満たす定数にしろとのことでした。

サンプル時間>定数×Cs(Rs+R1)

 

分解能 定数
8bit 6
10bit 8
12bit 9

 

この定数はルネサスの特定のCPUの場合なので、別のCPUでは変わると思います。
しかし、考え方は共通です。

 

ただ……世の中の普通のマイコン(TIとかSTMicroとかもろもろ)は、AD変換部のサンプリングホールド用のコンデンサの容量・抵抗の値なんてデータシートに書いてありません。
分解能と精度と入力電圧範囲外の仕様が全く公開されていないという酷いCPUだってあります。(しかもAD変換部の詳細仕様を問い合わせても「ない」で終わったりする)
問い合わせて分かるようであれば上記の式で目安が出せますが、出ないばあいはできる限り外付け抵抗を小さくしてサンプリング時間をとるしかありません。
最後はデバッグでサンプリング時間をいじって様子を見るしかないかもしれません。

 

 

3,コンデンサをつける

 

外付け抵抗が大きくて内部コンデンサになかなか充電されない場合は、ADC入力端子に外付けコンデンサをつけます。
これにより外部コンデンサ→内部コンデンサに電流が流れるので、高速で内部コンデンサに充電されるようになります。
遅い信号に限りますが、ADC入力端子にコンデンサをつける手は実際に結構使われます。
ただ、外付けコンデンサが小さいと内部コンデンサに電荷が移動した際に電圧が下がってしまうので、外付けコンデンサは内部コンデンサよりも大分大きい必要があります。

 

具体的には、

 

C1 > 2^n × Cs

 

を満たす必要があります。

つまり、10bitなら内部コンデンサの1024倍、16bitなら内部コンデンサの65536倍の容量のコンデンサをつける必要があります。
でないと精度がおちます。

 

4,AD変換時にマイコンに大電流を流さない

マイコン自体に大きな電流が流れていると、VCCやGNDの微少な抵抗成分によって、VCCとGNDの電圧がずれてしまいます。
それが原因となって精度が悪化します。
ということで可能な限りマイコンの消費電流を抑えた方が精度がよくなります。
クロックを落とすとか、LEDを直接駆動しないとか。

 

5,AD変換する信号の近くに高速信号を通さない

これは当たり前ですね。
隣の端子や併走する配線に高周波が乗っていればクロストークで乗ってきてしまうのでSN比が悪化します。

 

6,VREF-GND間にコンデンサをつける

これもわりと当たり前ですが、ちゃんとつけましょうって話です。
VREFがずれるとAD変換の結果もずれてしまうので。

 

というところでした。

CPUの下にはGNDを!

アートワークで配線をすると、ついついCPUの下に配線を走らせてしまいますが、それはよくありません。

なぜでしょうか。

 

CPUの中は高速の信号が飛び交っており、CPU自体がノイズをばらまく原因です。

ノイズを吸収するのはGNDベタですので、CPUの直下に置くことでノイズを吸収させるのです。

つまり、ノイズを出来るだけばらまかないために直下にGNDベタが必要なのです。

これが一点。

 

さらに、ノイズに一番近いCPU直下に配線を置くとその配線にノイズが乗りやすいのです。

つまり、CPU直下の配線の信号品質に問題が出やすいから。

これが二点。

 

さらに、CPUの周囲にはパスコンがあったりプルダウン抵抗があったりして、周辺の配線には安定したGNDが必要です。

なので、CPUの下でぶった切れているようなGNDベタはよろしくありません。

これがで3点。

 

このように、複数の理由がありますので、よーく気をつけましょう。

 

以上、小田切でした。

CPUのクロックにはどれだけの精度が必要なのか

CPUのクロックについて考えていると、

 

「CPUには内蔵発振器が入っていて精度が1-3%、水晶振動子を外につければ20ppm(0.002%)。もちろん、水晶振動子を使うほうが良いのは分かる。じゃあ、内蔵発振器でもいいのはどういうとき?」

 

という疑問にぶち当たります。

水晶振動子を使うのならまず問題ありませんが、内蔵発振器が入っているので可能ならそちらで済ませたいものです。

「誤差が大きくてダメだ!」

ということは簡単ですが、どの程度までの誤差が許されるのかきちんと認識していることは少ないのではないでしょうか。

 

◯精度を全く気にしなくていい場合

もし、その製品がスイッチを監視していて、スイッチが押されたらモータを回すだけというような……要は簡単な電子工作みたいなものだったら精度はまったく不要です。

なぜならここに時間的要素が一切ないからです。

(もし、モータを回す時間に1%のずれも許されないようであれば、駄目ですが)

 

基本的に、「何かを時間的にきっちり正確に動かす必要がなく、他のデバイスと非同期通信をしない」というのであればクロックの精度は不要になります。

 

 

◯精度は必要だが内蔵発振器でもいける可能性がある時

スイッチが押されたらモータを回す、という程度の機能であっても、他のデバイスと通信するとなるととたんに時間が大事になってきます。

SPIやI2Cのようなクロック信号がある同期信号では、お互いにクロックで同期をとるのでメインクロックのずれなど問題になりません。

しかし、UARTのようなクロック信号がない非同期信号では、一定の時間ごとにデータを送るので、メインクロックがずれているとデータを送るタイミング・受けるタイミングがずれて、ビットがずれたデータを送受信してしまいます。

そうすると、通信が確立しません。

 

なお、UARTでは2~3%のクロックのズレならば問題なく通信できる可能性が高いです。

しかし、送信と受信の両方で2%ずれたら合わせて最大4%ずれてしまいます。

片方が水晶振動子駆動で精度がよいという条件か、互いにズレが1%程度という条件でないと厳しくなります。

 

◯精度が必要すぎて水晶振動子が必須な場合

まず、時計です。

外付けのRTCなどを使用せずに、CPUが自分で時刻をカウントするという時点で水晶振動子は必須になります。

1%のずれがあったら、一日に14分もずれてしまうのでまったく実用になりません。

 

つぎに、無線内蔵CPUです。

無線通信(RF)では法律により、厳しく周波数の範囲を決められています。

たいてい50ppm程度しかずれてはいけません。

この時点で水晶振動子が必須です。

 

 

というようなところで、なんとなく感覚つかめたでしょうか。

 

以上、小田切でした。

CPUの消費電力はクロックに(ほぼ)比例する

CPUのデータシートを見たことがあれば、「低消費電力モード」だとか「低速モード」だとか「低速オシレータ」とかそんな言葉を見たことがあると思います。

そういったものを見ていると、

 

「CPUは速度を遅くすると電気を消費しないんだ」

 

と分かってくると思います。

でも、なんでクロックが遅いと電気を食わないのでしょうか。

CPUを抵抗成分だと仮定すると、電圧が一定ならばクロックがどうだろうと電流は同じはずです。

 

ということは、CPUは電源から見て抵抗ではないのです。

 

実は、CPUというのは、というかデジタル回路というのは、ロジックが遷移するときにだけ電気を食います。

High→Low

Low→High

のときに電気を消費するわけです。

レベルが変化しなければ電気は理想的にはゼロ、実際にも微々たるものです。

 

何故かと言うと、CPUがCMOSというFET回路の塊だからです。

大昔のIC・CPUはトランジスタで出来ていました。

トランジスタというのはONにするためには常に電流が流れていないといけません。

もし電流が流れなければOFFになってしまいます。

CPUの中には大量のデジタル信号があり、当然のONのトランジスタも多いわけですから、合計では莫大な電流を常時消費するわけです。

しかし、FET回路は電圧駆動です。

電圧をかければ電流がほぼ流れずON/OFFできます。

つまり、CPUの中でONのFETが多くても別に電流が流れないわけです。

理想ではなく、現実でもほとんと電流が流れません。

つまり、止まっている状態ではほとんど電気を食わないのです。

しかし、回路には寄生容量があります。コンデンサがあちこちについているのです。

なので、ロジックが変化するときにはそのコンデンサを充電・放電する必要があり、それが電流を消費するのです。

CMOS回路自体の消費電流は微々たるものだが、寄生容量が電気を食うということです。

 

そして、クロックが速ければロジックの変化が大きい=充放電回数が多い=消費電流が多い。という関係が成り立つわけです。

 

以上、小田切でした。

CPUの入力ピンにプルアップ・プルダウンをつけないと何がいけない?(初心者向け)

CPUの入力ピンやその他のICの入力ピンには、基本的にプルダウン抵抗かプルアップ抵抗をつなげないといけません。

 

「プルアップかプルダウンしないと、HighかLowか決まらないからでしょ。でも、使ってない機能とかHighでもLowでもどっちでもいいピンはどうでもいいんじゃない?」

 

と思うかと思いますが、そうじゃないんです。

デジタル回路は「High」か「Low」しかないんです。

中間値というのはないんです。

中間値を入れると大げさでなく壊れることが有ります。

中間の電圧を入れるとデジタル回路ないの回路構成上、IC内で電源とGNDがショートした形になり、大電流が流れてICが破損するのです。

(なので、HighからLowへの変化もあまりゆっくりだと問題がでます。変化も早くないといけません)

 

なので、全く使っていなくて「どっちでもいい」ピンであっても、かならずプルアップかプルダウンをいれましょう。

CPUの場合は出力ピンにすることでプルアップ・プルダウンが不要になりますが、入力しかできないピンはやはりプルアップ・プルダウンが必要です。

 

なお、プルアップ・プルダウンが内蔵されている場合は、外で抵抗を付けても着けなくてもいいですが、内蔵と逆方向に着けないように気をつけましょう。

 

以上、小田切でした。

意外と大事なI2Cのプルアップ抵抗

I2Cバスをご存知でしょうか。

I2Cはデータ線:SDAとクロック線:SCLで双方向通信ができる、とても低コストな信号規格です。

(正確にはもともとのI2Cの規格をきっちり守ったわけではない「なんちゃってI2C」ばかりですが、まぁ、I2Cです)

 

信号線が少ないだけでなく、「バス」なので複数のデバイスをつなげます。

つまり、CPUから伸びる配線はSDA&SCLの二つだけですが、そこにEEPROM、RTC、センサー・・・といろいろなデバイスを複数個繋げられるのです。

ピン数が少ないCPUでは非常に心強い味方です。

(ICごとにアドレスが違うので、CPUがアドレスを指定して通信することで複数個つなげても通信が混信しない)

 

また、信号速度も最大400kHzと低速です。

 

・信号線が2本のみ

・速度も遅い

 

ということで、ハードウェア設計的には非常に簡単です。

よほど酷いパターンをひかない限り普通に動きます。

 

が、一つだけ注意するべきところが「プルアップ抵抗」です。

 

I2Cは信号線がプルアップされており、それぞれのデバイスがそれをLに落とすことで通信をしています。

理想状態ではプルアップ抵抗は何Ωでも大丈夫なのですが、実際にはそうはいきません。

I2Cバスに接続される信号線にはGNDとの間に寄生容量が発生します。

さらに、各デバイスのピンにも寄生容量があります。

 

つまり、I2CのバスをLやHに変化させるときにはその寄生しているコンデンサを充放電する必要があるわけです。

その事自体はどんな信号線も同じです。SPIだろうがMIIだろうが。

でも、他の通信規格はたいていプッシュプルで駆動するので、寄生容量の充放電は速いのです。

ところが、I2Cは・・・

H→Lのときは、問題ありません。

デバイスが信号線とGNDをショートさせるので速やかに電荷が抜けてLになります。

問題は、L→Hのときです。

このとき、デバイスはハイインピーダンスになるだけです。

プッシュプルのように電源と信号線をショートさせたりしません。

ただ単純にプルアップ抵抗から流れてくる電流で寄生容量に充電していくのです。

ということは、「物凄く遅い」のです。

 

対策としてはプルアップ抵抗を小さくすることですが、あまりに小さくするとデバイスのドライブ能力を超えてしまいますし、消費電流も大きくなります。

なので波形的に問題ない範囲でプルアップ抵抗は大きくしたいのです。

というところで、現実的には1~10kΩという範囲内で大体うまく行きます。

 

I2Cを使う際には波形をきちんと見てプルアップ抵抗を調整しましょう!

 

以上、小田切でした。

見落としがちな電源立ち上がり順序

大規模なSoCなどになると、電源を複数持っています。

例えば、コアに1.2V、メモリ用に1.8V、外部I/O用に3.3V・・・と3つぐらいの電源があるのは当たり前です。

こうなってくると面倒なのは、電源を用意すればいいだけではなく順番も重要になることです。

 

例えば、SoCのデータシートが

「1.2V、1.8V、3.3Vの順番に電源を入れてください」

と記載してあるとします。

(大体低い電圧から入れるのが普通です)

 

しかし、普通に電源回路を作るとどうなるでしょうか。

3.3V生成→3.3Vから1.8Vを生成→3.3Vから1.2Vを生成

みたいな構成になることが多いと思います。

すると、電源が入る順番は

「3.3V→1.8V→1.2V」または「3.3V→1.2V→1,8V」になってしまいます。

つまり、電源回路を普通に作って供給すると、高い電圧から供給されてしまうのです。

 

非常に面倒な点です。

 

解決策の一つは、そのSoC専用に設計された電源ICがあればそれを利用することです。

そういうものがあればそれを利用するのもいいでしょう。

もう一つは、電源を制御するための回路を組み込む方法です。

上記の電源回路であれば、1.8Vと3.3Vの電源ラインにFETを入れておき、電流を遮断します。

そして、1.2Vの電圧が入ったら1.8VのFETをON、1.8Vの電圧が入ったら3.3VのFETをONにする回路を入れるのです。

 

初めてやると結構面倒な部分です。

 

ということで、複数電源があるICの電源投入順序は十分に気をつけましょう。

 

以上、小田切でした。

CPUやICでコンデンサを付けろと書いてある端子の正体

どんな部品も電源にはパスコンとしてコンデンサをつけますが、これはそのことではありません。

 

「この端子とGNDの間に0.47uFのコンデンサを接続する」とか書いてある端子のことです。

 

謎、ですよね。

 

CPUを含むどんなICも、ピン配置を見れば大体用途や意味がわかるものです。

「ああ、コレはJTAG用か」

「これはGPIOか」

「電源接続ね」

「USB通信用ね」

 

しかし、そうでないものがあります。

何の説明がなく「未接続」と書いてあるものや、今回話題にしている「コンデンサを接続しろ」という端子です。

こういうの、普通に不明です。

一体何でしょうか。

 

え、知らなくていい?

 

知らなくてもOKですが、ちょっと知識として知っておきましょう。

 

実はこんな例があります。

 

1,内部電源用

たとえば、外部給電は3.3Vであっても内部で1.2Vなどを生成しているICがあります。

要はレギュレータを内蔵しているICということです。

しかし、レギュレータそのものはIC内に内蔵できてもコンデンサは無理です。

そのため、コンデンサは外付けしないとレギュレータとして動作しません。

そのため「(レギュレータ用のコンデンサとして)この端子とGNDの間に0.47uFのコンデンサを接続する」と書いてあったりします。

 

2,ローパスフィルタとして

中でアナログ信号を平滑化する際にフィルタとしてコンデンサが必要です。

そのフィルタ用のコンデンサを外付けする場合があります。

 

一番多いのは「1」だと思います。

あやしいなと思ったらそのコンデンサの両端をテスタで触ってみましょう。

それっぽい電圧が出てたら「なるほど」と納得してにやにやしてみてください。

 

以上、小田切でした。

Ethernet(LAN)の実現方法

「基板にLANコネクタを付けて、Ethernetにつなげたい!」

 

というのはよくあるパターンです。

一応、方法は2つあります。

 

1,Ethernetの通信を全部処理してくれるモジュールを買って、UARTで通信する

例えばXPortのような製品です。

基板のメインCPUには全く普通のものを利用して、メインCPUからUARTなどでモジュールを制御します。

Ethernetのハードウェア・ソフトウェアを作らなくていいので非常に楽です。

ただ、コストが高いので、単価が高い製品にしか使えません。

 

2,メインCPUでEthernetを処理する

まずメインCPUの選定から違います。

「Ethernet対応」とうたっているCPUを選びます。

が、それを買って直結すれば実現できるかというとそんな簡単なものではありません。

CPUに載っているのはMAC層まで・・・

 

WikipediaのOSI参照モデルを見てもらいたいのですが↓

https://ja.wikipedia.org/wiki/OSI%E5%8F%82%E7%85%A7%E3%83%A2%E3%83%87%E3%83%AB

 

こんな風にネットワークは層構造で実現しています。

そしてCPUにのっているのは下から2番めのデータリンク層(MAC)までです。

一番下の物理的に通信する層は搭載されていません。

つまり、「通信するデータは作れるけど、実際に電気的に通信するハードウェアを持っていない」ということです。

 

「だめじゃん!」

 

いや、そういうものなんです。

ほとんどすべてのEthernet対応CPUがそうなので諦めてください。

ということで、PHYというものが必要になります。

 

1,Ethernet対応CPU

2,PHY(CPUと接続されるLSI)

→実際に通信する電気信号を作る部品

3,パルストランス

→ショートや他の機器との電位差などから製品を保護するために通信を絶縁する部品

4,LANコネクタ(RJ-45)

→よく見る四角コネクタです

 

とまぁ、これだけ必要になります。

結構面倒なので、メーカが出している資料をじっくり見ながら作ることになります。

また、ソフトウェアの方もLinuxやTRONなど、TCP/IPがちゃんと扱えるOSが必要になるので、開発もそれなりに大変です。

 

以上、小田切でした。

 

P.S.

SoC(System on Chip)では、PHYがCPUと一緒に内蔵されている製品もある模様。

組み込みCPUって小数の計算ができないの!?

という話題について。

INTELやAMDやARMだとか、パソコンやスマホに入っているCPUは計算能力に特化しているので、整数も小数も超高速に計算できます。

 

が、組み込み用途で使うようなCPU(マイコン・MPU)なんていうのは非常に貧弱なため、全然違います。

組み込みマイコンでも高い部類(千円に近い値段)のものは浮動小数点のハードウェアを持っているのでそれなりな速度で計算できますが、

普通の安いマイコンではそもそも浮動小数点のハードウェアを持っていません。

つまり、整数計算しかできません!

それもスマホやPCみたいに64bitなんてのではなく、16bitや下手したら8bitだったりします。

 

要は、小数の計算が出来ないどころではなく、整数の計算すらしょぼいのです。

8bitのマイコンでも32bitなどの大きな数値を計算することは出来ますが、「8bitごとに足し算して繰り上げて上の桁の計算に使用して……」なんてことをするので4倍以上の時間がかかります。

浮動小数点も同様です。

浮動小数点数の仮数部だけを個別に計算して、指数部もまた個別に計算して……

要はプログラムでビット操作を延々として浮動小数点数の計算を行うのです。

考えてみればわかると思いますが、浮動小数点数の計算をビット操作でやるなんてめっちゃ大変です。

普通に整数計算の数十倍とかかかります。(下手したらもっと?)

 

さらに「浮動小数点同士の足し算・引き算・掛け算・割り算」をソフトウェアで行う必要があるので、そのためのライブラリをプログラム内に入れる必要が出てきます。

容量が数十kBしかないCPUだとけっこうな負担になります。

 

……ということで、浮動小数点数のハードウェアを持っていないCPUでは基本的には

・計算がありえないほど遅い

・ROMの容量が足りなくなる

ということで使わないという判断をすることが普通です。

 

以上、小田切でした。