Datenlogger für Versuchsbienenstand

Hallo,

ein Freund und Kollege von mir möchte an seinem Versuchsbienenstand die Temperatur und Luftfeuchte in den Bienenkästen protokollieren.
Jetzt hat er 12 Stück DHT22 Sensoren, einen Arduino Mega und Unmengen Kabel zu mir gebracht.

Ich habe statt dem Mega einen UNO R3 von mir verwendet und das Data Logging Shield von Adafruit darauf gepflanzt.
Zum Auslesen der Sensoren verwende ich die Library von Adafruit: GitHub - adafruit/DHT-sensor-library: Arduino library for DHT11, DHT22, etc Temperature & Humidity Sensors
Mit einem modifizierten Beispielprogramm funktioniert das schon sehr schön, ich bekomme auf dem Serial Monitor immer Datum und Zeit und die Messwerte ausgegeben.
Für die Echtzeituhr verwende ich übrigens auch die Library von Adafruit: Downloads | Adafruit Data Logger Shield | Adafruit Learning System

Die ebenfalls unter diesem Link zu findende Library für die SD-Karte möchte ich auch verwenden.

Jetzt zum Problem:
Wir möchten die Daten, so wie sie jetzt auf dem Serial Monitor ausgegeben werden auf die SD-Card schreiben.
Irgendwie blicke ich das aber nicht mit dem dataString und so.
Gibt es vielleicht auch eine einfachere Möglichkeit, anstatt so einen dataString mit allen Werten zu basteln z.B. einfach die Ausgabe des Serial Monitors auf die SD Karte zu schreiben?

Hier mal das bisherige Programm, das wie gesagt nur über den Serial Monitor ausgibt und tadellos funktioniert:

// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

#include "DHT.h"
#include <Wire.h>
#include "RTClib.h"

#define DHT2PIN 2 // what pin we're connected to
#define DHT3PIN 3 // what pin we're connected to
#define DHT4PIN 4 // what pin we're connected to
#define DHT5PIN 5 // what pin we're connected to
#define DHT6PIN 6 // what pin we're connected to
#define DHT7PIN 7 // what pin we're connected to
#define DHT8PIN 8 // what pin we're connected to
#define DHT9PIN 9 // what pin we're connected to
#define DHT10PIN 10 // what pin we're connected to
#define DHT11PIN 11 // what pin we're connected to
#define DHT12PIN 12 // what pin we're connected to


// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11 
#define DHT2TYPE DHT22   // DHT 22  (AM2302)
#define DHT3TYPE DHT22
#define DHT4TYPE DHT22 
#define DHT5TYPE DHT22
#define DHT6TYPE DHT22
#define DHT7TYPE DHT22
#define DHT8TYPE DHT22
#define DHT9TYPE DHT22
#define DHT10TYPE DHT22
#define DHT11TYPE DHT22 
#define DHT12TYPE DHT22 
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

RTC_DS1307 rtc;

// Initialize DHT sensor for normal 16mhz Arduino
DHT dht2(DHT2PIN, DHT2TYPE);
DHT dht3(DHT3PIN, DHT3TYPE);
DHT dht4(DHT4PIN, DHT4TYPE);
DHT dht5(DHT5PIN, DHT5TYPE);
DHT dht6(DHT6PIN, DHT6TYPE);
DHT dht7(DHT7PIN, DHT7TYPE);
DHT dht8(DHT8PIN, DHT8TYPE);
DHT dht9(DHT9PIN, DHT9TYPE);
DHT dht10(DHT10PIN, DHT10TYPE);
DHT dht11(DHT11PIN, DHT11TYPE);
DHT dht12(DHT12PIN, DHT12TYPE);

// NOTE: For working with a faster chip, like an Arduino Due or Teensy, you
// might need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold.  It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value.  The default for a 16mhz AVR is a value of 6.  For an
// Arduino Due that runs at 84mhz a value of 30 works.
// Example to initialize DHT sensor for Arduino Due:
//DHT dht(DHTPIN, DHTTYPE, 30);

void setup() {
  Serial.begin(9600); 
  
  #ifdef AVR
  Wire.begin();
#else
  Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
  rtc.begin();

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
  
  Serial.println("DHTxx test!");
 
  dht2.begin();
  dht3.begin();
  dht4.begin();
  dht5.begin();
  dht6.begin();
  dht7.begin();
  dht8.begin();
  dht9.begin();
  dht10.begin();
  dht11.begin();
  dht12.begin();
}
}

void loop() {
  // Wait a few seconds between measurements.
  delay(20000);
  
   DateTime now = rtc.now();

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h2 = dht2.readHumidity();
  // Read temperature as Celsius
  float t2 = dht2.readTemperature();
  
  float h3 = dht3.readHumidity();
  // Read temperature as Celsius
  float t3 = dht3.readTemperature();
  
    float h4 = dht4.readHumidity();
  // Read temperature as Celsius
  float t4 = dht4.readTemperature();
  
  float h5 = dht5.readHumidity();
  // Read temperature as Celsius
  float t5 = dht5.readTemperature();
  
    float h6 = dht6.readHumidity();
  // Read temperature as Celsius
  float t6 = dht6.readTemperature();
  
  float h7 = dht7.readHumidity();
  // Read temperature as Celsius
  float t7 = dht7.readTemperature();
  
    float h8 = dht8.readHumidity();
  // Read temperature as Celsius
  float t8 = dht8.readTemperature();
  
  float h9 = dht9.readHumidity();
  // Read temperature as Celsius
  float t9 = dht9.readTemperature();
  
    float h10 = dht10.readHumidity();
  // Read temperature as Celsius
  float t10 = dht10.readTemperature();
  
  float h11 = dht11.readHumidity();
  // Read temperature as Celsius
  float t11 = dht11.readTemperature();
  
    float h12 = dht12.readHumidity();
  // Read temperature as Celsius
  float t12 = dht12.readTemperature();
  
   Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h2) || isnan(t2)) {
    Serial.println("Failed to read from DHT sensor 2!");
    return;
  }

  Serial.print("Humidity 2: "); 
  Serial.print(h2);
  Serial.print(" %\t");
  Serial.print("Temperature 2: "); 
  Serial.print(t2);
  Serial.println(" *C ");
  
   if (isnan(h3) || isnan(t3)) {
    Serial.println("Failed to read from DHT sensor 3!");
    return;
  }

  Serial.print("Humidity 3: "); 
  Serial.print(h3);
  Serial.print(" %\t");
  Serial.print("Temperature 3: "); 
  Serial.print(t3);
  Serial.println(" *C ");
  
     if (isnan(h4) || isnan(t4)) {
    Serial.println("Failed to read from DHT sensor 4!");
    return;
  }

  Serial.print("Humidity 4: "); 
  Serial.print(h4);
  Serial.print(" %\t");
  Serial.print("Temperature 4: "); 
  Serial.print(t4);
  Serial.println(" *C ");
  
  if (isnan(h5) || isnan(t5)) {
    Serial.println("Failed to read from DHT sensor 5!");
    return;
  }

  Serial.print("Humidity 5: "); 
  Serial.print(h5);
  Serial.print(" %\t");
  Serial.print("Temperature 5: "); 
  Serial.print(t5);
  Serial.println(" *C ");
  
  if (isnan(h6) || isnan(t6)) {
    Serial.println("Failed to read from DHT sensor 6!");
    return;
  }

  Serial.print("Humidity 6: "); 
  Serial.print(h7);
  Serial.print(" %\t");
  Serial.print("Temperature 7: "); 
  Serial.print(t7);
  Serial.println(" *C ");
  
  if (isnan(h8) || isnan(t8)) {
    Serial.println("Failed to read from DHT sensor 8!");
    return;
  }

  Serial.print("Humidity 8: "); 
  Serial.print(h8);
  Serial.print(" %\t");
  Serial.print("Temperature 8: "); 
  Serial.print(t8);
  Serial.println(" *C ");
  
  if (isnan(h9) || isnan(t9)) {
    Serial.println("Failed to read from DHT sensor 9!");
    return;
  }

  Serial.print("Humidity 9: "); 
  Serial.print(h9);
  Serial.print(" %\t");
  Serial.print("Temperature 9: "); 
  Serial.print(t9);
  Serial.println(" *C ");
  
  if (isnan(h10) || isnan(t10)) {
    Serial.println("Failed to read from DHT sensor 10!");
    return;
  }

  Serial.print("Humidity 10: "); 
  Serial.print(h10);
  Serial.print(" %\t");
  Serial.print("Temperature 10: "); 
  Serial.print(t10);
  Serial.println(" *C ");
  
  if (isnan(h11) || isnan(t11)) {
    Serial.println("Failed to read from DHT sensor 11!");
    return;
  }

  Serial.print("Humidity 11: "); 
  Serial.print(h11);
  Serial.print(" %\t");
  Serial.print("Temperature 11: "); 
  Serial.print(t11);
  Serial.println(" *C ");
  
  if (isnan(h12) || isnan(t12)) {
    Serial.println("Failed to read from DHT sensor 2!");
    return;
  }

  Serial.print("Humidity 12: "); 
  Serial.print(h12);
  Serial.print(" %\t");
  Serial.print("Temperature 12: "); 
  Serial.print(t12);
  Serial.println(" *C ");
  Serial.println("");
  
  
  
  
  
  
}

