Delaying an input dignal as dictated by an external clock

I am revisiting an old project from last year and needed some help again (previous topic: http://arduino.cc/forum/index.php/topic,66527.0.html)

Signals involved:
1 hz input signal (say connected to pin 2)
10 mhz input signal (external clock - say connected to pin 1)

The ultimate goal:
On every rising edge of the 10mhz signal (pin 1), I want to store the input value of pin 2. X amount of rising edges from pin 1 later (where X is a number I can choose - for now, let's say 10 cycles to give us a 1 microsecond delay), I want to output what was stored 10 rising edges previously to pins 5, 6, and 7.
The goal of this is to take the input 1hz signal, and to output the exact same signal on pins 5,6, and 7, but shortly delayed (by X/10 microseconds).

It has been a while since I have programmed for the arduino, and reading through the suggestions on page 2 of the previous topic is confusing me since I do not know how to use pointers - though it seems like that is the way to go?

Thanks for any help you can provide!

**note, in my last topic I said that the external clock was 1mhz -- it is actually 10mhz, as stated in this post.

10MHz interrupt, while you're running a 16MHz clock and an interrupt might be tricky. :expressionless:

What the other page said was for you to connect the external clock to an interrupt pin and inside the interrupt handler, save the status of the bit.
What was also mentioned was that you need to get the value of the input bit by using the input and output registers since digitalRead() is too slow for these speeds.

Is there any reason to do this? :expressionless: Couldn't you just measure the period of the 1Hz wave?

bubulindo:
10MHz interrupt, while you're running a 16MHz clock and an interrupt might be tricky. :expressionless:

What the other page said was for you to connect the external clock to an interrupt pin and inside the interrupt handler, save the status of the bit.
What was also mentioned was that you need to get the value of the input bit by using the input and output registers since digitalRead() is too slow for these speeds.

Is there any reason to do this? :expressionless: Couldn't you just measure the period of the 1Hz wave?

The 1Hz and 10Mhz are in phase, so I would like to use the 10Mhz as a clock rather than the 16Mhz arduino that is not in phase with the 1hz signal. Also, the 10Mhz crystal I have is much more accurate in terms of ppm than the Arduino.. I was thinking about the interrupt with 10 Mhz vs 16Mhz arduino clock.. unless the code in the interrupt can finish within 1.6 Arduino clock cycles, then this is totally pointless isn't it? In which case, I should use something other than an Arduino.

Edit: If i change it to interrupt every 16 10 MHz rising edges (can this be done?), this will still allow for microsecond precision, but will still only have 1.6*16 Arduino clock cycles to tun the interrupt, which may or may not be enough?

I agree, trying to process interrupts at 10 mHz with a 16 mHz processor is quite ambitious. My first thought is why do you not use the internal arduino timers? is the external clock source absolutely neccesary?

Anyways, I've written some code for you to get you started, I wanted to do some binary optimisation, since you are checking a digital input, you could record eight values in a single byte, but I discarded this, because of the fact that you want speed. so the cost is memory. The code uses 8 times more than what is theoretically needed.

I have not attached it to an external interrupt or an internal timer, but it is a simple excersise to do so. The speed I have it set to makes it quite nice to play with a switch or a loose wire, and see the lagging effect on an LED, currently about a second behind, but can be tweaked in the code.

the constant LAGBITS defines how many bits you want your signal to lag by (100 currently). The code also currently records a bit every 10 milliseconds, thus giving you a delay of 1 second, slower than what you want, but visually pretty cool! you can tune it down to microseconds as needed, but I'm not sure if you are going to get the speed you are after.

volatile int bitpos = 0;

#define LAGBITS 100 //how many bits should be buffered before it is played back
volatile byte array[LAGBITS]; //our byte array for recording. lots of memory to record bits, 
                              //but massive speed gain over trying to record bit positions.

void setup() {
 pinMode(5, OUTPUT); //Connected to an LED for testing
 pinMode(2, INPUT);  // connected to a loose wire that can be tapped against ground
 digitalWrite(2, HIGH); //ensures the loose wire don't pick up static.
}

void onTimer() {                     //This is the function you want to call on your external interrupt
  ++bitpos %= LAGBITS;               //This causes bitpos to count up to the array limit and then go back to 0
  array[bitpos] = PIND & 4;          //This reads pin 5 fast, and stores it in the array
  if (array[(bitpos + 1) % LAGBITS]) //this checks what is stored in the array at the following position, (which is actually the position recorded in LAGBIT intervals ago.)
     PORTD |= 1 << 5;                //This sets pin5 to HIGH, quickly
  else
     PORTD &= ~(1 << 5);             //This sets pin5 to LOW, quickly
}

void loop() {
  onTimer();                         //manually invoke our "interrupt" function. Can be attached to an actual interrupt  
  delay(10);                         //delay a bit before doing it again.
}

I agree, trying to process interrupts at 10 mHz with a 16 mHz processor is quite ambitious.

I would not agree I would say it was downright impossible, by a long way.

Grumpy_Mike:

I agree, trying to process interrupts at 10 mHz with a 16 mHz processor is quite ambitious.

I would not agree I would say it was downright impossible, by a long way.

:slight_smile: Yeah! but I didn't want to come across as grumpy, because that's your job!

Grumpy_Mike:

I agree, trying to process interrupts at 10 mHz with a 16 mHz processor is quite ambitious.

I would not agree I would say it was downright impossible, by a long way.

Now hold on there. Impossible is a rather strong word. If, by some significant miracle, the processor could be overclocked to 70 MHz, it would be possible to process interrupts occurring at 10 MHz. Unfortunately, the interrupt service routine would have to be empty and "process interrupts" would mean doing no useful work.

csnsc14320:
(where X is a number I can choose - for now, let's say 10 cycles to give us a 1 microsecond delay),

How? How do you choose this value? Send something through Serial? Upload a new sketch?

Does the value change while the sketch is running?

I want to output what was stored 10 rising edges previously to pins 5, 6, and 7.

Why 5, 6, and 7? Could it be 10, 11, 12?

What is the maximum delay?

Does it have to run on an Arduino? Would an ATmega328 on a breadboard suffice?

Thanks TRex, I will definitely give that a try tomorrow and see how it works!

[quote author=Coding Badly link=topic=111134.msg835186#msg835186 date=1340350858]
Does the value change while the sketch is running?[/quote]

No, I plan to re-upload the sketch based on the number I pick. Ideally, I'd like to input the number, but I do not have to time to implement that at the moment.

Why 5, 6, and 7? Could it be 10, 11, 12?

The actual pins don't matter, I just used 5,6,7 as an example. The important part is that three separate pins are used since one pin cannot put out enough current for 3 LEDs.

What is the maximum delay?

probably anywhere from 100us to 1s.

Does it have to run on an Arduino? Would an ATmega328 on a breadboard suffice?

I am using an arduino since that is what I have available to me right now. I am sure other things will work.

Another option I thought of (but have no idea how to do) to get around the 10 Mhz interrupt:

Is there a way that I can do this?

  1. Attach an interrupt to the rising edge of the 1hz signal
  2. Once detected, use the 10 MHz signal to begin incrementing a counter on each rising edge of the 10 Mhz
  3. Once the counter reaches a predetermined number (say 500), output HIGH to three pins.
  4. From here, either use another counter to determine whent o stop putting out high, or attach another interrupt to the falling edge of the 1Hz signal.

The only problem is, I do not know how to use counters on the arduino (I remember looking up the documentation on it a while back but came up with nothing useful). This seems like a simple idea in theory, a counter within an interrupt loop, but I do not know how to do this.

The benefit I see to this way is that I don't have to sample every single clock cycle of the 10 Mhz (only the 1 hz and using the 10Mhz to count up to a predetermined number) and that I can adjust how long the output signal stays on.

1 hz input signal (say connected to pin 2)
10 mhz input signal (external clock - say connected to pin 1)

I agree, trying to process interrupts at 10 mHz with a 16 mHz processor is quite ambitious.

People, we really need to exercise our shift keys.

I assume we're talking about a 16MHz processor, but I'm really unclear about the input signal.
10mHz (one cycle every 100 seconds) would be an absolute doddle.

csnsc14320:
2. Once detected, use the 10 MHz signal to begin incrementing a counter on each rising edge of the 10 Mhz

The folks at Atmel and Harry Nyquist both say "no".

I'll respond the to other stuff in a minute...

csnsc14320:

Does it have to run on an Arduino? Would an ATmega328 on a breadboard suffice?

I am using an arduino since that is what I have available to me right now. I am sure other things will work.

Not good enough. Either commit to making a valiant attempt or start searching for a dramatically different solution (much faster processor or hardware solution).

While it may seem like I was joking in Reply #6 I was not. The solutions currently on the table require a processor running much faster than 70 MHz. I have an idea that may work but it requires the processor to be clocked from your 10 MHz signal (which means no crystal and no resonator hence Arduino-ala-breadboard).

I don't understand the fascination of reading a 1 Hz signal with 10 MHz prescision. how can a once per second pulse require a 10 millionth of a second prescision? and to output to an LED? I hope it's IR at least, because a human won't notice it. but hey, it was fun writing the code, and it's actually fun playing with it tuned to a long delay, watching your exact taps to ground being played back to you a while later. Can keep the kids amused for hours... Could be a product!

AWOL:
People, we really need to exercise our shift keys.

I assume we're talking about a 16MHz processor, but I'm really unclear about the input signal.
10mHz (one cycle every 100 seconds) would be an absolute doddle.

Yeah, its 10 MHz, 16 Mhz, and 1Hz.. sorry for the sloppy notation - as a physics major I am ashamed! I swear I am not so lazy on paper. I will remember this in the future for online posts.

Yeah I don't think I will be able to do it with the Arduino after really considering the clock speeds I have available... I will most likely try to go for something with a fast enough processor to be able to use the 10 Mhz clock as an external clock.\

I assume the counter also works like an interrupt.. does it only increment the counter every Arduino clock cycle? If so, I see why this wouldn't work now (darn you nyquist!)

TRex:
I don't understand the fascination of reading a 1 Hz signal with 10 MHz prescision. how can a once per second pulse require a 10 millionth of a second prescision? and to output to an LED? I hope it's IR at least, because a human won't notice it. but hey, it was fun writing the code, and it's actually fun playing with it tuned to a long delay, watching your exact taps to ground being played back to you a while later. Can keep the kids amused for hours... Could be a product!

I definitely agree with actuallty being able to see the delay, it is a great learning tool that would be great for teaching about circuits! I actually kind of want to make this circuit so I can tap in a pattern and watch it come out ~5 seconds later :slight_smile:

The LEDs I am using are red, blue, and IR. I need such accuracy with the 1 Hz output since we are testing a device that can detect photons with microsecond precision. If we send photons from our LED at it and know exactly when we sent them, we can check for any inherent time delay within the other circuitry, since we know when we sent it and when we received it.

I think, you just forget about interrupt for a moment, they are no use at 10 MHz.

The goal of this is to take the input 1hz signal, and to output the exact same signal on pins 5,6, and 7, but shortly delayed (by X/10 microseconds).

If objective is simple triple delay line, with different settings for 3 outputs, than you can continuously read 1 input, and if (high) than you starting your timers. Timers are tree int8_t A = 7, B = 9, C = 5; with pre-set values. In a loop they simply decremented A--; B--; C--; and when it's reach "0" corresponding bit in port D would be set. All shoud be estimated at programming time, I mean if smallest value fires and CPU gonna set a port D, couple clock cycles should be subtracted from two others values pre-set values. Granularity 2/ 16, delay couldn't be spaced as 1/16.
CPU wouldn't be able to do anything alse, don't think a problem with small <1 $ separate IC. Also make it nice and use 20 MHz clock

If you really need this kind of accuracy, then careful consideration should be given to how you output those 3 pins. If they are set on 3 seperate instructions (i.e. if they are on different ports), they will not change at the same time. If all you are trying to do is drive 3 LED's, use one pin and a transistor or FET.

csnsc14320:
On every rising edge of the 10mhz signal (pin 1), I want to store the input value of pin 2. X amount of rising edges from pin 1 later (where X is a number I can choose - for now, let's say 10 cycles to give us a 1 microsecond delay), I want to output what was stored 10 rising edges previously to pins 5, 6, and 7.

I was confused when I first read this, and I still am. Where does 10 MHz (not mHz, heh) come into it at all?

Let's throw the 10 MHz signal out the window.

Now, we have a 1 Hz signal coming in. On a state transition, we want to mirror that on another pin after a few microseconds' delay. So, check the pin, if it changes, do a few NOPs and then toggle another pin. There will be a bit of jitter because the state change may happen at some indeterminate point in the checking loop.

If the delay is long enough to use interrupts (eg. 5 uS) you can eliminate the jitter by putting the processor to sleep, letting the state change wake it, and have an interrupt do the pin toggling.

If you want to do it after a few nanoseconds, better find different hardware.