Show Posts
Pages: [1] 2 3 ... 210
1  International / Deutsch / Re: Schnelle Impulse mit Analogread erfassen on: Today at 02:45:34 pm
cool, das hat geklappt Jurs =)

habe jetzt noch eine kleine frage. Ist es möglich die digitalen 0 bis 8 so zu belegen das wenn z.b beim Relaxometer eine Strom von 10mA eingestellt ist und ich da einen Wert von 100 erhalte den Ausgang 0 zu aktivieren für eine LED und bei sagen wir 20mA (Wert 200) ausgang 0 + 1?

ich habe eine Balken LED und möchte somit angezeigt bekommen welcher Strom eingestellt ist.

Dachte so an eine IF abfrage wie z.B:

If Wert 95-105
then ...

Da der Digitale Wert ja immer ein bisschen schwankt.

Als Ergänzung habe ich nochmal eine Ansteuerung für 8 LEDs gemacht, die die Stromstärkestufen von 10mA bis 80mA repräsentieren sollen, mit einem Abstand von 10 mA von Stufe zu Stufe. Dabei wird eine LED jeweils bereits 5mA vor ihrer Stufe angesteuert, d.h. die 40mA LED fängt bereits ab gemessenen 35 mA oder höher an zu leuchten.

Keine Ahnung, ob das mit Deiner Hardware und Deiner Schaltung so funktioniert, ich kann es bei mir mangels Hardware jedenfalls nicht wirklich testen.

Code:
#include <Servo.h>
Servo myservo; 

byte ledpins[]={2,3,4,5,6,7,8,9}; // Pins für LEDs
#define ANZAHLLEDS sizeof(ledpins)
int  ledlimit[ANZAHLLEDS];

void setFastADC()
{
  // Define various ADC prescaler
  const unsigned char PS_16 = (1 << ADPS2);
  const unsigned char PS_32 = (1 << ADPS2) | (1 << ADPS0);
  const unsigned char PS_64 = (1 << ADPS2) | (1 << ADPS1);
  const unsigned char PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
  // set up faster ADC
  ADCSRA &= ~PS_128;  // remove bits set by Arduino library
  // you can choose a prescaler from above constants,
  ADCSRA |= PS_16;    // set our own prescaler to 16
}


void setup() {
  Serial.begin(9600);
  setFastADC();  // superschnelle ADC-Messungen ermöglichen
  myservo.attach(9);  // Servo an Pin-9
  // Einschaltgrenzen für die LEDs ermitteln
  // Annahme 5V = 1023 analogRead = entsprechend 100 mA Stromstärke
  // die LEDs sollen je 10 mA Stromstärke repräsentieren
  // d.h. die 10 mA LED leuchtet ab >5 mA, die 20 mA LED ab >15 mA, die 30 mA LED ab >25 mA etc.
  for (int i=0;i<ANZAHLLEDS;i++)
  {
    ledlimit[i]=(5+10*i)/100.0*1023.0;
//    Serial.println(ledlimit[i]);  // zum Debugging
    pinMode(ledpins[i],OUTPUT); // LED-Pin auf OUTPUT setzen
  }
  delay(100);
}


unsigned long impulsStartzeit;
boolean impulsAktiv=false;
int lastVoltage=0;
#define ZEROVOLTAGE 25     // alles unterhalb wird als Nullspannung betrachtet
#define ZUCKDAUER 200000L  // Servo-Zuckzeit in Mikrosekunden

void loop() {
  int thisVoltage=analogRead(A0);
  if (thisVoltage>ZEROVOLTAGE && lastVoltage<=ZEROVOLTAGE)
  {
    impulsStartzeit=micros();
    impulsAktiv=true;
    myservo.write(45);
    for (int i=0;i<ANZAHLLEDS;i++)
    {
      if (thisVoltage>ledlimit[i]) digitalWrite(ledpins[i],HIGH); // LED an
    }
    Serial.println(thisVoltage);
  }
  lastVoltage=thisVoltage;
  if (impulsAktiv && micros()-impulsStartzeit>ZUCKDAUER)
  {
    impulsAktiv=false;
    myservo.write(90);
    for (int i=0;i<ANZAHLLEDS;i++) digitalWrite(ledpins[i],LOW); // LEDs aus
 }
}

Bei der Auswahl von LED-Pins würde ich die Pins 0 und 1 der seriellen Schnittstelle besser NICHT verwenden. Und einen passenden Vorwiderstand an den LEDs nicht vergessen, wenn Du testest!

Mit diesem Code werden die LEDs nur angesteuert, während der Servo aus der Ausgangslage herauszuckt und wieder abgeschaltet, wenn der Servo sich in die Ausgangslage zurückbewegt. Ist also mehr ein Aufblitzen.

Wenn die LEDs längere Zeit angesteuert werden sollen, müßte man das noch etwas ändern.
2  International / Deutsch / Re: 2 Motoren Problem on: Today at 01:34:44 pm
Ja es ist ein Arduino UNO mit einem USB-Shield von SainSmart oben drauf wo der Bluetooth Empfänger angeschlossen ist.

Das USB-Shield kommuniziert über die Hardware-SPI Schnittstelle (Pins 10 bis 13) mit dem UNO-Board, oder?

In dem Fall würde ich vermuten, dass Du die Pins 10 und 11 nicht auch noch gleichzeitig für PWM zur Motorsteuerung verwenden darfst.

