Microcontroller RF-Nano von Keywish

Der RF-Nano von Keywish kommt mit einem nRF24L01 und einem ATMEGA328P-MU Chip daher. In diesem Beitrag stelle ich dir diesen Mikrocontroller genauer vor und zeige dir, wie du Daten senden und empfangen kannst.

Vorstellen und betrieb des RF-Nano von Keywish

Der RF-Nano ist kein Ersatz für einen Mikrocontroller der ESP Reihe, denn dieser arbeitet im 2,4 GHz Funknetz und nicht über Wifi / WLAN.

Bezug

Den RF-Nano von Keywish habe ich für knapp 3,5 $ (3,13 €) über aliexpress bestellt. Bei ebay.de findest du diesen Mikrocontroller bereits für knapp 10 €, was doch ein sehr deutlicher Preisunterschied ist. Und da der Mikrocontroller so oder so aus dem asiatischen Raum geliefert wird, habe ich mich in diesem Fall für die Bestellung bei aliexpress entschieden.

Welche Erfahrungen ich bereits mit den verschiedenen Händlern gesammelt habe, erfährst du in folgendem Beitrag Arduino & Raspberry PI: Shops für Bauteile, Shields und Module. Dort stelle ich dir die Shops vor wo ich meine Bauteile für die Beiträge auf dem Blog bestelle.

Technische Daten des RF-Nano

Der RF-Nano verfügt wie der Arduino Nano über 

  • Chip –  ATmega328P mit 16 MHz
  • Betriebsspannung 5V
  • Eingangsspannung 7-12V (Vin)
  • Stromaufnahme 19mA
  • Speicher
    • Flash Speicher 32 KB (2KB durch den Bootloader reserviert)
    • SRAM 2KB
    • EEPROM 1 KB
  • Ein / Ausgänge
    • digitale Ein / Ausgänge  22
    • PWM Pins 8
    • analoge Eingänge 8
    • max. Stromaufnahme pro Pin 40 mA 
  • Abmaße (L x B) 48 mm x 18 mm
  • Gewicht 7g

Aufbau des RF-Nano

Der RF-Nano verfügt über eine Micro-USB-Buchse für die Verbindung zum Computer bzw. für die Stromzufuhr über ein externes USB Ladekabel.

Vergleich mit einem Arduino Nano V3

Wenn man nun einmal einen Arduino Nano gegen einen RF-Nano stellt, dann erkennt man das dieser über die gleiche Anzahl der Pins verfügt, jedoch fehlen diesem die SPI Pins, dafür ist dort die Antenne des nRF24L01 Moduls verbaut. 

Vergleich Arduino Nano und RF-Nano
Vergleich Arduino Nano und RF-Nano

Die SPI Pins sind auf der Rückseite des RF-Nano verbaut, somit könnte man mit einfachen Lötpunkten dies Abgreifen.

SPI Pins des RF-Nano
SPI Pins des RF-Nano

Pinout

Pinout des Microcontrollers RF-Nano
Pinout des Microcontrollers RF-Nano

nRF24L01

Das verbaute Modul nRF24L01 ist an den folgenden Pins angeschlossen:

PinBezeichnung
D9CSN
D10CE
D4MOSI
D5MISO

einrichten in der Arduino IDE

Der RF-Nano wird zunächst genauso angesprochen wie der Arduino Nano V3, es gibt jedoch wohl zwei Ausführungen, einmal mit dem alten Bootloader und einmal mit dem neuen. Mein Modell ist mit dem neuen.

Einstellungen für den RF-Nano in der Arduino IDE
Einstellungen für den RF-Nano in der Arduino IDE

Zum Testen ob der Mikrocontroller eingerichtet ist kann ein einfacher Sketch zum Blinken der Build-In-Led verwendet werden.

#define led 13

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

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

Wenn das Sketch erfolgreich hochgeladen wurde, dann sollte neben der Power LED die Build-In-Led im 0,5sek. Intervall blinken.

Beispiele / Projekte

Da der Mikrocontroller über einen nRF24L01 Chip verfügt und sonst die gleichen Pins hat wie der Arduino Nano, möchte ich mich auf Beispiele / Projekte mit dem Chip konzentrieren. 

Da wie bereits erwähnt das nRF24L01 Modul ein Funksender bzw. Empfänger ist benötigen wir eine Gegenstelle, hierzu habe ich mir zusätzlich das Erweiterungsboard für einen Arduino Nano sowie ein nRF24L01 Modul besorgt.

Arduino Nano mit nRF24L01 Erweiterungsboard
Arduino Nano mit nRF24L01 Erweiterungsboard

Für die nachfolgenden Beispiele verwende ich die Bibliothek von https://tmrh20.github.io/RF24 du kannst dir diese bequem vom GitHub Repository als ZIP Datei herunterladen. Und in die Arduino IDE integrieren. Wie du eine zusätzliche Bibliothek in der Arduino IDE installierst, habe ich im gleichnamigen Beitrag Arduino IDE, Einbinden einer Bibliothek ausführlich erläutert.

Beispiel I – übertragen von Zeichen

Als Erstes wollen wir einfach ein paar Zeichen senden und empfangen.

Die nachfolgenden Beispiele sind aus dem Tutorial „RF Nano“ entstanden, welches du unter http://fambach.net/rf-nano/ findest.

Sender
#include <SPI.h>

//Bibliotheken für die Kommunikation mit dem nRF24L01 Modul
//https://github.com/nRF24/RF24
#include "nRF24L01.h"
#include "RF24.h"

#define PIN_CE  10
#define PIN_CSN 9

RF24 radio(PIN_CE, PIN_CSN);

uint64_t writeAddress = 100;
uint64_t readAddress = 700;

int mode = 1;

//Konstante für die Größe des Arrays
const int BUFFER_SIZE = 20;
//Das Array für die Daten welche gesendet werden sollen
char textBuffer[20];

//der Index welcher hochgezählt wird
//(Ganzzahliger Wert)
long index = 0;

void setup() {
  //Beginn der seriellen Kommunikation mit 9600 baud
  Serial.begin(9600);
  while(!Serial){}

  Serial.println("initialisiere  nRF24L01 Modul");
  //initialisieren des nRF24L01 Modul
  radio.begin();    
  //setzen der Verbindungsversuche                   
  radio.setRetries(0, 15);
  //setzen des PA Levels(Power Amplifier)
  //mögliche Werte F24_PA_MIN (-18dBm), RF24_PA_LOW (-12dBm), RF24_PA_HIGH (-6dBm) oder RF24_PA_MAX (0dBm)
  radio.setPALevel(RF24_PA_LOW);      
  radio.openWritingPipe(writeAddress);  
  radio.openReadingPipe(1, readAddress);
  //das "nur" die Daten gesendet werden sollen, benötigen wir horchen ob Daten empfangen werden
  radio.stopListening();

}

void loop() {
  //erstellen einer Variable zum den Text zu speichern
  String text;
  //reservieren eines Speicherbereiches für den Text
  //https://www.arduino.cc/reference/de/language/variables/data-types/string/functions/reserve/
  //Der Wert des Speichers muss mit dem vom Empfänger übereinstimmen
  text.reserve(20);
  //Der Variable "text" den Wert "Hallo Welt! " zuweisen
  text = "Hallo Welt! ";
  //Wenn der Index größer als 9999998 dann...
  if(index > 9999998){
    //index auf -1 setzen
    //damit wir uns den else Zweig sparen können initialisiere ich diese Variable auf -1
    index = -1;
  }  
  //incrementieren (erhöhen des Wertes um 1) des Index
  //und dem Zwischenspeicher für den Text hinzufügen
  text += ++index;
  //aus dem Zwischenspeicher ein Array erzeugen
  text.toCharArray(textBuffer, BUFFER_SIZE);
  //senden des Arrays
  radio.write(textBuffer,sizeof(textBuffer));
  
  //ausgeben des Zwischenspeichers (des Textes) auf 
  //der seriellen Schnittstelle
  Serial.print("[transmitter] -> ");
  Serial.println(text);
  
  //eine Pause von 1sek.
  delay(1000);
}
Empfänger
#include <SPI.h>

//Bibliotheken für die Kommunikation mit dem nRF24L01 Modul
//https://github.com/nRF24/RF24
#include "nRF24L01.h"
#include "RF24.h"

#define PIN_CE  10
#define PIN_CSN 9

RF24 radio(PIN_CE, PIN_CSN);

uint64_t writeAddress = 700;
uint64_t readAddress = 100;

//Zwischenspeicher für die empfangenen Daten.
//Es werden 20 Zeichen gespeichert.
char textBuffer[20];

void setup() {
  //Beginn der seriellen Kommunikation mit 9600 baud
  Serial.begin(9600);
  while(!Serial){}
  
  Serial.println("SPI settings");
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_2XCLOCK_MASK);

  Serial.println("initialisiere  nRF24L01 Modul");
  //initialisieren des nRF24L01 Modul
  radio.begin();                     
  //setzen der Verbindungsversuche 
  radio.setRetries(0, 15); 
  //setzen des PA Levels(Power Amplifier)
  //mögliche Werte F24_PA_MIN (-18dBm), RF24_PA_LOW (-12dBm), RF24_PA_HIGH (-6dBm) oder RF24_PA_MAX (0dBm)
  radio.setPALevel(RF24_PA_LOW);      
  radio.openWritingPipe(writeAddress);
  radio.openReadingPipe(1, readAddress);
  //begin der Kommunikation bzw. auf einen Sender warten
  radio.startListening();             
}


void loop(){
   //solange Daten empfangen werden...
    while (radio.available()){
      //lesen der Daten und ablegen in den Zwischenspeicher
      //es werden zunächst die Daten gesammelt bis der Zwischenspeicher voll ist
      //der "Füllstand" wird initial durch die Größe des Zwischenspeichers ermittelt.
      //sollten also mehr Daten empfangen werden muss die Größe (auf beiden Seiten der Kommunikation)
      //angepasst werden.
      radio.read( textBuffer, sizeof(textBuffer));
      //ausgeben der Daten auf die serielle Schnittstelle
      Serial.println(textBuffer);
    }
}
Download

Hier nun die Sketche zum bequemen Download.

Ausgabe im seriellen Monitor der Arduino IDE

Wenn beide Programme / Sketche gestartet werden, dann solltest du folgende Ausgabe im seriellen Monitor der Arduino IDE finden.

Screenshot - serieller Monitor der Arduino IDE
Screenshot – serieller Monitor der Arduino IDE

Beispiel II – übertragen und anzeigen von Messwerten

Wenn einfache Zeichenketten per Funk übertragen werden können, dann natürlich auch Messwerte. Im nachfolgenden Beispiel sende ich die Messwerte eines DHT11 Sensors per Funkt an den RF-Nano welcher diese Daten auf einem OLED Display anzeigt.

Für den Aufbau verwende ich ein 400 Pin Breadboard, auf diesem ist genug Platz um die benötigten Bauteile für die Schaltung unterzubringen.

Sender

Für den Aufbau benötigst du folgende Bauteile:

  • 1x DHT11 Sensor,
  • 3x Breadboardkabel, 10cm, männlich – weiblich,

Zum Senden der Daten verwende ich wie auch im ersten Beispiel einen Arduino Nano mit einer Erweiterungsplatine und einem nRF24L01 Modul. Die Erweiterungsplatine verfügt über Schraubklemmen, an welche man bequem die Breadboardkabel anschließen (verschrauben) kann.

Arduino Nano V3 auf Erweiteurngspaltine mit nRF24L01 Modul und DHT11 Sensor
Arduino Nano V3 auf Erweiteurngspaltine mit nRF24L01 Modul und DHT11 Sensor
Anschluß des DHT11 Sensors

Der DHT11 Sensor verfügt über 3 Pins welche wie folgt an den Arduino Nano angeschlossen werden.

Wenn man bessere bzw. exakte Daten haben möchte, so sollte man auf einen DHT22 Sensor zurückgreifen. Der DHT22 Sensor kann fast 1:1 mit dem DHT11 ausgetauscht werden. Es muss „nur“ eine Konstante im Quellcode geändert werden (dazu aber später mehr).

Empfänger

Für den Aufbau benötigst du folgende Bauteile:

  • 1x OLED Display,
  • 4x Breadboardkabel, 10cm, männlich – männlich,
RF-Nano mit 0,91" OLED Display
RF-Nano mit 0,91″ OLED Display

Datenstruktur

Bevor wir mit dem eigentlichen Programm / Sketch loslegen, müssen wir eine Datenstruktur festlegen. Der DHT11 / DHT22 Sensor kann die Temperatur in Grad Celsius, Grad Fahrenheit sowie die relative Luftfeuchtigkeit messen. Je nach verwendetem Model (DHT11 oder DHT22) sind diese mit mehr Nachkommastellen.

Vorschlag 1 – Daten Abwechselnd senden

Das einfachste ist es, die Daten nacheinander zu senden. Hier muss man nur die Werte erfassen und einen Index von max. 3 hochzählen und prüfen, ob als Letztes ein Wert vom Typ X gesendet wurde. Ein weiterer Vorteil ist es, dass hier nur das Programm des Senders angepasst werden muss, denn der Empfänger kann fast so bleiben.

Sender
#include <SPI.h>

//Bibliotheken für die Kommunikation mit dem nRF24L01 Modul
//https://github.com/nRF24/RF24
#include "nRF24L01.h"
#include "RF24.h"

//DHT11 Bibliothek
#include <DHT.h>
#include <DHT_U.h>

#define PIN_CE  10
#define PIN_CSN 9

RF24 radio(PIN_CE, PIN_CSN);

#define dhtPin 2
//Wenn ein DHT22 Sensor verwendet wird,
//muss hier der Wert DHT22 gesetzt werden.
#define dhtType DHT11

//Objekt vom Typ DHT erzeugen
DHT dht(dhtPin, dhtType);

uint64_t writeAddress = 100;
uint64_t readAddress = 700;

int mode = 1;

//Konstante für die Größe des Arrays
const int BUFFER_SIZE = 20;
//Das Array für die Daten welche gesendet werden sollen
char textBuffer[20];

//der Index welcher hochgezählt wird
//(Ganzzahliger Wert)
unsigned int index = 0;

void setup() {
  //Beginn der seriellen Kommunikation mit 9600 baud
  Serial.begin(9600);
  while (!Serial) {}

  Serial.println("initialisiere  nRF24L01 Modul");
  //initialisieren des nRF24L01 Modul
  radio.begin();
  //setzen der Verbindungsversuche
  radio.setRetries(0, 15);
  //setzen des PA Levels(Power Amplifier)
  //mögliche Werte F24_PA_MIN (-18dBm), RF24_PA_LOW (-12dBm), RF24_PA_HIGH (-6dBm) oder RF24_PA_MAX (0dBm)
  radio.setPALevel(RF24_PA_LOW);
  radio.openWritingPipe(writeAddress);
  radio.openReadingPipe(1, readAddress);
  //das "nur" die Daten gesendet werden sollen, benötigen wir horchen ob Daten empfangen werden
  radio.stopListening();

  //begin des lesens vom DHT Sensor
  dht.begin();
}

void loop() {
  ++index;
  String text;
  switch (index) {
    case 1: text = readTempCelsius(); break;
    case 2: text = readTempFahrenheit(); break;
    case 3: text = readDht11Humidity() ; break;
  }

  //Wenn der Index größer gleich 3 ist dann soll wieder mit 0 begonnen werden.
  if (index >= 3) {
    index = 0;
  }

  //senden der Daten
  sendDHT11Data(text);
}

//Lesen der Temperatur in Grad Celsius
String readTempCelsius() {
  float tempCelsius = dht.readTemperature();
  String text;
  text.reserve(20);
  text = "Temp: ";
  //Damit die Gleitkommazahl nur mit 3 Nachkommastellen angezeigt werden muss im 
  //Konstuktur dieses übergeben werden.
  text += String(tempCelsius,3);
  text += "*C";
  return text;
}

//Lesen der Temperatur in Fahrenheit
String readTempFahrenheit() {
  float tempFahrenheit = dht.readTemperature(true);
  String text;
  text.reserve(20);
  text = "Temp: ";
  //Damit die Gleitkommazahl nur mit 3 Nachkommastellen angezeigt werden muss im 
  //Konstuktur dieses übergeben werden.
  text += String(tempFahrenheit, 3);
  text += "*F";
  return text;
}

//Lesen der relativen Luftfeuchtigkeit
String readDht11Humidity() {
  float humidity = dht.readHumidity();
  String text;
  text.reserve(20);
  text = "Humidity: ";
  //Damit die Gleitkommazahl nur mit 3 Nachkommastellen angezeigt werden muss im 
  //Konstuktur dieses übergeben werden.
  text += String(humidity, 3);
  text += "%";
  return text;
}

//Senden der Daten
void sendDHT11Data(String text) {
  text.toCharArray(textBuffer, BUFFER_SIZE);
  radio.write(textBuffer, sizeof(textBuffer));

  //ausgeben des Zwischenspeichers (des Textes) auf
  //der seriellen Schnittstelle
  Serial.print("[transmitter] -> ");
  Serial.println(text);

  //eine Pause von 1sek.
  delay(1000);
}
Empfänger

Zum Vorschlag 1 des Senders werden nur die Daten empfangen und statt auf der seriellen Schnittstelle geben wir diese Daten auf dem OLED Display aus. Dieses habe ich bereits im Beitrag Arduino Lektion 76: 0,91 Zoll OLED Display gemacht und kann somit auf das Programm teilweise zurückgreifen.

#include <SPI.h>

