OK so I just changed my code to use micros() instead of some of Don's code that I'd butchered for 0012 and it solved another problem I was having of spurious values being randomly returned from the Arduino (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1222726966/30)!!!! I've had a 555 timer running at 35Hz for about 30 minutes now and haven't had one mad value from the Arduino. I'm not too sure what was wrong with my original code, but here it is just for interest sake more then anything -

/*/ Times TTL pulses (rising-rising edge, interrupt driven) on pin 2 and stores them to a buffer,/ then sends them over the serial port as microsecond figures in an interruptable loop.// Philip Harrison December 2008 (All hpticks code by Don Kinzer [http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1226257074/5])*/

#define mTimeBufferSize 64 // MUST only be 2^x value, such as 2, 4, 8, 16, 32, 64, 128#define timer0TicksToMicroseconds(t) ((t) * 64L / (F_CPU / 1000000L)) // Function to convert the timer ticks counted by the hpticks() function to microseconds. Only works with CPU frequencies of 2^x numbers, such as 8MHz or 16MHz

volatile unsigned long mTimesBuffer[mTimeBufferSize]; // Buffer to store values before they are sent over serialvolatile unsigned long mTimesBufferStorePtr=0; // Pointer into the buffer showing where we are currently storing values to. Note this pointer does not loop over, it counts up continuallyvolatile unsigned long mTimesBufferSendPtr=0; // Pointer into the buffer showing where we are currently sending values over serial from. Note this pointer does not loop over, it counts up continually

unsigned long lastSent = 0; // Used to hold the previous hpticks() value sent to the PC so the difference from current hpticks can be calculated

