背景
atmega328pbとは、Arduino Unoなどに利用されるatmega328pというマイコンの後継機です。atmega328pよりも低価格で低消費電力ながら使えるピンの数が増えています。
atmega328pbで増えたピンをどう呼び出せば使えるか気になったので、調べて使ってみました。
備忘録を兼ねて取り組んだ内容を記事として共有します。
今回検証するピン: PORTE0〜PORTE3
atmega328pのデータシートのピン配列はこちらです。それに対してatmega328pbのデータシートのピン配列はこちらです。
赤字で示した部分、新しく追加されたPORTEのピンを利用してみます。
atmega328p -> atmega328p
GND -> PE0
VCC -> PE1
ADC6 -> PE2
ADC7 -> PE3
使ったもの
- PlatformIOをインストールしたPC
atmega328pb向けのプログラムをビルドしてライターに送信します。 - AVRライター
PCから送られてくるファームウェアをatmega328pbに書き込むための装置です。
今回はProMicroにArduino as ISP書き込んだものを利用します。 - atmega328pbを実装した基板
今回は自作したものを使っています。
atmega328pbが載った商品としては、発振子付きのボードがスイッチサイエンスで売られています。 - ブレッドボード、はんだごて、はんだ、信号線、LED、抵抗、ホットメルト
信号線を引き出して動作確認するのに使いました。
把握しているatmega328pb取扱時の注意点
atmega328pとは異なりフルスイングオシレーターが載っていないので、外部の振動子を利用する場合は水晶振動子ではなく発振子が必要
atmega328pbはプログラムは後位互換を保っていますが回路的にはこの変更があるため、外部の水晶振動子を利用する用途での置き換えは外部発振子を利用する回路に変更するなどの対応が必要です。(ネットに水晶振動子で動いたという記事があったりしますが、自分が以前試した水晶振動子では駆動できませんでした。)
fuseのhighとexternalはatmega328pと異なる
atmega328pbのデータシートとatmega328pのデータシートを比べると、external fuseの3bitでクロックの失敗検知機能の有無を設定できるようになり、high fuseの0-2bitは設定項目が「BOOTSZ」から「BODLEVEL」に変わっています。(BODLEVELはexternal fuseにもあるのにhigh fuseにも追加された意図を自分はまだ読み取れていません。)今回内部発振子の周波数設定に扱うlow fuseは同じなので、highとexternalのfuseは工場出荷時の設定で利用します。
なお、外部に発振子を付けてない状態でヒューズを外部発振子利用モードに書き換えるとマイコンが動かなくなるので、書き込み時に設定できるヒューズの設定には注意が必要です。
プログラムの書き込み環境
回路
Arduino as ISPとして動かしているProMicroからプログラムの書き込み信号と給電を行い、ブレッドボード上のLEDで動作確認を行う回路です。この回路では、ISPの信号線に繋がっているバネ付きピンを基板のISPパッドに押し付けることでプログラムを書き込みます。
(量産時の書き込みを楽にするための工夫です。)
各ピンを引き出しているパッドに線をはんだ付けして信号を引き出します。
はんだ付けしていても細い線は容易に剥がれるので、ホットメルトなどで取れないように補強することをお勧めします。
信号線はブレッドボードに引き出し、電位が高くなったらLEDが光るようにLEDと抵抗を接続しておきます。
また、GNDとVCCも引き出し、ProMicroからの給電を受けます。
PlatformIOの設定
PlatformIOでatmega328pb向けの環境を検索すると、「ATmega328PB」と「elektor_uno_r4」の2つのボード設定が見つかりました。$ pio boards | grep 328PB ATmega328PB ATMEGA328PB 16MHz 31.50KB 2KB ATmega328PB elektor_uno_r4 ATMEGA328PB 16MHz 31.50KB 2KB Elektor Uno R4
前者はMiniCoreというボード情報を、後者はElektorLabsのボード情報を利用しています。
前者は15日前に更新があり開発が進んでいるようですが、後者は3年前(2017年)のコミットを最後に開発が止まっていて、後者のWireライブラリを試そうとするとコンパイルエラーが出たり不安定な印象なので、この記事では前者のMiniCoreが提供するAtmega328PBを利用します。
Arduino as ISPでatmega328pbにプログラムを書き込むために、platormino.iniを下記の設定にしました。
(platformio.iniでは、行の「;」以後はコメントです。)
platformio.ini
[env:ATmega328PB] platform = atmelavr board = ATmega328PB framework = arduino board_build.f_cpu = 8000000L upload_protocol = stk500v1 upload_port = /dev/ttyACM0 upload_speed = 19200 upload_flags = -b$UPLOAD_SPEED -P$UPLOAD_PORT ; use internal 8MHz and not divide it by 8 -Ulfuse:w:0xE2:m
Arduino as ISPを書き込んだArduinoが認識されるポートはPCによって異なると思うので、環境に合わせて変更してください。
upload_port = /dev/ttyACM0
ATmega328PBもelektor_uno_r4も16MHz駆動が標準なので、board_build.f_cpuで駆動周波数を8MHzに変更しています。
board_build.f_cpu = 8000000L
low huseを内部クロックを利用して8MHzで動く設定にします。
; use internal 8MHz and not divide it by 8 -Ulfuse:w:0xE2:m
上記の設定でプロジェクトのフォルダに移動し、Arduino as ISPの書き込みピンをatmega328pbに接続した状態で下記のコマンドを入力すると、プログラムを書き込めます。
pio run -t program
ポートレジスタで操作
「ATMega328PB」にはPORTEの定義が追加されているため、ポートレジスタを操作する下記のプログラムで、PORTE0-3の電位を変化せられました。
src/main.cpp
#include <Arduino.h> void setup() { DDRE = 0b1111; } void loop() { PORTE = 0b0000; delay(1000); PORTE = 0b0001; delay(1000); PORTE = 0b0010; delay(1000); PORTE = 0b0100; delay(1000); PORTE = 0b1000; delay(1000); }
LEDを順番に点灯できました。
digitalWriteで制御
MinCoreのピン設定を見てみると、PORTE0〜3が23〜26で定義されていました。ということで、23〜26番ピンを制御するプログラムを作成して書き込みました。
src/main.cpp
#include <Arduino.h> void setup() { pinMode(23, OUTPUT); pinMode(24, OUTPUT); pinMode(25, OUTPUT); // A6 pinMode(26, OUTPUT); // A7 } void loop() { digitalWrite(23, LOW); digitalWrite(24, LOW); digitalWrite(25, LOW); digitalWrite(26, LOW); delay(1000); digitalWrite(23, HIGH); delay(1000); digitalWrite(23, LOW); digitalWrite(24, HIGH); delay(1000); digitalWrite(24, LOW); digitalWrite(25, HIGH); delay(1000); digitalWrite(25, LOW); digitalWrite(26, HIGH); delay(1000); }
digitalWriteを利用してもLEDを順番に点灯できました。
(表示しているgifは先ほどのものと一緒です。)
ちなみに、23〜26はPWM出力に対応していないようなので、analogWriteによるPWMの出力は試していません。
まとめ
PlatformIOでATMega328PBをボードとして利用することで、atmega328pbに追加されたPORTEを利用してLEDを点滅できました。atmega328pに比べて制御可能なピンが4ピン増えたので、atmega328pではギリギリピンの数が足りなくて諦めたものがatmega328pbなら作れるかもしれません。
この後、PORTE0とPORTE1で使える2つ目のI2Cポートを使ってみました。
良ければこちらもご覧ください。
atmega328pbのI2Cポート2つを使ってみた
変更履歴
2020.05.10 atmega328pbのI2Cポートを利用した記事のリンクをまとめに追加しました。2020.05.30 A6とA7の定義に関するMiniCoreの不具合は、miniCoreが更新されたことにより解消されたので、それに関する注意の記述を削除しました。
0 件のコメント :
コメントを投稿