Detect data value changes

I am uploading data received via the serial bus to Pachube (sd1 & sd2) and want the 'upload' statement timing to run as follows; Whenever data of a different value is detected = Run If no different data values are detected - an overall time limit of 10 minutes applies - Run My attempt at creating this was by using variables sd1a & sd2a to record the previous value and compare with present value;

    // check if new data has arrived...
    if (sd1 != sd1a || sd2 != sd2a || ((millis() - prevMillis1) > 600000)) { 
    
    // reset the indicators to current values
    sd1a = sd1; sd2a = sd2;
    prevMillis1=millis();
---The rest of the upload data code---

But it doesn't work! The statement does run every 10 minutes, but doesn't run on data change. Am I tackling this the wrong way?

The piece of code you quote looks correct so there may be something wrong elsewhere in the code.

The statement does run every 10 minutes

That's a bit surprising, since the 600000 literal will be interpreted by the compiler as an int. The value will not fit in an int, so overflow will occur. 600000UL would be interpreted as an unsigned long with better results.

PaulS:

The statement does run every 10 minutes

That's a bit surprising, since the 600000 literal will be interpreted by the compiler as an int. The value will not fit in an int, so overflow will occur. 600000UL would be interpreted as an unsigned long with better results.

I have double checked and it is running every 10 minutes. Could it be that the other part of the equation - prevMillis1 is declared as a unsigned long, and therefore the 600000 is treated the same? If I change the 600000 to 600000UL it doesn't work at all. Would I be better putting;

unsigned long timeDelay=600000;

in the declarations, and

    if (sd1 != sd1a || sd2 != sd2a || ((millis() - prevMillis1) > (timeDelay))) {

as the IF statement?

Literals are treated as integers in the absence of directives to the contrary, so:

unsigned long timeDelay=600000;

would still use an int register to hold the value (which is too small) before it was assigned to the variable timeDelay.

unsigned long timeDelay=600000UL;

uses an unsigned long register to hold the value before it is assigned to the unsigned long variable.

Using a variable in the if test IS better.

If I change the 600000 to 600000UL it doesn't work at all.

What does happen? "Nothing. The if block is never entered" is a perfectly valid answer.

Still, we need to see the rest of your code to see how the other variables in the if statement are valued.

Hi Paul The IF block was never entered. This is the full sketch http://pastebin.com/Z4AFxATC, (as it's too large for a forum post)

In Arduino_msg, a switch statement would be more effective.

You failed to mention, until now, that sd1, sd1a, sd2, and sd2a are doubles. Comparison of doubles using == or != is rarely a good idea. There may be difference in the 14th decimal place that you or I would ignore, but the compiler/computer is an idiot. It won't ever say "close enough".

Now, sd1 and sd2 get values from tvalue, which is an int. So, one has to wonder why sd1, sd2, sd1a, and sd2a are not also ints.

Try changing sd1, etc. to ints, if they really should be ints, or testing that the absolute value of the difference between sd1 and sd1a is less than some tolerance.

byte Ethernet::buffer[500];

That's a pretty large buffer when you only have 2048 bytes on a Duemilanove or UNO. Buffer sizes that are factors of 2 use memory more effectively, in general. 512 is such a factor. 500 is not.

PaulS: In Arduino_msg, a switch statement would be more effective.

You failed to mention, until now, that sd1, sd1a, sd2, and sd2a are doubles. Comparison of doubles using == or != is rarely a good idea. There may be difference in the 14th decimal place that you or I would ignore, but the compiler/computer is an idiot. It won't ever say "close enough".

Now, sd1 and sd2 get values from tvalue, which is an int. So, one has to wonder why sd1, sd2, sd1a, and sd2a are not also ints.

Try changing sd1, etc. to ints, if they really should be ints, or testing that the absolute value of the difference between sd1 and sd1a is less than some tolerance.

byte Ethernet::buffer[500];

That's a pretty large buffer when you only have 2048 bytes on a Duemilanove or UNO. Buffer sizes that are factors of 2 use memory more effectively, in general. 512 is such a factor. 500 is not.

Thanks Paul, I have changed sd1, sd1a, sd2, sd2a to int's, changed the buffer size. Changed the delay time to 600000UL and assigned it via a variable - (timedelay)

if (sd1 != sd1a || sd2 != sd2a || ((millis() - prevMillis1) > (timeDelay))) {

and it appears to be working OK What is a 'switch statement'??

Switch case default - http://arduino.cc/en/Reference/SwitchCase -

Please read the reference section carefully, time spend there is never lost, there is so much to learn for easier Arduino-ing ;) Same is true for the tutorial section. You will learn a lot about what an Arduino can do. You will get ideas and inspiration for projects too!