Bitte nicht wundern, dass es keinen Sensor 1 gibt, der ist kaputt.

Viele Grüße,
Andy

Hilfe! Wir müssen das heute fertig bekommen, damit wir noch genügend Daten sammeln können bevor die Saison vorbei ist!
:cold_sweat:

Du musst eigentlich nur deine Werte in einem String hintereinander reihen und den String dann auf die SD schreiben..
Schau dir mal z.b. den Beispiel Code "Datenlogger" in der Arduino IDE an.

Scherheinz:
Du musst eigentlich nur deine Werte in einem String hintereinander reihen und den String dann auf die SD schreiben..

Muss man gar nicht unbedingt. Der SD Karte ist wie Serial auch völlig egal, ob das ein einem String steht oder nicht. Daher kann man auch sowas machen:

file.print(var1);
file.print(",");
file.print(var2);

Wobei snprintf() (oder besser snprintf_P()) dabei etwas übersichtlicher ist, wenn man viele Variablen hat, aber auch selbst viel Flash belegt.

Hallo Scherheinz,

danke für deine Antwort.
Ich hab das jetzt mal ausprobiert, nur für Datum/Zeit und einen Sensor.
Das müsste dann so aussehen?:

// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

#include "DHT.h" // DHT
#include <Wire.h> // Uhr
#include "RTClib.h" // Uhr
#include <SPI.h> // SD
#include <SD.h> // SD

#define DHT2PIN 2 // what pin we're connected to
#define DHT3PIN 3 // what pin we're connected to
#define DHT4PIN 4 // what pin we're connected to
#define DHT5PIN 5 // what pin we're connected to
#define DHT6PIN 6 // what pin we're connected to
#define DHT7PIN 7 // what pin we're connected to
#define DHT8PIN 8 // what pin we're connected to
#define DHT9PIN 9 // what pin we're connected to
#define DHT10PIN 10 // what pin we're connected to
#define DHT11PIN 11 // what pin we're connected to
#define DHT12PIN 12 // what pin we're connected to


// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11 
#define DHT2TYPE DHT22   // DHT 22  (AM2302)
#define DHT3TYPE DHT22
#define DHT4TYPE DHT22 
#define DHT5TYPE DHT22
#define DHT6TYPE DHT22
#define DHT7TYPE DHT22
#define DHT8TYPE DHT22
#define DHT9TYPE DHT22
#define DHT10TYPE DHT22
#define DHT11TYPE DHT22 
#define DHT12TYPE DHT22 
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

RTC_DS1307 rtc;
const int chipSelect = 4;
File dataFile;

// Initialize DHT sensor for normal 16mhz Arduino
DHT dht2(DHT2PIN, DHT2TYPE);
DHT dht3(DHT3PIN, DHT3TYPE);
DHT dht4(DHT4PIN, DHT4TYPE);
DHT dht5(DHT5PIN, DHT5TYPE);
DHT dht6(DHT6PIN, DHT6TYPE);
DHT dht7(DHT7PIN, DHT7TYPE);
DHT dht8(DHT8PIN, DHT8TYPE);
DHT dht9(DHT9PIN, DHT9TYPE);
DHT dht10(DHT10PIN, DHT10TYPE);
DHT dht11(DHT11PIN, DHT11TYPE);
DHT dht12(DHT12PIN, DHT12TYPE);

// NOTE: For working with a faster chip, like an Arduino Due or Teensy, you
// might need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold.  It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value.  The default for a 16mhz AVR is a value of 6.  For an
// Arduino Due that runs at 84mhz a value of 30 works.
// Example to initialize DHT sensor for Arduino Due:
//DHT dht(DHTPIN, DHTTYPE, 30);

void setup() {
  Serial.begin(9600); 
  
  
  #ifdef AVR
  Wire.begin();
#else
  Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
  rtc.begin();

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
  
  Serial.println("DHTxx test!");
  
  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(SS, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1) ;
  }
  Serial.println("card initialized.");
  
  // Open up the file we're going to log to!
  dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (! dataFile) {
    Serial.println("error opening datalog.txt");
    // Wait forever since we cant write data
    while (1) ;
 
  dht2.begin();
  dht3.begin();
  dht4.begin();
  dht5.begin();
  dht6.begin();
  dht7.begin();
  dht8.begin();
  dht9.begin();
  dht10.begin();
  dht11.begin();
  dht12.begin();
}
}

void loop() {
  // Wait a few seconds between measurements.
  delay(20000);
  
   DateTime now = rtc.now();
   
    // make a string for assembling the data to log:
  String dataString = "";

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h2 = dht2.readHumidity();
  // Read temperature as Celsius
  float t2 = dht2.readTemperature();
  
  float h3 = dht3.readHumidity();
  // Read temperature as Celsius
  float t3 = dht3.readTemperature();
  
    float h4 = dht4.readHumidity();
  // Read temperature as Celsius
  float t4 = dht4.readTemperature();
  
  float h5 = dht5.readHumidity();
  // Read temperature as Celsius
  float t5 = dht5.readTemperature();
  
    float h6 = dht6.readHumidity();
  // Read temperature as Celsius
  float t6 = dht6.readTemperature();
  
  float h7 = dht7.readHumidity();
  // Read temperature as Celsius
  float t7 = dht7.readTemperature();
  
    float h8 = dht8.readHumidity();
  // Read temperature as Celsius
  float t8 = dht8.readTemperature();
  
  float h9 = dht9.readHumidity();
  // Read temperature as Celsius
  float t9 = dht9.readTemperature();
  
    float h10 = dht10.readHumidity();
  // Read temperature as Celsius
  float t10 = dht10.readTemperature();
  
  float h11 = dht11.readHumidity();
  // Read temperature as Celsius
  float t11 = dht11.readTemperature();
  
    float h12 = dht12.readHumidity();
  // Read temperature as Celsius
  float t12 = dht12.readTemperature();
  
   Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
    dataString += (now.year(), DEC);
    dataString += ('/');
    dataString += (now.month(), DEC);
    dataString += ('/');
    dataString += (now.day(), DEC);
    dataString += (' ');
    dataString += (now.hour(), DEC);
    dataString += (':');
    dataString += (now.minute(), DEC);
    dataString += (':');
    dataString += (now.second(), DEC);


  dataFile.println(dataString);
    
    

  // Check if any reads failed and exit early (to try again).
  if (isnan(h2) || isnan(t2)) {
    Serial.println("Failed to read from DHT sensor 2!");
    return;
  }

  Serial.print("Humidity 2: ");
  dataString += ("Humidity 2: ");
  Serial.print(h2);
  dataString += (h2);
  Serial.print(" %\t");
  dataString += (" %\t");
  Serial.print("Temperature 2: ");
  dataString += ("Temperature 2: "); 
  Serial.print(t2);
  dataString += (t2);
  Serial.println(" *C ");
  dataString += (" *C ");
  
   if (isnan(h3) || isnan(t3)) {
    Serial.println("Failed to read from DHT sensor 3!");
    return;
  }

  Serial.print("Humidity 3: "); 
  Serial.print(h3);
  Serial.print(" %\t");
  Serial.print("Temperature 3: "); 
  Serial.print(t3);
  Serial.println(" *C ");
  
  
  
}

Dann kommen folgende Fehlermeldungen beim Kompilieren:

a function-definition is not allowed here before '{' token

Loggen_Versuch.ino: In function 'void setup()':
Loggen_Versuch:121: error: a function-definition is not allowed here before '{' token
Loggen_Versuch:339: error: expected `}' at end of input

Ich denke da fehlt nur irgendwo eine Klammer, aber wo?

Hallo Serenifly,

dir auch vielen Dank.
Das wurde dann analog zu oben aussehen, nur dass ich keinen String anfange sondern einfach nur so:

...
Serial.print("Humidity 2: "); 
  Serial.print(h2);
  Serial.print(" %\t");
  Serial.print("Temperature 2: "); 
  Serial.print(t2);
  Serial.println(" *C ");

file.print("Humidity 2: "); 
file.print(h2);
file.print(" %\t");
file.print("Temperature 2: "); 
file.print(t2);
file.println(" *C ");
...

So wie es aussieht hat schon das unveränderte Beispielprogramm "Datalogger" irgendwo einen Haken.

/*
  SD card datalogger
 
 This example shows how to log data from three analog sensors 
 to an SD card using the SD library.
 	
 The circuit:
 * SD card attached to SPI bus as follows:
 ** UNO:  MOSI - pin 11, MISO - pin 12, CLK - pin 13, CS - pin 4 (CS pin can be changed)
  and pin #10 (SS) must be an output
 ** Mega:  MOSI - pin 51, MISO - pin 50, CLK - pin 52, CS - pin 4 (CS pin can be changed)
  and pin #52 (SS) must be an output
 ** Leonardo: Connect to hardware SPI via the ICSP header
 		Pin 4 used here for consistency with other Arduino examples
 
 created  24 Nov 2010
 modified 9 Apr 2012 by Tom Igoe
 
 This example code is in the public domain.
 	 
 */

#include <SPI.h>
#include <SD.h>

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 4;

File dataFile;

void setup()
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(SS, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1) ;
  }
  Serial.println("card initialized.");
  
  // Open up the file we're going to log to!
  dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (! dataFile) {
    Serial.println("error opening datalog.txt");
    // Wait forever since we cant write data
    while (1) ;
  }
}

void loop()
{
  // make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ","; 
    }
  }

  dataFile.println(dataString);

  // print to the serial port too:
  Serial.println(dataString);
  
  // The following line will 'save' the file to the SD card after every
  // line of data - this will use more power and slow down how much data
  // you can read but it's safer! 
  // If you want to speed up the system, remove the call to flush() and it
  // will save the file only every 512 bytes - every time a sector on the 
  // SD card is filled with data.
  dataFile.flush();
  
  // Take 1 measurement every 500 milliseconds
  delay(500);
}

Gibt beim Kompilieren folgende Fehlermeldungen:

Datalogger:42: error: expected constructor, destructor, or type conversion before '.' token
Datalogger:45: error: expected constructor, destructor, or type conversion before '(' token
Datalogger:48: error: expected unqualified-id before 'if'
Datalogger:53: error: expected constructor, destructor, or type conversion before '.' token
Datalogger:56: error: expected constructor, destructor, or type conversion before '=' token
Datalogger:57: error: expected unqualified-id before 'if'
Datalogger:62: error: expected declaration before '}' token

Da habe ich noch nichts dran gemacht, das ist so wie man es bei Adafruit runterladen kann.

Hier fehlt die abschließende Klammer:

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");

Und ein Laufzeit Fehler wird das sein:

if (! dataFile) {
    Serial.println("error opening datalog.txt");
    // Wait forever since we cant write data
    while (1) ;

    ...
}

Diese Abfrage sollte doch nach dem while(1) schon abgeschlossen werden

Sonst wird dht.begin() nie ausgeführt

Generell macht mal überall wo du print() mit String-Literalen verwendest ein F() um den String:

print(F("String im Flash"));

Sonst müllst du dir das RAM mit dem ganzen String Konstanten zu

Auf die String Klasse sollte man übrigens komplett verzichten. Gerade wenn du wie hier nicht weißt wie man sie korrekt verwendet. Dein endloses aneinanderreihen von Strings dauert ewig und ist ganz schlecht für den Speicher. Wenn überhaupt dann sollte man vorher unbedingt reserve() machen:

Dann wird nicht ständig Speicher neu angelegt wenn der String auch nur um 1 vergrößert werden muss.

Aber wie gesagt am besten du lässt es und machst einzelne Serial Aufrufe. Syntaktisch schöner und einfacher wird das hiermit:
http://arduiniana.org/libraries/streaming/
Damit hat man C++ Output Streams

Auf die String Klasse sollte man übrigens komplett verzichten. Gerade wenn du wie hier nicht weißt wie man sie korrekt verwendet. Dein endloses aneinanderreihen von Strings dauert ewig und ist ganz schlecht für den Speicher.

Das hab ich mir eben auch gedacht.

Wenn ich das aber jetzt mit file.print("irgendwas") mach, dann sagt er error: expected unqualified-id before '.' token, also kennt er "file" nicht ???
Ich nehme an, ich muss da oben bei den Definitionen irgendwo rein bringen, dass sich "file" auf der SD-Karte befindet und "datalogger.txt" heißt?

Das mit der Klammer hab ich hinbekommen, also in meinem Programm, nicht in dem Beispielprogramm.

Du musst den Code verstehen und nicht nur stur immer nur kopieren!

file ist ein Objekt der File Klasse. Bei dir heiß das halt dataFile

Serenifly:

Scherheinz:
Du musst eigentlich nur deine Werte in einem String hintereinander reihen und den String dann auf die SD schreiben..

Muss man gar nicht unbedingt. Der SD Karte ist wie Serial auch völlig egal, ob das ein einem String steht oder nicht. Daher kann man auch sowas machen:

Natürlich nicht, tut mir leid hab mcih falsch ausgedrückt. wollte eigentlich "du kannst" schreiben :cold_sweat:

Gerade Anfängern würde ich davon abraten, da die dann gleiche die String Klasse auspacken. Und das schafft mehr Probleme als es löst.

Wenn man nicht zu printf() greifen will, ist wie gesagt die Streaming Lib ein sehr schöner Weg um das angenehmer und übersichtlicher zu schreiben:
http://arduiniana.org/libraries/streaming/

Damit kann man einfach sowas machen:

dataFile << "Loggen:" << var1 << ',' << var2 << ',' << var2 << endl;

Das spart auch den Speicher für printf() und macht im Hintergrund im Prinzip das gleiche wie zig print() Aufrufe per Hand.

Hallo,
dieses SD-Card loggen nachträglich einführen ist immer etwas zweifelhaft.

Du hast z.B. das hier:

Serial.print("Humidity 2: "); 
  Serial.print(h2);
  Serial.print(" %\t");
  Serial.print("Temperature 2: "); 
  Serial.print(t2);
  Serial.println(" *C ");

da würde ich das draus machen:

Serial.print("Humidity 2: "); 
  Serial.print(h2,1);
  Serial.print(" %");
  Serial.print("Temperature 2: "); 
  Serial.print(t2,1);
  Serial.println(" *C ");

das sollte es mit einer Nachkommastelle ausgeben.

Das ist das Leichte…
In der IDE sind unter Beispiele->SD
Beispiel Sketche
Die würde ich erst einmal probieren, nur um zu sehen ob mit "SD" alles
in Ordnung ist.
An diesen Beispielen kannst Du auch sehen wie es gemacht wird.
Ich habe von SD auch keine Ahnung gehabt, mit den Beispielen ging das
RuckZuck.
Wenn Dir hier durch die ehrenwerte Hilfe der Mietglieder geheimnisvoller
Code angeboten wird, nützt Dir das reichlich wenig.
Weil Du bei einem Fehler einfach nicht weiß, was Du machst.
Gruß und Spaß
Andreas

Du musst den Code verstehen und nicht nur stur immer nur kopieren!

Wenn das so einfach wäre. Wir sind nur arme Biologen mit den rudimentären Kenntnissen die man in einer kleinen Vorlesung "Einführung in die Informatik für Biologen" vermittelt bekommt.
Trotzdem müssen wir es irgendwie schaffen in unseren Bienenvölkern zu messen.
Ich habe vor einiger Zeit angefangen mich mit dem Arduino zu beschäftigen, einfache Programme erstellt und eben ein bisschen rumgespielt. Da habe ich auch alles verstanden.
Bei dem Projekt jetzt ist das halt viel komplexer, das geht nicht von jetzt auf gleich, dass ich da wirklich verstehe wie das läuft. Aber irgendwie hinbekommen muss ich das trotzdem.

file ist ein Objekt der File Klasse. Bei dir heiß das halt dataFile

Ok, und was bedeutet das jetzt für mich und meinen Arduino? Das Programm kennt "file" offenbar nicht. Ich muss ihm irgendwie erklären was das ist?

Das Ganze muss heute funktionieren, hast du da vielleicht einen Tipp, wie ich das jetzt möglichst schnell und unkompliziert hinbekomme?
Verstehen wie das dann genau funktioniert hat, verbessern und mich um Details kümmern kann ich immer noch wenn das jetzt mal läuft. Dann wird es nächstes Jahr für die große Versuchsreihe perfekt.

Ich hoffe das kommt jetzt nicht verkehrt rüber, nicht dass ich erwarte das mir hier jemand die Arbeit abnimmt und bin euch sehr dankbar für alle bisherigen Tipps. Ich möchte das ja selbst lernen, aber im Moment eilt es halt sehr.

Gibt es vielleicht hier in der Nähe (Bad Tölz) jemanden, der heute noch vorbei kommen könnte und sich das anschauen?

file ist ein Objekt der File Klasse. Bei dir heiß das halt dataFile

Den Satz hab ich gerade verstanden. Da muss stehen dataFile.print, dann kennt der das.

File dataFile;
dataFile = SD.open("datalog.txt", FILE_WRITE);

Damit erstellst du eine Instanz/ein Objekt namens dataFile der Klasse File. Die File Klasse hat folgende Methoden:

Damit du diese aber nutzen kannst, musst du sie auf das Objekt anwenden. Also z.B.

dataFile.print(...);
dataFile.close();

Alles klar, vielen Dank.
Das ist jetzt alles drin, das Programm lässt sich auch kompilieren.
Wenn ich es aber starte passiert nichts.
Der Serial Monitor bleibt völlig leer.
Eigentlich müsste da doch zumindest "DHTxx test!" stehen und dann irgendeine Fehlermeldung, wenn etwas nicht funktioniert?

Das Programm sieht jetzt so aus:

#include "DHT.h"
#include <Wire.h>
#include "RTClib.h"
#include <SPI.h>
#include <SD.h>

#define DHT2PIN 2 // what pin we're connected to
#define DHT3PIN 3
#define DHT4PIN 4 
#define DHT5PIN 5 
#define DHT6PIN 6 
#define DHT7PIN 7 
#define DHT8PIN 8 
#define DHT9PIN 9 
#define DHT10PIN 10 
#define DHT11PIN 11 
#define DHT12PIN 12 



#define DHT2TYPE DHT22   
#define DHT3TYPE DHT22
#define DHT4TYPE DHT22 
#define DHT5TYPE DHT22
#define DHT6TYPE DHT22
#define DHT7TYPE DHT22
#define DHT8TYPE DHT22
#define DHT9TYPE DHT22
#define DHT10TYPE DHT22
#define DHT11TYPE DHT22 
#define DHT12TYPE DHT22 




RTC_DS1307 rtc;

const int chipSelect = 10;

File dataFile;

// Initialize DHT sensor
DHT dht2(DHT2PIN, DHT2TYPE);
DHT dht3(DHT3PIN, DHT3TYPE);
DHT dht4(DHT4PIN, DHT4TYPE);
DHT dht5(DHT5PIN, DHT5TYPE);
DHT dht6(DHT6PIN, DHT6TYPE);
DHT dht7(DHT7PIN, DHT7TYPE);
DHT dht8(DHT8PIN, DHT8TYPE);
DHT dht9(DHT9PIN, DHT9TYPE);
DHT dht10(DHT10PIN, DHT10TYPE);
DHT dht11(DHT11PIN, DHT11TYPE);
DHT dht12(DHT12PIN, DHT12TYPE);


void setup() {
  Serial.begin(9600); 
  
  #ifdef AVR
  Wire.begin();
#else
  Wire1.begin(); 
#endif
  rtc.begin();

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");}
  
  Serial.println("DHTxx test!");
 
  dht2.begin();
  dht3.begin();
  dht4.begin();
  dht5.begin();
  dht6.begin();
  dht7.begin();
  dht8.begin();
  dht9.begin();
  dht10.begin();
  dht11.begin();
  dht12.begin();


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(SS, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1) ;
  }
  Serial.println("card initialized.");
  
  // Open up the file we're going to log to!
  dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (! dataFile) {
    Serial.println("error opening datalog.txt");
    // Wait forever since we cant write data
    while (1) ;
  }}


void loop() {
  // Wait a few seconds between measurements.
  delay(20000);
  
   DateTime now = rtc.now();


  float h2 = dht2.readHumidity();

  float t2 = dht2.readTemperature();
  
  float h3 = dht3.readHumidity();

  float t3 = dht3.readTemperature();
  
    float h4 = dht4.readHumidity();

  float t4 = dht4.readTemperature();
  
  float h5 = dht5.readHumidity();
  
  float t5 = dht5.readTemperature();
  
    float h6 = dht6.readHumidity();
  
  float t6 = dht6.readTemperature();
  
  float h7 = dht7.readHumidity();

  float t7 = dht7.readTemperature();
  
    float h8 = dht8.readHumidity();

  float t8 = dht8.readTemperature();
  
  float h9 = dht9.readHumidity();
 
  float t9 = dht9.readTemperature();
  
    float h10 = dht10.readHumidity();
 
  float t10 = dht10.readTemperature();
  
  float h11 = dht11.readHumidity();
 
  float t11 = dht11.readTemperature();
  
    float h12 = dht12.readHumidity();

  float t12 = dht12.readTemperature();
  
   Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h2) || isnan(t2)) {
    Serial.println("Failed to read from DHT sensor 2!");
    return;
  }

  Serial.print("Humidity 2: "); 
  Serial.print(h2);
  Serial.print(" %\t");
  Serial.print("Temperature 2: "); 
  Serial.print(t2);
  Serial.println(" *C ");
  
  dataFile.print("Humidity 2: "); 
  dataFile.print(h2);
  dataFile.print(" %\t");
  dataFile.print("Temperature 2: "); 
  dataFile.print(t2);
  dataFile.println(" *C ");
  
   if (isnan(h3) || isnan(t3)) {
    Serial.println("Failed to read from DHT sensor 3!");
    return;
  }

  Serial.print("Humidity 3: "); 
  Serial.print(h3);
  Serial.print(" %\t");
  Serial.print("Temperature 3: "); 
  Serial.print(t3);
  Serial.println(" *C ");
  
     if (isnan(h4) || isnan(t4)) {
    Serial.println("Failed to read from DHT sensor 4!");
    return;
  }

  Serial.print("Humidity 4: "); 
  Serial.print(h4);
  Serial.print(" %\t");
  Serial.print("Temperature 4: "); 
  Serial.print(t4);
  Serial.println(" *C ");
  
  if (isnan(h5) || isnan(t5)) {
    Serial.println("Failed to read from DHT sensor 5!");
    return;
  }

  Serial.print("Humidity 5: "); 
  Serial.print(h5);
  Serial.print(" %\t");
  Serial.print("Temperature 5: "); 
  Serial.print(t5);
  Serial.println(" *C ");
  
  if (isnan(h6) || isnan(t6)) {
    Serial.println("Failed to read from DHT sensor 6!");
    return;
  }

  Serial.print("Humidity 6: "); 
  Serial.print(h6);
  Serial.print(" %\t");
  Serial.print("Temperature 6: "); 
  Serial.print(t6);
  Serial.println(" *C ");
  
   if (isnan(h7) || isnan(t7)) {
    Serial.println("Failed to read from DHT sensor 7!");
    return;
  }

  Serial.print("Humidity 7: "); 
  Serial.print(h7);
  Serial.print(" %\t");
  Serial.print("Temperature 7: "); 
  Serial.print(t7);
  Serial.println(" *C ");
  
  if (isnan(h8) || isnan(t8)) {
    Serial.println("Failed to read from DHT sensor 8!");
    return;
  }

  Serial.print("Humidity 8: "); 
  Serial.print(h8);
  Serial.print(" %\t");
  Serial.print("Temperature 8: "); 
  Serial.print(t8);
  Serial.println(" *C ");
  
  if (isnan(h9) || isnan(t9)) {
    Serial.println("Failed to read from DHT sensor 9!");
    return;
  }

  Serial.print("Humidity 9: "); 
  Serial.print(h9);
  Serial.print(" %\t");
  Serial.print("Temperature 9: "); 
  Serial.print(t9);
  Serial.println(" *C ");
  
  if (isnan(h10) || isnan(t10)) {
    Serial.println("Failed to read from DHT sensor 10!");
    return;
  }

  Serial.print("Humidity 10: "); 
  Serial.print(h10);
  Serial.print(" %\t");
  Serial.print("Temperature 10: "); 
  Serial.print(t10);
  Serial.println(" *C ");
  
  if (isnan(h11) || isnan(t11)) {
    Serial.println("Failed to read from DHT sensor 11!");
    return;
  }

  Serial.print("Humidity 11: "); 
  Serial.print(h11);
  Serial.print(" %\t");
  Serial.print("Temperature 11: "); 
  Serial.print(t11);
  Serial.println(" *C ");
  
  if (isnan(h12) || isnan(t12)) {
    Serial.println("Failed to read from DHT sensor 2!");
    return;
  }

  Serial.print("Humidity 12: "); 
  Serial.print(h12);
  Serial.print(" %\t");
  Serial.print("Temperature 12: "); 
  Serial.print(t12);
  Serial.println(" *C ");
  Serial.println("");
}

Bin mal gespannt, wie lange die Sensoren durchhalten, bis die Bienen ein Sensorkabel durchgefressen haben, bzw. bei den DHT's die Luftschlitze zugekittet haben ]:slight_smile:
3D-Temperaturmessung hat in www.imkerforum.de jemand schon realisiert. Der hat mehrere Sensoren pro Rähmchen und eine Visualisierung der Messwerte gemacht 8)
Im Imkeralltag muß man auch mal ein Rähmchen ziehen, versetzen, erweitern...
Ich würde vorschlagen, jedes Rähmchen autonom aufzubauen mit eigenem Akku, eigener CPU usw. und die an einen Bus anzuschließen (z.B. per Funk)
Prinzipiell eine interessante Sache (habe selber 10 Völker) :wink:

Gruß Gerald

Hallo Gerald,

es ist so gedacht, dass pro Volk ein Sensor eingebaut wird, wahrscheinlich im hinteren Teil der Beute und mit Metallgaze geschützt.

Leider funktioniert es aber immer noch nicht.
Könnte sich das bitte nochmal jemand anschauen?
Es gibt ein Glas Honig als Belohnung für denjenigen, der das so hinbekommt dass es funktioniert.

Die Ausgabe nur auf dem Serial Monitor hat wunderbar funktioniert, genau so wie wir uns das vorgestellt haben.
Wenn ich das Programm aber so wie oben erweitere, dann passiert gar nichts mehr. Der Serial Monitor und die SD-Karte bleiben komplett leer. Eigentlich müsste doch zumindest "Initializing SD" auf dem Serial Monitor stehen?

Du verwendest für die SD Karte den digitalen Pin 10 als Chip Select. Gleichzeitig ist daran ein Sensor angeschlossen. Das führt zu Problemen. Da musst du eine Funktion (am besten den Sensor) auf einen anderen Pin verschieben. z.B. auf einen freien analogen Pin. Die digitalen Pins 0 und 1 sind nicht empfehlenswert. Die SD Karte verwendet den SPI Datenbus. Dieser benötigt die Pins 11 -13 (+ 10 der als standard Chip Select dient). An diese Pins kannst du ebenfalls keine Sensoren anschliessen. Die SD Karte muss natürlich über diese Pins angeschlossen werden.

Dann kannst du noch

pinMode(SS, OUTPUT);

in

pinMode(chipSelect, OUTPUT);

ändern.