Can't detect short pulses with GPIO

Thanks for taking the time to help with this. Much appreciated.

I tried that code, I had to put a small delay in the main loop to trigger the pulses, hope that didn’t affect anything:

//trigger pulses, takes a few ms, blocking call
if (ms && (micros() - ms > 10000))
   {
     digitalWriteFast(D0, HIGH);
     ms = 0;
   }

That worked better than before, but not as well as I need:

As you can see, it again tripped the interrupt in the middle of the pulse, not the first rising edge. Here’s a zoomed image:

And now this is just getting crazy. I put this code on it in the main loop:

delay(100);
//trigger pulse
digitalWrite(D0,HIGH); // just for timing testing
delayMicroseconds(1);
for(int i=0;i<400000;i++){
    digitalWriteFast(D0, pinReadFast(D3));
}
digitalWrite(D0,HIGH);
delayMicroseconds(1); // just for timing testing

Literally just setting one pin to the other pin’s state. I timed this, and the full 400,000 samples run in 57 ms, so 0.11 us per sample; 105 samples per pulse. Should be impossible to miss the pulse. Yet it misses the >5000 pulses in the train almost all the time:

It should be copying the yellow trace exactly on the blue trace.

Weird.

I’m also very confused with your results.

I’ve just tested the timing of my code above and get a latency of avg. 360ns between triggering the interrupt and D0 responding.

So I’ve no idea what’s happening on your end.

Now I try to whip up a “copy-input-to-output” ISR and have a look at my scope.


With this code

SYSTEM_MODE(MANUAL)

volatile uint32_t ms;

void setup()
{
  pinMode(D0, OUTPUT);
  digitalWriteFast(D0, HIGH);

  pinMode(D3, INPUT_PULLDOWN);
  attachInterrupt(D3, interruptHandler, CHANGE);
}

void loop() { }

void interruptHandler() 
{
  digitalWriteFast(D0, pinReadFast(D3));
}

I get a signal-response delay of 800ns and can pick up and mirror a 200kHz 20% to 80% duty cycle square wave. When I change the duty cycle below 20% or above 80% the interrupt seems to stop being triggered.


Just a very heretic thought :sunglasses: Could you double check if you’ve got the correct pins wired - I just tried another Photon and got odd readings, till I relized I was checking triggering D2 and had D3 floating (INPUT instead of INPUT_PULLDOWN) :stuck_out_tongue_winking_eye:

    SYSTEM_MODE(MANUAL)

void setup()
{
    pinMode(DAC1, OUTPUT); 
    analogWrite(DAC1, 400); // just setting something up for the pulses
  pinMode(D0, OUTPUT);
  digitalWriteFast(D0, HIGH);
  pinMode(D1, OUTPUT);
  pinMode(D3, INPUT);
  attachInterrupt(D3, interruptHandler, CHANGE);
}

void loop()
{
    delay(100); // triggering some pulses
    for(int i=0;i<100;i++){
      digitalWriteFast(D1, HIGH);
      delayMicroseconds(12);
      digitalWriteFast(D1, LOW);
      delayMicroseconds(12);
  }
}

void interruptHandler() 
{
  digitalWriteFast(D0, pinReadFast(D3));
}

???

I don’t even.

DAC1 will give you an analog voltage and not a PWM signal, if this is your intention with

    pinMode(DAC1, OUTPUT); 
    analogWrite(DAC1, 400); // just setting something up for the pulses

And how have you wired your setup (e.g. which pin triggers D3)?

OK, I’ve now tried out your code from above (D1 -> D3 -> scope Ch1, D0 Ch2) and I get a good copy of D1 on D0 with a delay of 1µs


Have you tested with my code?

Yup, the code I tested above was yours, with my triggering code.

In regards to your previous comment, I have confirmed that the pin I’m using is the right one, and I’ve tried using a different one.

D1 drives a h-bridge at 40khz, sending an ultrasonic ping out of a transducer. This bounces off a wall and goes into another transducer. Then, I have a notch filter and a two stage amplifier that brings the recieved pulse to 3.3v amplitude so we can detect it on D3 digitally. DAC1 sets the threshold on a comparator on the receiver.

I’m very puzzled about this and since I can even reduce to delayMicroseconds(1); and still get a near perfect mirror response on my Photon(s), I’d have to hand this over to someone who can test this on a P1 (or have you got a Photon you could repeat your tests?)

Maybe @peekay123 or @BDub can help out with a P1.

I don’t have a photon, unfortunately.

I have tracked down the problem a bit more. Ran this code:

void setup()
{
  pinMode(D0, OUTPUT);
  digitalWriteFast(D0, HIGH);
  pinMode(D1, OUTPUT);
  pinMode(D3, INPUT);
  attachInterrupt(D3, interruptHandler, CHANGE);
}

void loop()
{
}

void interruptHandler() 
{
  digitalWriteFast(D0, pinReadFast(D3));
}

And then shorted D3 high.

I got a… wait for it…

1.25ms delay before D0 went high.

I’m not sure if this will help, but I implemented pulseIn() with interrupts like this:

Also, and non-interrupt driven pulseIn() will be available in 0.4.7 firmware.

I’m not exactly sure what you’d like me to test, can you spell it out please?

Also, digitalWriteFast(D0, HIGH/LOW) is not as fast as pinSetFast(D0) and pinResetFast(D0). If I remember correctly it’s about 5 times slower at 200ns or so vs 41ns.

Just as a quick test, could anyone try uploading this code on a p1 or a photon, shorting D3 high, and see what the delay is before D0 goes high? I don’t know if it’ll be constructive, but I’m getting crazy delays of milliseconds or more before it fires the interrupt.

void setup()
{
  pinMode(D0, OUTPUT);
  digitalWriteFast(D0, HIGH);
  pinMode(D1, OUTPUT);
  pinMode(D3, INPUT);
  attachInterrupt(D3, interruptHandler, CHANGE);
}

void loop()
{
}

void interruptHandler() 
{
  digitalWriteFast(D0, pinReadFast(D3));
}

By the way, thanks for all the help, everyone. This is an awesome community.

Brett, when I test the above code on my Photon (0.4.6) I see exactle the behaviour I’d expect (ignoring the speed gain with pin(Re)SetFast() rather than digitalWriteFast()) but Daniel can’t get anywhere near that behaviour with his P1.
What could be the reason for that?


@Arthur_dent_42_121, as said with my tested two Photons (0.4.5 & 0.4.6) I only get a delay of about 800 nano seconds - most of that probably cause be the reading of the pin state.
Just flipping a pin was 360ns, and given Brett’s advice this could be cut by another 70%.

Do you know if there was a batch of P1s made with an 8khz oscillator? :grinning:

@Arthur_dent_42_121, I have a P1 board I can test tonight. I’ll report back then. Shorting D3 seems less than ideal due to bounce. It may be better to use a PWM output pin as the trigger source to do the measurement. I’ll give that a shot.

Thanks. Good idea with the PWM.

If I just poll the pin normally,

void loop()
{
    digitalWriteFast(D1, pinReadFast(D3));
}

I get a 2.36ms delay.

EDIT: comments removed to avoid confusion :slight_smile:

@BDub, interrupts not working on D3/4/5 IS a real issue!! Can you setup a PWM pin an connect that as the D5 interrupt trigger and report on the delay?

@Arthur_dent_42_121, if you are not using a non-AUTOMATIC system mode, some of that 2.36ms delay is probably caused by the cloud routines.

But the remaining rest is still odd and Brett migh have found some issues here.

1 Like

Haha… I’m using a P1 break out board and none of the pins are labeled like D0-D7, they are all JTAG_TMS… etc… well there are two JTAG interfaces, ML_JTAG_TMS and M_JTAG_TMS… so, that’s why NOTHING is working :blush: Was using the wrong pins entirely!

Should of grabbed my Sparkfun P1 Redboard :smile:

One sec while I go back to square one with interrupts.

4 Likes

Ok this code works fine on my P1 breakout… the D7 pin toggles about 1us after the D5 input rises.

void setup()
{
    pinMode(D7, OUTPUT); // JTAG_TMS
    digitalWrite(D7, HIGH);
    
    pinMode(D5, INPUT); // JTAG_TDI
    attachInterrupt(D5, myHandler, RISING);
}

void loop()
{
}

void myHandler() 
{
    digitalWriteFast(D7, !pinReadFast(D7));
}

Code like this is not going to be very predictable, since the D5 input may not hold the same state for very long.

void myHandler() 
{
    digitalWriteFast(D7, pinReadFast(D5));
}
3 Likes