« Arduino-UNO + SDカードでシリアルデータロガー 完成形 | トップページ | どなたかいりませんか? まずは抵抗→コンデンサ→IC »

2020年4月25日 (土)

Arduino やっぱり気になる放置ポート

Arduino-UNOに搭載されているマイコンはATmega328P。
あれこれ公開されているArduinoの参考スケッチ、たいていの場合、使うポート以外はみんな放置したままなんです。
それが気になります。

例えば出力にするところは、
  pinMode(1, OUTPUT);
などとして、
  digitalWrite(1, HIGH);
と、出力をHに。

プルアップ付の入力なら
  pinMode(2, INPUT_PULLUP);
として、スイッチなどを対GNDにつなげば
  digitalRead(2);
で、スイッチのオン・オフが読み取れます。

ところが・・・スケッチで使わない入出力ポートは、何もしないのが普通になっています。
出力指定、あるいはプルアップ入力指定しないままだと、リセット後のそのポートは裸の入力のまま。
I/Oポートの構成図だとこんなふうになります。

A11_20200425151601
  ・ATmega328Pのデータシート(日本語訳)より

入力ピンに何もつながず放置しておくと、インピーダンスが非常に高いためH/Lが安定しません。
(オシロスコープで観察しようとしてプローブをつないだら、そのプローブの抵抗(たいてい10MΩ)でLレベルに安定してしまい、真の姿が見えない)

★マークのシュミットトリガ入力がその関門です。
入力ポートのシュミット、そのスレッショルド電圧は電源電圧のおよそ中央。
そしてヒステリシスが0.5Vほど。
つまり、何らかの原因(誘導ノイズなど)で入力レベルが変動してスレッショルド電圧付近に達したら・・・
C-MOSのシュミットゲート回路、入力がスレッショルド電圧付近になると電流が増えるという特性があります。
  ※昔々、いろんなシュミットIC(4584や4093、HC14、HC132、
   シュミット入力になったモノマルチなどその電流の増加を
   調べたことがあったんですが、資料行方不明。
   プロセッサ誌あたりに投稿した記憶がうっすらと)

ATmega328Pの入力でも同様のことが生じます。
何かの拍子、オープンになった入力ポートの電圧が電源電圧の半分近くになると・・・1つの入力につきざっと0.5mA~1mA電源電流が増加します。

USBから電源が供給されて動くArduino、こんなちょっとの電源電流増加は目立ちません。
Arduinoの環境ではなく、チップ単独で電池運用する時などにこの放置が問題になってくるでしょう。

未使用I/Oポート、その扱いの基本は、
・入力専用ポート
  抵抗でプルアップかプルダウン
  直接GNDあるいは電源につなぐ
・出力専用ポート
  放置
・入出力ポート(たいていのArduinoのポート)
  出力に指定して放置
  入力指定で(イニシャルせず)プルアップかプルダウン抵抗を付加
  入力にして内蔵プルアップ、プルダウン機能を有効に

リセット時の挙動、イニシャルプログラムが走る前のことも考えておかなくてはなりません。
ポートを出力にする。あるいは内蔵のプルアップやプルダウンを有効にする。これらはプログラムが正常に走りはじめてから設定できる機能です。
何らかの異常でリセット状態が続いた時、出力ポートにするはずのポートが入力のままで、これをC-MOSゲートで受けているとH/Lレベルが定まらず思いもよらない出力がオンしてしまうことがあります。
出力にもプルアップ、プルダウン抵抗が必要な場合があるのです。

もうひとつ。
ATmega328Pをスリープさせると入力ポートを外部から切り離してくれる機能があります。
  ※上の図、シュミットゲートの右側のスイッチ(Lへ落とすFETも)。
このおかげでスリープさせた時に入力が安定し(放置していた入力も)、スレッショルド付近の不安定な状態(シュミット回路の電流が増える)になりません。

未使用ポートの放置が気になって、私の書くプログラムはこんな具合に全ポートを入力か出力に区分けしています。
※例:JIS C8708:2019充放電実験回路のスケッチ (スペースがズレるかな)
// I/Oイニシャル
  PORTB = 0b00000000;   // data/pull up
  DDRB = 0b00111111;   // port指定
  //     |||||+---- PB0 IO8  out -
  //     ||||+----- PB1 IO9  out OC1A 充電PWM
  //     |||+------ PB2 IO10  out OC1B 放電PWM
  //     ||+------- PB3 IO11  out OC2A BZZ
  //     |+-------- PB4 IO12  out -
  //     +--------- PB5 IO13  out (LED)
  PORTC = 0b00001110;   // data/pull up
  DDRC = 0b00110000;   // port指定
  //     |||||+---- PC0 AD0  in 電池電圧 A/D入力
  //     ||||+----- PC1 AD1  in START SW
  //     |||+------ PC2 AD2  in ↑ TX SW
  //     ||+------- PC3 AD3  in ↓ MENU SW
  //     |+-------- PC4 AD4  out 充電オン
  //     +--------- PC5 AD5  out 放電オン
  PORTD = 0b00000011;   // data/pull up
  DDRD = 0b11111110;   // port指定
  //    |||||||+---- PD0 IO0  in RXD
  //    ||||||+----- PD1 IO1  out TXD
  //    |||||+------ PD2 IO2  out LCD RS
  //    ||||+------- PD3 IO3  out LCD E
  //    |||+-------- PD4 IO4  out LCD DB4
  //    ||+--------- PD5 IO5  out LCD DB5
  //    |+---------- PD6 IO6  out LCD DB6
  //    +----------- PD7 IO7  out LCD DB7

いっぱい書いてますが、実際の命令コードは6行だけ。

Arduino-UNO + SDカードでシリアルデータロガー 完成形 ではこんなの。
未使用ポートは出力にしています。
// I/Oイニシャル
  PORTB = 0b00011100;   // data/pull up
  DDRB = 0b00101111;   // port指定
  //     |||||+---- PB0 IO8  out 赤LED (Lでon)
  //     ||||+----- PB1 IO9  out 緑LED (Lでon)
  //     |||+------ PB2 IO10  out CS カードアクセス時Lに
  //     ||+------- PB3 IO11  out MOSI カードDI
  //     |+-------- PB4 IO12  in MISO カードDO
  //     +--------- PB5 IO13  out SCLK
  PORTC = 0b00000000;   // data/pull up
  DDRC = 0b00111111;   // port指定
  //     |||||+---- PC0 AD0  out -
  //     ||||+----- PC1 AD1  out -
  //     |||+------ PC2 AD2  out -
  //     ||+------- PC3 AD3  out -
  //     |+-------- PC4 AD4  out -
  //     +--------- PC5 AD5  out -
  PORTD = 0b10000011;   // data/pull up
  DDRD = 0b01111110;   // port指定
  //    |||||||+---- PD0 IO0  in RXD
  //    ||||||+----- PD1 IO1  out TXD
  //    |||||+------ PD2 IO2  out -
  //    ||||+------- PD3 IO3  out -
  //    |||+-------- PD4 IO4  out -
  //    ||+--------- PD5 IO5  out -
  //    |+---------- PD6 IO6  out -
  //    +----------- PD7 IO7  in SW入力 pull up

 

|

« Arduino-UNO + SDカードでシリアルデータロガー 完成形 | トップページ | どなたかいりませんか? まずは抵抗→コンデンサ→IC »

Arduino」カテゴリの記事

コメント

基板の絶縁抵抗は10の10乗Ωも無いだろうから、何もしなくてもLow側で安定しているはず、と思っていたのですが、
ちょっと確認してみると、基板(石?)によってはじわじわとVcc側に上がっていくピンがあったりして、あらら、と言う感じでした。もう少し調べてみますが、こりゃちゃんと対策しておいた方が良さそうです。

あと、DC的にはなんとか大丈夫でもラインの誘導には違いなく反応するので、やはり空き端子処理しておいた方がいろいろと安全なんでしょうね。ただプログラムが読み難くなるのが難点です。

投稿: ラジオペンチ | 2020年4月26日 (日) 21時34分

放置したポートの状態を検証。

スケッチ例 01.Basicの中のblink.inoをベースに。
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT); // そのまま
analogWrite(10, 64); // ★1 PWM output Digital10(PB2 16pin)
// pinMode(9, INPUT_PULLUP); // ▲1 D9 pullup
}

// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, digitalRead(9)); // ★2 D9=PB1 15pin input
}

デジタル9(PB1:15pin ATmega328Pの端っこの足)を入力にしたまま、その状態でデジタル13(PB5)のLEDポートを駆動します。
隣の16ピン(PB2)をPWM出力にして480Hzのパルスを出します。
15ピンを指先やピンセットの先で触ったり、近づけたり遠ざけたりしてみてください。
LEDを駆動するPB5ポートをオシロで見ながらごそごそすると状態がよくわかります。
商用電源周波数の誘導を拾っている様子、そして16ピンが出すパルスの誘導を観察できます。

次に▲1のコメントを取ってプルアップを有効にするスケッチを書き込みます。
すると、安定してLEDが点灯。
指で触ったくらいでは大丈夫。
15ピンと16ピンを短絡すると、PWMパルスでLEDが点きます。

投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年4月27日 (月) 09時37分

はい、やってみました。
UNOだと盛大に誘導していてそのまんまの波形がPB5に出てました。

ちなみに配線が短いArduino NANO で同じことをやると、こっちは大丈夫でした。NANO の Pin9 の引き出しパターン長は5mmくらいです。パッケージの根本で止めて余計なアンテナを付けなければ大丈夫なのかもしれません。まあ対策しておいた方が良いのは間違いないです。

居酒屋ガレージ日記さんは未使用ピンはLOW出力にされてますが、これって出来るだけインピーダンスを下げとこう、という狙いもあるのでしょうか。

投稿: ラジオペンチ | 2020年4月27日 (月) 18時28分

LOW出力での固定、特に意識はしていません。
空きポート、L出力にしているのは「処理タイミングのチェックでHパルスを出す」ということとも関係あるといえばあるかなぁっというところ。

投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年4月28日 (火) 21時53分

ラジオペンチさんによる実測 #1
http://radiopench.blog96.fc2.com/blog-entry-999.html

投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年4月29日 (水) 22時13分

ラジオペンチさんによる実測 #2
・Arduino よもやま話-15 (未使用ピンの電圧変化の観察)
http://radiopench.blog96.fc2.com/blog-entry-1000.html

以下、私の追実験。
・Arduino 放置したポートが及ぼす電源電流変化
http://igarage.cocolog-nifty.com/blog/2020/05/post-441cf8.html

・Arduino ポートの初期化と通信設定
http://igarage.cocolog-nifty.com/blog/2020/05/post-463930.html

投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年5月 3日 (日) 13時18分

コメントを書く



(ウェブ上には掲載しません)




« Arduino-UNO + SDカードでシリアルデータロガー 完成形 | トップページ | どなたかいりませんか? まずは抵抗→コンデンサ→IC »