Arduino Nano RP2040 Connect

Arduino Nano RP2040 Connect
(Quelle: arduino.cc)

Im Januar 2021 wurde von Arduino das Board Nano RP2040 Connect angekündigt, welches denselben Mikrocontroller enthalten soll wie der Raspberry Pi Pico. Am 17.05.2021 wurde nun die Veröffentlichung des Nano RP2040 Connect bekannt gegeben und davon habe ich mir auch eine bestellt, um dessen Möglichkeiten auszuprobieren.

Spezifikationen & Features

Laut der offiziellen Dokumentation verfügt der Nano RP2040 Connect über die folgende Ausstattung:

Mikrocontroller Raspberry Pi RP2040
Taktfrequenz 133 MHz
Flash-Speicher 16MB
SRAM 264kB
Digital I/O Pins 20
Analoge Eingänge 8
PWM pins 20 (außer A6 und A7)
Externe Interrupts 20 (außer A6 und A7)
Betriebsspannung VIN: 5-21V
VUSB: 5V
VLOGIK: 3,3V
VOUT: 3,3V
Max. Stromaufnahme pro Pin: 4mA
Zusätzliche Features
  • Mikro-USB-Anschluss (Spannungsversorgung/Programmierung)
  • 6-Achsen Gyroskop und Beschleunigungssensor LSM6DSOXTR IMU
  • MEMS-Mikrofon MP34DT06JTR
  • RGB LED (gemeinsame Anode)
  • Kryptografischen Koprozessor Microchip ATECC608A
  • UART, SPI, I2C
  • Verschiedene DeepSleep-Modi
  • SWD-Schnittstelle für Hardware-Debugging
  • Interner Temperatursensor
WiFi/Bluetooth U-blox® Nina W102-Modul

Verwendete Bauteile

Anschlüsse

Anschlüsse des Arduino Nano RP2040 Connect
(Quelle: arduino.cc)

Zusätzliche Hinweise/Einschränkungen

Halterung für Arduino Nano RP2040 Connect

Unterlage für den Arduino Nano RP2040 Connect

Diese Unterlage für den Arduino Nano RP2040 Connect kann verwendet werden, wenn dieser nicht auf ein Steckbrett montiert wird.

nano_rp2040_mount.scad

Programmierung

Arduino IDE

Der Arduino Nano RP2040 lässt sich direkt in der Arduino IDE (v1.8.x und v2.0.x) programmieren. Dazu muss im Boards Manager der Arduino Mbed OS Nano Boards core für das Board ausgewählt und installiert werden:

Installation des Arduino Mbed OS Nano Boards core
Abb.: In der Arduino IDE v1.8.x wird der Arduino Mbed OS Nano Boards core über den Boards Manager installiert.

Zur Einrichtung in der Arduino IDE 2.0.X (beta) siehe auch: Board manager with the Arduino IDE 2.0.
Nach der Installation des Cores wird nun der Arduino Nano RP2040 Connect im Menüpunkt Tools » Board ausgewählt.

Arduino IoT Cloud

Die Arduino IoT Cloud unterstützt bereits ebenfalls den Nano RP2040 Connect.
Einrichtung und Verwendung mit dieser Plattform kann in der Arduino IoT Cloud-Dokumentation nachgelesen werden.

Micropython

Eine Programmierung in Micropython ist ebenso möglich analog zur Beitrag mit der Programmierung des Raspberry Pi Pico in MicroPython. Um dafür den Nano RP2040 Connect in den richtigen Modus zu setzen muss er als Massenspeicher-Laufwerk vom PC erkannt werden. Dazu wird das Board zunächst vom PC getrennt, dann ein 2,54mm-Jumper zwischen GND und REC gesteckt und das Board wieder mit dem PC verbunden. (siehe auch: Bootloader)

Nano RP2040 Connect als Laufwerk erkennen lassen

Nun kann der Jumper wieder entfernt werden und z.B. mit der Entwicklungsumgebung "Thonny" das Board mit Micropython programmiert werden.

Experimente

Interne LED blinken lassen

Der einfachste Sketch ist zunächst die interne LED (orange) zum blinken zu bekommen.

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

void loop()
{
    digitalWrite(LED_BUILTIN, HIGH);
    delay(500);
    digitalWrite(LED_BUILTIN, LOW);
    delay(500);
}

Digitale Eingabe/Ausgabe

Um die digitale Ein- und Ausgabe zu testen, werden -wie im folgenden Schaltplan gezeigt- zwei verschiedenfarbige LEDs mit Vorwiderständen und zwei Mikrotaster an das Board angeschlossen und mit dem nachfolgenden Sketch programmiert.

Schaltplan
#define PIN_LED_GREEN    10
#define PIN_LED_RED       9
#define PIN_BUTTON_GREEN  8
#define PIN_BUTTON_RED    7

void setup()
{
    pinMode(PIN_LED_GREEN,    OUTPUT);
    pinMode(PIN_LED_RED,      OUTPUT);
    pinMode(PIN_BUTTON_GREEN, INPUT_PULLUP);
    pinMode(PIN_BUTTON_RED,   INPUT_PULLUP);
}

void loop()
{
    if (digitalRead(PIN_BUTTON_GREEN) == LOW) {
        digitalWrite(PIN_LED_GREEN, HIGH);
    } else {
        digitalWrite(PIN_LED_GREEN, LOW);
    }
    if (digitalRead(PIN_BUTTON_RED) == LOW) {
        digitalWrite(PIN_LED_RED, HIGH);
    } else {
        digitalWrite(PIN_LED_RED, LOW);
    }
}

Analoge Eingabe & PWM

Zum Test der analogen Eingabe und der PWM-Funktionalität wird ein Potentiometer und eine LED mit Vorwiderstand so mit dem Board verbunden wie der folgende Schaltplan zeigt:

Schaltplan

Der Sketch lässt die LED dann entsprechend der Stellung des Potentiometers heller bzw. dunkler leuchten.

#define PIN_POTI A0
#define PIN_LED  12

void setup()
{
    Serial.begin(9600);
    pinMode(PIN_LED, OUTPUT);
}

void loop()
{
    static int value = 0;
    value = analogRead(PIN_POTI);
    analogWrite(PIN_LED, map(value, 0, 1024, 0, 255));
}

Interne RGB-LED (gemeinsame Anode)

Um die eingebaute RGB-LED mit gemeinsamer Anode ansprechen zu können wird die Library WiFiNINA benötigt, denn die Pins können nur indirekt über das Nina W102-Modul angesprochen werden.

#include <WiFiNINA.h>

void setup()
{
    pinMode(LEDR, OUTPUT);
    pinMode(LEDG, OUTPUT);
    pinMode(LEDB, OUTPUT);
}

void loop()
{
    for (byte i = 0; i < 255; i++) {
        analogWrite(LEDR, random(0, 256));
        analogWrite(LEDG, random(0, 256));
        analogWrite(LEDB, random(0, 256));
        delay(500);
    }
}

MEMS-Mikrofon

Das auf dem Nano RP2040 Connect verbaute MEMS-Mikrofon zeichnet sich durch geringes Rauschen, einen breiten Dynamikbereich, geringe Verzerrung und hohe Widerstandsfähigkeit gegenüber akustischer Überlastung aus. Es soll sich daher gut für Anwendungen im Bereich der Spracherkennung eignen.
In diesem Beispiel sollen lediglich akustische Signale vom Mikrofon ausgelesen und mit dem seriellen Plotter grafisch darstellt werden. Die Library PDM erleichter den Umgang mit sog. PDM-Mikrofonen (Pulse-density modulation), wie dem auf dem Board verbauten MP34DT06JTR.
Der folgende Sketch entspricht mehr oder weniger dem Beispiel PDMSerialPlotter der PDM-Library:

#include <PDM.h>

static const char channels = 1;
static const int frequency = 16000;
short sampleBuffer[512];
volatile int samplesRead = 0;

void setup()
{
    Serial.begin(9600);
    while (!Serial);

    // Configure the data receive callback
    PDM.onReceive(onPDMdata);
    // PDM.setGain(30);

    if (!PDM.begin(channels, frequency)) {
        Serial.println("Failed to start PDM!");
        while (1);
    }
}

void loop()
{
    if (samplesRead) {
        for (int i = 0; i < samplesRead; i++) {
            Serial.println(sampleBuffer[i]);
        }

        // Clear the read count
        samplesRead = 0;
    }
}

void onPDMdata()
{
    int bytesAvailable = PDM.available();
    PDM.read(sampleBuffer, bytesAvailable);
    samplesRead = bytesAvailable / 2;
}

Leider wurden bei mir immer nur -128 als Wert ausgegeben, es scheint als würde hier entweder ein Defekt auf dem Board vorliegen oder in der Software besteht noch ein Fehler...

WLAN/WiFi + Temperatur-Sensor

Um das eingebaute Nina W102-Modul für WLAN (WiFi) auszuprobieren, wird im folgenden Sketch zunächst die aktuelle Temperatur des eingebauten Sensors ausgelesen und anschließend an ThingSpeak weitergereicht.
Zum Verbinden es WLAN-Netzwerks und des WWW-Servers wird wiederum die Library WiFiNINA benötigt.
Der interne Temperatursensor misst nicht wirklich die Umgebungstemperatur, sondern vielmehr die Temperatur des IC.

#include <WiFiNINA.h>

// WiFi settings:
const char* SSID     = "mySSID";
const char* PASSWORD = "myPassword";

// ThingSpeak settings:
const char* TS_HOST    = "api.thingspeak.com";
const char* TS_API_KEY = "myWriteApiKey";

WiFiClient client;

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

    // Init onboard temperature sensor
    adc_init();
    adc_set_temp_sensor_enabled(true);
    adc_select_input(4);
}

void loop()
{
    connectWiFi();
    String measureData = "&field1=" + String(getTemp());
    httpRequest(measureData);
    delay(15000);
}

void connectWiFi()
{
    if (WiFi.status() == WL_CONNECTED) {
        return;
    }

    Serial.print("Connecting to WiFi...");
    WiFi.begin(SSID, PASSWORD);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("[connected]");
}

void httpRequest(String data)
{
    String postData = "api_key=" + String(TS_API_KEY) + data;

    if (client.connect(TS_HOST, 80)) {
        client.println("POST /update HTTP/1.1");
        client.println("Host: " + String(TS_HOST));
        client.println("Connection: close");
        client.println("Content-Type: application/x-www-form-urlencoded");
        client.println("Content-Length: " + String(postData.length()));
        client.println();
        client.println(postData);

        Serial.println("Sent data to server: " + String(postData));
        String line = client.readStringUntil('\n');
        Serial.println(line);
    } else {
        Serial.println("Connection to server failed!");
    }

    client.stop();
}

int getTemp()
{
    uint16_t raw = adc_read();
    const float conversion_factor = 3.3f / (1 << 12);
    float result = raw * conversion_factor;
    float temp = 27 - (result - 0.706) / 0.001721;
    return (int)temp;
}

Da nur alle 15 Sekunden die gemessene Temperatur an ThingSpeak geschickt wird, kann erst nach ein paar Minuten ein brauchbarer Graph angezeigt werden:

Grafische Ausgabe in ThingSpeak
Abb.: Grafische Ausgabe der über die Zeit gemessenen Temperatur des Nano RP2040 Connect
zurück