【Arduino】Nano Every Atmega4808を使う

it

Microchip のAtmega4808搭載基板Nano Every Atmega4808を使ってみます。
Atmega328p搭載のArduino Nanoとの互換性と性能差に着目しながら比較します。

Nano Every Atmega4808

簡単紹介

Nano Every Atmega4808について : 外部サイト

◆入手

amazonなどで購入できます。
国内では\1,500~\1,700(送料込み)が目安になると思います。
今回Ali Expressで\870(送料込み)で入手しました。

◆梱包

ピンヘッダ一緒にケースに入っていました。
輸送破損の心配は低そうです。

◆関連記事

ピン配置

外観

使ってみた

◆開発環境

Arduino環境で開発しました。
ライブラリはAtmega4808用にボードライブラリ「MegaCoreX by MCUdude」をインストールします。
書き込みをデフォルトで行うと「Request ‘upload’ failed」が表示されて書き込みができないので変更します。
「Pinout:」を 「Nano4808」に変更します

環境についての説明はこちらでします。

◆開発

Arduino環境でのコンパイル時間について測ってみました。
コンパイル実行ボタンを押して、コンパイル終了のメッセージが表示されるまでをストップウォッチを手押しで計測しています。
GPIOの単純Low/High繰り返しのスケッチをコンパイルするのにかかった時間は約3秒です。

手持ちのマイコン基板では「Arduino nano(Atmega328p)」に並び最速です。

開発の作業性について。
printf()が使えます。
シリアル出力などで書式付き出力を使えるので、print()やprintln()を組み合わせて行数の増えるコードを削除できます。

◆CPU性能(繰り返し速度)

クロック設定が20MHzなのでGPIOの高速Low/High時間計測で試してみました。
デフォルト設定が16MHzだったので変更する必要があります。

クロック設定は1MHz~20MHzまで設定できて、デフォルトは16MHzになっています。
図は代表で16MHzと20MHz設定時のモニタ結果です。

各設定での計測時間と周期に変換した結果です。
設定クロックに対してリニアに変化しています。

設定クロック(MHz)Low/High計測時間(ns)周期変換(MHz)
2018600.538
1623200.431
1036800.272
846400.216
574000.135
494200.108
2184000.054
1368000.027


同じ条件(スケッチと、CPUクロック16MHz)で過去に測定したArduino nano 328Pの結果と比較をします。

単純にCPUのスペック値以外にもライブラリの設計で差が出ることもありますが、同CPUクロックでもNano Every Atmega4808の方が約3倍速い結果でした。

Nano Every Atmega4808Arduino nano 328P
Low/High計測時間(ns)23206640

◆I/O出力

GPIOロジックレベルについて測ってみました。
出力電圧の変更ができるようなので、VINへの入力電圧を変更して出力電圧を測りました。
Low/High計測と同じスケッチを使用しています。

試してみたのは3.3V、5Vで、USBからの電源供給も一緒に測りました。
USBからの供給では約4.5Vでしたが、同じ5Vでも少し高めに出力されています。

◆Arduino nano(ATmega328p)との互換性

今回試したライブラリはI2C制御のOLED(SSD1306)とSPI制御のLCD(ST7735)です。
ライブラリの関数個々の使用可否についてはすべて確認していませんが、初期化と表示ができたところで使用できたと判断しています。

Arduino nano(ATmega328p)と比べて専用の記載や修正なく使用できたので互換性はあると判断します。

モジュールライブラリの種類によっては新しいマイコンでは対応できていないものもあるので、今後発見があれば追記しようと思います。

まとめ

Arduino Nano(ATmega328p)と比較を主に使ってみました。

ハードウエア的なピン互換はありませんが、信号レベルやCPUクロックも柔軟性があります。
設定項目が増えるのは複雑になるのであまり好ましく思っていませんが、デフォルトで開発ができるのであまり気にする必要もなさそうです。

ソフトウエア的にはライブラリの互換もあり、機能ピン(UART、I2C、SPI)も固定なのでATmega328pの開発をしているような感覚で作業ができます。
printfが使える点もマルで、Arduino nano328pからの正常進化と感じます。

UARTの使い方に問題があり使いにくい部分があります。
復旧はできますが、UARTを使う前に躊躇いが出てしまいます。
(復旧方法はこちらに記述します。)

クロック以上の処理速度がありコスパ感ありそうですが、価格帯が\1,000付近になると多数使いや組み込み後に回収できない使い方は難しいと感じます。

準備

Arduino環境の作成

◆開発環境

Arduino環境を使用します。
Arduino環境の作成についてはこちらで紹介しています。

◆ボードライブラリ

ボードマネージャのURLの追加は要りません。
「BOARDS MANAGER」から「atmega4808」を検索することでライブラリが見つかります。

ボードマネージャのURL
検索atmega4808
ボードライブラリMegaCoreX by MCUdude
選択するボードMegaCoreX > ATmega4808
※動作確認では1.1.3を使用

◆モジュールライブラリ

I2CのサンプルではSSD1306 OLED、SPIのサンプルではST7735を使用します。
サンプルを使用しない場合はインストール不要です。

SSD1306

OLED(SSD1306)を使用する場合にインストールします。

ライブラリ名検索確認時のバージョン
Adafruit SSD1306 by AdafruitSSD13062.5.11
Adafruit GFX Library by AdafruitGFX1.11.10

LCD(ST7735)

LCD(ST7735)を使用する場合にインストールします。

ライブラリ名検索確認時のバージョン
Adafruit ST7735 and ST7789 Library by AdafruitST77351.10.4
Adafruit GFX Library by AdafruitGFX1.11.10

コンパイルと書き込み

USBからの書き込みとUPDIを使った書き込みを紹介します。
UPDIを使った書き込みでは今のところ任意のスケッチの書き込みができず、USBから書き込みができなくなった時の復旧として使用しました。

◆USB

パラメータを変更します。

Tools -> Pinout: で[Nano 4808]を選択します。
この変更をしないまま書き込みを行うと「Request ‘upload’ failed」メッセージが表示され書き込みされません。

◆UPDI

パラメータの変更、USBシリアル変換モジュールとUPDI書き込み回路を使用します。

手順

1.UPDIから書き込みを行うためのアダプタを作成します。
回路と回路の完成は以下の図です。
抵抗は470Ωを使用しました。

設定

ArduinoIDEのパラメータを変更します。

Pinout: “28 pin standard”
Programmer: “SerialUPDI(115200 baud)”
ボーレートは書き込みができる速度を選択します。

UPDI書き込みアダプタ

ユニバーサル基板でUPDI書き込みアダプタを作ります。

◆材料

USBシリアル変換モジュールを使用します。
完成物はFT232RLを使用したレシピです。

材料、型名補足情報
ユニバーサル基板 2.54mmピッチ6×6ホールにカット済み
ピンヘッダ 2.54mmピッチ6ピン1列(画像は3ピンです)
3ピンで完成できますが、安定させるために6ピンを使用しました。
ピンソケット 2.54mmピッチFT232RLと接続します
抵抗470Ω
ダイオード

◆配線

下図は配線の点線部をユニバーサル基板でモジュール化します。

◆完成形

ブレッドボードで使用した時に安定するためにピンヘッダを6ピンにしました。
使用するのは電源、GND、信号の3ピンです。

書き込み時の様子です。
FT232RLのジャンパスイッチは5V出力側に設定しています。

トラブル

USBからの書き込みができない1

◆症状

ArduinoIDEからのコンパイル&書き込みボタンを押した後、メッセージウインドウに
「Request ‘upload’ failed」 と表示される。

◆対処

ボードライブラリに「ATmega4808」を選択した時のデフォルトパラメータで
「Pinout:”32 pin standard”」 がデフォルトで選択されている場合に発生します。

USBからの書き込みでは 「Nano 4808」に変更します。

※補足
ボードライブラリのバージョンによりパラメータの変更、またはデフォルトパラメータの変更があることで症状が変更することがあります。

記事時点での情報は
使用したボードライブラリ : MegaCoreX by MCUdude
バージョン : 1.1.3

USBからの書き込みができない2

◆症状

UART出力LED(TX)が点灯しっぱなし。
ArduinoIDEでの書き込みを行うとコンパイル後の「Uploading…」メッセージが長く書き込みが終わらない。

◆対処

当サイトで紹介するUPDI書き込み方法では期待動作をするスケッチの書き込みまではできませんが、書き込みができる「復旧」することができます。
作業は2段階あります。

1.UPDIからの書き込みを行い「復旧」させる
2.復旧後にUSBコネクタから目的のスケッチを書きこむ

UPDIの書き込み手順はこちらです。

スケッチ

デジタル出力

説明

GPIOのデジタル出力を使います。
LowとHighを繰り返し、プログラム繰り返し速度の計測をします。

計測にはオシロスコープ(HDS272)を使用し、信号の立ち上がりから次の立ち上がり(または立下りから次の立下り)までの時間を計測します。

このスケッチをコンパイルするのにかかった時間をストップウォッチで計測します。

配線

配線不要
信号をモニタするために、GPIO23とGNDをオシロスコープでプローブします。

スケッチ

#define PIN    (23)

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

void loop()
{
  while(1)
  {
    digitalWrite(PIN, HIGH);
    digitalWrite(PIN, LOW);
  }
}

結果

スケッチのコンパイルにかかった時間は 3秒 でした。

オシロスコープ(HDS272)でGPIOのLow/High時間を計測しました。
クロック設定はデフォルトで16MHzです。

クロック設定を16MHのだと2320ns、クロック設定を20MHzに変更すると1860usになりました。

GPIOデジタル入出力

説明

GPIOのデジタル出力を使います。

LEDは基板実装のユーザLED(GPIO13)を使います。
没端はプルダウン抵抗を使った回路を組み、信号をGPIO23で読み取ります。

スケッチではGPIOの入出力を決定するpinMode()関数のパラメータに「INPUT_PULLUP」が設定できますが、GPIO23で読み取った信号は常にHIGHになるようです。

配線

スケッチ

#define LED_PIN       (13)
#define BUTTON_PIN    (23)

void setup()
{
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);

  while(1)
  {
    bool statButton = digitalRead(BUTTON_PIN);
    digitalWrite(LED_PIN, statButton);    
  }

}

void loop()
{
}

結果

ボタンを押していない間はLEDは点灯しません。
(画像上部の緑の点灯は電源LEDです)
ボタンを押すとユーザLED(赤)が点灯しました。

PWM出力

説明

Nano Every Atmega4808のPWMを使います。
PWM信号出力中の波形をオシロスコープ(HDS272)でモニタし、発振間隔を測ります。

PWMの周期は約2.5秒かけて0%から100%へ、約2.5秒かけて100%から0%へ変化します。

配線

配線不要
信号をモニタするために、GPIO23とGNDをオシロスコープでプローブします。

スケッチ

#define PWM_PIN (23)

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

void loop()
{
  const int16_t wai = 10;
  for(int16_t i = 0; i < 256; i ++)
  {
    analogWrite(PWM_PIN, i);
    delay(wai);
  }

  for(int16_t i = 0; i < 256; i ++)
  {
    analogWrite(PWM_PIN, (255 - i));
    delay(wai);
  }

}

結果

オシロスコープでPWM波形をモニタしました。
同じ周期で、信号のLow幅とHigh幅が変化している様子がわかります。

信号の幅を測定しました。
1.016msで約1kHzの周期です。

アナログ入力(ADC)

説明

Nano Every Atmega4808のADCに0~5Vのアナログ電圧を入力して読み取ります。

アナログ電圧の入力にはDACモジュール(MCP4725)を使います。
DACモジュールをRaspberryPi Picoから制御し、0~5Vを約2秒、5V~0Vを約2秒で出力させます。

Nano Every Atmega4808の電源電圧をUSBからの5V、VINから5Vと3.3Vで動作させたときのADCの読み取り値の変化を観察します。

配線

Nano Every Atmega4808の電源に3.3Vの時はRaspberry Pi Pico の3V3から供給しました(点線箇所)
5Vの時はRaspberry Pi PicoのVBUSから供給しました。

スケッチ

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

void loop()
{
  while(1)
  {
    digitalWrite(2, HIGH);
    digitalWrite(2, LOW);
  }
}

結果

同じスケッチを違う電源電圧で動作を確認しました。
確認した電源電圧は3.3V, USB, 5V。
(USBで動作させたときのロジックレベルは4.5Vでした)

読み取った結果をグラフにしました。
結果は各電源電圧がADC読み取りの最大値になりました。

ADCに入力する最大電圧は5Vです。
ロジックレベルを超える電圧はサチレーションにより1023に張り付きました。
こちらは実際に入力した電圧です。

入力した電圧は約2.5秒で5Vになるので、簡単に計算すると
3.3Vでは約1.65秒でサチレーションします。
USB(4.5V)では2.25秒でサチレーションします。

結果と予測値は概ね合っているようです。

UART

Nano Every Atmega4808のUART

※注意

Nano Every Atmega4808でシリアル通信(Serialオブジェクト)を連続出力するスケッチを書きこむと、スケッチの書き込みができなくなる現象があります。

Nano Every Atmega4808のUARTは3ポート使用できます。
このうち1ポート(UART0)の入出力はUSBシリアルと共通で同じ信号を入出力します。

各UARTポートとオブジェクトの関係

