2

I have written a code that detects an incoming pulse (square) of 7.875 kHz to trigger the output High for the entire duration of pulse, and trigger the output low if the pulse is off or not detected.

CODE

// Define pins
volatile int pulse1 = 2;    //incoming pulse 1 on pin 2    

const int ledPin = 13;   //output to trigger LED    
    

void setup() {

  pinMode(pulse1, INPUT);
  
  pinMode(ledPin, OUTPUT);
  
  // Timer Setup
  
  TCCR1A = 0;               // set entire TCCR1A register to 0
  TCCR1B = 0;               // same for TCCR1B
  TCNT1  = 65282;           // initialize counter value 
  TCCR1B |= (1<<CS10);      // set prescaler to 8 bit
  TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt

}
ISR(TIMER1_OVF_Vect){
  TCNT1 = 65282;
  attachInterrupt(digitalPinToInterrupt(pulse1), ISR_UV2, FALLING);
  }
  

void loop() {
  attachInterrupt(digitalPinToInterrupt(pulse1), ISR_UV1, RISING);
  
}

// Interrupt routines

void ISR_UV1(){
  digitalWrite(ledPin, HIGH);      // Send high signal
}

void ISR_UV2(){
  digitalWrite(ledPin, LOW);      // Send low signal
}

Is it the correct approach, or am I doing it wrong. One last thing that is bothering me is, every time I connect a wire (not connected to anything) to the input pin 2, it sends a high signal, and keeps the signal high until the Arduino is reset. The pulse is a square wave 50% duty cycle generated by a device. I dont need to measure it or count it. I am just using it as a trigger to send a HIGH signal when it occurs. So it stays on (occurs) for 25ms & turns off during which its freq. is 7.875MHz & then it is repeated by the device according to the device parameters. I am aware it is a very short pulse but for the purpose of project nothing else can be used as the trigger

Any help will be appreciated.

16
  • If you don't connect the wire to anything, the pin is still floating. It can have any value, even rapidly changing, depending on which noise it is currently picking up. The pin itself can already pick up noise. With an attached wire you are basically creating an antenna.
    – chrisl
    Aug 10 '20 at 11:42
  • Why are you attaching the interrupts again and again? You never detach the interrupts, so why attaching them over and over again?
    – chrisl
    Aug 10 '20 at 11:43
  • Also it does not make sense to me, where you are attaching the interrupts. I don't think it works, that you attach 2 interrupts to one pin. Then you are just changing the interrupt for a very short time, when the timer overflows. Instead you could just use 1 interrupt with CHANGE instead of RISING or FALLING. Inside it you can read the pin to check, which one happended. Have you tried, if that code is working? Or are you just asking in advance?
    – chrisl
    Aug 10 '20 at 11:51
  • Can you describe the pulse waveform more in detail? This is such a high freq that there's no way you can do anything in that time except maybe see if it occurred. Example of a detailed description: it is a 200ns HIGH pulse occurring once per second. Or, it is a 200ns HIGH followed by 200ns LOW, repeating. Aug 10 '20 at 15:50
  • What does it mean for the pulse to be "off" or "not detected"? Is OFF when the signal is LOW? Or is it when you haven't seen a HIGH pulse for X ns, or something else? Aug 10 '20 at 15:52
2

So i figured out what the problem was, I had to detach interrupts in the interrupt routines not in my main code. So basically these changes:

void loop() {
  digitalWrite(ledPin, LOW);
  attachInterrupt(digitalPinToInterrupt(pulse1), ISR_UV1, CHANGING);
  
}

& in the Interrupt routines:

digitalWrite(ledPin, HIGH);      // Send high or Low dpending on the routine 
detachInterrupt(digitalPinToInterrupt(pulse1));

& basically this works like a charm, & there are still issues with the timer, but that will be solved in my main code with another sensor.

0

I don't think, that your current approach will work. The logic seems flawed to me (though I cannot know, how exactly this code is embedded in your actual code) and the frequency is that high, that it will be difficult for the microcontroller to do much between the different interrupt triggers.

I would suggest 2 different approaches, based on the actual needs:

  1. You can build a demodulator, which just gives you a high value, when your signal is there, and a low one, if it is not. Here you would need extra components.

  2. You could feed the signal into one of the timers as clock source. Then the timer counts the pulses (actually twice the pulses, since the timer increments on every edge, rising or falling). You can use the overflow interrupt to get the value out of it. Lets say you use Timer 1 for the signal and still have Timer 0 for doing the Arduino time stuff (delay(), millis(), micros()). Then you can write an ISR for the Timer1 overflow interrupt. In there you take the current time and subtract the time of the last interrupt. Then you get the time, that it took the timer to overflow. Since you know, how many pulses are needed to overflow the timer, you now know the average frequency. If it is in the needed range, you set a simple single byte flag variable (be sure to declare it as volatile). You can tune the time for the average for example with the prescaler.

    In your main code you can then check for the flag being set and do stuff accordingly. Reset the flag, if you have done stuff, and save a timestamp. Check in your main code, if a specific time has passed since your last timestamp. If yes, that means, that the signal is lost. There you can act accordingly

5
  • Thank you so much once again for your suggestions, I will try those out & let you know if it works. I do suspect that in the end i would have to go to the de-modulator approach. Aug 11 '20 at 14:03
  • My apologies!!! The frequency is in KHz not MHz. I double checked it with a scope. Nonetheless.. i will try out your suggestions. Aug 11 '20 at 14:30
  • @MalikElahi, this new frequency changes everything! :) Also, the details you have provided us in your comments everywhere need to be in your question. Please update your question with all your new details and I'll see if I can provide an answer today. What you want to do is certainly doable. Aug 11 '20 at 15:27
  • @GabrielStaples Thank you so much, Yes certainly i will update the question. I tried my the code as suggested by chrisl to change the 'rising' to 'change' & it is working, but there is still few bugs & i am 90% sure that it gets stuck in timer interrupt or since the timer count is not a whole number the timer is off by couple of micro seconds Aug 12 '20 at 9:24
  • @MalikElahi you should consider to use direct port manipulation instead of calls to digitalWrite(). From my experience the highest frequency you can achieve with digitalWrite() is ~500Hz on an arduno uno. Actually, I wonder how you get this working at 7kHz.
    – Sim Son
    Aug 14 '20 at 10:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.