« LED点灯 ほったらかし実験 | トップページ | ほったらかしにならなかったLED点灯実験 »

2019年4月15日 (月)

Arduino PB5(デジタル入出力D13)に注意を

2019年3月22日:Arduinoのアナログ基準電圧入力の絡みで、Arduinoのブートローダーを眺めていて注意というか覚え書きをちょいとまとめておきます。

●PB5ポート
ATmega328の19番ピン。
Arduinoでいうところのデジタル入出力「D13」ポート。
SPI(Serial Peripheral Interface)での「SCK」。

●タイマー1
16bitタイマー

この2点、Arduinoのブートローダーで使われていますので、競合に注意が必要です。
タイマー1に関しては、オーバーフローをチェックしているだけで割り込みなどは使っていませんし、ユーザープログラムはリセット起動しますので問題は発生しません。
ブートローダー内でRUNしているという認識だけで良いかと。

※この他にも、TXD、RXDの通信ポート、ウォッチドッグタイマーが使われます。

ここで問題なのがPB5ポート
Arduinoのサンプルプログラムで基板に乗ったLEDを点滅させるのがこのポートです。

PB5ポート、ブートローダー起動で出力ポートに設定されます。
そして、起動確認のためにパルスを出力してLEDを点滅します。
つまり、ユーザープログラムが走る前に「出力ポート」に設定されて、なおかつ「H/L」のパルスが出力されるのです。
その後、ユーザープログラムに切り替わるといったんリセットされ、入力ポートになってからsetupが実行されます。
この起動待ちのおよそ1.5秒、「PB5は出力ポートになる」ということを記憶にとどめておいてください。
  ※これ、ネットを探しても注意書きが見つかりません。

具体的にどんなかオシロで見てみました。
入力と出力、そして内蔵プルアップ状態を見るため、PB5に47kΩの抵抗を2本つなぎ、それぞれ+5VとGNDにつなぎます。
すると・・・
  ・出力ポートなら0Vあるいは5Vに張り付く。
  ・入力ポートなら0V・5Vの中間レベル、2.5Vに。
  ・入力で内蔵プルアップ有りならHレベルが
   少し持ち上がり3Vくらいに。
これでPB5の状態を確認できます。

こんなスケッチを書き込みます。

void setup() { // デジタル13番ピン=PB5を
 pinMode(13, INPUT_PULLUP); // pullup有りの入力に
}

void loop() { // なにもしない
}

結果、こんな波形が観測されます。

Ard21

リセットスイッチ押し下げで、
(1)リセット状態なので中間レベル。
(2)ブートローダー開始で出力ポートになり
  H/Lのパルスを出力(LED点滅)。
    ※単発でHになるArduino UNOもありました
(3)LレベルのままPCからの通信待ち。
(4)通信無しが続くとリセットしてユーザー
  プログラム起動。
  いったん入力モードに。 中間レベルの2.5V。
(5)ユーザープログラムのsetupが走り始めて内蔵
  プルアップ有効で3Vほどに。

この(2)と(3)区間が問題なのです。
(a)PB5を出力として使った場合
  ブートローダー起動中に不要なパルスがユーザー回路
  に加わる。
  これが問題なければ気にする必要はないが、何かの
  出力を直接制御していると具合が悪いことがある。
    (リレーを駆動しているとか)

(b)PB5を入力として使った場合
  入力信号とPB5が衝突する。
  ユーザープログラムが走り始めれば問題ないが、
  ブートローダー起動中、PB5は出力になるのでこの期間、
  信号衝突の危険性がある。

(c)PB5=入力で、GNDに引っ張るスイッチやオープンコレクタ信号
  この場合も、Hパルスが出る区間(2)があるのでだめ。
  PB5がHの時、スイッチがオンしていたりOC信号が
  L駆動だったら短絡発生の可能性。

・対策方法:
<1> PB5は入出力として使わない。
    逃げの一手で!

<2>出力として使いたい時は、不要パルスが加わっても
  大丈夫な出力で使う。
   例:LED表示用出力やLCDのデータ線、7seg LEDの駆動出力
    ピピちゃん温度計     LCDのD7ライン
    バレーボール用得点表示器  7seg LED駆動出力

<3> どうしても入力として使いたいときは、衝突による
  大電流を避けるため1kΩ程度の抵抗を直列に挿入し
  ておく。
  すると、5V-0V間の衝突でも5mA程度の電流に押さえられる。
  内蔵プルアップを有効にした場合でも、十分ローレベル
  に引っ張れる。
    (内蔵プルアップ抵抗は20~50kΩ)

具体的には、
・ナダ電子製「プリンタシールド」応用例 Arduino UNOでチャートレコーダを実現

ここで紹介している回路の「PB5」を見てください。
スイッチにつないでいるんで、起動時にオンしている(GNDに落ちる)とPB5が短絡してしまいます。
それを防ぐため1kΩの抵抗を直列に入れています。


※ブートローダーに関連するファイル

■pin_defs.h
/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB5

■optiboot.c
#if LED_START_FLASHES > 0
// Set up Timer 1 for timeout counter
TCCR1B = _BV(CS12) | _BV(CS10); // div 1024  ←タイマー1起動
#endif

/* Set LED pin as output */
LED_DDR |= _BV(LED);  ←PB5を出力ポートに

#if LED_START_FLASHES > 0
void flash_led(uint8_t count) {  ←LED点滅処理
do {
TCNT1 = -(F_CPU/(1024*16));
TIFR1 = _BV(TOV1);
while(!(TIFR1 & _BV(TOV1)));
#ifdef __AVR_ATmega8__
LED_PORT ^= _BV(LED);
#else
LED_PIN |= _BV(LED);
#endif
watchdogReset();
} while (--count);
}
#endif


※ブートローダーからユーザープログラムの実行
ユーザープログラムの実行はウオッチドッグタイマーでリセットさせているようです。
MCUSRを見て、「通常リセットならブートローダーの処理へ」、「通常リセット以外はユーザープログラムを実行」という処理が入っています。
だもんで、ユーザープログラムはリセット状態からの実行になり、マイコン内のレジスタはリセット状態に初期化されます。
ブートローダーで使っているタイマー1は無視できますが、PB5は外に現れる現象ですんで無視できません。



|

« LED点灯 ほったらかし実験 | トップページ | ほったらかしにならなかったLED点灯実験 »

トラブル遭遇」カテゴリの記事

電子工作」カテゴリの記事

Arduino」カテゴリの記事

コメント

詳しい実験で、すっきりしました。
私も、このあたりもやもやして、
その際は、基板上のLEDのラインを切断したような記憶があります。
かなり、あぶないことなんですよね。

投稿: きゅうる村 | 2019年4月20日 (土) 14時17分

きゅうる村さん、お願いがあります。
何かの折・・・このPB5(D13)ポートへの注意が記されているサイトを見つけられたら、ここにコメントしていただけませんでしょうか。
このポートに対するブートローダの挙動、ユーザープログラムにおける操作上の注意を説明した場所を今もって発掘できていません。
どうぞよろしくです。

投稿: 居酒屋ガレージ店主(JH3DBO) | 2019年4月20日 (土) 22時57分

コメントを書く



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




« LED点灯 ほったらかし実験 | トップページ | ほったらかしにならなかったLED点灯実験 »