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.
2 Answers 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.
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:
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.
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 asvolatile
). 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
-
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.Malik Elahi– Malik Elahi08/11/2020 14:03:31Commented Aug 11, 2020 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.Malik Elahi– Malik Elahi08/11/2020 14:30:37Commented Aug 11, 2020 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.Gabriel Staples– Gabriel Staples08/11/2020 15:27:35Commented Aug 11, 2020 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 secondsMalik Elahi– Malik Elahi08/12/2020 09:24:15Commented Aug 12, 2020 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 withdigitalWrite()
is ~500Hz on an arduno uno. Actually, I wonder how you get this working at 7kHz.Sim Son– Sim Son08/14/2020 10:41:50Commented Aug 14, 2020 at 10:41
Explore related questions
See similar questions with these tags.
CHANGE
instead ofRISING
orFALLING
. 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?