I have a sensor which is attached to pin 2 of arduino uno. (This sensor is either active or inactive. When active, lets say it generates a 20 khz pulse. When inactive, no pulse)
When arduino receives pulse on pin 2, it should create a delayed pulse with a specific duration on pin 9. It is done using interrupter and timer attached to pin 2. When arduino receives no pulse, it should generate a pulse with frequency 12Khz on pin 9.(my problem is here)
#include <digitalWriteFast.h>
#include <PWM.h>
int32_t frequency=12000; //frequency in hz
volatile unsigned long counter;
volatile unsigned long current_tcn;
const boolean polarity = 1; //1: spark = HIGH, 0:spark = LOW
const boolean detectEdge = 0; //1:detect rising edge, 0:detect falling edge
volatile unsigned int sparkDelayTime = 14; // microseconds. max 1024000 (=1.024s)
volatile unsigned int sparkOnTime = 25; // microseconds. max 1024000 (=1.024s)
const byte FIRE_SENSOR = 2; // this port corresponds to interrupt 0 (for INT0_vect)
const byte SPARKPLUG = 9;
// allow for time taken to enter ISR (determine empirically)
const unsigned int isrDelayFactor = 4; // microseconds
// is spark currently on?
volatile boolean sparkOn;
volatile unsigned int prescaler_delay;
volatile unsigned int prescaler_duration;
void setup()
{
Serial.begin(9600);
TCCR1A = 0; // normal mode, we just need to set the values in register A of timer 1 to zero
TCCR1B = 0; // stop timer
TIMSK1 = 0; // cancel timer interrupt- using this we can enable timer compare interrupt, overflow, capture input
// timer 2
TCCR2A = 0;// set entire TCCR2A register to 0
TCCR2B = 0;// same for TCCR2B
// timer 0
EIMSK |= (1 << INT0); // Enable external interrupt INT0m, |= means or. for instance 1 | 0 would be 1, 1|1 would be 1
// define whether the external interrupt is activated on rising and/or falling edge of the INT0 pin or level sensed
EICRA &= ~(bit(ISC00) | bit (ISC01)); // clear existing flags, Computes the value of the specified bit (bit 0 is 1, bit 1 is 2, bit 2 is 4, etc.).
if (detectEdge == 0)
//1:detect rising edge
//0:detect falling edge
{
// Trigger INT0 on falling edge
EICRA |= (1 << ISC01); // 1<<0 (1), 1<<1 (2), 1<<2 (4), for instance 5 is (101). the values are shifted left based on ISC01
// here ISC01 is set to 1
EICRA |= (0 << ISC00);
// here ISC01 is set to 0
}
else {
// Trigger INT0 on rising edge
EICRA |= (1 << ISC01);
EICRA |= (1 << ISC00);
}
if (sparkDelayTime < 32000) {
prescaler_delay = 8;
}
pinMode (SPARKPLUG, OUTPUT);
pinMode (FIRE_SENSOR, INPUT_PULLUP); //by default it is high
activateInterrupt0 ();
} // end of setup
void activateInterrupt0 ()
{
EICRA &= ~(bit(ISC00) | bit (ISC01)); // clear existing flags, Bitwise NOT changes each bit to its opposite: 0 becomes 1, and 1 becomes 0.
//EICRA |= bit (ISC01); // set wanted flags (falling level interrupt)
if (detectEdge == 0) {
EICRA |= (1 << ISC01);
EICRA |= (0 << ISC00);
}
else {
EICRA |= (1 << ISC01);
EICRA |= (1 << ISC00);
}
EIFR = bit (INTF0); // clear flag for interrupt 0
//the flag can be cleared by writing '1' to it
EIMSK |= bit (INT0); // enable it
} // end of activateInterrupt0
void deactivateInterrupt0 ()
{
EIMSK &= ~bit (INT0); // disable it
} // end of deactivateInterrupt0
t 0
ISR (INT0_vect) // start timer for delay parameter
//ISR() is how you tell the compiler to associate a function with a specific interrupt source
{
counter=millis();
sparkOn = false; // make sure flag off just in case
// set up Timer 1
TCCR1A = 0; // normal mode
TCNT1 = 0; // count back to zero, TCNT1 is the current timer count
TCCR1B = bit(WGM12) | bit(CS11); // CTC, scale to clock / 8
// time before timer fires - zero relative
OCR1A = (sparkDelayTime * 2) - (isrDelayFactor * 2) - 1;
current_tcn=TCNT1;
TIMSK1 = bit (OCIE1A); // interrupt on Compare A Match
TCCR1B = bit(WGM12) | bit(CS11); // CTC, scale to clock / 8
// time before timer fires (zero relative)
// multiply by two because we are on a prescaler of 8
OCR1A = (sparkOnTime * 2) - (isrDelayFactor * 2) - 1;
//deactivateInterrupt0 (); // no more interrupts yet
} // end of ISR (INT0_vect)
ISR (TIMER1_COMPA_vect)
{
TCNT1 = 0;
sparkOn = !sparkOn;
digitalWrite (SPARKPLUG, sparkOn);
if (sparkOn==0)
{
TCCR1B = 0; // stop timer
TIMSK1 = 0; // cancel timer interrupt
//activateInterrupt0 (); // re-instate interrupts for firing time
}
} // end of TIMER1_COMPA_vect
void loop()
{
} // end of loop