void loop(){ if(mTimesBufferSendPtr < mTimesBufferStorePtr) { // The send pointer is behind the store pointer so there must have been a value written that we can send

//Serial.print(mTimesBufferStorePtr - mTimesBufferSendPtr); // Send how far the send pointer is behind the store pointer, if this gets higher then mTimeBufferSize a buffer overflow has occured and the data will not be accurate //Serial.print(","); //Serial.print(mTimesBuffer[mTimesBufferSendPtr & (unsigned long)(mTimeBufferSize-1)]); // Send the next hpticks count in the buffer, buffer is incremented later. Note hpticks() is not time, it needs to be converted //Serial.print(","); Serial.println(timer0TicksToMicroseconds(mTimesBuffer[mTimesBufferSendPtr & (unsigned long)(mTimeBufferSize-1)] - lastSent)); // Subtract the previous hpticks from this hpticks, then convert this to microseconds to get the pulse time for this pulse

// Function called on every interruptvoid onChangeX() { mTimesBuffer[mTimesBufferStorePtr & (unsigned long)(mTimeBufferSize-1)] = hpticks(); // Put the current ticks count into the next space in the buffer mTimesBufferStorePtr++; // Increment the buffer store pointer to the next location}

/*/ Times TTL pulses (rising-rising edge, interrupt driven) on pin 2 and stores them to a buffer,/ then sends them over the serial port as microsecond figures in an interruptable loop.// Philip Harrison March 2010*/

volatile unsigned long mTimesBuffer[mTimeBufferSize]; // Buffer to store values before they are sent over serialvolatile unsigned long mTimesBufferStorePtr=0; // Pointer into the buffer showing where we are currently storing values to. Note this pointer does not loop over, it counts up continuallyvolatile unsigned long mTimesBufferSendPtr=0; // Pointer into the buffer showing where we are currently sending values over serial from. Note this pointer does not loop over, it counts up continually

unsigned long lastSent = 0; // Used to hold the previous micros() value sent to the PC so the difference from current micros can be calculated

void loop(){ if(mTimesBufferSendPtr < mTimesBufferStorePtr) { // The send pointer is behind the store pointer so there must have been a value written that we can send

//Serial.print(mTimesBufferStorePtr - mTimesBufferSendPtr); // Send how far the send pointer is behind the store pointer, if this gets higher then mTimeBufferSize a buffer overflow has occured and the data will not be accurate //Serial.print(","); //Serial.print(mTimesBuffer[mTimesBufferSendPtr & (unsigned long)(mTimeBufferSize-1)]); // Send the next micros value in the buffer, buffer is incremented later. //Serial.print(","); Serial.println(mTimesBuffer[mTimesBufferSendPtr & (unsigned long)(mTimeBufferSize-1)] - lastSent); // Subtract the previous micros from this micros to get the pulse time and send across serial port

// Function called on every interruptvoid onChangeX() { mTimesBuffer[mTimesBufferStorePtr & (unsigned long)(mTimeBufferSize-1)] = micros(); // Put the current micros() value into the next space in the buffer mTimesBufferStorePtr++; // Increment the buffer store pointer to the next location}

the interrupt handler just shapes the overflow-counter if necessary...

IIRC a function call on a 16MHz arduino takes about 1.125usec...u can c it in the delayMicroseconds()-code in the above mentioned URL...the delay due to the computations can be estimated by looking at the datasheet of the atmega-cpu...

can u measure the real time between the flanks with an oscilloscope?then u could compare it to the results of ur arduino...or u create a certain frequency with a tlc555, but i dont know how exactly one can compute the frequency from the resistors and the capacitors...

There's a formula for working out the expected frequency of a 555 based on the RC circuit, but tbh I don't think the stability of the wave is good enough from a 555 to use it for proof of timing like this. As you say an oscilloscope would be the way to go, but I don't have access to one sadly.

As I say I'm only measuring the differences in time, so once the conversion to microseconds happens every call and is going to take a fixed amount of time every call (presumably it will?) then it makes no difference to me.

Initially I was outputting the level of the buffer so I could watch for an overflow, but at the speed the pulses were coming in, compared to the speed of the Arduino and serial port there was no risk of overflow. Having said that in the final implementation I intend to set a flag if the buffer overflows and indicate with a red LED or signal on the serial line. I did check for overflow during the problem time and am confident it wasn't the cause.

Glad to hear there is a new implementation of Serial as I was a bit suspicious of the error checking before, every now and then I'd see the end of strings missing in transmission.

I'll take you're word on the last two parts, that's all a bit of a black art to me, I just copied and pasted Don's code .

FWIW when I first cranked up the 555 the other day and started timing I was getting maybe 2-3 crazy outputs per minute. After updating to 0018 and changing to using the micros() function I ran it over night (1000000 results from the Arduino to my Processing code) and didn't see one crazy output! So feeling very confident about the whole thing .

Now for another quick question. I read the other day that the ticks counter (which presumably the micros() function relies on) doesn't get incremented during interrupt function calls? This isn't a problem in the code above, but the next part of this project will be to time pulses from the bike engine itself (probably an inductive pickup on the sparkplug lead), at the same time as timing the drum so tyre/clutch slippage (common problem as tyres heat and start to melt, or with worn clutches) can be checked for. In threory I'm going to need two interrupt handlers and two timer buffers to achieve this. Am I going to run into timing issues here because of the ticks counter not being incremented during interrupts? Is a second Arduino running in parallel a better idea (kinda looking for an excuse to get a Mega anyway lol)?

Ah OK, so are you saying the processor tick count register IS still incremented during an interrupt handler, but overflows wouldn't be noticed/registered if the handler is too slow? All I'll be doing in the two interrupt handlers is popping the current micros() value into my buffer, which will take considerably less then 1ms I'm sure. So I'm good to go with two high speed pulse feeds coming to the one Arduino?

It would be great if threads like this could be linked to the FAQ/Reference part of the Arduino site as there is some great and pretty important info here to anybody actually using the micros() function for high speed timing. Just thought this as I was filling in the Arduino survey that came around by email last week.

This thread may not be the right place for this, but it's the closest thing I could find after much Googling.

Quote

David, to my thinking, date/time functions like hour(), day(), etc. don't belong in the wiring.c "kernel". Tracking "clock-based" time seems to be a different problem than tracking "elapsed" time. While nearly every Arduino project depends on the latter -- millis() and delay(), etc. -- the need for "clock" time seems more limited. In my opinion, this should be placed in a library -- like mem's DateTime!

Yes, exactly.

Here's my problem: I need to be able to get the current "clock time", e.g. "time since the epoch" or "time with date/hour/minute/second", but with millisecond accuracy. From what I've been able to find, the current libraries don't have that functionality. Or do they?

JavaScript returns epoch time with millisecond accuracy, natively (if you want regular Unix time, in seconds, you have to /= 1000). That's the functionality I'm looking for.

Is there any hope of that? Or is that beyond most people's basic needs?

(Right now I'm having to combine millis() with now(), which is clearly not optimal since they have nothing to do with one another.)

I'm using the NTP functionality of Time.h to keep the clock in sync, but even though NTP ostensibly has millisecond resolution, that doesn't really do me any good because I can't report the time in anything more accurate than seconds, so I might as well be off +/- 0.5 sec.

Right now what I'm doing is manually measuring the drift of each of the three Arduino boards I have, then hard-coding the ppm into the sketch to compensate the number of millis() it reports since startup. But even that's only going to keep me inaccurate by a constant amount throughout the device's uptime.

hm - if u already have internet access, u could try to implement mem's approach:1. remembering the time when u sent the NTP request2. polling for the NTP response + remembering the time of arrival3. repeating that each hour and compute an average clock error

NTP should deliver even the micro seconds somewhere...i think the 4 bytes after the seconds (xmit_time) r the micro seconds.... :-)