//Bibliotheken für die Kommunikation mit dem nRF24L01 Modul
//https://github.com/nRF24/RF24
#include "nRF24L01.h"
#include "RF24.h"

//Bibliothek zum betreiben des OLED Displays
#include <Wire.h> //Bibliotheken für den betrieb des Displays 
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define PIN_CE  10
#define PIN_CSN 9

RF24 radio(PIN_CE, PIN_CSN);

uint64_t writeAddress = 700;
uint64_t readAddress = 100;

//Zwischenspeicher für die empfangenen Daten.
//Es werden 20 Zeichen gespeichert.
char textBuffer[20];

void setup() {
  //Beginn der seriellen Kommunikation mit 9600 baud
  Serial.begin(9600);
  while (!Serial) {}

  Serial.println("SPI settings");
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_2XCLOCK_MASK);

  Serial.println("initialisiere  nRF24L01 Modul");
  //initialisieren des nRF24L01 Modul
  radio.begin();
  //setzen der Verbindungsversuche
  radio.setRetries(0, 15);
  //setzen des PA Levels(Power Amplifier)
  //mögliche Werte F24_PA_MIN (-18dBm), RF24_PA_LOW (-12dBm), RF24_PA_HIGH (-6dBm) oder RF24_PA_MAX (0dBm)
  radio.setPALevel(RF24_PA_LOW);
  radio.openWritingPipe(writeAddress);
  radio.openReadingPipe(1, readAddress);
  //begin der Kommunikation bzw. auf einen Sender warten
  radio.startListening();

  //Begin der Kommunikation mit dem OLED Displays
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 
  display.display(); 
  display.clearDisplay();
}


void loop() {
  //solange Daten empfangen werden...
  while (radio.available()) {
    //lesen der Daten und ablegen in den Zwischenspeicher
    //es werden zunächst die Daten gesammelt bis der Zwischenspeicher voll ist
    //der "Füllstand" wird initial durch die Größe des Zwischenspeichers ermittelt.
    //sollten also mehr Daten empfangen werden muss die Größe (auf beiden Seiten der Kommunikation)
    //angepasst werden.
    radio.read( textBuffer, sizeof(textBuffer));
    //Displayinhalt löschen
    //wird benötigt damit die letzten angezeigten Daten entfernt werden
    display.clearDisplay();
    //Textgröße einstellen
    display.setTextSize(1);
    //Textfarbe einstellen
    //Das Display kann 2 Farbig darstellen,
    //d.h. das Display kann invertiert werden
    display.setTextColor(WHITE);
    //Position des Cursors zum schreiben in 
    //die erste Zeile und erste Spalte setzen
    display.setCursor(0,0);
    //Ausgeben der Zeichenkette
    display.println(textBuffer);
    //Darstellen / aktualisieren des Displays
    display.display();
    //eine Pause von einer Sekunde
    delay(1000);
  }
}

Video

Daten eines DHT11 Sensors per nRF24L01 versenden und emfangen
Vorschlag 2 – alle Daten in einem „rutsch“ senden

Wenn man alle Daten in einem „rutsch“ senden möchte, muss man diese Daten strukturiert aufarbeiten, damit diese später wieder geparst werden können. Wir haben im ersten Vorschlag die Daten einzeln gesendet. Jedoch haben wir diese immer zu einem Block von 20 Zeichen zusammengefasst. Wenn wir also nun diese Daten zu Blöcken bilden wie:

22.000;71.600;40.000

Wir haben also 3 Blöcke welche wir später auswerten wollen. Wir könnten also nun mit einer For-Schleife diese Zeichenkette nach einem Semikolon „durchsuchen“ und anhand der Position dann die einzelnen Werte entnehmen. ODER wir zerlegen die Zeichenkette an definierten Stellen die größe der Blöcke wird sich ja nicht ändern.

Block 1 – Temperatur in Celsius – von 0 bis 6
Block 2 – Temperatur in Fahrenheit – von 7 bis 13
Block 3 – rel. Luftfeuchtigkeit – ab 14

Sender

Da wir die Daten zu einem großen Block zusammen fassen, brauchen wir nur die Funktion loop wiefolgt anpassen.
Die Daten werden wie oben gezeigt mit einem Semikolon getrennt. (Diese beiden zusätzlichen Zeichen müssen wir beim Empfänger zusätzlich berücksichtigen!)

#include <SPI.h>

//Bibliotheken für die Kommunikation mit dem nRF24L01 Modul
//https://github.com/nRF24/RF24
#include "nRF24L01.h"
#include "RF24.h"

//DHT11 Bibliothek
#include <DHT.h>
#include <DHT_U.h>

#define PIN_CE  10
#define PIN_CSN 9

RF24 radio(PIN_CE, PIN_CSN);

#define dhtPin 2
//Wenn ein DHT22 Sensor verwendet wird,
//muss hier der Wert DHT22 gesetzt werden.
#define dhtType DHT11

//Objekt vom Typ DHT erzeugen
DHT dht(dhtPin, dhtType);

uint64_t writeAddress = 100;
uint64_t readAddress = 700;

int mode = 1;

//Konstante für die Größe des Arrays
const int BUFFER_SIZE = 26;
//Das Array für die Daten welche gesendet werden sollen
char textBuffer[26];

//der Index welcher hochgezählt wird
//(Ganzzahliger Wert)
unsigned int index = 0;

void setup() {
  //Beginn der seriellen Kommunikation mit 9600 baud
  Serial.begin(9600);
  while (!Serial) {}

  Serial.println("initialisiere  nRF24L01 Modul");
  //initialisieren des nRF24L01 Modul
  radio.begin();
  //setzen der Verbindungsversuche
  radio.setRetries(0, 15);
  //setzen des PA Levels(Power Amplifier)
  //mögliche Werte F24_PA_MIN (-18dBm), RF24_PA_LOW (-12dBm), RF24_PA_HIGH (-6dBm) oder RF24_PA_MAX (0dBm)
  radio.setPALevel(RF24_PA_LOW);
  radio.openWritingPipe(writeAddress);
  radio.openReadingPipe(1, readAddress);
  //das "nur" die Daten gesendet werden sollen, benötigen wir horchen ob Daten empfangen werden
  radio.stopListening();

  //begin des lesens vom DHT Sensor
  dht.begin();
}

void loop() {
  ++index;
  String text;
  text += readTempCelsius();
  text += ";";
  text += readTempFahrenheit();
  text += ";";
  text += readDht11Humidity();
  
  //senden der Daten
  sendDHT11Data(text);
}

//Lesen der Temperatur in Grad Celsius
String readTempCelsius() {
  float tempCelsius = dht.readTemperature();
  String text;
  text.reserve(8);
  //Damit die Gleitkommazahl nur mit 3 Nachkommastellen angezeigt werden muss im 
  //Konstuktur dieses übergeben werden.
  return String(tempCelsius,3);
}

//Lesen der Temperatur in Fahrenheit
String readTempFahrenheit() {
  float tempFahrenheit = dht.readTemperature(true);
  String text;
  text.reserve(8);
  //Damit die Gleitkommazahl nur mit 3 Nachkommastellen angezeigt werden muss im 
  //Konstuktur dieses übergeben werden.
  return String(tempFahrenheit, 3);
}

//Lesen der relativen Luftfeuchtigkeit
String readDht11Humidity() {
  float humidity = dht.readHumidity();
  String text;
  text.reserve(8);
  //Damit die Gleitkommazahl nur mit 3 Nachkommastellen angezeigt werden muss im 
  //Konstuktur dieses übergeben werden.
  return String(humidity, 3);
}

//Senden der Daten
void sendDHT11Data(String text) {
  text.toCharArray(textBuffer, BUFFER_SIZE);
  radio.write(textBuffer, sizeof(textBuffer));
  Serial.println(sizeof(textBuffer));
  
  //ausgeben des Zwischenspeichers (des Textes) auf
  //der seriellen Schnittstelle
  Serial.print("[transmitter] -> ");
  Serial.println(text);

  //eine Pause von 1sek.
  delay(1000);
}
Empfänger
#include <SPI.h>

//Bibliotheken für die Kommunikation mit dem nRF24L01 Modul
//https://github.com/nRF24/RF24
#include "nRF24L01.h"
#include "RF24.h"

//Bibliothek zum betreiben des OLED Displays
#include <Wire.h> //Bibliotheken für den betrieb des Displays 
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define PIN_CE  10
#define PIN_CSN 9

RF24 radio(PIN_CE, PIN_CSN);

uint64_t writeAddress = 700;
uint64_t readAddress = 100;

//Zwischenspeicher für die empfangenen Daten.
//Es werden 26 Zeichen gespeichert.
char textBuffer[26];

void setup() {
  //Beginn der seriellen Kommunikation mit 9600 baud
  Serial.begin(9600);
  while (!Serial) {}

  Serial.println("SPI settings");
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_2XCLOCK_MASK);

  Serial.println("initialisiere  nRF24L01 Modul");
  //initialisieren des nRF24L01 Modul
  radio.begin();
  //setzen der Verbindungsversuche
  radio.setRetries(0, 15);
  //setzen des PA Levels(Power Amplifier)
  //mögliche Werte F24_PA_MIN (-18dBm), RF24_PA_LOW (-12dBm), RF24_PA_HIGH (-6dBm) oder RF24_PA_MAX (0dBm)
  radio.setPALevel(RF24_PA_LOW);
  radio.openWritingPipe(writeAddress);
  radio.openReadingPipe(1, readAddress);
  //begin der Kommunikation bzw. auf einen Sender warten
  radio.startListening();

  //Begin der Kommunikation mit dem OLED Displays
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();
  display.clearDisplay();
}


void loop() {
  //solange Daten empfangen werden...
  while (radio.available()) {
    //lesen der Daten und ablegen in den Zwischenspeicher
    //es werden zunächst die Daten gesammelt bis der Zwischenspeicher voll ist
    //der "Füllstand" wird initial durch die Größe des Zwischenspeichers ermittelt.
    //sollten also mehr Daten empfangen werden muss die Größe (auf beiden Seiten der Kommunikation)
    //angepasst werden.
    radio.read( textBuffer, sizeof(textBuffer));
    Serial.println(sizeof(textBuffer));
    Serial.println(textBuffer);
    

    String text;
    text.reserve(62);
    text = textBuffer;
    Serial.println(text);
    String tempCelsius = "Temp: ";
    tempCelsius += text.substring(0, 6);
    tempCelsius += "*C";
     
    String tempFahrenheit = "Temp: ";
    tempFahrenheit += text.substring(7,13);
    tempFahrenheit += "*F";

    
    String humidity = "Humidity: ";
    humidity += text.substring(14);
    humidity += "%";
    
    displayText(tempCelsius);
    delay(750);
    displayText(tempFahrenheit);
    delay(750);
    displayText(humidity);
    delay(750);
  }
}

void displayText(String text) {
  //Displayinhalt löschen
  //wird benötigt damit die letzten angezeigten Daten entfernt werden
  display.clearDisplay();
  //Textgröße einstellen
  display.setTextSize(1);
  //Textfarbe einstellen
  //Das Display kann 2 Farbig darstellen,
  //d.h. das Display kann invertiert werden
  display.setTextColor(WHITE);
  //Position des Cursors zum schreiben in
  //die erste Zeile und erste Spalte setzen
  display.setCursor(0, 0);
  //Ausgeben der Zeichenkette
  display.println(text);
  Serial.println(text);
  //Darstellen / aktualisieren des Displays
  display.display();
}

Das Ergebnis auf dem Display ist das gleiche, nur werden die Daten in diesem Fall mit einem mal gesendet.

Daten des DHT11 Sensors per nRF24L01 Modul auf einem OLED Display angezeigt
Daten des DHT11 Sensors per nRF24L01 Modul auf einem OLED Display angezeigt

Reichweite

Mit den beiden Sketchen / Programmen aus dem „Beispiel I – übertragen von Zeichen“ kann man gut die Reichweite der Module testen. Da ich die Module später für eine kleine Wetterstation nutzen möchte (dazu erfolgt ein separater Beitrag) muss ich prüfen, inwieweit dieses überhaupt nutzbar wäre. 

Bei einer Wetterstation ist es sinnvoll diese soweit wie möglich (und nötig) von beheizten Gebäuden aufzubauen, denn nur so erhält man zuverlässige Werte der Temperatur.

Innerhalb eines Gebäudes

In der Wohnung (Gebäude von ca. 1980, Backsteinwände, Decke mit Putz und Holzdielen) reicht die Kommunikation zwischen zwei Räumen jedoch über eine Etage (ca. 3,5 m) nicht mehr.

Außerhalb eines Gebäudes (bebautes Gelände)

Der zweite Test ist, dass, der Sender außerhalb des Gebäudes ist und der Empfänger innerhalb. Ich habe hier einmal den Sender auf dem Hof gelegt und der Empfänger ist hinter einem Fenster.

Reichweitentest mit dem RF-Nano
Reichweitentest mit dem RF-Nano

Der Abstand zwischen Sender und Empfänger betrug ca. 5m.

Auf freiem Feld

Die ersten beiden Tests konnte ich mit einer Stromversorgung von 230V realisieren, da diese beiden im bzw. am Gebäude stattgefunden haben. Im dritten Test ging es aufs freie Feld, hier musste ich auf eine bzw. zwei Powerbanks zurückgreifen. 

einfache Powerbanks für den betrieb eines Microcontrollers
einfache Powerbanks für den betrieb eines Microcontrollers

Jedoch musste ich feststellen, dass nicht jede Powerbank zuverlässig den Strom liefert welcher für die Mikrocontroller benötigt werden. Die schwarze von der Marke „PowerAdd“ (ca. 6 € über amazon.de) funktionierte am RF-Nano gar nicht bzw. startete dieser immer wieder neu. Die weiße Powerbank gibt es bei Tedi für knapp 5 € (Leistung 2200mAh bei 3,7V) und funktionierte deutlich besser. Daher werde ich einen Mikrocontroller mit einer 9V Blockbatterie betreiben und den RF-Nano mit einer Powerbank (die von Tedi). 

In näherer Zukunft werde ich mir wohl mal etwas mehr Geld investieren und zwei vernüftige Powerbanks besorgen.

Da es ein offenes aber auch bebautes Gelände gibt und ein offenes Gelände (freies Feld) möchte ich diesen Test unterteilen. 

bebautes, offenes Gelände

Zunächst prüfe ich wieweit der Sender reicht, wenn man im bebauten, offenen Gelände den Sender und Empfänger betreibt. Dabei wird der Sender quasi „Sichtkontakt“ mit dem Empfänger haben.

Reichweitentest mit dem RF-Nano im offenen, bebautem Gelände
Reichweitentest mit dem RF-Nano im offenen, bebautem Gelände

Es wurde eine maximale Reichweite von 26 Meter erreicht.

offenes Gelände

Der Idealzustand für eine Funkübertragung ist wohl das offene Gelände ohne irgendwelche störende Gebäude und Überlandleitungen (Strommasten).

Test der Reichweite des RF-Nano in offenem Gelände
Test der Reichweite des RF-Nano in offenem Gelände

Auf freiem Feld konnte ich eine Reichweite von knapp 20 Meter erreicht werden.

Fazit

Da die Reichweite für mein Projekt „Wetterstation“ doch sehr dürftig ist, werde ich wohl auf eine Mischung von nRF24L01 & WLAN zurückgreifen, denn das ermöglicht es mir die doch sehr stromsparende Funkübertragung zu nutzen und das Signal in das bereits bestehende WLAN zu integrieren.

Ansonsten ist der RF-Nano ein kleiner feiner Mikrocontroller welcher dem Arduino Nano in nichts nachsteht. Der Preis liegt derzeit (stand 18.01.2020) zwischen 3,63 € über aliexpress.com und knapp 11 € über ebay.de. Ich würde daher zu einem Kauf bei aliexpress.com raten. Jedoch muss man die langen Lieferzeiten einplanen und wenn etwas schiefläuft auch eine sehr schleppende bis hin zu gar keine Kommunikation mit dem Verkäufer „einrechnen“.

6 Kommentare

  1. Hallo,
    kannst Du mir sagen wie ich die Kopplung eines BLE Nano mit einem Andriod Handy hin bekomme? Der BLE verlangt per AT Befehl ein sechs stelliges Passwort. Der BLE wir im Handy angezeigt, nur die Kopplung scheitert weil das Handy nur ein vier stelliges PW versteht.
    Ist die Kopplung nicht gewollt oder nicht vorgesehen oder bin ich hier ganz und gar auf dem Holzpfad unterwegs.

    Gruß Eckard!

    1. Hi,

      den BLE Nano habe ich noch nicht aber ist auf den Weg.
      Ich habe diverse Bluetooth Module jedoch werden dort nur 4 Stellige Passwörter verlangt.

      Gruß,

      Stefan Draeger

  2. Hallo,
    hier die Fehlermeldung, wenn man den BLE ein vier stelliges PW anbietet.
    Baudeinstellung auf 9600 , NL und CR
    Auf Großschreibung achten. HC5 u. 6 Module verstehen auch Kleinschreibung. So ist meine Erfahrung.

    AT+PASS=0000

    EEROR
    SetPassWord
    Must 6bit length
    Must 0~10 numble

    Gruß Eckard

  3. Ich habe den Bootloader mit ein falsches Program leider zerstört. Gibt es mit dieser Karte die möglichkeit den bootloader wieder zu flaschen?

    1. Hi R.,

      auf der Rückseite des Microcontroller solltest du den ICSP Anschluss hier könntest du einen passenden Adapter anlöten und einen neuen Bootloader über den PC hochladen.

      Gruß,

      Stefan

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert