Ardui­no UNO R4 WiFi

Lese­zeit: 12 Minu­ten

Das Board UNO R4 WiFi stellt neben dem Mikro­con­trol­ler auch ein ESP32-Modul bereit. Damit kön­nen Ver­bin­dun­gen zu WLAN-Netz­wer­ken und ande­ren Blue­tooth-Gerä­ten auf­ge­baut werden.

Pin­be­le­gung

Quel­le: 🔗https://​docs​.ardui​no​.cc/​h​a​r​d​w​a​r​e​/​u​n​o​-​r​4​-​w​ifi (eige­ne Bear­bei­tung abge­ru­fen am 06.07.23)

An die­se Ein- und Aus­gän­ge kön­nen zum Bei­spiel ➨LEDs, Laut­spre­cher, Dis­plays, Moto­ren oder Sen­so­ren ange­schlos­sen wer­den. Der Mikro­con­trol­ler kann alle die­se Bau­tei­le steu­ern, Signa­le aus­le­sen und auf­grund der gele­se­nen Daten ver­schie­de­ne Aktio­nen auslösen. 

digi­ta­le Pins

  • Der Reset-Knopf star­tet das gera­de hoch­ge­la­de­ne Pro­gramm neu.
  • Die digi­ta­len Ein-/Aus­gän­ge lie­fern im Nor­mal­fall ein HIGH (1) oder LOW (0). Eine Aus­nah­me bil­den die mit einem ~ gekenn­zeich­ne­ten Pins. Sie kön­nen mit der Puls­wei­ten­mo­du­la­ti­on ange­spro­chen werden.
  • Die ana­lo­gen Ein­gän­ge mes­sen die anlie­gen­de Span­nung. Die­se Span­nung (5V) wird vom Ana­log-Digi­tal-Wand­ler (ADC = Ana­log Digi­tal Con­ver­ter) in digi­ta­le Wer­te zwi­schen 0 und 1023 (10 Bit) umge­wan­delt.
    Die Stan­dard­auf­lö­sung kann auf 12 Bit (0−4096) oder 14 Bit (0−65355) erhöht werden. 
  • Der ➨SPI-Bus ver­wen­det die Ein­gän­ge D10 CS (Chip Sel­ect), D11 COPI (Con­trol­ler Out Peri­phe­rie In), D12 CIPO (Con­trol­ler In Peri­phe­rie Out) und D13 SCK (Seri­al Clock)
  • Die Ein­gän­ge SCL und SDA wer­den über den ➨I2C-Bus angesteuert.
  • QWIIC ist ein zusätz­li­cher I2C-Bus
    Die ver­bun­de­nen Gerä­te kön­nen mit einem Pro­gramm abge­fragt werden.
  • die Pins 0 (RX - Recei­ver = Emp­fän­ger) und 1 (TX -Trans­mit­ter = Sen­der) wer­den für die Kom­mu­ni­ka­ti­on mit dem Com­pu­ter über die USB-Schnitt­stel­le ver­wen­det. Sie kön­nen nur dann als digi­ta­le Ein- oder Aus­gän­ge ver­wen­det wer­den, wenn der Ardui­no über eine exter­ne Strom­zu­fuhr betrie­ben wird.

Board instal­lie­ren

  • Icon für den Board­ver­wal­ter ankli­cken oder Werk­zeu­ge-> Board -> Boardverwalter
  • nach dem UNO R4 Board suchen
  • Board instal­lie­ren

Board aus­wäh­len

LinuxWin­dows

Der Name des USB-Ports unter­schei­det sich je nach dem ver­wen­de­ten Betriebssystem.

LED-Matrix

Auf dem Board befin­det sich zusätz­lich eine 12×8 gro­ße LED-Matrix.

Die LED-Matrix kann als ➨zwei­di­men­sio­na­les Array defi­niert wer­den. Eine 0 mar­kiert eine aus­ge­schal­te­te LED, eine 1 zeigt eine leuch­ten­de LED. Die­se Schreib­wei­se hat den Vor­teil, dass der Auf­bau der Matrix sicht­bar wird und eine Ände­rung schnell mög­lich ist.

Bei­spie­le:

byte PfeilRechts[8][12] = 
{
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 
  { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 },
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }
};

Das voll­stän­di­ge Programm:

#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix Matrix;

byte PfeilLinks[8][12] = 
{
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 
  { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
  { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }
};

byte PfeilRechts[8][12] = 
{
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 
  { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 },
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }
};

void setup() 
{
  Matrix.begin();
  Matrix.renderBitmap(PfeilLinks, 8, 12);
  delay(1000);
  Matrix.renderBitmap(PfeilRechts, 8, 12);
}

void loop() 
{
  // bleibt leer, Programm läuft nur einmal
}

Das voll­stän­di­ge Programm:

# include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix Matrix;

const unsigned long PfeilRechts[] = 
{
   0x800,
   0xcffeffff,
   0xfe00c008,
};

const unsigned long PfeilLinks[] = 
{
   0x10030,
   0x7fffff7,
   0xff300100,
};

void setup() 
{
  Matrix.begin();
  Matrix.loadFrame(PfeilLinks);
  delay(1000);
  Matrix.loadFrame(PfeilRechts);
}

void loop() 
{
  // bleibt leer, Programm läuft nur einmal
}

In der Ardui­no IDE fin­dest du unter Bei­spie­le -> LED_Matrix das Pro­gramm Matrix­Frame­Buf­fer. Ich habe das Pro­gramm als Vor­la­ge genom­men und ver­ein­facht. Das Pro­gramm erzeugt zufäl­li­ge Pixelmuster.

# include "Arduino_LED_Matrix.h"

// Name der Matrix
ArduinoLEDMatrix Matrix;

#define Reihen 8
#define Spalten 12
int PunktX = 0;
int PunktY = 0;

// Rahmen definieren, beim Start sind alle Pixel ausgeschaltet
byte Rahmen[8][12] = 
{
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

void setup() 
{
  // Matrix starten
  Matrix.begin();
}

void loop() 
{
  // Punkte zufällig bestimmen
  PunktX = random(Spalten);
  PunktY = random(Reihen);

  // Pixel zufällig ein- oder ausschalten
  int Pixelwert = random(2);

  // Rahmen mit den neuen Werte aktualisieren
  Rahmen[PunktY][PunktX] = Pixelwert;

  // Rahmen anzeigen
  Matrix.renderBitmap(Rahmen, 8, 12);
  delay(50);
}

Text scrol­len

In der Ardui­no IDE fin­dest du unter Bei­spie­le -> LED_Matrix das Pro­gramm Text­Wi­t­hAr­dui­no­Gra­phics. Ich habe das Pro­gramm ver­ein­facht und kom­men­tiert.
Du musst dafür eine zusätz­li­che Biblio­thek installieren.

# include "ArduinoGraphics.h"
# include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix Matrix;

void setup() 
{
  Matrix.begin();
}

void loop() 
{
  // Zeichnen starten
  Matrix.beginDraw();

  // Scrollgeschwindigkeit
  Matrix.textScrollSpeed(50);

  // Fontgrößen: Font_4x6, Font_5x7  
  Matrix.textFont(Font_5x7);

  // beginText(Spalte, Zeile, Farbe)
  Matrix.beginText(0, 1, 0xFFFFFF);

  // Text anzeigen
  Matrix.print("    Text scrollen    ");

  // nach links scrollen
  Matrix.endText(SCROLL_LEFT);

  // Ausgabe beenden
  Matrix.endDraw();
}

➨Bei­spiel: Tem­pe­ra­tur­mes­sung und Anzei­ge der Daten 

RTC-Modul

Auf dem Board befin­det sich auch ein RTC-Modul (RTC = Real Time Clock). Es ist aller­dings nicht über eine Bat­te­rie gepuf­fert, nach dem Aus­schal­ten muss das aktu­el­le Datum und die Zeit neu gesetzt werden.

# include "RTC.h"

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

  RTC.begin();

  // aktuelles Datum/Zeit setzen
  RTCTime Zeit(11, Month::JULY, 2023, 8, 32, 00, DayOfWeek::MONDAY, SaveLight::SAVING_TIME_ACTIVE);
  RTC.setTime(Zeit);
}

void loop() 
{
  RTCTime aktuelleZeit;

  // aktuelle Zeit holen
  RTC.getTime(aktuelleZeit);

  // Wochentag als Objekt von DayOfWeek erzeugen
  DayOfWeek Wochentag = aktuelleZeit.getDayOfWeek();
  switch (Wochentag) 
  {
    case DayOfWeek::SUNDAY:
      Serial.print("Sonntag ");
      break;

    case DayOfWeek::MONDAY:
      Serial.print("Montag ");
      break;

    case DayOfWeek::TUESDAY:
      Serial.print("Dienstag ");
      break;

    case DayOfWeek::WEDNESDAY:
      Serial.print("Mittwoch ");
      break;

    case DayOfWeek::THURSDAY:
      Serial.print("Donnerstag ");
      break;

    case DayOfWeek::FRIDAY:
      Serial.print("Freitag ");
      break;

    case DayOfWeek::SATURDAY:
      Serial.print("Samstag ");
      break;
  }

  // wenn Tag < 10 führende 0 ergänzen
  if (aktuelleZeit.getDayOfMonth() < 10) Serial.print("0");
  Serial.print(aktuelleZeit.getDayOfMonth());
  Serial.print(".");

  // wenn Monat < 10 führende 0 ergänzen
  if (Month2int(aktuelleZeit.getMonth()) < 10) Serial.print("0");
  Serial.print(Month2int(aktuelleZeit.getMonth()));
  Serial.print(".");
  Serial.print(aktuelleZeit.getYear());
  Serial.print(" - ");

  // Uhrzeit
  Serial.print("Uhrzeit: ");

  // wenn Stunde < 10 führende 0 ergänzen
  if (aktuelleZeit.getHour() < 10) Serial.print("0");
  Serial.print(aktuelleZeit.getHour());
  Serial.print(":");

  // wenn Minuten < 10 führende 0 ergänzen
  if (aktuelleZeit.getMinutes() < 10) Serial.print("0");

  Serial.print(aktuelleZeit.getMinutes());
  Serial.print(":");

  // wenn Sekunden < 10 führende 0 ergänzen
  if (aktuelleZeit.getSeconds() < 10) Serial.print("0");
  Serial.println(aktuelleZeit.getSeconds());

  delay(1000);
}

QWIIC

Auf dem Board befin­det sich ein zwei­ter I2C-Anschluss mit QWIIC-Stecker.

Bei­spiel­pro­gramm ➨Wet­ter­sta­ti­on

Blue­tooth (BLE)

Zunächst musst du die Biblio­thek Ardui­no­BLE installieren:

Über­prü­fe, ob die aktu­el­le Firm­ware instal­liert ist: 🔗https://​sup​port​.ardui​no​.cc/​h​c​/​e​n​-​u​s​/​a​r​t​i​c​l​e​s​/​9​6​7​0​9​8​6​0​5​8​7​8​0​-​U​p​d​a​t​e​-​t​h​e​-​w​i​r​e​l​e​s​s​-​c​o​n​n​e​c​t​i​v​i​t​y​-​f​i​r​m​w​a​r​e​-​o​n​-​U​N​O​-​R​4​-​W​iFi

Das Pro­gramm schal­tet die ein­ge­bau­te LED:
1 -> ein­schal­ten, 0 -> ausschalten:

# include "ArduinoBLE.h"

/* 
  eindeutige  UUID bestimmen: 
  https://www.guidgenerator.com/online-guid-generator.aspx
  https://www.uuidgenerator.net/
  BLERead | BLEWrite | BLENotify
  -> schreiben, lesen, Info
*/

// Name BLE-Service
BLEService LEDSchalten("19b10000-e8f2-537e-4f6c-d104768a1214");

BLEUnsignedCharCharacteristic Auswahl("19b10000-e8f2-537e-4f6c-d104768a1214", BLERead | BLEWrite | BLENotify);

// eingebaute LED
int LED = 13;

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

  // pinMode festlegen
  pinMode(LED, OUTPUT);
 
  // BLE starten
  if (!BLE.begin()) Serial.println("Bluetooth-Modul konnte nicht gestartet werden!");
  else Serial.println("Bluetooth-Modul erfolgreich gestartet!");

  // Name festlegen (wird in der App angezeigt) und den Service (LEDSchalten) zuweisen
  BLE.setLocalName("LED schalten");
  BLE.setAdvertisedService(LEDSchalten);

  // Auswahl als Platzhalter für den in der App gewählten Wert
  LEDSchalten.addCharacteristic(Auswahl);

  // Service LEDSchalten hinzufügen
  BLE.addService(LEDSchalten);

  // Startwert für die Kommunikation schreiben
  Auswahl.writeValue(0);

  // Zuweisung starten
  BLE.advertise();
}

void loop()
{
  // auf die Verbindung zu Geräten warten
  BLEDevice Verbindung = BLE.central();

  // wenn der UNO R4 mit einem Gerät verbunden ist ...
  if (Verbindung)
  {
    Serial.println("Verbunden ... ");

    // solange der Controller mit einem Gerät verbunden ist ...
    while (Verbindung.connected())
    {
      if (Auswahl.written())
      {
        // LED einschalten
        if (Auswahl.value() == 1)
        {
          Serial.print(Auswahl.value());
          Serial.println(" -> LED ein");
          digitalWrite(LED, HIGH);
        }

        // LED ausschalten
        if (Auswahl.value() == 0)
        {
          Serial.print(Auswahl.value());
          Serial.println(F(" -> LED aus"));
          digitalWrite(LED, LOW);
        }    
      }
    }
  }
}

App Light­Blue

WiFi

Bei­spiel: Das Pro­gramm zeigt im Brow­ser 6 Zufalls­zah­len an.
Im Seri­el­len Moni­tor wird die IP des Ardui­no UNO R4 angezeigt.

Die­se Adres­se musst du in einem Brow­ser dei­ner Wahl eingeben

#include "WiFiS3.h"

char Router[] = "Router_SSID";
char Passwort[] = "xxxxxxxx";

// Minimum/Maximum der Zufallszahlen
const byte Minimum = 1;
const byte Maximum = 49;

WiFiServer WiFiServer(80);
WiFiClient WiFiClient;

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

  // auf serielle Verbindung warten
  while (!Serial) ;
  delay(500);

  // WiFi starten
  WiFi.begin(Router, Passwort);

  // Verbindung herstellen
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(200);
    Serial.print(".");
  }

  // SSID des Routers anzeigen
  Serial.println();
  Serial.print("Verbunden mit ");
  Serial.println(WiFi.SSID());

  // IP anzeigen
  Serial.println(WiFi.localIP());

  // Webserver starten
  WiFiServer.begin();

  // IP des Servers/des verbunden Computers anzeigen
  Serial.print("Server: ");
  Serial.println(WiFi.SSID());

  // IP des Arduinos anzeigen
  Serial.print("IP Adresse Arduino DHCP: ");
  Serial.println(WiFi.localIP());

  // Zufallsgenerator mit dem Signal an A0 starten
  randomSeed(analogRead(0));
}

void loop() 
{
  // auf WiFiClienten warten ...
  WiFiClient = WiFiServer.available();
  if (WiFiClient) 
  {
    // Seite aufbauen wenn SeiteAufbauen true ist
    boolean SeiteAufbauen = true;

    // solange der WiFiClient verbunden ist ...
    while (WiFiClient.connected()) 
    {
      if (WiFiClient.available()) 
      {
        // Anforderung vom WiFiClienten lesen ...
        char Zeichen = WiFiClient.read();

        // wenn als Zeichen neue Zeile (\n) übergeben wird
        // SeiteAufbauen true ist -> Seite anzeigen
        if (Zeichen == '\n' && SeiteAufbauen) 
        {
          /*
              HTML-Seite aufbauen
              die folgenden Anweisungen müssen
              mit print oder println gesendet werden
              println "verschönert" den Quelltext
              (erzeugt einen Zeilenumbruch im Quelltext)
          */
          WiFiClient.println("HTTP/1.1 200 OK");
          WiFiClient.println("Content-type:text/html");

          // Leerzeile zwingend erforderlich
          WiFiClient.println();
          WiFiClient.println("<!doctype html>");
          WiFiClient.println("<html>");
          WiFiClient.println("<body>");

          // <h2> Überschrift H2
          WiFiClient.println("<h2>Zufallszahlen</h2>");

          // <hr> horizontale Linie
          WiFiClient.println("<hr>");

          // Zufallszahlen anzeigen
          for (int i = 0; i < 7; i++) 
          {
            int Zahl = random(Minimum, Maximum);
            WiFiClient.println(Zahl);
            WiFiClient.println(" ");
          }

          WiFiClient.print("<hr>");

          // IPs anzeigen
          WiFiClient.print("Eigene IP-Adresse: ");
          WiFiClient.print(WiFiClient.remoteIP());
          WiFiClient.print("</b>");
          WiFiClient.print("<br>IP-Adresse Arduino: ");
          WiFiClient.print(WiFi.localIP());
          WiFiClient.println("</body>");
          WiFiClient.println("</html>");

          // HTTP-Antwort endet mit neuer Zeile
          WiFiClient.println();

          // Seite vollständig geladen -> loop verlassen
          break;
        }
        // neue Zeile -> SeiteAufbauen auf true setzen
        if (Zeichen == '\n') SeiteAufbauen = true;

        // die aktuelle Zeile enthält ein Zeichen
        else if (Zeichen != '\r') SeiteAufbauen = false;
      }
    }
    delay(1);

    WiFiClient.stop();
  }
}

Letzte Aktualisierung: 25. Mrz 2024 @ 15:47