Pages: [1]   Go Down
Author Topic: kleines Problem im Programm?  (Read 1226 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Schönen guten Morgen,

ich habe vor einiger Zeit ein Programm geschrieben, was eine Temperatur misst und die gemessenen Werte auf eine SD-Karte speichert. Wie oft der Wert gespeichert werden soll, sollte dabei einstellbar sein.

Jetzt habe ich das Problem, dass das Programm bei einer Speicherzeit von 56min aufwärts keine Werte mehr speichert. Die Funktion soll aber bis Eine Stunde loggen vorhanden sein. Ist das irgendwie realisierbar oder kann mir vlt. einer sagen woran das liegen könnte?

Hier mal der Code

Code:
#include <Wire.h>
#include <RTClib.h>
#include <OneWire.h>
#include <SD.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd ( A2, A1, 6, 5, 2, 3 );             // Pinbelegung des LC - Displays
const int chipSelect = 4;
OneWire  ds ( 9 );                                   // on pin 9
RTC_DS1307 RTC;

const int hoch = 7;                                  // Taster für Hochzählen defenieren
const int runter = 8;                                // Taster für Runterzählen defenierern
int l = 0;
double Wert  = 1;                                    // Wert = Fließkommazahl

void setup()
{
  lcd.begin(16,2);                                   // lcd initialisieren
 
  pinMode ( hoch, INPUT );                           // Port als input
  pinMode ( runter, INPUT );                         // Port als input
    digitalWrite ( hoch, HIGH );                     // Pull up
    digitalWrite ( runter, HIGH );                   // pull up
 
  Wire.begin();                                      //RTC
  RTC.begin();                                       //RTC
 
  lcd.print ( "Init SD card..." );
        delay ( 1000 );
 
                                                     // see if the card is present and can be initialized:
 
  if (!SD.begin(chipSelect)) {
      lcd.clear();
      lcd.print("Card failed");
        delay ( 2000 );
                                                     // don't do anything more:
    return;
  }
 
    lcd.clear();
    lcd.print("card init.");
        delay ( 2000 );
    lcd.clear();
 
    lcd.print("Log: ");
    lcd.print(Wert);
    lcd.print(" min.");
}

void loop()
{
  DateTime now = RTC.now();
                                                     // DS1820 Routine
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;

  if ( !ds.search(addr)) {
    ds.reset_search();
      delay(250);
    return;
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      return;
  } 
                                                     // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      type_s = 1;
      break;
    case 0x28:
      type_s = 0;
      break;
    default:
      return;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         
 
    delay(750);     
   
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);                                    // Read Scratchpad

  for ( i = 0; i < 9; i++) {                         // we need 9 bytes
    data[i] = ds.read();

  }
    // convert the data to actual temperature
  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3;                                  // 9 bit resolution default
    if (data[7] == 0x10) {
                                                     // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;                 // 9 bit resolution, 93.75 ms
      else if (cfg == 0x20) raw = raw << 2;          // 10 bit res, 187.5 ms
      else if (cfg == 0x40) raw = raw << 1;          // 11 bit res, 375 ms
                                                     // default is 12 bit resolution, 750 ms conversion time
  }

  celsius = (float)raw / 16.0;
                                                      // Temperatur auf LCD ausgeben
  if ( celsius >= 100 ) {
     lcd.setCursor ( 0,1 );
     lcd.print ( "Temp: ");
     lcd.print ( "-");
     lcd.print ( 4095 - celsius );                     // Wenn Temperatur ins Negative geht, dann diese Berechnung
     lcd.print(0xDF,BYTE);                             // 0xDF, BYTE geht nur für LCD
     lcd.print("C");
  } else {
    lcd.setCursor ( 0,1 );
    lcd.print("Temp.: ");
    lcd.print(celsius );                               // Temperatur im positiven ausgeben
    lcd.print(0xDF,BYTE);                              // 0xDF, BYTE geht nur für LCD
    lcd.print("C");
  }
                                                       // Routine für's Speichern auf die SD Karte
  File dataFile = SD.open("datalog.txt", FILE_WRITE);  // Temperatur in .txt schreiben

  if (dataFile) {
    if ( celsius >= 100 ) {
     dataFile.print ( "-");
     dataFile.print ( 4095 - celsius );
     
     dataFile.print ( " ; " );
     
     dataFile.print(now.hour(),DEC);
     dataFile.print(":");
     dataFile.println(now.minute(),DEC);
     dataFile.close();
  } else {
      dataFile.print(celsius);
     
      dataFile.print ( " ; " );
     
      dataFile.print(now.hour(),DEC);
      dataFile.print(":");
      dataFile.println(now.minute(),DEC);
      dataFile.close();
  }}
                                                        // Schleife für Datenlog intervall ( mit Tasterabfrage )
  for ( l = 0; l <= Wert * 590; l++ ) {                 // Tasterabfrage alle 59 Sekunden * Wert ( restliche Sekunde im laufe des Programms als delay )
                                                        // Taster für Hochzählen abfragen
  if ( digitalRead ( hoch ) == LOW ) {
    l = 0;
    Wert += 1.0f;                                       // zählt in 1,0'ner schritten hoch
      lcd.clear();
      lcd.print ( "Log: " );
      lcd.print ( Wert );
      lcd.print ( " min." );
                                                        // Entprellung
    while ( digitalRead ( hoch ) == LOW ) {}
    }
                                                        // Taster für Runterzählen abfragen
   if ( digitalRead ( runter ) == LOW ) {
    l = 0;
    Wert -= 1.0f;                                       // zählt in 1,0'ner schritten runter
      lcd.clear();
      lcd.print ( "Log: " );
      lcd.print ( Wert );
      lcd.print ( " min." );
                                                        // Entprellung
    while ( digitalRead ( runter ) == LOW ) {}
    }
        delay ( 100 );
 }}

Schonmal vielen Dank!

Liebe Grüße
Logged

Forum Moderator
BZ (I)
Online Online
Brattain Member
*****
Karma: 272
Posts: 21939
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

"double Wert  = 1;" ist keine Fließkommazahl
Zu was brauchst Du eine Fließkommazahl?  Da ist eine unsigned long Variable besser!!!

Die Entprellung funktioniert nicht so wie Du sie programiert hast. Prellen bedeutet, daß der Kontakt ein paar mal hüpft und so einige Impulse entstehen bevor der Kontakt entgültig geschlossen / geöffnet ist. http://de.wikipedia.org/wiki/Prellen

Wieso realisierst Du die Verzögerung über ein Delay und eine for Schleife?
Wieso nimmst Du nicht millis() oder die Zeit der RTC?

Grüße Uwe


« Last Edit: April 24, 2012, 01:33:44 am by uwefed » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Das "double Wert  = 1;" habe ich dafür genommen, weil ich die Temperatur mit zwei nach Kommazahlen ausgeben möchte.
Okey das mit dem Entrpellen hat mir mal ein Kumpel so erklärt darum hab ich das so gemacht und es hat auch den Effekt wie ich mir das eig. vorstelle^^.
Das beides werde ich nochmal überarbeiten.

Und das mit der Verzögerung. Es liegt daran das ich es so gemacht habe wie ich es jetzt gemacht habe, weil ich noch nicht so fit bin im Programmieren und ich das erst mit einem timer interrupt machen wollte, es aber nicht so geklappt hat.

Ich werde mich auch hierzu nochmal belesen! Was ist deiner Meinung nach besser über die RTC die Verzögerung zu programmieren oder über millis() oder vlt. timer interrupt?
Logged

Forum Moderator
BZ (I)
Online Online
Brattain Member
*****
Karma: 272
Posts: 21939
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Die Variable Wert benutzt Du um die Zeit der  Verzögerung zu definieren, nicht um den Temperaturwert zu speichern!!.

Quote
Ich werde mich auch hierzu nochmal belesen! Was ist deiner Meinung nach besser über die RTC die Verzögerung zu programmieren oder über millis() oder vlt. timer interrupt?
Kommt auf die Zeit an und auf die Genauigkeit.
Schau Dir mal das Beispiel "Blink without delay" in den Beispielen der IDE an.

Grüße Uwe
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh schuldige stimmt. Das war wegen dem " Wert += 1.0f; "  dachte das ich es so schreiben musste, wegen dem 1.0f.
( is auch schon wieder paar Tage her wo ich das programmiert hatte )

Wegen der Genauigkeit. Es kommt nicht auf die Sekunde drauf an ( da kann ich ruhig Toleranzen haben, nur die Temperatur solte möglichst genau gemessen werden ).

Gruß
Logged

Forum Moderator
BZ (I)
Online Online
Brattain Member
*****
Karma: 272
Posts: 21939
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Wegen der Genauigkeit. Es kommt nicht auf die Sekunde drauf an ( da kann ich ruhig Toleranzen haben, nur die Temperatur solte möglichst genau gemessen werden ).
Dann über millis() oder mit dem RTC.
Wenn die RTC eine Alarmfunktion hätte könnte man es auch über diese machen.
Grüße Uwe
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Okey dann setzt ich mich mal dran und versuch das mit millis() erstmal!

Danke bis dahin smiley)

Gruß
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Schönen guten Morgen,

ich habe das jetzt einmal mit Interrupts probiert. Es scheint soweit zu laufen ( die Grundfunktion ist gegeben ) aber es geht immer noch nicht mit den 60 min. Ich kann maximal mit einem Intervall von 55 min die Temperatur auslesen und speichern.

Der Code gefällt mir im allgemeinen auch noch nicht, es ist sehr unübersichtlich, weiß aber nicht wie ich es besser machen kann?.
Vlt. habt Ihr noch ein paar kleine Tipps wie ich das Programm verbessern kann und meine gewünschte Funktion erreichen kann.

Hier der Code
Code:
#include <avr/io.h>
#include <avr/interrupt.h>

#include <Wire.h>
#include <OneWire.h>
#include <LiquidCrystal.h>
#include <SD.h>
#include "RTClib.h"

LiquidCrystal lcd ( A2, A1, 6, 5, 2, 3 );
OneWire  ds ( 9 );
const int chipSelect = 4;
RTC_DS1307 RTC;

byte secound;
double Wert  = 1;
byte timer = 0;
const int hoch = 7;                                  // Taster für Hochzählen defenieren
const int runter = 8;                                // Taster für Runterzählen defenierern
int l = 0;

void setup () {
  lcd.begin(16,2);                                   // lcd initialisieren
  lcd.clear ();
  pinMode ( hoch, INPUT );                           // Port als input
  pinMode ( runter, INPUT );                         // Port als input
    digitalWrite ( hoch, HIGH );                     // Pull up
    digitalWrite ( runter, HIGH );                   // pull up
   
    Wire.begin();
    RTC.begin();
   
 lcd.print ( "Init SD card..." );
        delay ( 1000 );
                                                       // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
      lcd.clear();
      lcd.print("Card failed");
        delay ( 2000 );                               // don't do anything more:
    return;
  }
  lcd.clear();
  lcd.print("card init.");
    delay ( 2000 );
  lcd.clear();
 
  cli();
 
  TCCR1A = 0;
  TCCR1B = 0;

    OCR1A = 15624;
    // turn on CTC mode:
    TCCR1B |= (1 << WGM12);
    // Set CS10 and CS12 bits for 1024 prescaler:
    TCCR1B |= (1 << CS10);
    TCCR1B |= (1 << CS12);
    // enable timer compare interrupt:
    TIMSK1 |= (1 << OCIE1A);
 
  sei();
 
     lcd.setCursor ( 0,0 );
     lcd.print ( "Log:  " );
     lcd.print ( Wert );
     lcd.print ( " min." );
}

void loop () {
         
  if ( digitalRead ( hoch ) == LOW ) {
    l = 0;

    Wert += 1.0f;                                       // zählt in 1,0'ner schritten hoch
      lcd.clear();
      lcd.setCursor ( 0,0 );
      lcd.print ( "Log:  " );
      lcd.print ( Wert );
      lcd.print ( " min." );
      secound = 0;           
      // Entprellung
      while ( digitalRead ( hoch ) == LOW ) {}
    }
                                                        // Taster für Runterzählen abfragen
   if ( digitalRead ( runter ) == LOW ) {
    l = 0;
    Wert -= 1.0f;                                       // zählt in 1,0'ner schritten runter
      lcd.clear();
      lcd.setCursor ( 0,0 );
      lcd.print ( "Log:  " );
      lcd.print ( Wert );
      lcd.print ( " min." );
      secound = 0;
                                                        // Entprellung
    while ( digitalRead ( runter ) == LOW ) {}
    }
}

ISR ( TIMER1_COMPA_vect) {

  secound ++;
  if ( secound == 60 ) {
     secound = 0;
     timer ++;
  }
  if ( timer == Wert ) {
  timer = 0;
 
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;

  if ( !ds.search(addr)) {
    ds.reset_search();
      delay(250);
    return;
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      return;
  } 
                                                     // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      type_s = 1;
      break;
    case 0x28:
      type_s = 0;
      break;
    default:
      return;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         
 
    delay(750);     
   
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);                                    // Read Scratchpad

  for ( i = 0; i < 9; i++) {                         // we need 9 bytes
    data[i] = ds.read();

  }
    // convert the data to actual temperature
  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3;                                  // 9 bit resolution default
    if (data[7] == 0x10) {
                                                     // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;                 // 9 bit resolution, 93.75 ms
      else if (cfg == 0x20) raw = raw << 2;          // 10 bit res, 187.5 ms
      else if (cfg == 0x40) raw = raw << 1;          // 11 bit res, 375 ms
                                                     // default is 12 bit resolution, 750 ms conversion time
  }

  celsius = (float)raw / 16.0;
 
  if ( celsius >= 100 ) {
     lcd.setCursor ( 0,1 );
     lcd.print ( "Temp: ");
     lcd.print ( "-");
     lcd.print ( 4095 - celsius );                     // Wenn Temperatur ins Negative geht, dann diese Berechnung
     lcd.print(0xDF,BYTE);                             // 0xDF, BYTE geht nur für LCD
     lcd.print("C");
  } else {
    lcd.setCursor ( 0,1 );
    lcd.print("Temp.: ");
    lcd.print(celsius );                               // Temperatur im positiven ausgeben
    lcd.print(0xDF,BYTE);                              // 0xDF, BYTE geht nur für LCD
    lcd.print("C");
  }
 
  DateTime now = RTC.now();
  File dataFile = SD.open("datalog.txt", FILE_WRITE);  // Temperatur in .txt schreiben

  if (dataFile) {
    if ( celsius >= 100 ) {
     dataFile.print ( "-");
     dataFile.print ( 4095 - celsius );
   
     dataFile.print ( " ; " );
     
     dataFile.print(now.hour(),DEC);
     dataFile.print(":");
     dataFile.print(now.minute(),DEC);
       
     dataFile.print ( " ; " );
     
     dataFile.print(now.day(),DEC);
     dataFile.print(".");
     dataFile.print(now.month(),DEC);
     dataFile.print(".");
     dataFile.println(now.year(),DEC);
     dataFile.close();
  } else {
      dataFile.print(celsius);
     
      dataFile.print ( " ; " );
     
      dataFile.print(now.hour(),DEC);
      dataFile.print(":");
      dataFile.print(now.minute(),DEC);
         
      dataFile.print ( " ; " );
 
      dataFile.print(now.day(),DEC);
      dataFile.print(".");
      dataFile.print(now.month(),DEC);
      dataFile.print(".");
      dataFile.println(now.year(),DEC);
      dataFile.close();
  }}
  }
}


Liebe Grüße
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bis 56min. geht der Intervall*
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

wieso nimmst du für eine Variable, die im moment von 0-56 in ganzzahlenschritten benutzt wird einen double-type? int tuts hier locker.

weiterhin ist mir in deinem 2. Code aufgefallen, dass die loop schleife in maximalgeschindigkeit ein digitalRead ausführt und andererseits die Interrupt-Routine zum Datenauslesen arbeitet (welche dann deinen loop unterbricht). für eine methode solltest du dich entscheiden, aber nicht mischen. klemm doch die 2 Taster an INT0 und INT1 und bau dir dafür auch Interrupts. dann kannst du den loop komplett leer lassen und hast eine saubere Lösung

cu markus
Logged

Pages: [1]   Go Up
Jump to: