Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 23 of 23

Thread: Creating a manual clock pulse within an interrupt service routine

  1. #1

    Creating a manual clock pulse within an interrupt service routine

    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

    Click image for larger version. 

Name:	Capture.PNG 
Views:	23 
Size:	48.6 KB 
ID:	25391

    Thank you,
    ~RRkt

  2. #2
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,648
    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

  3. #3
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,904
    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");

  4. #4
    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().

    Click image for larger version. 

Name:	Capture2.PNG 
Views:	12 
Size:	16.5 KB 
ID:	25392

  5. #5
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,648
    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.

  6. #6
    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.

  7. #7
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,904
    This should be an input: pinMode(InterruptPin, OUTPUT);

    Not sure how that would affect the pin setup and response.

  8. #8
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,904
    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

  9. #9
    Sorry for the typo originally, it is INPUT in the code. And I tried your steps and now I get this erratic mess:

    Click image for larger version. 

Name:	Capture3.PNG 
Views:	17 
Size:	15.6 KB 
ID:	25395

    Click image for larger version. 

Name:	Capture4.PNG 
Views:	16 
Size:	17.7 KB 
ID:	25396
    Last edited by RandoRkt; 07-28-2021 at 10:14 PM. Reason: typo... again

  10. #10
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,904
    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 ...

  11. #11
    OK, so now its just dead, other than a sporadic spike on the falling edge

    Click image for larger version. 

Name:	Capture5.PNG 
Views:	16 
Size:	15.1 KB 
ID:	25397

    However, the serial monitor still outputs "Hello World" as fast as it can

  12. #12
    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.

  13. #13
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,607
    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:

    Click image for larger version. 

Name:	Screenshot 2021-07-29 195000.gif 
Views:	16 
Size:	52.7 KB 
ID:	25402

    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 :-)

  14. #14
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    1,061
    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.

  15. #15
    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:

    Click image for larger version. 

Name:	Capture6.PNG 
Views:	13 
Size:	51.3 KB 
ID:	25403

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

    Click image for larger version. 

Name:	Capture7.PNG 
Views:	14 
Size:	54.3 KB 
ID:	25404

    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.:

    Click image for larger version. 

Name:	Capture8.PNG 
Views:	12 
Size:	54.1 KB 
ID:	25405

    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 by RandoRkt; 07-29-2021 at 07:06 PM. Reason: Added screenshot... again

  16. #16
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,607
    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);
    }
    Click image for larger version. 

Name:	Screenshot 2021-07-29 212744.gif 
Views:	14 
Size:	56.3 KB 
ID:	25406

    And here without the 10Ás delay. As you see my LA (24MHz) is not able to catch all of those short pulses.
    Click image for larger version. 

Name:	Screenshot 2021-07-29 213216.jpg 
Views:	18 
Size:	31.4 KB 
ID:	25407

    I strongly suggest to check your hardware. Freq. generator + LA. Can you post a picture of your setup?
    Last edited by luni; 07-29-2021 at 07:44 PM.

  17. #17
    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:

    Click image for larger version. 

Name:	yep.PNG 
Views:	19 
Size:	51.8 KB 
ID:	25408

  18. #18
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,607
    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.

  19. #19
    Might pass the signal through a diode then, just to be safe.

  20. #20
    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:

    Click image for larger version. 

Name:	WHY.PNG 
Views:	11 
Size:	50.6 KB 
ID:	25409

  21. #21
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,904
    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?

  22. #22
    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.

    Click image for larger version. 

Name:	better.PNG 
Views:	13 
Size:	53.6 KB 
ID:	25417

  23. #23
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •