Pages: [1]   Go Down
Author Topic: Refresh time...Can anyone help me please??  (Read 1086 times)
0 Members and 1 Guest are viewing this topic.
Spain
Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, I´m newbie in this forum and relatively newbie in Arduino Platform.....But I made other projects with this platform successfuly. In may I finished my studies of "Graduate of Marine Engineering" and simultaneously of "Naval Technical Engineering: Specialized in propulsion and ship services". In this second studies, I need to make a final studies project and I decided to make a datalogger of temperatures and other conditions of the engine room, saving this parameters in an SD card and being viewed in an LCD. Now I have a part of the components like an SD card writer-reader or DS18B20 temperature sensor. I tried a lot of codes and I make a lot of modifications and I always have the same problem: The refresh time isn´t exact....Each minute it delays about one second. I bought a DS1307 RTC too for display time and date, but I dont know when it will arrive....It will help me to have precission delays? or should I do any modification in my actual code without DS1307?


In both codes I have a txt file (COMMANDS.txt) with the refresh_rate in the first line.



This is one code:

Quote
/*Desarrollado a partir de Datalogger de la libreria SD y del script de 18B20*/

#include <SD.h>
#include <OneWire.h>
#include <DallasTemperature.h>

long lastReadTime = 0;  

//Define puerto 18B20s
#define ONE_WIRE_BUS 11
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

//SPI SD Card Pins
//MOSI = Pin 11
//MISO = Pin 12
//SCLK = PIN 13
int CS_pin = 53;
int pow_pin = 8;

float refresh_rate = 0.0;  //Dataloger Refresh Rate

void setup(void)
{
  Serial.begin(9600);
  sensors.begin();//Inicializa sensores 18B20
  
  //--------------------------------------------------------------TARJETA---------------------------------------------------
  Serial.println("Inicializando tarjeta");
  
  pinMode(CS_pin, OUTPUT);//Pin CS es la salida

  pinMode(pow_pin, OUTPUT);  //De donde toma tension
  digitalWrite(pow_pin, HIGH);//La debe tomar alta
 
  if (!SD.begin(CS_pin)) //inicializa tarjeta SD
  {
    Serial.println("Fallo de tarjeta SD");
    return;
  }
  Serial.println("Tarjeta lista");



  //Lee informacion de configuracion
  File commandFile = SD.open("COMMANDS.txt");
  if (commandFile)
  {
    Serial.println("Leyendo configuracion");

    float decade = pow(10, (commandFile.available() - 1));
    while(commandFile.available())
    {
      float temp = (commandFile.read() - '0');
      refresh_rate = temp*decade+refresh_rate;
      decade = decade/10;
    }
    Serial.print("Tiempo refresco = ");
    Serial.print(refresh_rate);
    Serial.println("ms");
    commandFile.close();
  }
  else
  {
    Serial.println("No se puede leer configuracion");
    return;
  }

  //Write Log File Header
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(", , , ,"); //Dejar linea en blanco si no hay datos previos
    String header = "ID, Light, Temp, IR1, IR2";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else
  {
    Serial.println("No se puede abrir LOG");
  } 
  

}
  //--------------------------------------------------------------FIN TARJETA-------------------------------------------------



void loop()
  {
    sensors.requestTemperatures(); // Obtener temperaturas DS18B20
    
     
     
 long currentTime = millis();

  if (currentTime > lastReadTime + refresh_rate) {
    File logFile = SD.open("LOG.csv", FILE_WRITE);
          logFile.println(sensors.getTempCByIndex(0));
      logFile.close();
       Serial.println(sensors.getTempCByIndex(0));
    lastReadTime = millis();
        
      }
   
  }

















Thanks a lot for your time smiley

Logged

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

And this is another code I tried:


Quote
/*Desarrollado a partir de Datalogger de la libreria SD y del script de 18B20*/

#include <SD.h>
#include <OneWire.h>
#include <DallasTemperature.h>

//Define puerto 18B20s
#define ONE_WIRE_BUS 11
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

//SPI SD Card Pins
//MOSI = Pin 11
//MISO = Pin 12
//SCLK = PIN 13
int CS_pin = 53;
int pow_pin = 8;

float refresh_rate = 0.0;  //Dataloger Refresh Rate

void setup(void)
{
  sensors.begin();//Inicializa sensores 18B20
  Serial.begin(9600);
  
  //--------------------------------------------------------------TARJETA---------------------------------------------------
  Serial.println("Inicializando tarjeta");
  //CS Pin is an output
  pinMode(CS_pin, OUTPUT);

  //SD Card will Draw Power from Pin 8, so set it high
  pinMode(pow_pin, OUTPUT);  
  digitalWrite(pow_pin, HIGH);

  //inicializa tarjeta SD
  if (!SD.begin(CS_pin))
  {
    Serial.println("Fallo de tarjeta SD");
    return;
  }
  Serial.println("Tarjeta lista");



  //Lee informacion de configuracion
  File commandFile = SD.open("COMMANDS.txt");
  if (commandFile)
  {
    Serial.println("Leyendo configuracion");

    float decade = pow(10, (commandFile.available() - 1));
    while(commandFile.available())
    {
      float temp = (commandFile.read() - '0');
      refresh_rate = temp*decade+refresh_rate;
      decade = decade/10;
    }
    Serial.print("Tiempo refresco = ");
    Serial.print(refresh_rate);
    Serial.println("ms");
    commandFile.close();
  }
  else
  {
    Serial.println("No se puede leer configuracion");
    return;
  }
  //Write Log File Header
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(", , , ,"); //Just a leading blank line, incase there was previous data
    String header = "ID, Light, Temp, IR1, IR2";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else
  {
    Serial.println("No se puede abrir LOG");
  } 

}

  //--------------------------------------------------------------FIN TARJETA-------------------------------------------------
void loop()

  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus

  sensors.requestTemperatures(); // Send the command to get temperatures

  {

    //Open a file to write to
    //Only one file can be open at a time
    File logFile = SD.open("LOG.csv", FILE_WRITE);
    if (logFile)
    {
      logFile.println(sensors.getTempCByIndex(0));
      logFile.close();
      Serial.println(sensors.getTempCByIndex(0));
    }
    else
    {
      Serial.println("No se puede abrir LOG");
    }


  }

  delay(refresh_rate);
}




I accept all recomendations of my problem or something else. Thanks!
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 111
Posts: 5225
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

First of all: You didn't post the contents of the COMMANDS.txt.

What is the refresh rate? 1000?

The second code part will not work accurately because you need some time to write the data to the SD card too and that's not calculated into the refresh rate.

Change this

Code:
if (currentTime > lastReadTime + refresh_rate) {

to this

Code:
if (currentTime >= lastReadTime + refresh_rate) {

to not loose a millisecond in every refresh loop. Also set the new value of the lastReadTime first in the if-block and not after you wrote the entry (you need some time to write to the SD card).
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50043
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You have defined refresh_rate as a float. All time on the Arduino is int based. You should not be mixing types like that.
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 544
Posts: 27352
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Aren't time elements unsigned long?

http://arduino.cc/en/Reference/Millis

PaulS comment about mixing types still applies.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50043
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Aren't time elements unsigned long?
Yes, but longs are still integers. I guess I should have spelled out integer.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The slip occurs because it takes your sketch a finite time to detect that the interval has passed, and you are starting timing the next interval based on when you finished processing the current one. You need to change this so that the next interval ends a fixed tie after the current interval ends, as shown below. If you use this technique then it doesn't make any difference how long it takes your sketch to get round to checking whether the event is due or how long it takes to complete processing of the event.

Also note the use of subtraction instead of addition when comparing timer values. Conceptually this makes no difference, but in practice the code below is needed to correctly handle timer overflow situations. I don't know whether your sketch will ever run for long enough for that to be an issue, but you should get in the habit of coding correctly for that situation anyway.

Code:
void loop()
{
    sensors.requestTemperatures(); // Obtener temperaturas DS18B20

    if (millis()- lastReadTime > refresh_rate)
    {
        lastReadTime += refresh_rate;
        // do all the other stuff you want to happen at refresh_rate
    }
}
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50043
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Also note the use of subtraction instead of addition when comparing timer values.
Then, you potentially cause an overflow here:
Code:
lastReadTime += refresh_rate;

Shouldn't what is being recorded by when an action last occurred (millis()) not some future time when the action should happen again?

In any case, refresh_rate should not be a float.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Also note the use of subtraction instead of addition when comparing timer values.
Then, you potentially cause an overflow here:
Code:
lastReadTime += refresh_rate;

Yes, it overflows in exactly the same way that millis() overflows, resulting in the required behaviour.

Code:
lastReadTime += refresh_rate;
Shouldn't what is being recorded by when an action last occurred (millis()) not some future time when the action should happen again?

After that statement has executed, lastReadTime contains the time at which the event just processed was due. In other words, a value close to the current value of millis().

Logged

I only provide help via the forum - please do not contact me for private consultancy.

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

At first...thank you to everyone for your fast answers:

Pylon:
First of all: You didn't post the contents of the COMMANDS.txt.

What is the refresh rate? 1000?

In my txt file of commans.txt only you can see in the first line: 15000
With this I answered your questions.

I changed:
Quote
int refresh_rate = 0.0;  //Dataloger Refresh Rate


and:
Quote
  if (currentTime >= lastReadTime + refresh_rate) {
    lastReadTime = millis();
    File logFile = SD.open("LOG.csv", FILE_WRITE);
          logFile.println(sensors.getTempCByIndex(0));
      logFile.close();
       Serial.println(sensors.getTempCByIndex(0));
           
      }


As a result I got a delay about a half as before (before 1 second in a minute), with this 1 second in 2 minutes. It is important the precission for this project because it will take measurements for 10 days or more...


PeterH


You have the best solution for my problem now...I tried this code:
Quote
void loop()
{
    sensors.requestTemperatures(); // Obtener temperaturas DS18B20

    if (millis()- lastReadTime > refresh_rate)
    {
        lastReadTime += refresh_rate;
               File logFile = SD.open("LOG.csv", FILE_WRITE);
          logFile.println(sensors.getTempCByIndex(0));
      logFile.close();
       Serial.println(sensors.getTempCByIndex(0));
    }
}


And I got a delay of a second each 5 minutes. But as I said before I need more precission.

Thank you to everyone! smiley
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50043
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I changed:

int refresh_rate = 0.0;  //Dataloger Refresh Rate
0.0? Do you not understand what an integer value is?

Code:
  if (currentTime >= lastReadTime + refresh_rate) {
    lastReadTime = millis();
    File logFile = SD.open("LOG.csv", FILE_WRITE);
          logFile.println(sensors.getTempCByIndex(0));
So, lastReadTime is the last time you wrote to the file. I see. Do you have another variable, lastWriteTime, for the last time you read from the file?
Logged

Leeds, England, (dis)UK
Offline Offline
God Member
*****
Karma: 16
Posts: 702
Quick, chuck it in the bin before the boss finds out...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think that I have read on the forums that the crystal for the DS1307 needs to be kept around body temperature for optimal performance otherwise the time will drift (it's intended for use in wrist watches?). Now I suspect that an engine room might be a bit warmer than that?

The DS323x family might be a better bet as they are temperature compensated.
Logged

Beginners guide to using the Seeedstudio SIM900 GPRS/GSM Shield

Switzerland
Offline Offline
Faraday Member
**
Karma: 111
Posts: 5225
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You told us several times that you need more precision but never what your precision limit is.

You have two possibilities to get more precision:

1. Get an Arduino with a crystal as clock source and not a resonator (as the UNO has). This increases the precision by a factor of around 1000.

2. Take the advice from dannable and buy a DS3231. It's does not only have temperature compensated RTC but also two programmable interrupts. You can program your next log action and it will be timed very accurately (although you don't get millisecond resolution).
Logged

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

Thank you to everyone!

PaulS
Yes, I now whats an integer....This must be only 0 without comma. A lot of hours trying possible solutions, my brain isnt too accurate...

Good idea to put lastWriteTime, Ill try possible solutions

dannable:
I take your advice, and pylon´s too and I will buy a DS3231.
An engine room is between 25-55 degrees, and the idea is taking temperatures inside the engine room and in the inputs and outpus of air intractions and extractions....This is only the beggining of the project, I will do other measurements of other parameters.....I will post future doubts about that, Im sure that it will be any...

pylon:
I want the best precission I´ll can get.
I think that my arduinos have a crystal oscillator: I have a Mega 1280 and a Mega 2560.
As I said before, I´ll take your advices and I will buy a DS 3231.


But now my doubt is: Where do you buy your components??  I usually buy in dealextreme and eforchina and Im a few days seeking a website to buy components, ICs...where do you recommend me to buy it??

Thanks a lot for your replies
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 111
Posts: 5225
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I think that my arduinos have a crystal oscillator: I have a Mega 1280 and a Mega 2560.

At least the Mega2560 has a ceramic resonator too, the Mega1280 seems to have a crystal (on the pictures, I don't have one).
Logged

Pages: [1]   Go Up
Jump to: