google-site-verification: google3bd66dd162ef54c7.html
fc2ブログ

3.3VのI2Cを5VのArduinoに接続する場合の注意事項

 このところ0.96インチOLEDでいろいろ遊んでいますがそろそろネタ切れです。そんなことで、このデバイスを使う時のコツみたいなものをまとめてみようと思っていました。

 内容としては、「画面を部分消去するより、全画面消去した方がずっと速い」だとか、「display.display()コマンドで画面が更新されるので、チマチマと書き換えても舞台裏は見えない」、はたまた「Adafluitのロゴを表示するために、フラッシュメモリを無駄使いしていてけしからん」なんてことを思っていました。

 ところがI2Cバスの使い方でもっと重要な話が出てきました。ということで今回の記事ではそのあたりに絞って書きたいと思います。

◆0.96インチOLED
0.96インチOLED
 インターフェイスにSSD1306を使ったOLEDです。

 このデバイスはインターフェイス基板付きで売られていて、基板には3.3VのLDOシリーズレギュレーターが入っているので電源電圧は5Vから3.3Vまで使えます。また、I2Cバスは基板内の3.3Vに4.7kΩでプルアップされています。
 詳しくはこちらの解説記事参照

 この記事を書いた時は、「そうか、5Vでも3.3Vでも使えて便利じゃん!」と思いました。でも最近気付いたのですが、3.3Vでも5Vでも良いのは電源電圧だけで、I2Cの信号レベルは3.3V固定なので、5VのArduinoに接続する時にはレベル変換が必要になります。

 I2Cで3.3V/5Vレベルが混在している時には2N7000を使ったレベルコンバーターを入れていたのに、とんだ勘違いをしたもんです。

 ただ、このOLEDを使った他の方の製作記事を見るとI2Cのレベル変換なんて余計な回路は入っていないようです。3.3Vロジックの信号を5V側で受ける時に問題が起きそうですが、VIHは0.6Vcc以上あれば良いので、5VのArduinoなら3V以上あれば大丈夫なはず。ということは、3.3Vあればいけるんじゃないの?という考え方が成立しそうです。(注:後記しますが、ArduinoというかATmega328PのWireインターフェイスのVIHは0.7Vcc以上必要です)

▼Arduinoで使う場合
OLEDをArduinoに接続(I2C)
 もう一つ考慮すべき点として、wireライブラリを使った時にArduino(ATmega328P)側に自動的に入るプルアップ抵抗があります。上の回路図のRarduinoの35kΩです(ATmega328Pのデーターシートによるとプルアップ抵抗は20-50kΩとなっているのでその中間の35kΩと表現しています)。
 この抵抗で5Vへ引っ張ると、D3がONになりますが、信号がLOWになるとD3はOFFになるので、D3の逆回復時間の影響で波形に段が付きそうでちょっと心配になります。保護ダイオードの特性なんてどこにも書いて無い、というか何の保証もないので、ONになることを前提にして使うのは気持ち悪いです。

 そんなことを考えていました。でもよく考えてみたら、

▼プルアップの等価回路
テブナン終端の等価回路
 プルアップ抵抗の部分だけを取り出して、テブナン終端を等価回路に描き直すとこのようになります。3.5Vに4.14kΩで引っ張っていることになり、3.3V電源に入っているダイオードは0.2Vだけ正にバイアスされるだけです。これくらいなら飽和していないので、逆回復時間とかは全く考えないで良いはずです。

 なるほど、これなら大丈夫そうです。それにArduino側で5Vにプルアップしておけば、I2Cバスの電圧が僅かに上昇するのでマージンが少し増えることが期待できます。

 理論的な話は分かったので、実際の波形を見てみます。

▼Arduino側プルアップ無し(OLED側のプルアップだけ)
OLEDのプルアップだけ
 上がSDA,下がSCLで、SCLの負スロープでトリガしています。なお、プルアップ無しにするには、I2Cの(OLEDの)初期化が終わった後で、pinMode(SCL,INPUT); pinMode(SDA,INPUT); と入れています。

▼Arduino側プルアップ有り(ArduinoとOLEDの両方でプルアップ)
Arduino側のプルアップあり
 なるほど、少しレベルが上がっています。それに立ち上がり速度も少し速くなっています。

 少しでもレベルが上がれば5V側のVIHのマージンが増えるので、Arduino側のプルアップは入れたままにした方が良いということです。というか、余計なことはしない方が良かったです。

◆マージンの確認
 とりあえず大丈夫な感じではありますが、3.3/5Vのレベル変換回路を省略するとギリギリのマージンで動かすことになります。そんな訳で、もしやるなら、配線は最短にして、ノイズの飛び込みを減らすために、GNDに近付けて配線すべきでしょう。

 ノイズマージンを見るのに、SDAピンに触ったりしてハングアップしないか見るのが手っ取り早いです。DSO-SHELLのように入力の静電容量が大きなオシロ(約90pFもあります)を接続すると、しばらくするとハングアップしたりするので、これでもマージンの確認が出来ます。まあ、プロならESDテストとかやる、というか最初からこんな無茶はしないのでしょう。

◆データーシート上のVIH
 また見たくなると思うので、ATmega328PのデーターシートのVIHの項を転載しておきます。

▼一般IOピン (32.2.DC特性)
IOピンのVIH
 0.6Vccとなっています。

▼wireピン (32.7. 2線直列インターフェイス特性)
WireピンのVIH
 0.7Vccとなっています。内部で引きずっているものが多いので、マージンを大きくしておく必要があるのでしょうか?

◆まとめ
 OLEDのI2Cインターフェイスの回路についてはなんだかもやもやしていたのですが、纏めてみてすっきりしました。結論をもう一度書くと、5VのArduinoに3.3VのI2Cインタフェースのデバイスを接続する場合、3.3V側をプルアップするだけで直結しても大丈夫だと思います。

 ATmega328Pのデーターシートを読むと、一般ピンのVIHは0.6Vcc、つまり5Vで使うなら3Vですが、wireのピンでは、0.7Vcc必要。つまりHighレベルには3.5V必要となっています。ArduinoとOLEDの両側でプルアップすることで、3.5Vにプルアップしていることになり、ギリギリでOKと考えることが出来ます。但しマージンはゼロです。でも、スペック自体がマージンを持っているので、アマチュアがやるなら大丈夫だと思います。

 I2Cバスではありませんが、CMOSの3.5V/5V間のインターフェイスについて、ケプストラム社のwebの、5V系・3.3V系信号レベル変換という記事に同じような話の解説がありました。こういう情報はほんとうに貴重です。

 あと記事中でダイオードの飽和を嫌っていますが、私の世代は飽和型と非飽和型ロジックの性能差について刷り込まれているので、条件反射的に反応しちゃいます。TTLからショットキーTTL、はたまたECLやらCMLなんてのがあったのは、70年から80年代だったか、(遠い目、、)
関連記事

コメントの投稿

管理者にだけ表示を許可する

No title

すごくなるほどな内容でした。ありがとうございます。

I2Cの入力電圧は0.7Vcc必要っていうのを知らなかったので、やっぱりデータシート大事ですね。

nekosan おはようございます

レベル変換回路をすっ飛ばして作っちゃったので、後付けでアリバイ工作をやったという疑いもありますが、、

No title

LSIの入力セル内部の保護ダイオードの飽和がまずいのは、意図的に大電流を流すような使い方をすると(シリコン)基板やウェルに流れ込む電流で(シリコン)基板電位・ウェル電位が浮いたりするからです(正常な使い方、正常な状態では電流が流れるはずの無いパスですから)

re:とおりすがりさん

なるほど、そういうこともあるんですね。
カレンダー
03 | 2024/04 | 05
- 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 - - - -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。
記事の内容のご利用は読者の自己責任でお願いします。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード