Problem mit DHT-22 via I2C und I2C_Anything

Heyho,

hab hier 2 Arduino's und möchte das der eine Arduino die Temperatur und RLF-Daten des DHT-22
via I2C an den anderen Arduino sendet.

Leider kriege ich das nicht ganz so hin. Habe schon I2C_Anything versucht und auch damit die Daten manuell
via dtostrf in char umzuwandeln um diese zu übertragen. Leider ergebnislos.

Vllt. könnt ihr euch meinen Code mal ansehen und entdeckt einen Fehler?
Ich bin hier fast am verzweifeln.

Hier Code Nummer 1 :slight_smile:

#include <DHT.h>
#include <Wire.h>
#include <I2C_Anything.h>

//DEKLARATION DER PINS
#define DHTPIN 13

float tdht;
float hdht;

//#define DHTTYPE DHT11   
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);


//SETUP
void setup() 
{
  //EINGAENGE/AUSGAENGE SETZEN
  pinMode(DHTPIN, INPUT);

  //I2C ADRESSE
  Wire.begin(5); 
  
  //SERIELLE AUSGABE BEGINNEN
  Serial.begin(115200); 
  dht.begin();
}


//BEGINN DER LOOP

void loop() {
  
  //Sensor(en) Auslesen
  
  float tdht = dht.readTemperature();
  float hdht = dht.readHumidity();
  
  
  //SERIELLE AUSGABE DER SENSORWERTE
              
  Serial.println("-----------------------------------");
  Serial.print("DHT Temperatur:        ");
  Serial.print(tdht);
  Serial.println(" *C");
  Serial.print("DHT Luftfeuchtigkeit:  ");
  Serial.print(hdht);
  Serial.println(" %\t");
  Serial.println("-----------------------------------");
    
  delay(2000);
    
}

//I2C DATEN SENDEN
  
  void requestEvent()
    {
    Wire.beginTransmission(4);
    I2C_writeAnything(tdht);
    delay(10);
    I2C_writeAnything(hdht);
    }

Und hier Code Nr. 2 :slight_smile:

#include <Wire.h>
#include <I2C_Anything.h>

char tdht;
char hdht;

//SETUP
void setup() 
{
  //I2C ADRESSE
  Wire.begin(4); 

  //SERIELLE AUSGABE BEGINNEN
  Serial.begin(115200); 
}


void loop() 

{
  
      //I2C DATEN EMPFANGEN

      Wire.requestFrom(5,11);
      while(Wire.available())
        {
        I2C_readAnything(tdht);
        delay(10);
        I2C_readAnything(hdht);

}
        
  //SERIELLE AUSGABE DER SENSORWERTE
              
  Serial.println("-----------------------------------");
  Serial.print("DHT Temperatur:        ");
  Serial.print(tdht);
  Serial.println(" *C");
  Serial.print("DHT Luftfeuchtigkeit:  ");
  Serial.print(hdht);
  Serial.println(" %\t");
  Serial.println("-----------------------------------");
  
  delay(2000);
}

So kriege ich jedenfalls nur "NaN" zugesendet!

Grüße und Danke schonmal im Voraus.

EDIT: Hab schon mit den Werten von Wire.requestFrom rumgespielt! Bzw. mit dem 2. der ja angibt wievile Byte kommen sollen!

Nur wenn du im Empfänger float statt char nimmst, könntest du NaN sehen, wärst aber schonmal einen Schritt weiter ?!

while(Wire.available()) solltest du evtl. auch anders lösen:
Wenn beide unabhängig voneinander 2 sec Zyklen fahren, ist das sicher nicht gut.

Das while(Wire.available()) hab ich nun rausschmeissen!
Das hatte ich so aus nem Beispielcode entnommen!

Und du hast Recht!
Nehme ich "float" statt "char" habe ich NaN.
Nehme ich "char" kommt folgendes:

DHT Temperatur: *C
DHT Luftfeuchtigkeit: ÿ %

Also auch nur Müll! :-/

Pardon, ich hab die Nacht so viel rum probiert... ich hab den Wald vor lauter Bäumen nicht mehr gesehen!

Grüße

Edit: Das ist aber nicht das erste mal das mir dieses "ÿ" begegnet... es stand auch schonmal bei Temperatur und RLF als ich gestern Nacht verzweifelt versucht hab es ans laufen zu kriegen :slight_smile:

Also auch nur Müll! :-/

Naja, das Beste was dein Programm, so wie du es programmiert hast, machen kann.
ÿ ist halt ein char, das früher mal Teil eines float war.

Dein Problem ist eher, warum readAnything nicht das zurückliefert, was WriteAnything(float) geschrieben hat.

Da musst du I2C_Anything.h studieren, examples durchsehen,
--- und wenn du I2C_Anything.cpp verstanden hast, weisst du auch, wie es einfacher ohne geht --- :wink:

Die Fragen sind: wie kriegt readAnything mit, dass zwei floats kommen, wie liefert es diese an das aufrufende Programm,
und wie sorgt man dafür, dass Schreiben und Lesen synchron sind und bleiben ?

CoMcE:
hab hier 2 Arduino's und möchte das der eine Arduino die Temperatur und RLF-Daten des DHT-22
via I2C an den anderen Arduino sendet.

Warum möchtest Du die Daten unbedingt über I2C von Arduino zu Arduino senden, mit einer Library im frühen Betastadium?

Warum nicht einfach seriell mit einer bewährten Standardlibrary wie SoftwareSerial?

Vor allem dann, wenn Du Dich mit Programmierung so wenig auskennst, da ist doch hier im Forum die Chance, eine Hilfe zu einer häufig eingesetzten Standard-Library zu bekommen viel höher als zu einer Superspezial-Betastatus-Besonders-Selten-Library?!

Nun Jurs... gute Frage...
Hier die Antwort:
Mir war bis dato nicht bekannt das es noch eine andere Möglichkeit gibt sowas zu übertragen bzw. das SoftwareSerial existiert.

Es läuft sowieso darauf hinaus das die Daten irgendwann via XBee/WifiBee/Wie auch immer drahtlos übertragen werden nur
würde ich es gerne vorher via Kabel auf die Reihe bekommen! :slight_smile:

@Michael
Ich hatte schon eine Möglichkeit OHNE I2C_Anything!
Und zwar indem ich die float Werte mittels dtostrf umgewandelt habe

dtostrf(tdht, 4, 2, tdht_str);
dtostrf(hdht, 4, 2, hdht_str);

Die Werte die dabei rauskamen waren zwar richtig aber auch diese wurden nicht richtig übertragen! :smiley:
Aber gut das ich nun weiss das irgendwas mit meiner Übertragung nicht stimmt!
Nun weiss ich zumindest wo ich suchen muss!

Grüße

Edit: Ich hab aber auch schon versucht nur eine Zeichenfolge oder Zahl zu übertragen!
Das hat auch nicht funktioniert! bzw. kam auch nur Murks bei raus.

I2C mit Wire.h hat erstmal nichts mit I2C_Anything zu tun und kann durchaus verwendet werden ( auch um float Zahlen binär zu übertragen ).

Einerseits hast du Recht: Serial hat den Vorteil, dass man die beiden Seiten leicht für sich testen kann, und einfach sehen kann, was übertragen wird.
Aber aus einem Text wieder die gleiche float-Zahl zu machen, ist ein echtes Problem, sollte man mehr wollen als im Rahmen der Messgenauigkeit bleiben ...

Meine Idee wäre, auf beiden Seiten

union DATA {byte bin[8]; float f[2];}; 

DATA data;
#define tdht data.f[0]
#define hdht data.f]1]

zu definieren, und 8 byte von data.bin nach data.bin zu übertragen.

Aber vielleicht liegts ja nur daran, dass requestEvent() nie aufgerufen wird ?
Ich vermisse im Sende-Slave (1) ein
Wire.onRequest(requestEvent); // register event

Ein delay während der Übertragung eines Request ist seltsam. Wo hast du denn das her ?

Zum einen stimme ich micheal_x zu, dass Wire.onRequest() im setup aufgerufen werden müsste, damit das funktionieren könnte.

Weshalb gibst Du dem I2C Master eine Adresse?

Wire.begin(4);

Wie kommst Du auf die Idee, dass Du 11 Bytes abfragen musst, damit 2 floats übertragen werden? 5.5 Bytes pro float oder wie soll das gehen:

Wire.requestFrom(5,11);

Ansonsten ist das I2C_Anything.h nur ein kurzes Header-File:

// Written by Nick Gammon
// May 2012

#include <Arduino.h>
#include <Wire.h>

template <typename T> int I2C_writeAnything (const T& value)
  {
    const byte * p = (const byte*) &value;
    unsigned int i;
    for (i = 0; i < sizeof value; i++)
          Wire.write(*p++);
    return i;
  }  // end of I2C_writeAnything

template <typename T> int I2C_readAnything(T& value)
  {
    byte * p = (byte*) &value;
    unsigned int i;
    for (i = 0; i < sizeof value; i++)
          *p++ = Wire.read();
    return i;
  }  // end of I2C_readAnything

I2C ist eigentlich die ideale Lösung für die Kommunikation zwischen zwei oder mehr Arduinos.
Und die I2C_Anything (kannte ich bisher noch nicht) macht auch einen guten Eindruck.
Aber anscheinend gibt es Probleme, wenn I2C_writeAnything() im onRequest Handler verwendet wird. Hier gibt es einen Thread dazu nebst Lösung: Arduino Forum
Laut dem Thread soll es mit dieser Erweiterung funktionieren (nicht getestet):

template <typename T> int I2C_singleWriteAnything (const T& value) {
  int size = sizeof value;
  byte vals[size];
  const byte* p = (const byte*) &value;
  unsigned int i;
  for (i = 0; i < sizeof value; i++) {
    vals[i] = *p++;
  }
  
  Wire.write(vals, size);
  return i;
}

So... nachdem ich einige Tage die Schnauze voll hatte hab ich mich nochmal dran gesetzt... und siehe da... es funktioniert zumindest schonmal mit einem Wert!!!
GOTT SEI DANK!

Zum einen war folgendes zu tun:

MaFu:
I2C ist eigentlich die ideale Lösung für die Kommunikation zwischen zwei oder mehr Arduinos.
Und die I2C_Anything (kannte ich bisher noch nicht) macht auch einen guten Eindruck.
Aber anscheinend gibt es Probleme, wenn I2C_writeAnything() im onRequest Handler verwendet wird. Hier gibt es einen Thread dazu nebst Lösung: Arduino Forum
Laut dem Thread soll es mit dieser Erweiterung funktionieren (nicht getestet):

template <typename T> int I2C_singleWriteAnything (const T& value) {

int size = sizeof value;
 byte vals[size];
 const byte* p = (const byte*) &value;
 unsigned int i;
 for (i = 0; i < sizeof value; i++) {
   vals[i] = *p++;
 }
 
 Wire.write(vals, size);
 return i;
}

DANKE DAFÜR MAFU!

Zum anderen durfte ich bei I2C_singleWriteAnything() nicht das "tdht" benutzen sondern musste "dht.readTemperature()" übersenden!
Ich hoffe das ist verständlich so ^^

Jetzt muss ich nur noch herausfinden wie ich dem Arduino sage das noch ein 2. Wert ankommt und wie er den 1. vom 2. unterscheidet.
Denn wenn ich einfach I2C_singleWriteAnything 2 mal hintereinander (einmal für Temp und einmal für die RLF) einfach so übertrage kommt 2x 0.00 an.

Manchmal kommt auch noch "ovf" an (Overflow?) Gibt es eine Möglichkeit das in den Griff zu kriegen? bzw. ihm zu sagen wenn etwas anderes als ne reelle
Zahl kommt ihm zu er soll das einfach ignorieren und dann doch nicht den Wert tdht setzen? Kann er ja dann beim nächsten durchgang tun wenn der Wert richtig ankam. ---> DONE!

Grüße

Könntest Du Deinen ganzen Code nochmals posten, so wie Du ihn momentan verwendest?