Go Down

Topic: Millis() timer (Read 1 time) previous topic - next topic

iegj

In my program i've used Millis() instead of delay for my program to run every 2 minutes. I've done it exactly like the example "BlinkWithoutDelay". But now the arduino stops after a couple of hours.

What am i doing wrong?

Thanks in advance,

Iegj

Nick Gammon

http://www.gammon.com.au/electronics

Graynomad

Quote
I've done it exactly like the example "BlinkWithoutDelay"

Obviously not or it would work.

Code?



Nope, not seeing it.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

iegj

sorry!, here is my code:

Code: [Select]

/*

Project Arduino, FINAL V1.0 3 Sensors,Time&Date,FTP,SD,Errorlog

-  Leest temperatuur en vochtigheid uit met behulp van SHT11 temperatuur/vochtigheid sensoren van Sensirion
-  Slaat de logdata op SD op en verzend deze naar een FTP server
-  Tijd word opgehaald van NTP server en gebruikt in de errorlog en logfile
-  Filenaam om de Arduino te indentificeren instellen door het TXT bestand filename aan te passen op de SD kaart
-  Errorlog word op de SD opgelsagen onder de naam ERRORLOG.TXT

By: Jan Verhoeckx
*/


// INCLUDED LIBRARIES
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\

//Libraries:
#include <SPI.h>        
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SD.h>
#include <Time.h>
#include <FTPsend.h>
#include <SHT1x.h>
#include <Streaming.h>



// GLOBALE VARIABELEN
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\

//Pin 4 reserveren voor SD:
const int chipSelect = 4;

//Globale variabelen:
int localtimeA = 0;
int localtimeB = 0;
int localtimeC = 0;
char time[20] = {0};
char fileName[50] = {0};
float temp_c;
float humidity;
float temp_c2;
float humidity2;
float temp_c3;
float humidity3;
long previousMillis = 0;
long interval = 1000;    

// ETHERNET INSTELLINGEN
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\

// MAC adres van de Arduino
byte mac[] = {  
 0x90, 0xA2, 0xDA, 0x0D, 0x2A, 0x59 };


// PINNEN VOOR SENSOREN DEFINEREN
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\

// SHT11 sensor define datapin en clockpin
#define dataPin3 8
#define dataPin2 9
#define dataPin  10
#define clockPin 11
SHT1x sht1x(dataPin, clockPin);
SHT1x sht2x(dataPin2, clockPin);
SHT1x sht3x(dataPin3, clockPin);


// BEGIN SETUP && ETHERNET VERBINDING STARTEN && VERSIE PRINTEN VIA SD
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\

void setup()
{
// Serial output:
Serial.begin(38400);
Serial.println("STX11 sensors with time, SD, Ethernet, FTP, Errorlog  --->>  By: Jan Verhoeckx  FINAL V1.0 <<---");

 
// start Ethernet en UDP connectie
 if (Ethernet.begin(mac) == 0) {
 Serial.println("Failed to configure Ethernet using DHCP");
 // Als er geen verbinding kan worden gemaamkt, niet verder gaan:
 for(;;);
 }
 
 
Serial.println("My IP address: ");
 for (byte thisByte = 0; thisByte < 4; thisByte++) {
 // print het ip over serial:
 Serial.print(Ethernet.localIP()[thisByte], DEC);
 Serial.print(".");
 }  
 
 
//UDP begin:
Udp.begin(localPort);


// SD INITIALISEREN  
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\

//SD begin:  
digitalWrite(10, HIGH);  
// Kijken of er een SD kaart aanwezig is, aangeven via serial of de SD gereed is:
 if (!SD.begin(chipSelect)) {
  Serial.println("Card failed, or not present");
  return;
 }
Serial.println("card initialized.");

}

// BEGIN LOOP && TIMER INSTELLEN OM DE MINUUT METEN
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\

void loop()
{
//Om de minuut meten en de data naar de FTP server verzenden:      
 unsigned long currentMillis = millis();

 if(currentMillis - previousMillis > interval) {
   // save the last time you blinked the LED
   previousMillis = currentMillis;  

// TIJD BEREKENEN VAN NTP SERVER  
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\
 
 //Tijd van NTP server verkrijgen:
 
 sendNTPpacket(timeServer); // send an NTP packet to a time server

 // wait to see if a reply is available
  if ( Udp.parsePacket() ) {  
   // We've received a packet, read the data from it
   Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer

   //the timestamp starts at byte 40 of the received packet and is four bytes,
   // or two words, long. First, esxtract the two words:

   unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
   unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
   // combine the four bytes (two words) into a long integer
   // this is NTP time (seconds since Jan 1 1900):
   unsigned long secsSince1900 = highWord << 16 | lowWord;                
   
   // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
   const unsigned long seventyYears = 2208988800UL;    
   // subtract seventy years:
   unsigned long epoch = secsSince1900 - seventyYears;    
 
   // Set time voor time librarie
   setTime(secsSince1900 - seventyYears);

   //Bereken local time en schrijf weg naar localtimeA, B en C
   localtimeA = ((epoch % 86400L) /3600 +1);    //86400L   //9300L
   localtimeB = ((epoch  % 3600) / 60);
   localtimeC = (epoch % 60);
 }


// SENSOREN UITLEZEN
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\  
 
 // Data van de sensor uitlezen
 temp_c = sht1x.readTemperatureC();
 humidity = sht1x.readHumidity();
 //sensor2
 temp_c2 = sht2x.readTemperatureC();
 humidity2 = sht2x.readHumidity();
 //sensor3
 temp_c3 = sht3x.readTemperatureC();
 humidity3 = sht3x.readHumidity();


// LOGDATA NAAR SD SCHRIJVEN
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\

//Naam van het bestand van de SD kaart aflezen, zo word de Arduino in Hobbit geïndentificeerd.
 File FileNameonSD = SD.open("filename.txt");
 byte index = 0;
   while (FileNameonSD.available())
   {
      fileName[index++] = FileNameonSD.read();
      fileName[index] = '\0';
   }
   
 Serial.println(fileName);
 
 
 //tijd, en meetwaardes naar SD schrijven

 //verwijder oud logfile
 SD.remove(fileName);

 Serial.print("naar SD schrijven...");
 File dataFile = SD.open(fileName, FILE_WRITE);
 if (dataFile) {  
   if (localtimeB < 10 ) {
       dataFile << "" << "Localtime: " << localtimeA << ":" << "0" << localtimeB << "\n" << endl;}
     else{
       dataFile << "" << "Localtime: " << localtimeA << ":" << localtimeB << "\n" << endl;}  
    dataFile << "" << "Sensor1 Humidity: " << humidity << " %\t " << "Temperature: " << temp_c << " *C\n" << endl;
    dataFile << "" << "Sensor2 Humidity: " << humidity2 << " %\t " << "Temperature: " << temp_c2 << " *C\n" << endl;
    dataFile << "" << "Sensor3 Humidity: " << humidity3 << " %\t " << "Temperature: " << temp_c3 << " *C\n" << endl;      
    dataFile.close();
 }  
 // Als de SD niet bereikbaar is, geef een error via serial en in de errorlog:
 else {
   Serial.println("error opening SD");
 }
 

// LOGDATA VIA FTP VERZENDEN
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\\

//Gegevens over FTP naar FTP server verzenden
 //FTP
 if(sentFile(fileName)){
   Serial.println("FTP OK");
 }
 else{
   Serial.println("FTP FAIL");
   File errorfile = SD.open("errorlog.txt", FILE_WRITE);
   if (errorfile) {
     errorfile << "local time: " << year() << "/" << month() << "/" << day() << "" << endl;
     if (localtimeB < 10 ) {
       dataFile << "" << "Localtime: " << localtimeA << ":" << "0" << localtimeB << "Failed sending data over FTP\n" << endl;}  
     else{
       dataFile << "" << "Localtime: " << localtimeA << ":" << localtimeB << "Failed sending data over FTP\n" << endl;}  
     errorfile.close();
     }
 }
}
}

 

guix

#4
Nov 26, 2012, 10:26 am Last Edit: Nov 26, 2012, 10:33 am by guix Reason: 1
Try change long previousMillis to unsigned long previousMillis, also 2 minutes are 120000 milliseconds :)

tuxduino

also unsigned long interval

tuxduino

Code: [Select]

char fileName[50] = {0};

//...

File FileNameonSD = SD.open("filename.txt");
byte index = 0;
while (FileNameonSD.available())
{
    fileName[index++] = FileNameonSD.read();
    fileName[index] = '\0';
}
Serial.println(fileName);


You don't have any guard against buffer overrun. What if you read more than 49 bytes ?

iegj

Thanks for the replies.

I changed the long's to unsigned long's, we will see if that work, becouse before it stopped in about 4 hours.

But why does it stop? Millis() should not stop counting wright? The Arduino goes to run unattended for a long time so i have to be sure it won't stop. Maybe i should use delay(), if it is more reliable.

Thanks,

Iegj

tuxduino

You suppose millis() could "stop counting" (it _doesn't_ count, btw) yet you have ignored my remark about avoiding a buffer overrun. Go figure. :)

I'd print index right before Serial.println(fileName).

And btw if you doubt abount millis(), how can you think delay() would be "more reliable" ?

billroy

Interesting case.  Can you please say precisely what you mean by "stop"?  Because the arduino doesn't do stop (though your code can hang or crash).  

Are you saying that expected printed output stopped coming?  That socket connections stopped being accepted?  That outbound NTP polling stopped?  An LED stopped flashing?

What is the last thing it says before stopping?  Is it the same every time?  Does it restart?

Are you on a Mega?  Looking at your program, I'm guessing you must be to fit all those big libraries.  And there are a lot of Serial.print strings consuming ram too.  Have you checked the free ram?  One common cause of unaccountable seize-ups is running out of ram.  (An easy fix is the F() macro, which you can search for doc about here.)

Also, is it possible that you could have two or three of the larger libraries doing active work at the same time, but only occasionally?  That kind of behavior can overflow the stack even if it looks like you have plenty of free ram at ide.

-br
http://bitlash.net

iegj

it won't because i know how long the filename is, it is defined by myself on the SD card.

Because first I used delay instead of Millis() and with delay the program ran for 2 weeks without a problem.

The program still runs. I can still ping the Arduino and it replies. I think the Millis() function stops working and stop to run the rest of my code. (based on the fact that if I use delay the code works fine.)





tuxduino

Code: [Select]
[quote author=iegj link=topic=134250.msg1010192#msg1010192 date=1353935075]
it won't because i know how long the filename is, it is defined by myself on the SD card.


Until in a month you forget you wrote 50 at line 125. ;)
It's a very bad coding practice to take an unspecified number of bytes and stuffing them into a fixed size array without checking if the array size is being exceeded.

Anyway apparently that's not the cause of your problem, and not the point of this thread.


Because first I used delay instead of Millis() and with delay the program ran for 2 weeks without a problem.

The program still runs. I can still ping the Arduino and it replies. I think the Millis() function stops working and stop to run the rest of my code. (based on the fact that if I use delay the code works fine.)


If that was my code, I'd think I'm probably misusing millis(), rather than conclude it "stops", whatever that means (millis() _doesn't count_).

Still, it's not clear to me what is the exact misbehaviour that you see when you use millis() (i.e. blink without delay technique) instead of delay().

billroy

One little problem with your theory: delay() uses millis(). 

So the program doesn't stop, you can still ping it.  What part stops, then?  What makes you think it is stopping?

-br

iegj

Let me try explain:

My program should send data to my ftp server every 2 minutes, but after about 4 hours it stops sending data. I can still ping the Arduino, so it doesn't hang, but i think the code that should run if currentMillis - previousMillis > interval doesn't run.

I think this is caused by the millis() function because since I replaced the delay function for Millis() this problem occurs.

billroy

It is doubtful, as tux and I have said several times now, that millis() stops.  It could happen, but it is unlikely given the combination of libraries you are using.

When debugging, if you hear hoofbeats, think horse, not zebra.  It is much more likely that you have a ram corruption issue.  A stack overflow or a wild pointer could easily corrupt the value of previousMillis, causing the clause not to fire even though millis() keeps running.  This is the sort of horse I smell here.

Check the free ram; search the forum here and you'll find a magic function to report how much you have free.  Move the strings in Serial.print into F() to save a bunch of ram.  Log previousMillis and currentMillis per tux's suggestion.

Anyway, that's what I'd do.

-br

Go Up