【Arduino】秋月AE-nRF52840を使う

it

秋月から発売されているAE-nRF52840を使いました。
基本的なマイコンのGPIO操作と有線通信、BLEを使った内容を記載します。

AE-nRF52840

簡単紹介

技適付きnRF52840搭載基板としてはお手頃に入手できる開発基板。
秋月オリジナル設計で多くのGPIOを使うことができます。
Qwiic互換コネクタを実装。

◆入手

秋月電子通商にて購入できます。
記事作成時(2025/5)の価格は税込み \1,780(送料含まず)。

◆関連記事

ピン配置

外観

400穴ブレッドボードに載せました。
左右2列使うことができます。
全体の半分強程度を占めますが、小型のモジュール程度ならブレッドボード1枚で作業できます。

使ってみた

◆開発環境

Arduino環境で開発しました。
ボードライブラリは「Adafruit nRF52 by Adafruit」を使用しました。

単純なスケッチのコンパイル時間は10秒程度でもそれほど遅くありません。
カット&トライを繰り返す作業ではコンパイル時間が短いほど有利です。

スケッチを書きこんだ後時々シリアル認識されなくなります。
リセットボタンを素早く2回押すことで認識されるようになりますが、少し煩わしいと感じます。

◆使ってみた

nRF5280搭載基板は何らかのセンサ付きが多い印象があります。
Ex)micro:bit、XIAO nRF52840 Sense

付属機能があまりませんが、技適付きで無線が使えるnRF52840基板としては多くのGPIOが使えて手ごろな価格帯だと思います。

BLE

BLEを使ったUART、HIDマウス、HIDキーボードを試してみました。
いずれもライブラリサンプルを使うことで簡単に確認ができます。

パラメータなどカスタムすることなく使えますが、スケッチ上の手続きが多い(行数が多い)のでとっつきの悪さを感じます。

BLE UART

スマートフォンとBLE UARTで通信しました。
簡単な電文の送受信ですが、必要なコードが多く手軽さはイマイチです。

スマートフォンから離れた場所の基板に指示を出したり、状態を読み出せたりできます。

BLE マウス

Windows上のマウスポインタの方向操作を試してみました。
移動幅でカスタムできますが、作ったサンプルの動きはもっさりしています。
手元にあったアナログ入力モジュール(JOYスティックモジュール)を方向判定だけで定量移動させています。
方向入力のストローク調整の難しいモジュールだったための処置ですが、入力操作性の良いモジュールならなめらかな操作ができると思います。

BLE キーボード

Windows上のメモ帳を使って試してみました。
タクトボタンを押すことで”Hello world”と入力しました。

文字列の入力をキー操作を一つずつ行ったためにゆったりとした入力になってしまいました。
1ストロークで複数の文字や、ストロークごとに違う入力ができるガジェットも作ることができます。

準備

Arduino環境の作成

◆開発環境

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

◆ボードライブラリ

ボードライブラリにはAdafruit製ライブラリを使いました。

ボードマネージャのURLhttps://adafruit.github.io/arduino-board-index/package_adafruit_index.json
検索nRF52
ボードライブラリAdafruit nRF52 by Adafruit バージョン x.x.x
選択するボードAdafruit nRF52 > Feather nRF52840 Express
※ x.x.x 動作確認では1.6.0を使用

◆モジュールライブラリ

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

SSD1306

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

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

ST7735S

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

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

コンパイルと書き込み

USBケーブルでパソコンと接続し、ArduinoIDEの書き込みボタンから書き込みができます。

選択するボードは「Feather nRF52840 Express」です。
違うボードを選択するとコンパイルまでは終わりますが書き込みをしません。

準備

Bluetoothペアリング(Windows10)

Bluetooth、BLEを使う場合ペアリングをします。
ペアリングはスケッチを書き込み、AE-nRF52840が無線通信を開始した状態で行います。

下図はWindows10でのBLE HIDのペアリング方法例です。
※環境により異なることがあります。

Bluetoothペアリング(スマートフォン)

数はAndroidスマートフォンとのペアリングの例です。
使用する機種により操作や画面が異なります。

トラブル

◆症状

USB接続をしてもパソコンから認識されない。
認識されないためArduinoIDEからの書き込みができない。

◆対処

基板上のリセットボタンを素早く2回押す(0.5秒以内に2回程度)

スケッチ

GPIOデジタル出力

説明

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

GPIO14のLowとHighを繰り返し信号の周期を計測します。
計測にはオシロスコープ(HDS272)を使い、信号の立ち上がりから次の立ち上がり(または立下りから次の立下り)の時間を計測します。

単純なスケッチですがコンパイルにかかった時間をストップウォッチで計測します。

配線

GPIO0とGNDをオシロスコープでプローブします。

スケッチ

#define IO_PIN    (0)

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

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

結果

このスケッチをコンパイルするのにかかった時間は約5秒です。
Arduino環境でコンパイルできるマイコンとしては速い方だと思います。

Low/High1周期(A-B間)の時間は0.916nsでした。
1秒あたりに繰り返す回数は約100万回(1.09MHz)でした。

GPIO入出力(ボタン、ユーザLED)

説明

GPIO入出力を使います。
タクトボタンの状態を読み取り、ボタンが押されていればユーザLEDを点灯、ボタンが放されていればユーザLEDを消灯します。

AE-nRF52840のユーザLED(GPIO13)は赤点灯で電圧Highで点灯、Lowで消灯します。

配線

スケッチ

#define BUTTON_PIN    (12)
#define LED_PIN       (13)

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

void loop()
{
  digitalWrite(LED_PIN, digitalRead(BUTTON_PIN));
}

結果

ボタンを押すことでユーザLED(赤)が点灯、放すことで消灯しました。

PWM出力

PWMを使ってLEDの輝度を制御します。
Dutyを3段階変化(設定値0~255の内1/255, 128/255, 254/255) させます。

PWMの出力信号をオシロスコープ(HDS272)で周期とDutyの変化の様子をモニタします。

配線

スケッチ

#define PWM_PIN     (14)

void setup()
{
  int16_t tblPWM[] = {1, 128, 254};
  int16_t tableCount = sizeof(tblPWM) / sizeof(int16_t);

  pinMode(PWM_PIN, OUTPUT);
  
  while(1)
  {
    for(int16_t i = 0; i < tableCount; i ++)
    {
      analogWrite(PWM_PIN, tblPWM[i]);
      delay(1000);
    }
  }
}

void loop()
{
}

結果

PWM1周期15.92us(62.9kHz)でした。

PWMの周期は短いですが拡大した波形でもしっかり0~3.3V(少し足りない?)にクリップしているようです。
LEDの発光も他の1kHz前後のマイコンに比べて点滅が認識できないレベルです。

アナログ入力(ADC)

説明

AE-nRF52840のADCを使ってアナログ電圧を読み取ります。
読み取った結果をUSBシリアルに出力します。
ADCは0~3.3Vを10bit(0~1023)の分解能で読み取ります。

アナログ電圧の入力元にはXIAO SAMD21のDACを使い、0から3.3Vを約2秒, 3.3から0Vを約2秒かけて変化するスケッチを書きこみました。

配線

スケッチ

#include <Adafruit_TinyUSB.h>

void setup()
{
  Serial.begin(115200);
  delay(1000);

  pinMode(A0, INPUT);

  while(1)
  {
    delay(2);
    Serial.println(analogRead(A0));
  }
}

void loop()
{
}

結果

UART

説明

AE-nRF52840のUARTを使います。
AE-nRF52840ではUSBシリアルからの通信も可能で、UARTと独立して使用できます。

通信I/Fオブジェクトピン
USBシリアルSerial
UARTSerial1TX(GPIO0), RX(GPIO1)

USBシリアルからは”USB Serial”、UARTからは”UART”の文字列を1秒ごとに出力します。

配線

スケッチ

#include <Adafruit_TinyUSB.h>

void setup()
{
  Serial.begin(115200);
  Serial1.begin(115200);
  delay(1000);

  while(1)
  {
    delay(1000);
    Serial.println("USB Serial");
    Serial1.println("UART");
  }
}

void loop()
{
}

結果

USBシリアル(AE-nRF52840)はCOM17、UART変換アダプタ(FT232RL)はCOM3で認識されました。
COM17側には”USB Serial”、COM3側には”UART”の文字列が1秒ごとに表示されました。

I2C(SSD1306)

説明

AE-nRF52840のI2Cを使って小型のOLED(SSD1306)を表示制御します。
文字列”TAMANEGI”を中抜き風に表示します。

このスケッチを実行するために、以下のモジュールライブラリが必要です。

・Adafruit SSD1306 by Adafruit
・Adafruit GFX Library by Adafruit

nRF52840のI2Cのピン位置は変更できません。
SDAをGPIO22, SCLをGPIO23に配線します。

配線

スケッチ

#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);

  const uint16_t posX = 20;
  const uint16_t posY = 25;

  display.setCursor(posX + 1, posY + 1);
  display.print(F("TAMANEGI"));

  display.setCursor(posX - 1, posY - 1);
  display.print(F("TAMANEGI"));

  display.setCursor(posX + 1, posY - 1);
  display.print(F("TAMANEGI"));

  display.setCursor(posX - 1, posY + 1);
  display.print(F("TAMANEGI"));

  display.setTextColor(SSD1306_BLACK);
  display.setCursor(posX, posY);
  display.print(F("TAMANEGI"));

  display.display();
}

void loop()
{
}

結果

黄色発光のOLEDを使用しました。
“TAMANEGI”の文字列が中抜き文字風に表示されました。

SPI(ST7735S)

説明

AE-nRF52840のSPIを使って小型のLCD(ST7735S)を表示制御します。
このスケッチを実行するには、以下のモジュールライブラリのインストールが必要です。

・Adafruit ST7735 and ST7789 Library by Adafruit
・Adafruit GFX Library by Adafruit

表示内容は矩形の枠内に”TAMANEGI”と表示。
全体をグレー調で表示に凹凸効果を加えています。

nRF52840のSPIピンの内、MISO, MOSI, SCK位置は変更できません。
CSおよび、表示に使用するRST, DCは任意の位置にピン設定することができます。

配線

スケッチ

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

#define TFT_CS      (SS)
#define TFT_RST     (0)
#define TFT_DC      (1)

#define TFT_LGRAY   (0xbdf7)
#define TFT_GRAY    (0x7bef)
#define TFT_DGRAY   (0x39e7)

Adafruit_ST7735 tft = Adafruit_ST7735(&SPI, TFT_CS, TFT_DC, TFT_RST);
                                        
void setup()
{
  tft.initR(INITR_MINI160x80_PLUGIN);
  tft.fillScreen(TFT_GRAY);
  tft.setRotation(3);
  tft.setTextSize(2);

  const uint16_t posX = 30;
  const uint16_t posY = 25;

  tft.setCursor(posX + 1, posY + 1);
  tft.setTextColor(TFT_LGRAY);
  tft.printf("TAMANEGI\n");

  tft.setCursor(posX - 1, posY - 1);
  tft.setTextColor(TFT_DGRAY);
  tft.printf("TAMANEGI\n");

  tft.setCursor(posX, posY);
  tft.setTextColor(TFT_GRAY);
  tft.printf("TAMANEGI\n");

  tft.drawRect(19, 9, 119, 49, TFT_DGRAY);
  tft.drawRect(20, 10, 120, 50, TFT_LGRAY);
}

void loop()
{
}

結果

LCDに文字列を表示しました。
グレースケールでの凹凸効果があり立体的な表示に見えます。

BLE(UARTクライアント)

説明

AE-nRF52840とスマートフォンでBLE UARTを使った通信をします。

この作業は準備が必要で、こちらに手順を記載しています。
スケッチを書きこんだ後にスマートフォンとBluetoothのペアリングをします。
BLE UART通信をするために、スマートフォンに通信アプリケーションをインストールします。

配線

ジャンパワイヤによる配線はありません。

スケッチ

#include <bluefruit.h>
#include <Adafruit_LittleFS.h>
#include <InternalFileSystem.h>

BLEDfu  bledfu;
BLEDis  bledis;
BLEUart bleuart;
BLEBas  blebas;

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

#if CFG_DEBUG
  while ( !Serial ) yield();
#endif
  
  Serial.println("Bluefruit52 BLEUART Example");
  Serial.println("---------------------------\n");

  Bluefruit.autoConnLed(true);

  Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);

  Bluefruit.begin();
  Bluefruit.setTxPower(4);
  Bluefruit.Periph.setConnectCallback(connect_callback);
  Bluefruit.Periph.setDisconnectCallback(disconnect_callback);

  bledfu.begin();

  bledis.setManufacturer("Adafruit Industries");
  bledis.setModel("Bluefruit Feather52");
  bledis.begin();

  bleuart.begin();

  blebas.begin();
  blebas.write(100);

  startAdv();
}

void startAdv(void)
{
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();

  Bluefruit.Advertising.addService(bleuart);

  Bluefruit.ScanResponse.addName();
  
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);
  Bluefruit.Advertising.setFastTimeout(30);
  Bluefruit.Advertising.start(0);
}

void loop()
{
  while (Serial.available())
  {
    delay(2);

    uint8_t buf[64];
    int count = Serial.readBytes(buf, sizeof(buf));
    bleuart.write( buf, count );
  }

  while ( bleuart.available() )
  {
    uint8_t ch;
    ch = (uint8_t) bleuart.read();
    Serial.write(ch);
  }
}

void connect_callback(uint16_t conn_handle)
{
  BLEConnection* connection = Bluefruit.Connection(conn_handle);

  char central_name[32] = { 0 };
  connection->getPeerName(central_name, sizeof(central_name));

  Serial.print("Connected to ");
  Serial.println(central_name);
}

void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
  (void) conn_handle;
  (void) reason;

  Serial.println();
  Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
}

結果

スマートフォンアプリ「SerialBluetooth」を使いました。

簡単な接続例です。
あらかじめスマートフォンとAE-nRF52840をペアリングした状態で以下作業をします。

スマートフォン側から「hello」を送信すると、AE-nRF52840が受信しUSBシリアルから「hello」と表示しました。
Serial Monitorから「world」を送信すると、スマートフォンに「world」と表示されました。

BLE(HID マウス)

説明

AE-nRF52840のBLEを使ったHIDマウスを使ってみます。

マウスポインタを動かす方向モジュールにはJOYスティックモジュールを使います。
スライド式で方向以外に入力量はアナログ読み出しをします。
スライド量が小さくマウスの制御量に比例させてもよくわからなかったので、マウスカーソルの移動量は定量にします。

始めにニュートラルポジションのアナログ値を読み取ります。
その値を中心に「遊び」を設定し、アナログ値の大小で移動方向を決定します。

配線

スケッチ

#include <Adafruit_TinyUSB.h>
#include <bluefruit.h>
#include <Wire.h>

BLEDis bledis;
BLEHidAdafruit blehid;

#define MOUSECOUNT        (5)
#define ADC_X             (A0)
#define ADC_Y             (A1)
#define PLAY_XY           (20)
#define ADC_RESOLUSION    (3)

int16_t center_x = 0;
int16_t center_y = 0;

void setup() 
{

  Serial.begin(115200);
  delay(1000);

  pinMode(ADC_X, INPUT);
  pinMode(ADC_Y, INPUT);

  Bluefruit.begin();

  bledis.setManufacturer("Adafruit Industries");
  bledis.setModel("Bluefruit Feather 52");
  bledis.begin();

  blehid.begin();

  startAdv();

  center_x = analogRead(ADC_X);
  center_y = analogRead(ADC_Y);
}

void startAdv(void)
{  
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_MOUSE);
  
  Bluefruit.Advertising.addService(blehid);
  Bluefruit.Advertising.addName();
  
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);
  Bluefruit.Advertising.setFastTimeout(30);
  Bluefruit.Advertising.start(0); 
}

void loop() 
{
  int16_t move_x = 0;
  int16_t move_y = 0;
  
  int16_t x = analogRead(ADC_X);
  int16_t y = analogRead(ADC_Y);
//  Serial.printf("x = %d, y = %d\r\n", x, y);

  if(x < (center_x - PLAY_XY) || (center_x + PLAY_XY) < x)
  {
    move_x = (center_x < x) ? -MOUSECOUNT : MOUSECOUNT; 
  }

  if(y < (center_y - PLAY_XY) || (center_y + PLAY_XY) < y)
  {
    move_y = (center_y < y) ? -MOUSECOUNT : MOUSECOUNT; 
  }
  
  blehid.mouseMove(move_x, move_y);
}

結果

Windowsのマウスカーソルで確認しました。
動作の確認にはペアリングをする必要があります。

ジョイスティックを操作することで昔のシューティングゲーム風な8方向動作をしました。

BLE(HID キーボード)

説明

AE-nRF52840のBLEを使ったHIDキーボードを使ってみます。
タクトボタンを押すことで”Hello world”とタイプします。

タクトボタンのチャタリング対策としてボタンを押してから10ms後にもう一度押されている判定をします。
文字列をタイプした後に、ボタンのリリースを確認する処理へモード遷移します。

配線

スケッチ

#include <bluefruit.h>
#include <Wire.h>

BLEDis bledis;
BLEHidAdafruit blehid;

#define BUTTON_PIN    (12)

const char strKey[] = "Hello world";

void setup() 
{

  pinMode(BUTTON_PIN, INPUT_PULLDOWN);

  Bluefruit.begin();
  Bluefruit.setTxPower(4);
  bledis.setManufacturer("Adafruit Industries");
  bledis.setModel("Bluefruit Feather 52");
  bledis.begin();
  
  blehid.begin();

  startAdv();

  Wire.begin();
}

void startAdv(void)
{  
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);
  
  Bluefruit.Advertising.addName();
  
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);
  Bluefruit.Advertising.setFastTimeout(30);
  Bluefruit.Advertising.start(0);
}

void loop() 
{

  boolean bButton;
  int16_t mode = 0;
  while(1)
  {
    bButton = digitalRead(BUTTON_PIN);

    if(mode == 0)
    {
      if(digitalRead(BUTTON_PIN) == true)
      {
        delay(10);
        if(digitalRead(BUTTON_PIN) == true)
        {
          for(int16_t i = 0; i < sizeof(strKey); i ++)
          {
            blehid.keyPress(strKey[i]);
            blehid.keyRelease();
          }
          mode = 1;
        }
      }
    }
    else
    {
      if(digitalRead(BUTTON_PIN) == false)
      {
        delay(10);
        if(digitalRead(BUTTON_PIN) == false)
        {
          mode = 0;
        }
      }
    }
  }
}

結果

確認にWindowsのメモ帳などを使います。
動作の確認にはペアリングをする必要があります。

タクトボタンを押すことで”Hello world”と入力されました。

コメント

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