ポート名オブジェクトGPIOピン
USBシリアルSerial
UART0SerialTX(0), RX(1)
UART1Serial1TX(11), RX(12)
UART2Serial2TX(2), RX(3)


説明

Nano Every Atmega4808のUART1とArduino nano 328PのUARTで通信します。

通信相手はArduino nano 328Pです。
Arduino nano 328PのUARTはオウム返しをするスケッチを書きこんでおきます。

Nano Every Atmega4808はUSBシリアルから読み取った電文をUART1(TX)へ送信します。
UART1(RX)から読み取った電文はUSBシリアルへ送信します。

配線

スケッチ

void setup()
{
  Serial.begin(115200);
  Serial1.begin(115200);
}

void loop()
{
  if(Serial.available())
  {
    Serial1.write(Serial.read());
  }

  if(Serial1.available())
  {
    Serial.write(Serial1.read());
  }
}

結果

Teratermから確認しました。
今回Nano Every Atmega4808はCOM18で認識されました。

ローカルエコーはONです。
“tamanegi”と入力すると、1文字ずつ返答があるのでTeraterm上には”ttaammaanneeggii”と表示されました。

I2C(SSD1306)

説明

I2Cを使いOLED(SSD1306)の表示制御をします。

ベースはArduino nano(Atmega328p)で使用したサンプルスケッチをベースに表示文言とコメントを修正したものです。

表示サンプルはAdafruit Exampleを参考にしました。
メニュー > Examples > Adafruit SSD1306 > ssd1306_128x64_i2c

配線

スケッチ

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH      (128)
#define SCREEN_HEIGHT     (64)

#define OLED_RESET        (-1)
#define SCREEN_ADDRESS    (0x3C)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
                                        
void setup()
{  

  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    for(;;);
  }

  display.clearDisplay();
  
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(20, 0);
  display.print(F("TAMANEGI"));
  display.setCursor(15, 25);
  display.print(F("OLED 0.96"));
  display.setCursor(25, 45);
  display.print(F("SSD1306"));
 
  display.display();
}

void loop()
{
}

結果

Arduino nano Atmega328pと同スケッチでOLED(SSD1306)の制御ができました。
マイコンやボードライブラリが変わっていても対応できていることが確認できました。

SPI(ST7735)

説明

Nano Every Atmega4808のSPIを使いLCD(ST7735)の表示制御をします。

表示内容は
“NanoEvery4808”
“TAMANEGI”
ですが、表示色とズラし表示により凹凸効果のある表示をしています。

表示サンプルはAdafruit Exampleを参考にしました。
メニュー > Examples > Adafruit ST7735 and ST7789 Library > graphicstest

配線

スケッチ

#include <Adafruit_GFX.h> 
#include <Adafruit_ST7735.h>
#include <SPI.h>

#define TFT_CS      (10)
#define TFT_RST     (25)
#define TFT_DC      (14)

//16のbit情報, 赤 5bit, 緑 6bit, 青 5bit, (RRRR RGGG GGGB BBBB)
#define LCD16BIT_LGRAY   (0xbdf7)
#define LCD16BIT_GRAY    (0x7bef)
#define LCD16BIT_DGRAY   (0x39e7)


Adafruit_ST7735 tft = Adafruit_ST7735(&SPI, TFT_CS, TFT_DC, TFT_RST);

void setup(void) 
{
  tft.initR(INITR_BLACKTAB);
  tft.fillScreen(LCD16BIT_GRAY);
  
  tft.setRotation(3);
  tft.setTextSize(2);
  
  tft.setCursor(0, 20);
  tft.setTextColor(LCD16BIT_LGRAY);
  tft.printf("NanoEvery4808\n");
  tft.setCursor(2, 22);
  tft.setTextColor(LCD16BIT_DGRAY);
  tft.printf("NanoEvery4808\n");
  tft.setCursor(1, 21);
  tft.setTextColor(LCD16BIT_GRAY);
  tft.printf("NanoEvery4808\n");

  tft.setTextSize(3);
  tft.setCursor(9, 49);
  tft.setTextColor(LCD16BIT_DGRAY);
  tft.printf("TAMANEGI\n");
  tft.setCursor(11, 51);
  tft.setTextColor(LCD16BIT_LGRAY);
  tft.printf("TAMANEGI\n");
  tft.setCursor(10, 50);
  tft.setTextColor(LCD16BIT_GRAY);
  tft.printf("TAMANEGI\n");
  
}

void loop()
{
}

結果
Arduino nanoと同じようにST7735モジュールライブラリの制御ができました。

コメント

タイトルとURLをコピーしました