1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Arduino からのステップアップとして ATmega 88PA-PU で L チカしよう

1
Last updated at Posted at 2026-08-15

Arduino で電子工作をしている方、最近増えてきたように思います。
思ったものを形にできるって楽しいですよね。しかも 3D プリンタも組み合わせると、より創造性が増します。

今回は Arduino をより深く潜り、Arduino に搭載されていることが多い ATmega というマイコンを直に扱って L チカさせてみましょう。

対象読者

  • Arduino の使い方は完全に理解した方
  • Arduino をより深く知りたい方
  • Arduino の不要な回路を捨て、電池で長期間動かせるようになりたい方

プロの組み込みエンジニアの方は対象外です。
私はしがない Web エンジニアでハードウェアは専門外なので、説明が足りないところもありますが、なにとぞご容赦ください。

用意するもの

ATmega48/88/168/328 系の 28pin DIP を手に入れてください。
秋月電子で買うと安いです。
e.g. ATmega 328P-PU, ATmega 168A-PU, ATmega 88PA-PU

ISP 書き込み用の適当な Arduino ボードも必須です。私は手持ちの Arduino Nano クローンを利用しました。

データシート:https://www.microchip.com/content/dam/mchp/documents/MCU08/ProductDocuments/DataSheets/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061B.pdf

前提知識

今回利用する ATmega のピンアサインはデータシートの P12 にあります。

image.png

全体をざっと読んでください…というのは少し残酷なので、必要な箇所をピックアップします。

電源周り

まず、ピンアサインを見ているとお気づきかもしれませんが、見慣れない AVCC とやらがありますね。
これは何なのかと言うと、データシートの P14 1.1.7 に記載があります。

AVCC is the supply voltage pin for the A/D Converter, PC3:0, and ADC7:6. It should be externally connected to
VCC, even if the ADC is not used. If the ADC is used, it should be connected to VCC through a low-pass filter.
Note that PC6...4 use digital supply voltage, VCC.

これには 1.1.8 および 1.1.9 で説明がある ADC や AREF が関連してきます。

ざっくり ATmega 内部の回路を説明すると、例えば ATmega 88PA であれば

                 ATmega88PA

 VCC ─────────┬── CPU
              ├── SRAM / Flash
              ├── Timer
              ├── PORT B / D
              └── 一部 PORT C

 AVCC ────────┬── ADC 本体
              │    ├─ Analog MUX
              │    ├─ Sample & Hold
              │    └─ A/D Converter
              │
              └── PC3:0 周辺の I/O 回路

 AREF ─────────── ADC の基準電圧

という感じです。

ADC ってなんだよという方に説明ですが、Analog-to-Digital Converter の略です。
アナログの電圧を例えば 8bit の分解能であれば 0-255、今回の ATmega88PA に搭載されている 10 bit ADC なら基本的に 0~1023 の値として扱えます。

要するにいつも使っているような VCC とは別で AVCC というのは ADC 周りの機能を動かすための別の電源ピンです。
Arduino では意識せず ADC を使っていた方も多いかも知れませんが、実は内部では回路が分かれていて、しかも ADC 用の電源ピンが存在していた、ということですね。
さらに PC3:0 の電源にもなっていると記載があります。PC0 PC1 PC2 PC3 を使いたい場合は AVCC への電源供給が必須です。

なお ADC7:6 つまり ADC7 ピンと ADC6 ピンは 28pin の今回の ATmega には存在しません。データシートにも記載があるはずなので、気になる方は読んでみてください。
ADC7:6 に関しては一旦無視して OK です。

要するに、我々が従来使っていた Arduino Nano のように全部のピンを自由に使うのであれば、VCC から AVCC に給電してあげなければなりません。
さらにノイズなどを抑えて ADC を利用するためにもローパスフィルタを噛ませることが推奨されています。

将来的に ADC をちゃんと使いたいのであれば、P249 にあるとおり
image.png
のように、10μH のコイルと 100nF (0.1μF)のコンデンサを用意してあげるべきでしょう。

とはいえ今回は L チカです。ADC なんて使いませんし、精度も要りません。一旦忘れて以下のような回路にしましょう。

              ATmega88PA
電源 ───────── VCC
 │             │
 │           0.1 µF
 │             │
 │            GND
 │
 └─────────── AVCC
               │
             0.1 µF
               │
              GND
              
AREF ───────── NC(何も繋がない)

これなら今回の用途では最低限問題なく使えます。
0.1 µF のコンデンサはそれぞれ VCC / AVCC ピンのできるだけ近くに配置します。
それと、今回は電解コンデンサではなくセラミックコンデンサを使いましょう。
0.1 µF 程度の小容量ならセラミックコンデンサのほうが一般的ですし、電解コンデンサと比べて高周波特性にも優れています。
マイコンのデカップリングコンデンサとしても教科書的です。