Lasse mich mal raten:
Ist es der Motor, den Du mit den Pins 10 und 11 steuern möchtest, der nicht funktioniert?
3  International / Deutsch / Re: 2 Motoren Problem on: Today at 11:49:53 am
Also a und b habe ich mir nochmal mittels Serial.print ausgeben lassen und beide werte sind soweit richtig bei 254 wenn ich jeweils RT oder LT drücke.
Also wenn ich RT drücke dreht sich der Motor so wie er es soll, nur wenn LT drücke Summt der andere Motor uns macht nichts.

Oben schreibst Du "mit dem Arduino verbunden" und "Der Arduino ist am PC".
Handelt es sich womöglich nicht um einen Arduino UNO?
Wenn nein, welches Arduino-Board verwendest Du?
4  International / Deutsch / Re: 2 Motoren Problem on: Today at 10:29:53 am
Funktioniert aber immer noch nicht richtig.

Mit welchen Werten für a und b möchtest Du die Motoren denn ansteuern?

Code:
analogWrite(motor1_Speed,a); // speed counts from 0 to 255
 analogWrite(motor2_Speed,b); // speed counts from 0 to 255 

Die Werte a und b werden von Dir auf 0 initialisiert und sie bekommen nur in ganz besonderen Fällen andere Werte zugewiesen:

Code:
if (Xbox.XboxReceiverConnected) {
...
      if (Xbox.Xbox360Connected[i]) {

Wenn diese Bedingungen nicht erfüllt sind, bleiben a und b bei 0.
Vielleicht mal mit Debug-Messages auf Serial überprüfen, mit welchen Werten für a und b Du die Motoren tatsächlich ansteuerst?

Code:
         // motor1
         digitalWrite(motor1_A,HIGH); // A = HIGH and B = LOW means the motor will turn right
         digitalWrite(motor1_B,LOW);
         Serial.print("a= ");Serial.println(a);
         analogWrite(motor1_Speed,a); // speed counts from 0 to 255
         // motor2       
         digitalWrite(motor2_A,HIGH); // A = HIGH and B = LOW means the motor will turn right
         digitalWrite(motor2_B,LOW);
         Serial.print("b= ");Serial.println(b);
         analogWrite(motor2_Speed,b); // speed counts from 0 to 255 
5  International / Deutsch / Re: 2 Motoren Problem on: Today at 09:55:40 am
Hoffe ihr habt irgendwelche Tips oder Ratschläge parat.

Ist Dir vielleicht mit den geschweiften Klammern etwas durcheinander geraten?

Code:
if (Usb.Init() == -1) {
    Serial.print(F("\r\nOSC did not start"));
    while (1); //halt
   
  pinMode(motor1_A,OUTPUT);
  pinMode(motor1_B,OUTPUT);
 
  pinMode(motor2_A,OUTPUT);
  pinMode(motor2_B,OUTPUT);
   
  }

Wenn "Usb.Init()" fehlschlägt, dann mache erstmal eine gemütliche Endlosschleife mit "while (1);".

Und wenn die Endlosschleife irgendwann fertig ist, dann die Motor-Pins auf Output setzen?

Ich kann mir kaum vorstellen, dass das die beabsichtigte Programmlogik sein soll.
6  International / Deutsch / Re: Datenlogger für Versuchsbienenstand on: Today at 09:25:29 am
Ja, vergießen mit 2k Harz ist auch meine Lieblingslösung bei meinem U-Boot-Projekt (ach Gott, das verstaubt im Keller, weil keine Zeit...)
Wo keine Luft ist kommt auch kein Wasser hin.

Allerdings könnte es bei einem SD-Datenlogger dann schwierig werden, die SD-Karte zum Auslesen zu entfernen, wenn die Platine in Elektronik-Vergußmasse eingegossen ist.

Die Alternative, um Platinen beim Einsatz im Außenbereich gegen rauhe Bedingungen und zeitweise entstehendes Kondenswasser abzuhärten ist die Lackierung der bestückten Boards mit Speziallacken.

Bei Conrad gibt es für den Zweck zum Beispiel Sprühdosen mit "PLASTIK 70", einem hochisolierenden Schutzlack, der Korrosionserscheinungen an Elektronikplatinen im Außenbereich verhindert. Den SD-Kartenschacht müßte man vor dem Einsprühen aber wohl abkleben, wenn man so einen Sprühlack verwendet.

Über mögliche LED-Lichteffekte, die den Betriebszustand des Datenloggers nach außen signalisieren, habe ich auch nochmal nachgedacht. Also wenn man eine grüne und eine rote LED verwendet, könnte man es zum Beispiel so machen:

Grüne LED:
- wird nach erfolgreichem setup() auf "Pulsschlag" geschaltet, 1s an, 1s aus wenn das Programm läuft
- zeigt einige Sekunden lang dauer-grün während die Sensoren ausgelesen werden
Das regelmäßige Ein- und Ausschalten der grünen LED signalisiert dann, dass das Programm läuft und nicht hängt oder abgestürzt ist.

Rote LED:
- wird nach erfolgreichem setup() auf "aus" geschaltet und leuchtet danach nur im Fehlerfall
- rotes Blinken ==> Sensoren sind ausgefallen
- rotes Dauerlicht ==> SD-Karte oder RTC-Uhr funktioniert nicht
Das rote Blinken bei ausgefallenen Sensoren könnte man von der Anzahl der ausgefallenen Sensoren abhängig machen. Zum Beispiel bei 12 Sensoren macht man eine 3-Sekunden Blinkperiode und steuert diese Periode wie folgt:
- 1 Sensor ausgefallen ==> 250 ms rot an, 2750 ms aus
- 2 Sensoren ausgefallen ==> 500 ms rot an, 2500 ms aus
- 3 Sensoren ausgefallen ==> 750 ms rot an, 2250 ms aus
- 4Sensoren ausgefallen ==> 1000 ms rot an, 2000 ms aus
etc.
D.h. je mehr Sensoren ausgefallen sind, desto länger bleibt die rote LED an.

So könnte man dann mit einer kurzen Sichtkontrolle der LEDs jederzeit kontrollieren, ob noch alles wunschgemäß läuft.
7  International / Deutsch / Re: DCF77 – macht keinen Spaß on: Today at 08:49:40 am
Ich finde NTP zu störanfallig: mein Arduino holt sich 1 mal am Tag die Zeit übers Internet, wenn aber keine Daten verfügbar sind,  dann bleibt der komplette Sketch stehen und ich muss Reset drücken  smiley-sad

Das kann eigentlich gar nicht angehen. Bei NTP sendest Du ein UDP-Paket und schaust eine Sekunde später nach, ob Du ein UDP-Paket zurückbekommen hast. Wenn Du nichts zurückbekommen hast, machst Du nichts, wenn Du was zurückbekommen hast, hast Du eine neue Zeit.

Hänger mit Stehenbleiben des gesamten Sketches stelle ich eher bei HTTP-Anwendungen fest, wenn Verbindungen aufgebaut, Daten bei stehender Verbindung ausgetauscht und die Verbindung dann wieder beendet wird.

Vlt hat aber auch mein Netshield ne Macke.... manchmal wird die SD-Karte beim starten nicht erkannt, oder der Arduino bekommt keine  IP-Adresse (trotz fester Zuweisung). Teilweise läuft der Sketch auch tagelang und es kann plötzlich nicht mehr von der SD-Karte gelesen werden

Im Endeffekt kommt es auch auf das Programm an: Wenn die Hardware nicht optimal anstesteuert wird, können Probleme auftreten. In Bezug auf NTP stelle ich zum Beispiel auch hier im deutschsprachigen Forum fest, dass die Leute dazu neigen, Code aus dürftigsten Programmbeispielen direkt zu übernehmen und extrem fehlerträchig zu programmieren.

Das fängt dann damit an, dass NTP-Server nicht über den Namen angesprochen werden, sondern nur über die IP-Nummer, die sich jederzeit ändern kann, wenn der Server neu aufgesetzt oder eine andere Hardware ans Internet angeschlossen wird. Und das geht damit weiter, dass als NTP-Server irgendein dubioser Server einer Frickler-Organisation in Übersee eingetragen wird statt in Deutschland die zuverlässigen Server der Physikalisch-Technischen Bundesanstalt in Braunschweig zu verwenden, die wir mit Steuergeld bezahlen, damit sie die amtliche Zeit zuverlässig und genau verbreiten.

Ich stelle jetzt jedenfalls auf DCF um, denke mal dass ich damit besser fahre.

Auch da kommt es auf die Software an, und wie gut diese mit dem verwendeten DCF-Modul harmoniert. Fast alle im Internet verbreiteten Codes zur DCF-Auswertung harmonieren nur mit solchen Modulen gut, die ein tiefpassgefiltertes Signal ausgeben, wie das Modul von Pollin. Mit Modulen wie dem Conrad-DCF-Modul, das ein ungefiltertes Signal ausgibt, kommen nur wenige DCF-Auswertungen gut klar, sobald das Signal gestört wird, wie zum Beispiel der Code von Udo.
8  International / Deutsch / Re: Wie setze ich die dauer einer action? on: Today at 05:58:46 am
Und da hänge ich fest. Aktuell benutze ich den befehl delay(20000), LCD geht dann auch für 20 sec an aber die Sensordaten aktualisieren sich auch 20 sec. lang nicht da der loop ja wartet. Wegen der Sensordaten(Temp,Luftdruck...) weiter nicht schlimm, aber wenn eine Uhr dazu soll geht das so nicht.

Ja, "delay" ist ein Befehl zum Blockieren der Programmausführung für eine bestimmte Zeit.

Für Programme, die nicht blockiert werden sollen, ist delay völlig ungeeignet.

Meine Frage; wie bestimme ich die dauer von lcd.backlight() ohne die anzeige der Sensordaten damit zu beeinflussen?

Ohne delay natürlich. Am besten deklarierst Du Dir oberhalb der loop-Funktion sowas in der Art:
Code:
#define BACKLIGHTDURATION 20000L  // Anzahl Millisekunden Einschaltzeit
boolean backlightOn=false;
unsigned long backlightOnTime=0;  // Einschaltzeitpunkt in Millisekunden
Und in der loop behandelst Du es dann ungefähr so (ungetestet hingeschrieben):
Code:
void loop() {
  // Irgendwas an Code
  if (backlightOn && millis()-backlightOnTime>BACKLIGHTDURATION)
  {
    lcd.noBacklight(); //backlight Off
    backlightOn=false;
  }
  else if (!backlightOn && digitalRead(inputPin))
  {
    lcd.backlight(); // backlight on
    backlightOn=true;
    backlightOnTime=millis();
  }
  // Noch irgendwas anderes an Code
}

Funktioniert's?
9  International / Deutsch / Re: Datenlogger für Versuchsbienenstand on: September 13, 2014, 01:01:13 pm
Wenn's nach mir geht, dann hätte ich gerne zwei LEDs, eine grüne und eine rote.
Wenn alles perfekt ist, dann leuchtet die grüne andauernd.

Eine dauergrüne LED zeigt nur wenig brauchbares an. Dafür brauchst Du keinen IO, die hängst Du am besten mit Vorwiderstand gleich an 5V und dann leuchtet sie dauernd, solange das Board mit Spannung versorgt wird. Quasi eine Spannungskontrolle.

Dauergrün würde ja auch leuchten, wenn
- das Programm in einer Endlosschleife festhängt
- das Programm schon lange abgestürzt ist
- die loop-Funktion aus anderen Gründen überhaupt nicht mehr aufgerufen wird oder nicht durchläuft
Mehr als eine grobe Kontrolle der Betriebsspannung kann das nicht sein.

Mit Blinksignalen der verschiedensten Art läßt sich etwas anfangen.

Wenn einer oder mehrere Sensoren nicht senden, dann leuchtet die grüne andauernd und die rote blinkt.
Wenn keine Aufzeichnung mehr möglich ist (alle Sensoren i.A. oder SD funktioniert nicht), dann leuchtet die rote andauernd.
Dann könnte man schon bei der regelmäßigen Kontrolle der Völker erkennen ob es ein Problem gibt und dann nachschauen woran das liegt.

Könnte man machen. Braucht einen I/O-Pin.
Soll ich dafür mal einen Vorschlag machen?

Funktioniert der gepostete Code mit Deiner SD-Karte?

Das Ding muss halt monatelang im Freien stehen. Da ist mir eine übertriebene Dichtheit lieber als dass es bei starkem Regen irgendwo reinsuppt.

Es ist ein Irrglaube, Gehäuse möglichst "dicht" zu machen, damit es keine Schäden durch Feuchtigkeit gibt. Am billigsten und extrem gut funktioniert es im Freien, ein Gerät "regengeschützt" anzubringen (kleine Überdachung, die für Trockenheit sorgt) und ein stinknormales "undichtes" Gehäuse zu verwenden, möglicherweise sogar mit Lüftungsschlitzen.

Die meisten selbstgebauten elektronischen Gerät im Freien geben nämlich wegen Kondenswasser in schlecht durchlüfteten Gehäusen den Geist auf, weil irgendjemand meint, das Gehäuse müsse "dicht" gemacht werden. Stattdessen mus es nur regengeschützt angebracht werden in einem stinknormalen "undichten" 08/15 Gehäuse.

In das Gehäuse kommt aber noch ein Beutel Silica Gel oder anderes Trockenmittel (ich hätte Calciumchlorid da).

Das Silica-Gel als Trocknungsmittel reißt es in einem geschlossenen Gehäuse natürlich wieder raus: Wenn die Luftfeuchte im Innern bei Abkühlung ansteigt, kann das Trocknungsmittel die überschüssige Luftfeuchte aufnehmen. Dazu wäre es allerdings vorteilhaft, das Gehäuse nicht nur "wasserdicht" sondern sogar "luftdicht" zu haben, und das Trocknungsmittel bei Bedarf auszutauschen, wenn seine Wasseraufnahmefähigkeit erschöpft ist. Eine relativ teure und nicht ganz wartungsfreie Angelegenheit.

Ansonsten gilt eher: Regenschutzdach von oben, Sensorgehäuse mit guter Durchlüftung darunter angebracht.
10  International / Deutsch / Re: Datenlogger für Versuchsbienenstand on: September 13, 2014, 11:43:40 am
Noch mehr Funktionen?
Ich denke das reicht jetzt erst Mal für den Prototypen.
Die Karte über Serial auslesen ist nicht nötig,
OK, dann habe ich das nur mal so weit eingebaut, wie ich es zum Debuggen brauchte. Es gibt derzeitig nur ein einziges serielles Kommando und das sieht so aus: Egal was über Serial gesendet wird (leere Zeile reicht aus) wird die gerade aktuelle Datei ausgelesen und am Bildschirm angezeigt (mit ein paar Matschzeichen am Dateiende).

Wenn Du das deaktivieren möchtest, kommentiere den Aufruf von " handleSerialCommand();" in der loop einfach aus!

ChipSelect Deiner SD-Karte ist wohl Pin-10?
Ich hatte mit dem SD-Kartenschacht auf einem Ethernet-Shield getestet, da ist es Pin-4.

Hier mein Code, wie gesagt, mit Sensoren konnte ich nicht testen:
Code:
#include "DHT.h"
#include <Wire.h>
#include <SPI.h>
#include <SD.h>

#define LOGWAITTIME 20 // Anzahl der Sekunden zwischen zwei Log-Einträgen
#define CHIPSELECT 10  // ChipSelect-Pin der SD-Karte, 4 bei Ethernet-Shield

DHT dhtSensoren[]={ // hier die Sensoren mit ihren Pins eintragen
  DHT(2, DHT22),
  DHT(3, DHT22),
  DHT(4, DHT22),
  DHT(5, DHT22),
  DHT(6, DHT22),
  DHT(7, DHT22),
  DHT(8, DHT22),
  DHT(9, DHT22),
};

#define ANZAHLSENSOREN sizeof(dhtSensoren)/sizeof(dhtSensoren[0])

#define RTC_I2C_ADDRESS 0x68

byte bcdToDec(byte val)  // Hilfsfunktion zum Lesen/Schreiben der RTC
{ // Convert binary coded decimal to decimal number
  return ( (val/16*10) + (val%16) );
}

void rtcReadTime(int &jahre, int &monate, int &tage, int &stunden, int &minuten, int &sekunden)
{ // aktuelle Zeit aus RTC auslesen
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);  // Reset the register pointer
  Wire.endTransmission();
  Wire.requestFrom(RTC_I2C_ADDRESS, 7);
  // A few of these need masks because certain bits are control bits
  sekunden    = bcdToDec(Wire.read() & 0x7f);
  minuten     = bcdToDec(Wire.read());
  stunden     = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  /*wochentag   = */bcdToDec(Wire.read());
  tage        = bcdToDec(Wire.read());
  monate      = bcdToDec(Wire.read());
  jahre       = bcdToDec(Wire.read())+2000; 
}


int freeRam () { // ermittelt freien RAM-Speicher
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

char* floatFormatKomma(float f, int decimals, char* str)
{ // Gleitkommazahl zwischen -999 und 999 mit Dezimalkomma formatieren
  // Zielpuffer str muss groß genug sein!
  if (abs(f)>999) strcpy(str,"???.?");
  else dtostrf(f,decimals+1,decimals,str);
  char* c=strchr(str,'.');
  if (c!=NULL) c[0]=',';
  return str;
}

void setup() {
  Serial.begin(9600);
  Serial.print("Free RAM: ");Serial.println(freeRam());
 
#ifdef AVR
  Wire.begin();
#else
  Wire1.begin();
#endif
  Serial.println(F("DHT22-Sensoren initialisieren..."));
  for (int i=0;i<ANZAHLSENSOREN;i++) dhtSensoren[i].begin();
  Serial.print(F("SD-Karte initialisieren... "));
  pinMode(SS,OUTPUT);
  pinMode(CHIPSELECT, OUTPUT);
  delay(1);
  if (!SD.begin(CHIPSELECT)) {
    Serial.println(F("Kartenfehler oder SD-Karte nicht vorhanden"));
    // don't do anything more:
    while (1) ;
  }
  Serial.println(F(" OK"));
}

boolean timeToLogEntries(int &jahre, int &monate, int &tage, int &stunden, int &minuten, int &sekunden)
{ // gibt true zurück, wenn es wieder Zeit ist, einen Datensatz zu loggen
  static long lastSecond;
  rtcReadTime(jahre,monate,tage,stunden,minuten,sekunden);
  long thisSecond=stunden*3600L+minuten*60+sekunden;
  if (lastSecond/LOGWAITTIME != thisSecond/LOGWAITTIME)
  {
    lastSecond=thisSecond;
    return true;
  }
  else return false;
}

void logEntries(int jahre, int monate, int tage, int stunden, int minuten, int sekunden)
{ // Einen Datensatz loggen und auf Serial und in Datei ausgeben
  char str[18];
  snprintf(str,sizeof(str),"%04d",jahre); // Verzeichnisname = Jahreszahl
  SD.mkdir(str);  // legt das Jahresverzeichnis an, falls es nicht existiert
  snprintf(str,sizeof(str),"%04d/%04d_%02d.txt",jahre,jahre,monate);
  File file=SD.open(str, FILE_WRITE);
  if (!file) Serial.print(F("Error "));
  Serial.print(F("Writing File "));
  Serial.println(str);  // Dateiname mit vollständigem Pfad
  snprintf(str,sizeof(str),"%02d.%02d.%04d ",tage, monate, jahre);
  Serial.print(str);
  if (file) file.print(str);
  snprintf(str,sizeof(str),"%02d:%02d\t",stunden,minuten);
  Serial.print(str);
  if (file) file.print(str);
  for(int i=0;i<ANZAHLSENSOREN;i++)
  {
    float humidity=dhtSensoren[i].readHumidity();
    float temperature=dhtSensoren[i].readTemperature();
    if (isnan(humidity) || isnan(temperature))
    {
      Serial.print(F("***\t***\t"));
      if (file) file.print(F("***\t***\t"));
    }
    else
    {
      floatFormatKomma(humidity,1,str);
      Serial.print(str);
      if (file) file.print(str);
      Serial.print('\t');
      if (file) file.print('\t');
      floatFormatKomma(temperature,2,str);
      Serial.print(str);
      if (file) file.print(str);
      Serial.print('\t');
      if (file) file.print('\t');
    }
  }
  Serial.println();
  if (file) file.println();
  if (file) file.close();
}

void handleSerialCommand()
{ // Funktion zum Debuggen: Gibt die aktuelle Datei auf Serial aus
  char str[18];
  byte buf[64];
  if (!Serial.available()) return;
  int jahre,monate,tage,stunden,minuten,sekunden;
  rtcReadTime(jahre,monate,tage,stunden,minuten,sekunden);
  snprintf(str,sizeof(str),"%04d/%04d_%02d.txt",jahre,jahre,monate);
  Serial.println();
  File file=SD.open(str, FILE_READ);
  if (!file) Serial.print("Error ");
  Serial.print("Reading File ");
  Serial.println(str);
  while (file.available())
  {
    file.read(buf,sizeof(buf));
    Serial.write(buf,sizeof(buf)); // sizeof(buf));
  }
  Serial.println();
  Serial.println();
  file.close();
  while (Serial.available()) Serial.read();
}


void loop() {
  delay(1000); // In diesem Abstand wird geprüft, ob neue Werte zu loggen sind
  int jahre,monate,tage,stunden,minuten,sekunden;
  if (timeToLogEntries(jahre, monate, tage, stunden, minuten, sekunden))
    logEntries(jahre, monate, tage, stunden, minuten, sekunden);
  handleSerialCommand();
}

das Ganze kommt in ein wasserdichtes Gehäuse und es wird eher schwierig da während dem Betrieb ein USB-Kabel anzuschließen.

Vorsicht mit "wasserdichten" Gehäusen, das kann bei Kondenswasserbildung zu ganz üblen Korrosionsschäden führen! Das wäre ggf. nochmal genauer zu diskutieren.

Die Uhr einstellen ist auch überflüssig, die wird ja soweit genau gehen dass sie eine Saison lang ungefähr stimmt. Eine Minute hin oder her ist egal. Und weil wir eh nur im Sommer messen können muss man auch keine Winterzeit einstellen können.

Alles klar, also ohne Zeiteinstellung.
Spart Arbeit bei der Funktion "handleSerialCommand();"

Wünschenswert wäre vielleicht noch eine kleine Statusanzeige per blinkender LED außen am Gerät.
So ungefähr wie:
- langsames Blinken ==> alles in Ordnung, Programm läuft fehlerfrei
- schnelles Blinken ==> Kartenfehler, kann nicht auf SD-Karte schreiben
- lang und kurz abwechselnd Blinken ==> Sensorfehler, mindestens ein Sensor liefert keine Werte
Damit man von außen ggf. direkt erkennen kann, ob eine Störung vorliegt oder ob das Programm wie gewünscht funktioniert.
11  International / Deutsch / Re: Datenlogger für Versuchsbienenstand on: September 13, 2014, 09:21:57 am
Auf dem Serial Monitor wird das so ausgegeben:

Das sieht doch schon mal sehr gut aus!

- RTC ist richtig angeschlossen und funktioniert
- RTC ist richtig gestellt
- DHT22-Sensoren sind richtig angeschlossen und funktionieren

An den protokollierten Daten müßte man jetzt eigentlich nur noch ändern, dass anstelle des Dezimalpunktes ein Dezimalkomma ausgegeben wird. Und dann die Daten in Datei auf SD-Karte wegschreiben.

761 Bytes RAM-Speicher sind noch frei, die man im Programm verbraten kann, das sollte locker reichen.

Was brauchst Du denn noch an Zusatzfunktionen?

Soll man sich die protokollierten Daten zwecks Debugging auch von der Karte auslesen und auf Serial anzeigen lassen können, damit man zum Debuggen nicht immer die Karte entnehmen und umständlich am PC auslesen muss? Ich glaube, das wäre zum Debuggen ganz praktisch.

Soll man die RTC-Uhr auch über den Seriellen Monitor direkt vom Programm aus neu stellen können?
12  International / Deutsch / Re: Datenlogger für Versuchsbienenstand on: September 13, 2014, 08:40:31 am
Jurs, das funktioniert perfekt!

Das hört sich ja schon mal gut an.

Ich hätte vielleicht noch erwähnen müssen, dass das Ganze bei mir auf einem Mac ist, also auch eine Excel-Version für Mac.
Die Auswertung wird dann wahrscheinlich auf einem Windows PC erfolgen.

Das sollte kein Problem sein. Ich habe das gepostete Datenformat getestet mit einer "Windows Starter-Edition" von MS-Excel. Sollte dann soweit OK sein. Und das Datenformat der Textdatei kann man ggf. später natürlich auch noch ändern. Aber man muß natürlich erstmal etwas haben, das man ausgeben möchte.

Bevor die Textdatei ausgegeben wird, habe ich nun aber erstmal die Programstruktur geändert, so dass
a) RAM-Speicher gespart wird und
b) Die Sensoren reihum in einer for-Schleife abgefragt werden
c) und ein paar Dinge mehr

Beispielsweise habe ich die RTClib rausgeschmissen und lese die RTC direkt mit einer eigenen Funktion aus.

Anbei mal ein Sketch zum Testen.
Ich habe momentan hier keine DHT22-Sensoren angeschlossen, bei mir erscheint anstelle der Luftfeuchte- und Temperaturwerte nur die Fehlerausgabe "***" an den Stellen, wo Werte nicht ausgelesen werden können (also eigentlich überall.

Das sollte mit dem Testprogramm funktionieren:
- Ausgabe auf Serial (aber noch KEINE Ausgabe in Datei)
- lauffähig auf UNO-Board (weil ausreichend RAM-Speicher eingespart wird)
- vorprogrammierter Zeitabstand zum Testen: 20 Sekunden (definiert in LOGWAITTIME)

Zum Aufzeichnungszeitpunkt sollte ausgegeben werden:
- Dateiname, in den die Daten geschrieben würden
- ein Datensatz mit allen ausgelesenen Sensorwerten

Läuft das bei Dir soweit?
Code:
#include "DHT.h"
#include <Wire.h>
#include <SPI.h>
#include <SD.h>

#define LOGWAITTIME 20

DHT dhtSensoren[]={ // hier die Sensoren mit ihren Pins eintragen
  DHT(2, DHT22),
  DHT(3, DHT22),
  DHT(4, DHT22),
  DHT(5, DHT22),
  DHT(6, DHT22),
  DHT(7, DHT22),
  DHT(8, DHT22),
  DHT(9, DHT22),
};

#define ANZAHLSENSOREN sizeof(dhtSensoren)/sizeof(dhtSensoren[0])

float humidity[ANZAHLSENSOREN];
float temperature[ANZAHLSENSOREN];

// RTC_DS1307 rtc;

#define RTC_I2C_ADDRESS 0x68

byte bcdToDec(byte val)  // Hilfsfunktion zum Lesen/Schreiben der RTC
{ // Convert binary coded decimal to decimal number
  return ( (val/16*10) + (val%16) );
}

void rtcReadTime(int &jahre, int &monate, int &tage, int &stunden, int &minuten, int &sekunden)
{ // aktuelle Zeit aus RTC auslesen
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);  // Reset the register pointer
  Wire.endTransmission();
  Wire.requestFrom(RTC_I2C_ADDRESS, 7);
  // A few of these need masks because certain bits are control bits
  sekunden    = bcdToDec(Wire.read() & 0x7f);
  minuten     = bcdToDec(Wire.read());
  stunden     = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  /*wochentag   = */bcdToDec(Wire.read());
  tage        = bcdToDec(Wire.read());
  monate      = bcdToDec(Wire.read());
  jahre       = bcdToDec(Wire.read())+2000; 
}


const int chipSelect = 10;

File dataFile;

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

void setup() {
  Serial.begin(9600);
  Serial.print("Free RAM: ");Serial.println(freeRam());
 
#ifdef AVR
  Wire.begin();
#else
  Wire1.begin();
#endif
/*
  rtc.begin();
  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");}
*/ 
  Serial.println("DHTxx test!");
  for (int i=0;i<ANZAHLSENSOREN;i++) dhtSensoren[i].begin();
return;   // Eingefügt: Keine SD-Kartenfunktion in dieser Testversion

  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(chipSelect, 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) ;
  }
}

boolean timeToLogEntries(int &jahre, int &monate, int &tage, int &stunden, int &minuten, int &sekunden)
{
  static long lastSecond;
  rtcReadTime(jahre,monate,tage,stunden,minuten,sekunden);
  long thisSecond=stunden*3600L+minuten*60+sekunden;
  if (lastSecond/LOGWAITTIME != thisSecond/LOGWAITTIME)
  {
    lastSecond=thisSecond;
    return true;
  }
  else return false;
}

void logEntries(int jahre, int monate, int tage, int stunden, int minuten, int sekunden)
{
  char str[18];
  snprintf(str,sizeof(str),"%04d\\%04d_%02d.txt",jahre,jahre,monate);
  Serial.println(str);  // Das wäre die Datei, in die die Daten geschrieben werden
  snprintf(str,sizeof(str),"%02d.%02d.%04d ",tage, monate, jahre);
  Serial.print(str);
  snprintf(str,sizeof(str),"%02d:%02d\t",stunden,minuten);
  Serial.print(str);
  for(int i=0;i<ANZAHLSENSOREN;i++)
  {
    float humidity=dhtSensoren[i].readHumidity();
    float temperature=dhtSensoren[i].readTemperature();
    if (isnan(humidity) || isnan(temperature))
      Serial.print("***\t***\t");
    else
    {
      Serial.print(humidity,1);
      Serial.print('\t');
      Serial.print(temperature,2);
      Serial.print('\t');
    }
  }
  Serial.println();
}


void loop() {
  delay(1000); // In diesem Abstand wird geprüft, ob neue Werte zu loggen sind
  int jahre,monate,tage,stunden,minuten,sekunden;
  if (timeToLogEntries(jahre, monate, tage, stunden, minuten, sekunden))
    logEntries(jahre, monate, tage, stunden, minuten, sekunden);
}

Du kannst ja mal eine Testausgabe aus Deinem seriellen Monitor herauskopieren und hier posten.
13  International / Deutsch / Re: Datenlogger für Versuchsbienenstand on: September 13, 2014, 06:15:44 am
Also als Intervall für die Aufzeichnung sollte eigentlich eine ganze oder halbe Sunde genügen.

OK, das ist ja sehr entspannt. Bei stündlichem Schreibvorgang wären das 24 Schreibvorgänge pro Tag oder ca. 30*24= 720 pro Monat, damit würde es über 100 Monate dauern, bis der erste Sektor kaputtgeschrieben ist, wenn Du über 100 Monate lang immer in dieselbe Datei schreibst. Überhaupt kein Problem.

Ich schlage mal vor: Viertelstündlich schreiben, macht 4*24= 96 Schreibvorgänge pro Tag und ca. 30*96= 2880 Schreibvorgänge pro Monat. In einen FAT-Sektor von 512 Bytes passen 32 Dateieinträge a 16 Bytes, also alle 32 Dateien wird in einen anderen FAT-Sektor geschrieben. Wenn Du nun jeden Monat in eine andere Log-Datei schreibst, finden maximal ca. 32*2880 Schreibvorgänge im selben FAT-Sektor statt = 92160 Schreibvorgänge für den am stärksten belasteten FAT-Sektor.

Das sollte eine hochwertige SD-Karte noch schaffen, ohne dabei defekt zu werden oder Ersatzsektoren zu verwenden, so dass Du die Karte damit viele Jahre lang beschreiben kannst, bis sie voll ist (Voraussetzung: Keine bereits geschriebenen Dateien löschen).

Jetzt ist es ja noch so, dass an die Pins 0,1,10,11,12,13 keine Sensoren angeschlossen werden können. Wir haben aber 12 Sensoren, könnte man die vier, die vorher auf 1,10,11,12 angeschlossen waren noch auf den analogen Pins unterbringen?

Du kannst die Pins A0 bis A5 auf dem UNO auch als digitale Pins verwenden.

Über das zu schreibende Datenformat habe ich mir folgende Gedanken gemacht:
Wenn die Daten in Excel weiterverarbeitet werden sollen, dann wäre ein Datenformat praktisch, das sich ruckzuck und ohne Aufwand in Excel importieren läßt. Beim Datenimport beachtet Excel offenbar die Ländereinstellungen des PCs, so dass auf einem auf "Deutschland/Deutsch" eingestellten PC das Datumsformat "dd.mm.yyyy" verwendet wird und für Zahlen mit Nachkommastellen das Komma und nicht der Dezimalpunkt als Trennzeichen erwartet wird.

Ich habe mal eine Musterdatei als Textdatei mit Zufallsdaten gemacht und versucht, diese dann in Excel zu importieren und zu verarbeiten. Probiere bitte mal aus, ob Du mit so einer "test.txt" Datei auch etwas anfangen und diese leicht in Excel öffnen und die Daten verarbeiten kannst!

Diese test.txt Datei sollte so vorbereitet sein, dass Du beim Excel Import-Wizard auf einem PC mit "Deutsch" Einstellung nur die Standardvorgaben bestätigen mußt, und schon wird die Datei ohne weitere Einstellungen direkt geöffnet bzw. importiert. Funktioniert das bei Dir?
14  International / Deutsch / Re: Datenlogger für Versuchsbienenstand on: September 12, 2014, 02:52:30 pm
Ja das wäre perfekt.
Auswertung wird mit Excel erfolgen.

OK, also schreibt man am besten ein Format, das sich in Excel besonders leicht importieren läßt. Also beispielsweise TAB-Seperated ASCII-Text.

Muss ich mal schauen, irgendwo muß ich noch eine Excel Starter-Edition auf einem PC haben. Ich glaube, auf deutschen Excel-Versionen mit Lokaleinstellung Deutschland importiert man Gleitkommazahlen besser mit Dezimalkomma als mit Dezimalpunkt. damit sie problemlos als Zahlen importiert werden? Muss ich mal ausprobieren.

Mir ist noch aufgefallen dass bei der Version, die nur auf Serial Monitor ausgibt das, bei einem Fehler nicht weiter geht.

Mit Fehlerbehandlung kann man sich wahrscheinlich länger beschäftigen als mit der Programmierung einer Prototypen-Firmware.

Als wichtigen Parameter müßte man noch wissen:
Wie oft sollen Daten aufgezeichnet werden? Jede Viertelstunde? Alle Fünf Minuten? Jede Minute? Häufiger?

Ggf. muß man sich nämlich Gedanken über das Kaputtschreiben von SD-Kartensektoren machen. Mal angenommen, ein SD-Kartensektor kann 100000 mal beschrieben werden und Du schreibst einmal pro Sekunde Daten in eine Datei, die dazu jedesmal geöffnet, beschrieben und geschlossen wird, dann wird bei jedem Schließen der Datei der FAT-Sektor mit der Dateigröße neu beschrieben. In dem Fall wäre der FAT-Sektor bereits nach etwas über einem Tag kaputtgeschrieben.

Zwar hat eine SD-Karte immer "Ersatzsektoren", die der Kartencontroller für kaputtgeschriebene Sektoren als Ersatz in das Dateisystem einblenden kann, aber diese stehen nur begrenzt in nicht allzu großer Anzahl zur Verfügung. Wenn alle Ersatzsektoren verbraucht und ebenfalls kaputtgeschrieben sind, ist die Karte defekt und unbrauchbar.

Also wie oft sollen die Daten auf Karte geschrieben werden?

Das wäre dann auch eine Frage des Datenumfangs, mit dem Du zu hantieren hast. Mal angenommen, Du machst eine Aufzeichnung einmal pro Minute, dann bekommst Du 1440 Datensätze pro Tage = ca.30*1440 = 43200 Datensätze pro Monat zum Auswerten. Bei einer Aufzeichnung alle 10 Minuten wäre es nur ein Zehntel der Datenmenge.

Hast Du Dir schon überlegt, wie viele Daten Du wie oft erzeugen und aufzeichnen möchtest?
Alle Daten in eine einzige Datei?
Oder die Daten jeden Tag oder jede Woche oder jeden Monat in eine neue Datei?
15  International / Deutsch / Re: Datenlogger für Versuchsbienenstand on: September 12, 2014, 12:17:35 pm
Das ist alles hier bei mir!

Alles klar, optimale Voraussetzungen!

Jetzt habe ich mal grob über das Ausgabeformat drübergeschaut, dass Du auf Serial ausgeben läßt.

Das schaut ja ungefähr so aus (Temperaturwerte sind nur Zufallszahlen):
Code:
Humidity 0: 91.00 % Temperature 0: 47.00 *C
Humidity 1: 4.00 % Temperature 1: -3.00 *C
Humidity 2: 17.00 % Temperature 2: 24.00 *C
Humidity 3: 14.00 % Temperature 3: -14.00 *C
Humidity 4: 86.00 % Temperature 4: -30.00 *C
Failed to read from DHT sensor 5
Humidity 6: 74.00 % Temperature 6: -34.00 *C
Humidity 7: 53.00 % Temperature 7: -14.00 *C

Wie und womit möchtest Du das auswerten, wenn auf auf SD-Karte geschrieben wird?

Normalerweise würde sich zur Aufzeichnung eher ein solches Format eigenen:
- Eine Zeile pro Datensatz
- Ein Datensatz besteht aus Datum, Zeit, und 12x Sensorwerten Humidity/Temperature
(alle Werte mit einem Trennzeichen getrennt, z.B. Semikolon oder Tabulatorzeichen)

Solche Dateien könntest Du dann relativ einfach weiterverarbeiten, z.B. mit MS-Excel oder anderen Programmen.

Soll ich Dir die Ausgabe gleich so umstellen, dass alle Werte eines Datensatzes in einer Zeile ausgegeben werden?
(Zusammengehörende Werte stehen dann spaltenweise untereinander)
Was meinst Du?
Pages: [1] 2 3 ... 210