Creating a manual clock pulse within an interrupt service routine

Status
Not open for further replies.

RandoRkt

Member
Hello all,

I am attempting to create a manual clock pulse inside of a interrupt service routine by doing:

Code:
attachInterrupt(digitalPinToInterrupt(InterruptPin), ISR, RISING);

void ISR(){
   digitalWrite(PINx, HIGH);
   digitalWrite(PINx, LOW);
}

This pulse will tell a peripheral when to activate, additionally, I need the pin to stay high for exactly 30ns, which is 18 CPU cycles at the 600MHz clock of the T4.x

Running this interrupt with an external clock of any frequency, the code enters the subroutine, writes PINx to high as expected, then when it writes it low, it does, but it acts as though the ISR is repeating as many times as it possibly can execute. Picture shows the digital logic, the green line is the trigger to enter the interrupt, and the yellow line is the logic of PINx. I want PINx to go high for 30ns, then go low again, just once inside of the ISR

Capture.PNG

Thank you,
~RRkt
 
maybe provide a runnable sketch that demonstrates the problem. this works for me ...
Code:
void ding() {
  digitalWrite(23,1);
  digitalWrite(23,0);
}
void setup() {
    pinMode(23,OUTPUT);
    analogWriteFrequency(3,100000);
    analogWrite(3,128);
    attachInterrupt(12,ding,RISING);
}

void loop() {
  
}
jumper pin 3 to pin 12, and put scope on pin 23. i see a 31 ns pulse every 10 us

digitalWriteFast() with constant pin value will have faster pulse
 
Posting a complete sketch that will repro to would show more - what pins and other code ... and allow others to confirm/test/modify.

It isn't uncommon for an _isr() to double in cases - but a couple dozen isn't normal without something else going on.
> putting this in the _isr() makes sure the interrupt flag is registered: asm("dsb");
 
Code:
const byte InterruptPin = 2;
const byte CNV = 20;

void setup(){
   pinMode(InterruptPin, OUTPUT);
   pinMode(CNV, OUTPUT);
   attachInterrupt(digitalPinToInterrupt(InterruptPin), ISR, RISING);
}

void loop(){
}

void ISR(){
   digitalWrite(CNV, HIGH);
   Serial.println("Hello World");
   digitalWrite(CNV, LOW);
}

When I run this with a 1Hz InterruptPin, the serial monitor will print out "Hello World" as fast as it can crashing the monitor under 2 seconds after filling up the memory. So I'm not sure why it does that instead of just running the inner interrupt once.

Here is with "asm("dsb")" added into ISR().

Capture2.PNG
 
can you attach a photo of your setup? what is source of interrupt? Signal should be 3.3v, Teensy 4 is NOT 5 v tolerant. Also external signal requires a common ground with the T4.
 
I am feeding in a 1Hz square wave pulse with a p-p amplitude of 3v and a 50% duty cycle. I have the ground pin tied to the common ground, so I know it's not those causing the issue.
 
This should be an input: pinMode(InterruptPin, OUTPUT);

Not sure how that would affect the pin setup and response.
 
Seems the "dsb" help reduce the follow on repeat calls?

Try replacing the external input pin with code by @manitou
Code:
    analogWriteFrequency(3,100000);
    analogWrite(3,128);
    attachInterrupt(InterruptPin ,ding,RISING);

Then wire InterruptPin==2 to pin 3 instead of external
 
Sorry for the typo originally, it is INPUT in the code. And I tried your steps and now I get this erratic mess:

Capture3.PNG

Capture4.PNG
 
Last edited:
For an external trigger the interrupt pin should be INPUT

Well that got rid of the multiple hits per rising pin for sure :(

To slow things down try : analogWriteFrequency(3,1000);

Check the wiring/soldering something doesn't seem right ...
 
OK, so now its just dead, other than a sporadic spike on the falling edge

Capture5.PNG

However, the serial monitor still outputs "Hello World" as fast as it can
 
I am thinking about writing the InterruptPin HIGH then LOW directly instead of using the "digitalWrite()" command. Can you help me to understand how to do port manipulation on the Teensy4.0? I am very lost trying to understand the instructions to use. I have a second thread going where I am asking for help in trying to read a port of 8 pins, and I am not getting any help on that front, or if I am, perhaps it's just going over my head. I liked how simple the AVR based T3.x was to program to do port manipulations with the PORTx, DDRx, and PINx commands. But you can't beat that 600MHz clock in the T4.x, so that's why I made the switch.
 
Are you sure that your logic analyzer is fast enough to see the short pulses?

I'd first try the code from @manitou given in #2 but with lower frequency and place a delayMicroseconds(10) between the digitalWrites for testing. I.e. try exaclty this code, connect pin 0 with pin1, place your probes at pin 1 and pin 2 and see what happens.
Code:
void ding()
{
    digitalWrite(2, HIGH);   // output a 10µs pulse on pin 2
    delayMicroseconds(10);
    digitalWrite(2, LOW);
}
void setup()
{
    pinMode(2, OUTPUT);

    analogWriteFrequency(0, 10'000);  // generate 10kHz on pin 0
    analogWrite(0, 128);              // 50% duty cycle

    attachInterrupt(1, ding, RISING); // don't forget to wire pin 0 to pin1
}

void loop(){
}

This code generates the following signal here:

Screenshot 2021-07-29 195000.gif

I liked how simple the AVR based T3.x was to program to do port manipulations with the PORTx, DDRx, and PINx commands.
You probably meant T2.x? But sure, switching from a bicycle to a Porsche requires some learning but at the end its worth it :)
 
As luni says, don't expect to see 30 ns and shorter pulses when you sample at 500 sps. A decent oscilloscope will work at 30 ns.
 
I only have it set that speed since I am only testing with <5Hz right now. It can probe up to 100Msps which should be sufficient to see a spike as small as 10ns.

Also, I tried your code from #13 and get this:

Capture6.PNG

And here is when I remove the connection from pin 0 to 1 and instead feed a 10kHz signal into pin 1:

Capture7.PNG

I kept the 10us delay in there too, and still it act erratic. If I remove the delay, the interrupt runs as many pulses as it can, instead of just once, eg.:

Capture8.PNG

Can I see what your output looks like when you run this code and feed an external signal of 5Hz at 3v into pin 1?

Code:
void ding()
{
    digitalWrite(2, HIGH);   // output a 10µs pulse on pin 2
    //delayMicroseconds(10);
    digitalWrite(2, LOW);
}
void setup()
{
    pinMode(2, OUTPUT);
    pinMode(1, INPUT);
    //analogWriteFrequency(0, 10'000);  // generate 10kHz on pin 0
    //analogWrite(0, 128);              // 50% duty cycle

    attachInterrupt(1, ding, RISING); // don't forget to wire pin 0 to pin1
}

void loop(){
}
 
Last edited:
Also, I tried your code from #13 and get this:
This is very strange, you should get the pulse at the rising edge. Can it be that your LA inverts the signal on pin1?
EDIT: which would still not explain the shown signal...

And here is when I remove the connection from pin 0 to 1 and instead feed a 10kHz signal into pin 1:
Can it be that your external signal is not clean or the voltage is too low. You should have some 3V-3.3V as input signal, do you have a scope to measure the real input signal?

Can I see what your output looks like when you run this code and feed an external signal of 5Hz at 3v into pin 1?
I don't have an external generator available here the output of the following code

Code:
void ding()
{
    digitalWrite(2, HIGH);   // output a 10µs pulse on pin 2
    delayMicroseconds(10);
    digitalWrite(2, LOW);
}
void setup()
{
    pinMode(0, OUTPUT);
    pinMode(2, OUTPUT);
    attachInterrupt(1, ding, RISING); // don't forget to wire pin 0 to pin1
}

void loop(){
    digitalToggleFast(0);
    delay(100);
}

Screenshot 2021-07-29 212744.gif

And here without the 10µs delay. As you see my LA (24MHz) is not able to catch all of those short pulses.
Screenshot 2021-07-29 213216.jpg

I strongly suggest to check your hardware. Freq. generator + LA. Can you post a picture of your setup?
 
Last edited:
Thank you so much! I was feeding in 3.3v_p-p. Didn't realize it needed 3.3v_rms, so now feeding in 6v_p-p gives me this:

yep.PNG
 
Much better :) But, I'd be carful with 6V pp. I don't know if the Teensy can sustain -3V on a pin. Would look at the datasheet first before using this for longer time.
 
New issue, I tried to pass it through a diode, but the Teensy started spewing out random waveforms from both my probes, so I removed it and put the signal directly back in and reset it, but now I am getting this:

WHY.PNG
 
This external ref device isn't providing appropriate signal it seems.

If the Teensy hasn't been damaged then the Post #2 Self Reference code from PWM would be a safe input - or run that from a second Teensy.

Neg voltages are bad to present based on forum notes by PJRC IIRC.
The diode will drop the passed positive voltage and when NEG it is dumping to GND that may be changing or putting noise on the ref voltage level giving the Random Waveforms?
 
I am using the ADALM2000 to produce and analyze my frequencies. I switched over to the "Pattern Generator" mode to produce my clock signal instead of the "Signal Generator" so now I'm not inputting any negative voltages thankfully. I don't know why I didn't think about that issue beforehand. But here is the output now, the interrupt seems to be activating right before the falling edge of the clock.

better.PNG
 
Fixed #22 issue, just had to reboot my equipment. It works as expected now, thankfully. :) Now to just figure out that pesky port manipulation to read in 8 bits at once and store them somehow. Thanks everyone for your help on this issue. I hope to not have to post on this thread further. But who knows.
 
Status
Not open for further replies.
Back
Top