まえがき
SpresenseではArduino nanoサイズのメインボードと,Arduino UNOサイズの拡張ボードが販売されています.
チップ(CPU)はメインボードに取り付けられているので一応メインボード単体で動作させることができます.ただし1.8V系なので外部回路が3.3V系や5V系だと問題が起こりえます.
そこで拡張ボードを使います.
拡張ボードを使うと3.3V系や5V系の回路にSpresenseを組み込むことができます.
ところがこの拡張ボード,IOピンの仕様に注意が必要です.
公式ドキュメントからGPIOピンの仕様に関する記述を抜き出すと
このレベルシフタはピンソケット側が1kΩで5Vまたは3.3Vに常にプルアップされています。
Spresenseハードウェアドキュメント 1.14節より
この記述で何が起こるのか,また注意点が分かる方は問題ありません.
本記事では,公式ドキュメントの記載でだから何?と疑問を持たれた方,及び
- Spresenseの拡張ピンから出ている電圧が低い(LEDが暗い等)気がする?
- Spresenseをリセットしたら外に着けた回路(LEDやらモータやら)が暴走したんだが???
となってしまった方向けに,原因や注意点を述べたいと思います.
なお,先に言ってしまうと,上述の問題が発生した場合,残念ながらソフトウェア的な解決は不可能で,何等か回路上の対策を施す必要があります.
拡張ボードの原理と電気的な2つの注意点
まずは公式ドキュメントの図に従って,レベルシフトの原理を考えてみます.
なお,以下の考察はレベルシフタが回路図の通りMOSFETで構成されている場合に成り立つものです.
もし実際にはレベルシフタがより複雑な回路で,あくまでMOSFETは機能を省略して示しただけであれば,違った挙動になっている可能性がありますのでご注意ください.
CPUが論理Lowのとき
プログラムでGPIOピンをLowレベルとした時の挙動は以下の通りと考えられます.
① CPU側がGNDに接続され,レベルシフタ(MOSFET)のソースが接地される.
② レベルシフタのゲートソース間電位差$V_{\rm GS} = 1.8$VよりFETが開通し,$V_{\rm DS}\simeq 0$とみなせる.
③デジタルピンソケットの出力は0V(Lowレベル)となる.
CPUが論理Highのとき
一方,CPUを論理Highに設定したときには以下のように動いていると考えられます.
① CPU側が1.8V電源に接続され,レベルシフタのソース電位は1.8Vとなる.
② ゲートソース間電位差$V_{\rm GS} = 0$VよりFETは開かず,ドレインソース間電流$I_{\rm DS}$は流れない.
③ GPIO出力は1kΩのプルアップ抵抗を介してレベルシフト後の電源(3.3Vor5V)に接続される.
このようにして,プログラムによって切り替えたHighLowが拡張ボードのGPIOピンに出力されていると考えられます.
ただし,この仕組みであるとすると主に次の2つの注意点が生じます.
- デジタル出力の出力インピーダンスが大きい
- ハイインピーダンスと論理Highの出力状態が同じ
この2点についてそれぞれ説明していきます.
1.デジタル出力の出力インピーダンスが大きい
要するに,拡張ボードのHigh出力には最初から抵抗が入っている,ということです.
先の説明でCPUが論理Highになったときに,プルアップ抵抗を介して電源に接続されると説明しました.
これにより,GPIOのHigh出力は必ず抵抗を介して供給されるため,直接電源に接続されません.従って3.3Vや5.0Vの電位をGPIOピンから得られない場合があります.
したがって,LEDが思ったより暗いといった現象を引き起こします.
具体例として,GPIOピンから3.3Vが出ると思った上で,$V_F=2.1$Vの赤色LEDを10mAで光らせることを考えます.
この場合,外付け抵抗$R$の計算は
$$
R = \frac{3.3-V_F}{10{\rm mA}} = \frac{3.3-2.1}{0.01} = 120 \Omega
$$
となり,120Ωの抵抗器をつければよいと考えられます(下図(a)).
ただし,実際は(b)のようにGPIOピンは1kΩの抵抗が予め接続されています.従ってLEDに流れる電流$I_F$は
$$
I_F = \frac{3.3-V_F}{120\Omega+1{\rm k}\Omega} = \frac{1.2}{1120}\simeq 1.07{\rm mA}
$$
なんと,直接つながっていると考えた時に比べて,電流が十分の一程度になってしまっていることがわかります.
なお,このときGPIO出力とGND間の電位を計測すると2V程度しか出ずにびっくりします.
このようにGPIOピンの出力電圧が思ったよりも低くなる現象は,接続する負荷の抵抗値(入力インピーダンス)が小さい,つまり多くの電流を引き出そうとしたときに顕著です.
逆に言えば,接続先が多くの電流を必要としない場合にはあまり気になりません.
デジタル信号をやりとりする場合,多くのICでは入力インピーダンスが高く設計されているはずなので,Spresense-他マイコン間,Spresense-論理IC間の通信等では問題にならないはずです.
この辺りのことは公式ドキュメントに以下のような記載があります.
したがってピンソケットに接続する回路が低いインピーダンスを持つ回路である場合には、CPUの検出する閾値が変動してしまう事から正しく論理を検出できなくなります。
この,"インピーダンスが低い回路"というのにはLED点灯回路のようなものも含まれますので,十分注意が必要,ということです.
そもそもマイコンのGPIOから大電流を引き出そうとするのは,マイコンの破損等に繋がりよろしくありません(それでも出力インピーダンス1kΩは大きい気がしますが).
電流が必要な回路では適当なFETやドライバをかまして対処しましょう.
以下では,GPIOピンに接続される負荷の入力インピーダンスは十分に大きいと仮定します.
2.ハイインピーダンスと論理Highの出力状態が同じ
1つ目の問題はマイコンのお作法を強めに意識すればよいのですが,こちらはより根が深い問題です.
原理を考察した際に,CPUがLow→出力0V,CPUがHigh→出力プルアップであることを確認しました.
では電源の投入直後やマイコンのリセット時にはどのような電位になっているのでしょうか.
これについては公式ページからダウンロードできるコネクタピンリストに記載があります.
下図はPWMピンを確認した場合です.
Hi-Zつまりハイインピーダンス状態(接続されていない,あるいは非常に大きい抵抗で電源やGNDに接続されている)と記載されています.
CPUがハイインピーダンスのとき,出力状態は以下のようになると考えられます.
①CPUがハイインピーダンスになる.
②ソースからGNDまでの抵抗が非常に大きいため,ドレイン-ソース間に電流は流れない.
③拡張ボードの出力ピンはプルアップ抵抗を介して3.3Vないし5V電源に接続される.
つまり,起動時の状態が論理Highの状態と同じになってしまいます.
CPUがハイインピーダンス→ハイインピーダンスではなく,プルアップ抵抗経由で電源に繋がってしまうのです.
先ほど接続先の入力インピーダンスが大きいとしましたので,書き込み時やリセット時のCPUがハイインピーダンスのとき,入力回路側はHighと判定してしまいます.
これにより,例えば拡張ボードの出力ピンにLEDが接続されていると,書き込み時やリセット時に必ず点灯してしまいます.
また,PWMでモータ速度を決めるようなモータドライバ(例えばこれ)を使用していた場合,起動してからプログラムが走り出すまではモータが回ってしまいます.
これを何とかするのは結構大変です.
場当たり的な方法は,モタドラ側の電源を切ってからSpresenseを起動させ,Spresenseが起動したことを見計らってモタドラの電源を入れる方法でしょうか.
回路的に,モタドラ側の電源スイッチを作り,Spresenseのデジタルピンを使って電源を入れることも考えられます.
(ただし,拡張ボードの出力電圧はHighから始まりますので,立下りを検知することになります.)
おわりに
Spresneseの拡張ボードでは,レベルシフタの都合Highサイドの出力は1kΩのプルアップ抵抗から供給されることを見ました.
これによって入力インピーダンスの小さい回路では問題が生じる場合があります.
これはFETやドライバを外付けすることで対応できます.
また,CPUがハイインピーダンスで起動してもデジタルIOの出力がプルアップ抵抗に接続されることから,接続したLEDやモータが突然動き出す可能性があることを確認しました.
こちらの対応は結構大変です.
特に後者の仕様はロボット製作に使おうとか思った場合は結構面倒です.
I2CとかSPIとかシリアル通信を使うだけなら多くの場合問題にならないとは思いますが,そうするとPWMピンとかの意味は…という気がしないでもないです。
確認してみたところ,拡張ボードで使っているレベルシフタICにはENピンがちゃんとあるようです.
ただプルアップされてしまっているので,こちらからアクセスすることはできません.
ボード作り直してなんとかしてほしいなあという気持ちです.