Timer, interrupt,delay,pwm

Hi,
Thanks for your help in advance.

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)

Do you have any idea?

what range and resolution for duration?

certainly < 50 usec.

Seems like you've decided on the exact technique very early in the development process. School assignment?

Post the current sketch.

The delayed part and duration is done.
But when there is no pulse on pin 2, I need to generate 12k pulse instead of the delayed one.

I will as soon as I go back to my workplace.


#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

I commented out some of the lines to make it simpler without compromising its functionality.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.