Write and Run

it's a simple way, but the only way.

ATmega328Pを内部発振でArduino化して便利に使う

最近 AVR(ATmega328P)でいろいろ作ってたので、そのときに学んだことをまとめておきます。

ATmega328Pを内部発振で動かせば水晶発振子は必要はありませんし、Arduino化すれば、Arduino IDE やそのライブラリが使えるのでとっても便利です。

ひつようなもの

  • ATmega328P
    • 秋月で売ってる。250円。たくさん買おう。
  • AVR ISP mkII
    • 秋月で売ってる。2千円くらいかな。
  • 適当な基盤とかブレッドードとか
  • (あると便利)USB から5V 取り出すケーブル
    • 自作しましょう
  • パソコン
    • 今回は MBA。Win/Linux/Mac なんでもいいと思う
  • avrdude
    • コマンドラインの AVR 書き込みプログラム
    • Mac なら brew でインストールできる気がする

準備

1

ATmega328P を基盤なりブレッドボードなりに実装。ISP 端子も実装しましょう。んで電源を接続する。(後述する AVR ISPmkII は 5V を供給してくれない)

2

AVR ISP mkII を接続。このとき、USB から 5V 取れると便利。

3

avrdude コマンドでヒューズビットを書き込む。コマンドはこんな感じで。

avrdude -p m328p -c avrispmkII -b 115200 -P usb -U lfuse:w:0xE2:m -U hfuse:w:0xDA:m -U efuse:w:0x05:m

ここまでで、ハードウェアの方の準備はおわり。このあとはソフトウェア側の準備。

4

Arduino のプロファイル(?)を書き換える。Mac なら /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/boards.txt を書き換える(他の OS は知らない)。以下の行を良い感じの場所に挿入。

##############################################################

avr_int8.name=Arduino Internal 8MHz
avr_int8.upload.protocol=arduino
avr_int8.upload.maximum_size=32256
avr_int8.upload.speed=57600
avr_int8.bootloader.low_fuses=0xe2
avr_int8.bootloader.high_fuses=0xde
avr_int8.bootloader.extended_fuses=0x05
avr_int8.bootloader.path=optiboot
avr_int8.bootloader.file=optiboot_atmega328.hex
avr_int8.bootloader.unlock_bits=0x3F
avr_int8.bootloader.lock_bits=0x0F
avr_int8.build.mcu=atmega328p
avr_int8.build.f_cpu=8000000L
avr_int8.build.core=arduino
avr_int8.build.variant=int_8

5

ピンのマッピングを書き換える。内部発振にすることでクリスタル用のピンも I/O に使えるようになるので、使えるようにする。

/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/variants/standard をコピーして /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/variants/int_8 とし、その中にある pins_arduino.h を書き換える。132行目からをこんな感じに置き換える。

const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
	PD, /* 0 */
	PD,
	PD,
	PD,
	PD,
	PD,
	PD,
	PD,
	PB, /* 8 */
	PB,
	PB,
	PB,
	PB,
	PB,
	PC, /* 14 */
	PC,
	PC,
	PC,
	PC,
	PC,
	PB, /* 20  - PB6*/
	PB, /* 21  - PB7*/
};

const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
	_BV(0), /* 0, port D */
	_BV(1),
	_BV(2),
	_BV(3),
	_BV(4),
	_BV(5),
	_BV(6),
	_BV(7),
	_BV(0), /* 8, port B */
	_BV(1),
	_BV(2),
	_BV(3),
	_BV(4),
	_BV(5),
	_BV(0), /* 14, port C */
	_BV(1),
	_BV(2),
	_BV(3),
	_BV(4),
	_BV(5),
	_BV(6), /* 20 - PB6 */
	_BV(7), /* 21 - PB7 */
};

これでデジタルピンに20と21が増えました。

プログラムを流し込む

あとはプログラムを流しこむだけです。適当に Blink とかを examples から開いて書き込みましょう。AVR ISP mkII を通して書き込むので、書き込みボタンを押すときは Shift を押しながらです。すると AVR ISP mkII を使って書き込めます。このように書込装置を使う場合、ブートローダは必要ありません。

まとめ

内部発振では動作速度は 8MHz となりますが、delay などが遅くなったりということはありません。boards.txt でクロックを指定しているので分周設定をうまいことやってるんだと思います。あと、内部発振は精度が悪いので通信とか厳しいかなと思ったのですが、I2C や 9600bps のシリアル通信は問題なく動きました。内部発振は CR 発振なので動作温度に依るところがありそうですが、常温だとひとまず平気っぽいです。

これで高いカネ払ってボード買わなくても Arduino の開発環境が使えますし、ライブラリも豊富なので、非常に便利ですね!