AREF については…… ADC を使わないので今回は忘れましょう。何にもつなぎません。
ADC を使いたくなったらデータシートを LLM にでも見せて、やり方を聞いてみると良いと思います。

それと、大事なことですが、8と22の GND ピンはどちらも GND に落としましょう。
絶対に忘れないでくださいね! 絶対ですよ!

書き込み周り

Arduino では、コンパイルしたプログラムの書き込みは USB ポートに挿しておけば何も考える必要はありませんでした。
しかし残念ながら ATmega 28pin のマイコンには USB ポートは(当たり前ですが)ついていません。

そこで重要なのが以下のピンです

  • PB3 / MOSI
  • PB4 / MISO
  • PB5 / SCK
  • PC6 / RESET

今回は ISP という方法で書き込みますが、 PB5:3 は非常に重要な PIN です。
PC6 は RESET ピンなので、再起動などでも使えますが、今回の ISP 書き込みでも使います。
この辺りは大事なのでデータシートをしっかり見ていきましょう。

1. PC6 / RESET

1.1.5 に色々書いてありますが、ざっくり

  • RSTDISBL fuse が未設定なら RESET
  • RSTDISBL fuse を設定すると PC6 という GPIO
  • RESET が一定時間 Low になるとリセット
  • クロックが動いていなくてもリセットされる

という感じです。
工場出荷状態では RSTDISBL = 1 (unprogrammed) なので、標準では RESET ピンとして機能するはずです。
RESET は active-low として機能します。これは 1.1.5 に

PC6 is used as a Reset input. A low level on this pin for longer than
the minimum pulse length will generate a Reset, even if the clock is not running.

と記載があります。
要するに、一定期間 PC6 が LOW に落ちたら RESET がかかるというわけです。

内部にプルアップ抵抗が入っていますが、こちらの方でもプルアップしておくのが無難でしょう。製造元もそう言っているので、そうします。(再度ですが、気になる方は調べてみてください案件です)

よって PC6 まわりはこんな感じになります。

VCC
 │
10 kΩ
 │
 ├──── RESET (PC6)
 │
 └─ 必要ならリセットボタン ── GND

2. PB3 / MOSI、PB4 / MISO、PB5 / SCK

書き込みに使います。めちゃ大事です。

データシート P303~304 の 28.8 Serial Programming を見ると、ISP programming の接続は

image.png

つまり

  • MOSI = PB3 = Serial Data In
  • MISO = PB4 = Serial Data Out
  • SCK = PB5 = Serial Clock

となっています。

これに先程の RESET と、おなじみの VCC、GND を足すと

Programmer                   ATmega88PA

MOSI  ────────────────────── PB3 / pin 17
MISO  ────────────────────── PB4 / pin 18
SCK   ────────────────────── PB5 / pin 19
RESET ────────────────────── RESET / pin 1
VCC   ────────────────────── VCC
GND   ────────────────────── GND

となります。これで ISP 書き込みができます。
(Programmer については後述しますが、一旦今は書き込み機だと思っておいてください)

ちなみになぜ RESET ピンを組み合わせるのかです。
我々は PB5:3 を SPI としても扱うと思います。SPI 接続の周辺機器ってたくさんありますからね。
そうした時に、ISP で書き込みたいなと PB5:3 を接続しても、ATmega は「こいつは SPI 接続したいのか? Flash に書き込みたがっている気もする、どっちだ?」と混乱します。

そこで ISP Programmer が RESET を LOW にして書き込みモードにしてくれます。
その辺りの細かい話はデータシートの 28.8.2 Serial Programming Algorithm に書いてあります。
興味がある方は LLM と一緒にでも解読してみてください。

おまけ. PB6 / XTAL1、 PB7 / XTAL2

データシート P36 から System Clock and Clock Options が始まります。
P37 の 9.2 Clock Sources を見ると、ATmega88PA はかなり色々なクロック源を選べることがわかりますね。

image.png

どれを使うかは CKSEL fuse で決めることが出来ますが、この度々出てくる fuse というのは、マイコン内部の不揮発の環境変数みたいなものです。

そしてすぐ下の 9.2.1 Default Clock Source に記載のある内容が今回とても重要です。

Default Clock Source
The device is shipped with internal RC oscillator at 8.0MHz and with the fuse CKDIV8 programmed, resulting in
1.0MHz system clock. The startup time is set to maximum and time-out period enabled. (CKSEL = "0010", SUT
= "10", CKDIV8 = "0"). The default setting ensures that all users can make their desired clock source setting
using any available programming interface.

書いてあるとおり、工場出荷時は 1.0MHz です。
外部の発振器無しでそのままマイコンを利用できるのは便利ですね。

では Arduino Nano などの 16MHz などは何だったのかと言うと、ボードに発振器がついています。
下の画像で言うところの、マイコンの右上の銀色の長方形のヤツです。

image.png

これが ATmega328P の発振回路で 16 MHz のクロックを作るために使われています。
生の ATmega を利用することで、我々はついにこの部分を自由に選べるようになった、ということでもあります。

ちなみにシートにもある通り

The device is shipped with internal RC oscillator at 8.0MHz and with the fuse CKDIV8 programmed

なので、 CKDIV8 fuse を無効にしてやると、内蔵発振器をそのまま 8 MHz で利用できます。

ちなみに fuse を書き換えずとも、プログラム側から動作周波数の分周を変更することが出来ます。
これは 9.11 System Clock Prescaler あたりに以下のように書いてあります。

To avoid unintentional changes of clock frequency, a special write procedure must be followed to change the
CLKPS bits:

  1. Write the Clock Prescaler Change Enable (CLKPCE) bit to one and all other bits in CLKPR to zero.
  2. Within four cycles, write the desired value to CLKPS while writing a zero to CLKPCE.

Interrupts must be disabled when changing prescaler setting to make sure the write procedure is not interrupted.

要するに、ほぼそのまま訳しただけですが

  1. CLKPCE を 1 にし、CLKPR の他の bit をすべて 0 にする
  2. 4 cycle 以内に、CLKPCE を 0 にしつつ目的の CLKPS を書く

ということです。

CLKPR の構造はデータシートにある通り

Bit 7 6 5 4 3 2 1 0
Name CLKPCE Reserved Reserved Reserved CLKPS3 CLKPS2 CLKPS1 CLKPS0

です。

なので

#include <avr/io.h>
#include <avr/interrupt.h>

// 起動後に分周比を ÷1 にする(8MHz 動作)
uint8_t sreg = SREG;
cli();
CLKPR = (1 << CLKPCE);
CLKPR = 0;
SREG = sreg;

のようにすると起動後にクロックを 8MHz にすることが出来ます。
以下のように組み込みのマクロを使うのもありです。

#include <avr/power.h>

clock_prescale_set(clock_div_1);  // 手続きと割り込み禁止を内部でやってくれる
CLKPS3:0 分周比 8 MHz なら
0000 ÷1 8 MHz
0001 ÷2 4 MHz
0010 ÷4 2 MHz
0011 ÷8 1 MHz
0100 ÷16 0.5 MHz
0101 ÷32 250 kHz
0110 ÷64 125 kHz
0111 ÷128 62.5 kHz
1000 ÷256 31.25 kHz
10011111 Reserved 使用しない

なので、全部 0 にすると 8MHz になる、というわけです。

とはいえ今回は L チカです。そんな高周波数は要りません。
一旦デフォルトのままでいくとしましょう。

ただし注意点があります。Arduino IDE の delay() や millis()、Serial のボーレート計算は、コンパイル時に決まる F_CPU という定数を基準にしています。
これはボードメニューで選んだクロック設定から決まる値で、実行時に CLKPR を書き換えても変わりません。

つまり F_CPU = 1000000 のままこのコードで 8MHz にすると、delay(500) は 1/8 され、実際には 62.5ms になります。

単にクロックを上げたいなら、CKDIV8 fuse を書き換える(MiniCore なら Tools でクロックを選んで Burn Bootloader を押す)ほうが楽です。
CLKPR は「普段は低速で回して、必要なときだけ上げる」などといった動的な省電力制御をしたい場面に効果的かも知れません。

今回の回路

前提知識のまとめのようなものになりますが、以下です。

PC6 / RESET (pin 1) ── 10 kΩ ── VCC

VCC          (pin 7) ────────── +5 V
                         │
                       0.1 µF
                         │
                        GND

GND          (pin 8) ────────── GND

PB6 / XTAL1  (pin 9) ────────── NC
PB7 / XTAL2 (pin 10) ────────── NC

PB0         (pin 14) ── 抵抗 ── LED ── GND

PB3 / MOSI  (pin 17) ────────── Programmer MOSI
PB4 / MISO  (pin 18) ────────── Programmer MISO
PB5 / SCK   (pin 19) ────────── Programmer SCK

AVCC        (pin 20) ────────── +5 V
                         │
                       0.1 µF
                         │
                        GND

AREF        (pin 21) ────────── NC
GND         (pin 22) ────────── GND

PB3 ってどこだっけ……となりがちなので、画像をもう一度貼っておきます

image.png

L チカには PB0 を使います。
また、今回は +5V としていますが、これは PC の USB バスをそのまま使うためです。
実際は ATmega 88PA-PU であれば 1.8V - 5.5V で動作するので、例えば CR123A のような電池を利用することも出来ます。
実際に組み込む場合の電圧は、必要なクロック周波数と、繋ぐ予定の周辺機器に合わせるのが良さそうです。

そうして出来上がったものはこれです。
たいへん汚くて申し訳なす……(しかも配線を一つずらして間違っているので、参考にしないでください)
image.png

  • 黒: GND
  • 赤: VCC +5V
  • 緑: RESET
  • 白: SCK
  • 橙: MISO
  • 青: MOSI

という感じです。

書き込み

書き込みには手元の Arduino ボードを使います。

Arduino IDE から Examples > ArduinoISP > ArduinoISP を開いて、任意のボードにフラッシュしてください。

これが、先程ずっと出てきていた ISP Programmer の役割を果たしてくれます。

私の場合は以下の結線です

ATmega88PA 側 Arduino Nano 側
GND GND
VCC / AVCC 5V
RESET / PC6 D10
SCK / PB5 D13 / SCK
MISO / PB4 D12 / MISO
MOSI / PB3 D11 / MOSI

このようになりました。

image.png

そして、この avrdude を導入し、PC -> USB -> Arduino ISP -> ATmega 88PA-PU をきちんと認識できているかを調べます。

私は mac かつ面倒なので

% brew install avrdude
% avrdude --version
Avrdude version 8.2
Copyright see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
Use https://github.com/avrdudes/avrdude/issues to report bugs and ask questions

としました。

私の環境では Arduino Nano は /dev/cu.usbserial-1130 です。
なので

avrdude \
  -p m88pa \
  -c stk500v1 \
  -P /dev/cu.usbserial-1130 \
  -b 19200 \
  -v

とします。
この辺りの細かなコマンドはドキュメントを読んでもらうのが一番良いかと思います。
このあたりも参考になるかも知れません: https://github.com/arduino/ArduinoCore-avr/blob/11b9130371e8447920edb65a75706a6c951e51fc/programmers.txt

結果は以下です

% avrdude \
  -p m88pa \
  -c stk500v1 \
  -P /dev/cu.usbserial-1130 \
  -b 19200 \
  -v
Avrdude version 8.2
Copyright see https://github.com/avrdudes/avrdude/blob/main/AUTHORS

System wide configuration file is /opt/homebrew/etc/avrdude.conf
User configuration file /Users/****/.avrduderc does not exist

Using port            : /dev/cu.usbserial-1130
Using programmer      : stk500v1
Setting baud rate     : 19200
AVR part              : ATmega88PA
Programming modes     : SPM, ISP, HVPP, debugWIRE
Programmer type       : STK500
Description           : Atmel STK500 v1
HW Version            : 2
FW Version            : 1.18
Topcard               : Unknown
Vtarget               : 0.0 V
Varef                 : 0.0 V
Oscillator            : Off
SCK period            : 0.0 us
XTAL frequency        : 7.372800 MHz

AVR device initialized and ready to accept instructions
Device signature = 1E 93 0F (ATmega88P, ATmega88PA, LGT8F88P)

Avrdude done.  Thank you.

成功です。 Device signature = 1E 93 0F の署名が確認できました。

正常に認識されていることも分かったので、これで書き込み準備ができました。

このまま avrdude を利用して書き込みを行う方法でもよいのですが、我々は Arduino ユーザなので、今回は素直に ArduinoIDE から書き込みましょう。

ArduinoIDE > Preferences で Additional boards manager URLs に https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json を追加し、MiniCore をインストールします。

設定はこのようにしてください

image.png

そして通常の Upload ではなく Upload Using Programmer を利用します。

スケッチは以下です

#define LED_PIN 8 // MiniCore の Standard pinout では D8 = PB0(物理 14 番ピン)

void setup() {
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_PIN, HIGH);
  delay(500);

  digitalWrite(LED_PIN, LOW);
  delay(500);
}

すると……

out2.gif

やりましたね! これで今日からあなたも生の AVR ユーザです。

さいごに

ここまで読んでくださり、ありがとうございました。

ATmega 88PA-PU ではまだ大きい! という人はもっと小さなものにチャレンジしてみても良いと思いますし、Arduino IDE を使わずに直に使いたいんだ! という方は avr-gcc あたりを導入して自分でコンパイルから書き込みまでを ArduinoIDE に頼らずやってみても良いかも知れません。

今回のように直に AVR を使うと Arduino ボード上の電圧レギュレータや USB-serial IC、電源 LED などの消費を省けるため、省電力化もしやすくなります。
さらにはクロックや sleep などを詰めれば、電池駆動時間をかなり伸ばせます。

例えば ATmega には Power-down mode があり、CPU や多くの周辺回路を停止したまま、Watchdog や外部割り込みなどだけを残して待機できます。
例えばおおよそ1時間に一度センサーを読んで何かをするだけといった機器なら、処理時間の大半を Power-down にできます。

AVR はこのように様々な機能があり、しかも今回やったとおり、簡単に ArduinoIDE から利用できます。

なにか面白いものを作ったら、ぜひ教えてください!

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?