DHT 11 Werte per 433 Mhz Senden und Empfangen

Hallo zusammen,

ich nutze einen Arduino Nano als Sender:

Sensor: DHT 11 an PIN 2
Sender: 433 mhz an PIN 8

Zurzeit möchte ich den Empfangenen Wert im Seriellen Monitor Anzeigen und sie später auf einem OLED Display anzeigen. (das wird wohl noch etwas dauen :slight_smile:

Auf dem Sender wird im Seriellen Monitor schon das richtige Angezeigt :
Temp:
29.00
C
HUM:
46.0

Auf dem Empfänger wird im Seriellen Monitor leider nur ein Punkt und ein Quadrat angezeigt.

Liegt es daran das ich krampfhaft versuche den Wert direkt zu versenden ohne Ihn in einen String umzuwandeln ? ( das habe ich noch nicht bekommen).

Ich hoffe jemand kann mir bei meinem Problem Weiter Helfen.

Hier der Sketch des Senders:

#include <dht11.h>
#include <VirtualWire.h>

dht11 DHT11;
#define DHT11PIN 2

void setup() {


Serial.begin(9600);  

vw_setup(2000);
vw_set_tx_pin(8);

}

void loop() {

int chk = DHT11.read(DHT11PIN);

Serial.println("Temp: ");
Serial.println((float)DHT11.temperature, 2);
Serial.println(" C");
delay(500);

Serial.println("HUM: ");
Serial.println((float)DHT11.humidity, 2);
Serial.println(" C");

char msg[2] = {DHT11.humidity, 2};
vw_send((uint8_t *)msg, 2);
 vw_wait_tx(); // Wait until the whole message is gone


delay(5000);



}

Hier der Sketch des Empfängers:

#include <VirtualWire.h>


int i;
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

void setup()
{
 Serial.begin(9600);
 Serial.println("device is ready...");

 vw_set_rx_pin(12);
 vw_setup(2000); // bps
 vw_rx_start();
}

void loop()
{


 if (vw_get_message(buf, &buflen)) { // überprüfen ob eine Nachricht eingegangen ist
   for (i=0;i< buflen;i++) {
      Serial.print((char)buf[i]);    // Nachricht aus buf ausgeben
   }
   Serial.println(" ");
 }
}

Langsam bin ich verzweifelt, massages wie Hallo oder ähnliches habe bereits hinbekommen, aber einen ausgelesenen wert aus dem DHT 11 leider noch nicht, zu mal er irgendwann auch beide werte übertragen sollte. Wichtig ist vielleicht noch zu sagen das DHT 11 ohne Kommastellen die werte ausgibt (erstmal schwierig genug :confused: )

Sender_mit_DHT11.ino (540 Bytes)

Arduino_uno_empf_nger.ino (501 Bytes)

setze deinen Sketch bitte hier in Code-Tags rein, Schaltfläche </> dazu verwenden. Das kannst du auch noch nachträglich machen.

Dann wird dieser Sketch auch fehlerfrei und formatiert hier angezeigt.

Und dein "Messwert" muss als "char" gesendet werden.

dazu legst du dir erst eine Variable mit max. Länge an.

Danach wandelst du den Messwert in char und übergibst diesen an die Variable und sendest anschließend den char-Wert.

Das Senden wird in den Beispiel auch sehr gut beschrieben.

Mehrere Angaben kannst du per "strcat" in eine gemeinsame char-Variable zusammenfügen.
Achte immer darauf, dass die Variable groß genug gewählt wird.

HotSystems:
Und dein "Messwert" muss als "char" gesendet werden.

Sehe ich nicht so (die Werte passen nicht in ein Byte und könnten genauso binär übertragen werden).

HotSystems:
dazu legst du dir erst eine Variable mit max. Länge an.

Geht nicht, chars haben immer die Länge von einem Byte.

Zu unterschlagen, dass es du mit "char" "char-Arrays" meinst, ist sehr sinnentstellend.

Whandall:
Zu unterschlagen, dass es du mit "char" "char-Arrays" meinst, ist sehr sinnentstellend.

Dafür korrigierst du es ja, danke...

char msg[2] = {DHT11.humidity, 2};

Das ist totaler Schwachsinn. Erstens ist das Array zu klein (man braucht mindestens Platz für die Anzahl aller Zeichen + 1). Zweitens kannst du nicht einfach einen Float/Double in ein char Array Schreiben. Das mit ,2 geht nur mit print()/println()

Um Float in einen C String zu konvertieren gibt es dtostrf():
https://www.mikrocontroller.net/topic/86391
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42

width ist dabei die Mindestbreite aller Zeichen. Wenn du also 2 Vorkommastellen + 2 Nachkommastellen hast, dann ist das 5, da der Punkt noch dazukommt. Wenn der String kleiner wäre, wird mit Leerzeichen aufgefüllt.

Hallo zusammen,
danke schon mal für Antworten.

Hätte noch erwähnen sollen das ich erstmal den DHT 11 nutze, er hat keine Nach-Komma Stellen. (kann auch leider nicht im Minus bereich Messen), irgendwann werde ich wohl mal auf DHT 22 umsteigen.

Leider finde ich auch keine Anschaulichen Beispiele.

Das Projekt war so geplant : Das der Nano die Temperatur zum Uno überträgt und dieser die Empfangene Temperatur und Luftfeuchtigkeit auf einem OLED anzeigt. Das eben per 433 MhZ.

Wenn ich es richtig verstanden habe dann muss ich für einen zweistelligen Wert kein Float zu String umwandeln.

Ich frage mich ebenso ob es wirklich nur funktioniert diesen wert per String zu versenden.
Gibt es keinen Einfacheren weg? (ich habe Projekte gesehen die nutzen die RCSwitch.h.

Was sagt Ihr ist die Empfangsseite denn bis jetzt richtig?

Danke für eure Hilfe

(Ich habe vor ein Paar Monaten angefangen mich mit dem Arduino zu beschäftigen - es sei noch gesagt das ich bisher keine Vorkenntnisse in Programmiersprachen hatte :slight_smile: , mein letztes Projekt war ein RFID Türschloss Öffner - das super Funktioniert. )

Die DHT Library verwaltet einen Float/Double. Das hast du ja in deinem Sketch auch. Was hast du denn gedacht wozu das ,2 bei print()/println() da ist? Hier wird sogar noch explizit auf float gecastet:

Serial.println((float)DHT11.humidity, 2);

Wenn du meinst keine Nachkommastellen zu brauchen, caste den Wert auf int. Dann werden die Nachkommastellen abgeschnitten. Dann kannst du itoa() zur Konvertierung verwenden (integer to ascii):
http://www.cplusplus.com/reference/cstdlib/itoa/

Auch hier darauf achten, dass das Array groß genug ist und daran denken, dass C Strings Null-terminiert sind (also das Array mindestens 1 größer als die Anzahl der sichtbaren Zeichen sein muss)

Oky, vielen Dank!

oh :o , das ist ja gar nicht so "leicht" zu verstehen.

Das heisst ich muss in jedem Fall den wert in einen String umwandeln um ihn per vw_send zu senden?

entweder per : Float to String? ( leider sind hier auch alle seiten und beispiele die man ggf. adaptieren kann sehr kompliziert oder in Englisch)

oder per: sprintf(str,"%d",value) converts to decimal base, leider Steige ich auch hier nicht so wirklich durch :slight_smile:

Hast du vielleicht ein Praktikabeles Beispiel?

ist die RCSwitch Lib in der Lage diesen Wert "Automatisch" umzuwandeln?

Leider habe ich nur im meinem Fachabi - leichte einblicke in C bekommen können :slight_smile:
SPS - Chemietechnik war da doch einfacher :slight_smile:

Ich glaube die Idee des 433 Mhz Senders war keine gute Idee, bei WLAN z.b gäbe es ja dieses Problem wohl nicht.

Starcounter:
Ich frage mich ebenso ob es wirklich nur funktioniert diesen wert per String zu versenden.

Da kommst du nicht drum herum. :wink:
Und wenn es nicht funktioniert, gibt es doch immer "Fehlermeldungen", die helfen dann weiter.

Gibt es keinen Einfacheren weg? (ich habe Projekte gesehen die nutzen die RCSwitch.h.

Mit RCSwitch funktioniert es nicht, das ist, wie der Name sagt, zu ferngesteuerten Schalten gedacht.

Starcounter:
Ich glaube die Idee des 433 Mhz Senders war keine gute Idee, bei WLAN z.b gäbe es ja dieses Problem wohl nicht.

Das sehe ich nicht so, da musst du es ähnlich anstellen und bekommst mit dem WLan-Modul evtl. ganz andere Probleme.

Es geht auch ohne Strings, aber das verstehst du dann noch weniger. Vor allem wenn man die Daten am anderen Ende direkt anzeigen möchte ist es praktisch wenn man gleich Strings hat. Und wenn nicht gibt es auch Funktionen um die Strings wieder in Zahlen zu konvertieren.

Ich habe dir doch zwei einfache Funktionen gezeigt um Werte in Strings zu konvertieren. dtostrf() für Gleitkommazahlen und itoa() für Integer. Auf beiden Seiten sind alle Parameter erklärt und es sind Beispiele dabei.

printf() und deren Derivate gehen für Integer-Zahlen (aber auf den AVR Arduinos nicht für Floats!). Wenn du aber schon die anderen Funktionen nicht verstehst, dann wird es mit printf() auch nichts. Die Funktion ist wegen der sehr vielen Format-Optionen sehr kompliziert. Und braucht auch viel Speicher.

Hier ist etwas allgemeiner Test Code rein für die Konvertierung:

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

  char buffer[10];

  float temp1 = 1.5;
  float temp2 = 10.5;
  float temp3 = 12.34;

  dtostrf(temp1, 4, 1, buffer);     //mindestens 4 Zeichen. 1 Nachkommastelle
  Serial.println(buffer);
  dtostrf(temp2, 4, 1, buffer);
  Serial.println(buffer);
  dtostrf(temp3, 5, 2, buffer);     //mindestens 5 Zeichen. 2 Nachkommastellen
  Serial.println(buffer);

  itoa((int)temp1, buffer, 10);
  Serial.println(buffer);
  itoa((int)temp2, buffer, 10);
  Serial.println(buffer);

}

void loop() 
{
}

Danke dir.

Ich hab da ein paar fragen :slight_smile:

Ja nach-Komma Stellen währen schon gut! (vorallem wenn an irgendwann DHT 22 nutzen möchte)
Der DHT 11 kann ja keine, kommt dann quatsch heraus oder passt das ?

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

  char buffer[10];         // Hier wird ein Array (charckter) angelegt richtig ? , was definiert die 10 ? //

  float temp1 = 1.5;
  float temp2 = 10.5;
  float temp3 = 12.34;

  dtostrf(temp1, 4, 1, buffer);     // wird hier der String erzeugt für 1,5 grad? und in buffer gehalten? was ist hier ,4 und ,1 ? //
  Serial.println(buffer);              // hier wird in den seriellen Monitor der gehaltene wert gesendet?//
  dtostrf(temp2, 4, 1, buffer);      wird hier der String erzeugt für 10,5 grad? und in buffer gehalten? was ist hier ,4 und ,1 ? //
  Serial.println(buffer);
  dtostrf(temp3, 5, 2, buffer);     //mindestens 5 Zeichen. 2 Nachkommastellen
  Serial.println(buffer);

  itoa((int)temp1, buffer, 10);    // was wird hier genau gemacht? //
  Serial.println(buffer);
  itoa((int)temp2, buffer, 10);
  Serial.println(buffer);

}

void loop() 
{
}

kann ich z.b an stelle von 10,5 den read befehl einsetzten?

(DHT11.temperature)

verstehe ich es richtig das ich dann schon :

vw_send((uint8_t *)temp1, buffer, 10,);

durchführen kann?

Müsste es dann zur anzeige an einem Display nach dem Empfang wieder zurück gerechnet werden?

Mein problem scheint ja wirklich nur der Sende teil zu sein :

char msg[2] = {DHT11.humidity, 2};
vw_send((uint8_t *)msg, 2);
  vw_wait_tx(); // Wait until the whole message is gone

Sorry wenn ich so intensiv nachfrage :slight_smile:
Ich möchte das gerne verstehen.

Liebe Grüße

Starcounter:
Mein problem scheint ja wirklich nur der Sende teil zu sein :

Nein, dein Problem ist, du liest die gemachten Posts nicht richtig durch und versuchst nicht, dich selbst ein wenig über Google schlau zu machen.

Viele deiner Fragen wurden schon beantwortet und auch entsprechend dokumentiert.
Den Rest findest du bei Google mit dem richtigen Suchbegriff.

Z.B. "dtostrf Erklärung"

Ein wenig Eigeninitiative sollte man schon mitbringen. :wink:

Sieh dir einfach noch mal den Thread von Serenifly an, da ist ein super Beispiel, welches du verwenden kannst.
Und probiere es aus.

Hallo Starcounter
Sorry wenn ich das so direkt sage, aber befasse dich erstmal mit den C-Grundlagen.

char buffer[10];         // Hier wird ein Array (charckter) angelegt richtig ? , was definiert die 10 ? //

Richtig dies definiert ein char array und die 10 bestimmt die Anzahl der Zeichen die das array aufnehmen kann.
Index 0..9.

Für die Stringfunktionen ist hier eine gute Quelle

Ich habe sowas auch mal programmiert, denke mit Serenifly's Konvertierung hast du schon einen guten Ansatz.
Wenn du später mehrere Wert schicken willst, brauchst du ein Zeichen das die Werte im String trennt.
Zb so: aaa#bbbbb#cccc#

Auf der Empfängerseite ist dann strtok ein mächtiges Tool.

Wie gesagt ein wenig Lesen und testen hilft das ganze zu verstehen.

Grüße Rudi

Wenn du eine unbekannte Funktion hast musst dir ansehen wie diese definiert ist und was die Parameter bedeuten.

Wenn wir man der Einfachheit halber den Rückgabewert ignorieren ist dtostrf() so definiert:

dtostrf (double val, char width, unsigned char prec, char* s)

val: der Wert den man Konvertieren will
width: Mindesbreite des gesamten Strings inklusive Vorzeichen und Punkt
prec: für "precision". Anzahl der Nachkommastellen
s: das Ziel Array

Wenn der String kleiner als die Mindestbreite ist wird mit Leerzeichen aufgefüllt. Das sieht man in dem Beispielcode auch bei "1.5". Du könntest auch sagen Breite 3 und 1 Nachkommastelle. Dann wird jeder String gerade so breit wie er sein müsste.

Bei itoa() genauso:

itoa (int value, char* str, int base)

value: zu konvertierender Wert
str: Ziel Array
base: Basis des Zahlensystems. Hier 10 für das Dezimalsystem

Wie man dann zwei Werte überträgt und diese unterscheidet ist eine andere Sache. Der gibt es mehrere Optionen. Wie gesagt, könnte man auch ohne Strings einfach 4 Bytes pro Zahl übertragen und diese am Ende wieder als Zahlen interpretieren. Aber wenn du Strings schon nicht verstehst...

Vielen Dank für Eure Hilfe erstmal!!
Ich habe es jetzt mal wie oben beschrieben ohne Komma stellen versucht, leider kommen beim Empfänger nur leer Zeichen an im seriellen Monitor auch wenn ich gar nichts sende.
Hochladen ging ohne Probleme.

Sender:

#include <dht11.h>
#include <VirtualWire.h>

dht11 DHT11;
#define DHT11PIN 2

void setup() {


Serial.begin(9600);  

vw_setup(2000);
vw_set_tx_pin(8);

}

void loop() {

int chk = DHT11.read(DHT11PIN);

Serial.println("Temp: ");
Serial.println((float)DHT11.temperature, 2);
Serial.println(" C");
delay(500);

Serial.println("HUM: ");
Serial.println((float)DHT11.humidity, 2);
Serial.println(" C");

char msg[10];
 itoa(DHT11.temperature,msg,10);
 vw_send((uint8_t *)msg, strlen(msg));
 vw_wait_tx(); // Wait until the whole message is gone


delay(5000);



}

Empfänger :

#include <VirtualWire.h>


int i;
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

void setup()
{
 Serial.begin(9600);
 Serial.println("device is ready...");

 vw_set_rx_pin(12);
 vw_setup(2000); // bps
 vw_rx_start();
}

void loop()
{


 buflen = VW_MAX_MESSAGE_LEN;  //auf den Maximalwert einstellen
if (vw_get_message(buf, &buflen)) { // überprüfen ob eine Nachricht eingegangen ist

  Serial.print((char)buf[i]);    // Nachricht aus buf ausgeben
   }
   Serial.println(" ");
 }

Parallel habe ich heute den ganzen tag an der Konvertierung gearbeitet und danke nochmal für den Vorschlag strcat zu benutzen zum zusammen fügen ...

Sender :

#include <VirtualWire.h>
#include <DHT.h>


#define dhtPin 4
#define dhtType DHT11
#define txPowerPin 8

// libery
DHT dht(2, DHT11);

// hier lege ich meine variabelen fest 
char msg0[3];
char msg1[3];

int tem = 0;
int hum = 0;


void setup() {
  pinMode(txPowerPin, OUTPUT);
  pinMode(txPowerPin, LOW);
  vw_setup(4800);     // übertraghung
  vw_set_tx_pin(9);  // pin data
}
void loop() {
  digitalWrite(txPowerPin, HIGH);  
  hum = dht.readHumidity();             //hier halte ich die variabele hum
  tem = dht.readTemperature();          // hier die variabele temp
  itoa(hum, msg1, 10);                  // hier packe ich das arry hum
  itoa(tem, msg0, 10);                   // hier erzeuge ich das aray temp
  strcat(msg0, msg1);                    // jetzt packe ich beide arays zusammen
  vw_send((uint8_t *)msg0, strlen(msg0)); // jetzt sende ich die nachricht
  vw_wait_tx();                         // waren on fertig

  digitalWrite(txPowerPin, LOW);
 
  delay(5000);                          // delay

Empfänger (ein OLED war mir heute zu schwer) :

#include <VirtualWire.h>
#include <LiquidCrystal.h>


#define RS 9
#define E 10
#define D4 5
#define D5 6
#define D6 7
#define D7 8

LiquidCrystal lcd(RS, E, D4, D5, D6, D7);


byte degreesymbol[8] = {
  B01100,
  B10010,
  B10010,
  B01100,
  B00000,
  B00000,
  B00000,
  B00000  
};


int tem = 0;
int i;


void setup() {
  lcd.begin(16,2);                  // 
  lcd.createChar(1, degreesymbol);  // 
  Serial.begin(9600);              
  vw_setup(4800);                  // übertragung
  vw_rx_start();                   // senden start
  vw_set_rx_pin(2);                // pin data
  lcd.clear();                     // 
}


void loop() {
  uint8_t buf[VW_MAX_MESSAGE_LEN];      // variabele die die nachricht speichert
  uint8_t buflen = VW_MAX_MESSAGE_LEN;  // variabele die die länge der nachricht beschreibt
  lcd.setCursor(0,0);  
  lcd.print("Temp: ");
  if (vw_get_message(buf, &buflen))    // ist was angekommen?
  {
    for (i=0;i<2;i++)               // die ersten beiden byts
  {
  Serial.write(buf[i]);                // Störung?
  lcd.write(buf[i]);                   // die ersten bytes
  }  
  Serial.println();                    // störung?
  lcd.write(1);                        // temp symbol
  lcd.print(" C"); 
  lcd.setCursor(0,1);
  lcd.print("Hum:  "); 
    for (i=2;i<4;i++)              // die letzten 2 byts
    {
      Serial.write(buf[i]);                // störung?
      lcd.write(buf[i]);                    // die letzten byts auf lcd
    }  
  lcd.print("% RH");      
  }
}

Werde es morgen mal Hochladen :slight_smile:

Hast du denn schon jemals eine funktionierende "Funkübertragung" zum Laufen bekommen?

Du solltest mal eine einfache Verbindung (Beispiel aus der Library) aufbauen und den funktionierenden Empfänger so lassen, bis du auch den Senderteil mit allen Sensoren in Funktion hast.

Für diesen Fall habe ich mir z.B. einen einfachen "Atmega-StandAlone" mit einem Empfängermodul gebaut, der die Übertragung mit VirtualWire und RCSwitch (umschaltbar) darstellen kann.

Beim Sender fängst du mit einer einfachen Textübertragung "Hallo Arduino" o.ä. an und erweiterst dies Stück für Stück.

Wenn du dann die einzelnen Sensoren und Datentypwandlungen in jeweils einzelne Funktionen aufbaust, kannst du dich besser rantasten.

Folgende Anmerkungen:

  1. Welchen Empfänger setzt du ein? Bitte Link posten.
  2. Wozu schaltest du die Spannung des Senders?
  3. Hast du mal die Baudrate auf 2400 Bd gesetzt? Bei 4800 hatte ich auch öfter Probleme!
  4. Lass dir im Sender mal den Inhalt der Variable (msg0) im SerialMonitor anzeigen, den du senden möchtest.
  5. Beispiel:
void loop() {
  Read_Sensor1();  
  Read_Sensor2();
  Send_Data();
}

void Read_Sensor1() {
  tem = dht.readTemperature();             
  itoa(tem, msg0, 10);                   
}

void Read_Sensor2() {
  hum = dht.readHumidity();             
  itoa(tem, msg1, 10);                   
}

void Send_Data() {
  strcat(msg0, msg1);
  Serial.println(msg0);
  vw_send((uint8_t *)msg0, strlen(msg0));
  vw_wait_tx();
}

Dieses Beispiel ist nur ein Vorschlag und nicht getestet.
Du kannst aber damit leicht deinen Funktionsumfang erweitern und auch besser prüfen.

Hi,

ja, "Hallo" Versendet und Empfangen ja.

Wie gesagt die Variante : char msg[10] gab ohne Empfang nur Leerzeichen aus.

Die Methode mit Konvertierung habe ich noch nicht ausprobiert.

Mein Sender/Empfänger:
http://www.ebay.de/itm/221652085232?_trksid=p2057872.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT

  1. Da er irgendwann auf Batterie laufen soll raten alle Projekte dazu, ich weis es macht es "unnötig schwierig".

  2. Das habe ich noch nicht Versucht! (guter Tipp)

  3. das geht einfach per println oder?

Ich muss sagen das dein Post neben ein, zwei anderen der Beste und am leichtesten zu verstehen ! Danke!

Im Grunde genommen möchte ich nur die Sensor Werte des DHT an eine Basisstation im Haus Senden ( ist schon Fertig, die RTC Real Time Clock hat mich fast Wahnsinnig gemacht :slight_smile: )

Danke nochmal!

Dann teste es doch mal so, wie in meinem Beispiel beschrieben.
Da findest du auch die Serial.print Anweisung.
Empfangen solltest du das Signal mal ohne die Aufteilung in einzelne Ergebnisse.
Nur um sicher zu gehen, dass hier kein Fehler im Empfänger vorliegt.

Hallo,
ich habe mir jetzt mal deinen Sender-Sketch vorgenommen und mangels DHT-Sensor feste Werte eingetragen.

Der funktioniert bei mir und wird richtig übertragen.

#include <dht11.h>
#include <VirtualWire.h>

dht11 DHT11;
#define DHT11PIN 2

char msg1[10];
char msg2[10];

int tem = 0;
int hum = 0;

void setup() {
  Serial.begin(9600);
  vw_setup(2000);
  vw_set_tx_pin(8);
}

void loop() {
  Read_Sensor1();
  Read_Sensor2();
  Send_Data();
  delay(5000);
}

void Read_Sensor1() {
  tem = dht.readTemperature();
  //tem = 22;
  itoa(tem, msg1, 10);
}

void Read_Sensor2() {
  hum = dht.readHumidity();             
  //hum = 66;             
  itoa(hum, msg2, 10);                   
}

void Send_Data() {
  strcat(msg1, msg2);
  Serial.println(msg1);
  vw_send((uint8_t *)msg1, strlen(msg1));
  vw_wait_tx();
}

Der sollte jetzt bei dir auch laufen.
Mit den festen Werten wird "2266" übertragen.

Wenn noch Problem sind, liegt es am Empfängerteil.

Was die Schaltfunktion des Senders betrifft, das kannst du dir sparen.
Der Sender hat, bedingt durch die Modulationsart, nur Stromverbrauch wenn Daten gesendet werden. Das kannst du leicht nachmessen.