Time Domain Calculations

I am somewhat experienced with industrial PLCs and am new to Arduino. In modern PLCs you have access to time elapsed since the last scan of the code. This is very useful for derivative and integral calculations. The only access to a "delta time" I have seen in searching is the millis command which gives you number of milliseconds that have passed. This seems useless if scan times are in the micro second range. Does anyone know a command or example to access the delta-time to a microsecond accuracy?

Thanks,
Adam

This seems useless if scan times are in the micro second range. Does anyone know a command or example to access the delta-time to a microsecond accuracy?

Of course - micros().

Ahh.... Seems obvious now. My guess is you would need to combine the micros, millis, and sec commands to capture the counter "roll-over"?

No. Just need simple subtraction.
All time calculations are done in unsigned long (32 bit) match.

After the rollover, the math works by dropping bits off above 32.

So time after rollover: 0x00000020
Time before rollover: 0xFFFFFF20
The elapsed time then is "current time - previous time",
or 0x00000020 - 0xFFFFFF20 = 0x00000100

Try it on windows calculator in HEX mode (programming mode in win7)
Result is FFFFFFFF00000100 - throw away all but lowest 32 bits, result is 00000100

Can think of it as (0x20 after the rollover) + (0xE0 before the rollover) = 0x0100

void loop(){
currentMicros = micros(); // capture the current "time"
elapsedMicros1 = currentMicros - previousMicros1; // my example above
  if (elapsedMicros1 >= durationMicros1){ // time passed for next event?
  previousMicros1 = previousMicros1 + durationMicros1; // set time for next periodic event
  // do your event occurred stuff
  } // end duration check
// perform time check for other event with different duration
elapsedMicros2 = currentMicros - previousMicros2; // my example above
  if (elapsedMicros2 >= durationMicros2){ // time passed for next event?
  previousMicros2 = previousMicros2 + durationMicros2; // set time for next periodic event
  // do your event occurred stuff
  } // end duration check
// do other non-time related stuff, reading button, serial data check, etc.
} // end loop

Accuracy is limited to >=4uS, that's how long the micros() interrupt takes to process that keeps track of "time".

Nice. That rollover math is super helpful.

Is the 4 micro sec time on a certain chip? Am I correct in thinking the interrupt takes x number of clock cycles and for a certain chip x clock cycles is 4 microseconds? (meaning this would be less for a faster chip)

The timing is all done on the microprocessor on your board: '328P, '2560, '1284P, whatever you have.

Aredweeno:
Nice. That rollover math is super helpful.

Is the 4 micro sec time on a certain chip? Am I correct in thinking the interrupt takes x number of clock cycles and for a certain chip x clock cycles is 4 microseconds? (meaning this would be less for a faster chip)

Most if not all of the AVR chips have 20 MHz capable versions. But at 16 (a power of 2) MHz, timing is easier.

You can achieve closer timing than 4 microseconds on a 16 MHz AVR by using a tight check-and-count loop. You can make very precise short delays just inlining NOP instructions at 1 cycle each.

The rollover math is simply unsigned math. The BlinkWithoutDelay example mixes (signed) long with unsigned long which is a non-critical error, it only cuts the longest time interval down to almost 25 days instead of almost 50. Morris Dovey here left a 64-bit time library that could probably time our sun past the red dwarf stage.

The example sketches are full of small goofs and some outright gaffes. They were written by PC programmers with ingrained PC coding habits usually involving wasting RAM. Why use a byte when an int will do, hey? Why use well-behaved C strings when in small code you can teach C++ String objects that will eventually posting HELP HELP on the forum? Why? Because that's how we've been taught to program computers with loads of RAM. Knowledge of hardware is for techs, right? And so the examples teach some bad to very bad habits.

You might like the contents of this blog very much:

It's got all the pieces to breadboard ATmega328P (2K SRAM, 28 pins) and ATmega1284P (16K SRAM, 44 pins).

There are core files available to program many other AVR chips using the Arduino IDE. The GCC that Arduino runs on top of though I'm pretty sure that we have cores for all the supported devices listed.
http://www.nongnu.org/avr-libc/user-manual/index.html

And for someone like you there is no substitute for the datasheets, right? Here's the ATmega line:
http://www.atmel.com/products/microcontrollers/avr/megaAVR.aspx

Thanks everyone,
I went out and bought my first board and started playing.

unsigned long This_u = 0 ;
unsigned long Last_u = 0 ;
unsigned long Delta_u = 0 ;
float DeltaT = 0.0 ;
void setup() 
{
  Serial.begin(9600);   
}

void loop() 
{
  for (int x = 0; x<100; x++) {
  This_u = micros();         //Get micros value
  Delta_u = This_u-Last_u;   //Do the math as an unsigned long to correctly calculate on the counter rollover
  DeltaT = Delta_u*0.000001; //convert to float and back to seconds
  Last_u = This_u;           //store micros value for next iteration
  if (x == 90) { 
  Serial.println(DeltaT,DEC);} //Display as decimal to get enough significant figures 
  }    
 
}

seems to work well. I have it sending the DeltaT every 100 times the loop cycles. I realize the loop that goes out to send the value is much longer than the others. But this has given me a good feel for how to calculate Delta Time. I will have a look at some PID examples since I am interested in how others are calculating derivative of signals.

That 32-bit float (double is also 32 bit) really costs you in cycles and that old pile-of-sand IEEE FP accuracy.

You'd be much better off on both counts using fixed-point integers.
For example if I want to measure single-digit meters to the millimeter, my working units might be micrometers and the decimal point only appear in human-readable text results. The extra 3 places I use give me a margin.

The way you have that, the whole for-next could be put in setup().
The loop() function returns to run loop(), it's the frame for real time code, finite state machines and all that.

  Serial.println(DeltaT,DEC);} //Display as decimal to get enough significant figures

That is NOT what that code does. The value is a float, so the second argument defines how many decimal places to print. Since a float has approximately 7 digits of accuracy, printing 10 digits after the decimal point will NOT improve the accuracy of the value. All it will do is print more crap.

Probably should mention that Arduino has no FPU.

  Serial.println(DeltaT,DEC);} //Display as decimal to get enough significant figures

That is NOT what that code does. The value is a float, so the second argument defines how many decimal places to print. Since a float has approximately 7 digits of accuracy, printing 10 digits after the decimal point will NOT improve the accuracy of the value. All it will do is print more crap.

If i don't put the DEC it was showing 0.00 instead of 0.000060000. The only reason I did a floating point calculation was to show me in seconds what the elapsed time was. Also, I don't remember typing anything about it be more "accurate" by displaying it as a DEC. I'm sure the code can be optimized, but I was happy to see something run in the first hour I every touched an arduino.

Aredweeno:
If i don't put the DEC it was showing 0.00 instead of 0.000060000.

Use microseconds instead of seconds as your unit and replace float with int or byte. That's 60 usecs above, isn't it?
See how fast your code runs then!

Yeah I did.. It was down to 4-8u. Except the serial write loop takes like 1 milli. Thanks again for the help.

I just looked up PLC's, never heard of them. I see they have a built-in OS?

AVR very different. No OS. Write your own bugs.

Do you know about PLD's? I can't find an intro level for hobbyists. I want to mess with ATF16's as glue chips.

Yeah, I guess they do have a minimal OS. Task scheduling and time calculations are done outside of the code you write. I never hear of PLDs. They look like some kind of IC you put code onto, right? What are they typically used for?

They're some form of array logic newer than PAL and lesser (and far cheaper) than FPGA.