0

This is my timer interrupt:

void setup() {
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), count_time_of_k_pulses, RISING);

  pinMode(OE_BAR_PIN, OUTPUT);
  pinMode(S0_PIN, OUTPUT);
  pinMode(S1_PIN, OUTPUT);
  pinMode(S2_PIN, OUTPUT);

  TIMER1_init();

  Serial.begin(BAUD_RATE);
  while (! Serial);
}

void count_time_of_k_pulses()
{
  if (interrupts_enabled)
  {
    pulse_counter++;

    if (pulse_counter == 1)
      TIMER1_start();

    if (pulse_counter == number_of_samples)
    {
      TIMER1_stop();

      measurement_finished = true;
      interrupts_enabled = false;
    }
  }
}

The logic behind this is that it will receive signals from a digital circuit on an arduino pin. When it receives the first signal it will start a timer. After it receives as many signals, as set by number_of_samples, it will stop. This information will help my identify the resitance of a resistor.

There is a problem though. Imagine that while the timer interrupt runs (signals are coming and the timer is running), i remove one pin from the resistor and the signal stops arriving at the arduino pin.

Then the program will lock, because it will be stuck inside the timer interrupt, constantly waiting for if (pulse_counter == number_of_samples) to be satisfied.

So is there a way, while inside the timer interrupt, to detect when the timer interrupt is stuck, without using more timers?

EDIT: BELOW IS THE WHOLE CODE

/***** CONSTANTS *****/
const int BAUD_RATE = 9600;
const int INTERRUPT_PIN = 3;
const int S0_PIN = 4;
const int S1_PIN = 5;
const int S2_PIN = 6;
const int OE_BAR_PIN = 22;
const int NUM_OF_SENSORS = 8;

/***** ANALOG CIRCUIT CONSTANTS *****/
const double CAPACITOR_VALUE = 400; //pF
const double GAIN_VALUE = 3.5222672065;
const double R_BIAS_VALUE = 98.7; //kΩ

/***** GLOBAL VARIABLES *****/
int number_of_samples = 500;
int sensor_coord;
boolean full_mode = false;

unsigned long overflows = 0;
unsigned long ticks = 0;
double period = 0;

//variables for determining if a resistance cannot be measured 
unsigned long timestamp = 0;
unsigned long measurement_timeout = 5000;  //5 seconds is the timeout time
boolean sensor_corruption[8]; //each element of the array is the sensor info. If false, resistance is working. If it's true, resistance is open.
boolean ISR_unavailable = false; //this flag is raised, when the ISR does not run, because no signal comes from the circuit, because resistance is open circuit

//variables that get changed inside the ISR 
volatile int pulse_counter = 0;
volatile boolean interrupts_enabled = false;
volatile boolean measurement_finished = false;



void setup()
{
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), count_time_of_k_pulses, RISING);

  digitalWrite(OE_BAR_PIN, HIGH);
  pinMode(OE_BAR_PIN, OUTPUT);
  pinMode(S0_PIN, OUTPUT);
  pinMode(S1_PIN, OUTPUT);
  pinMode(S2_PIN, OUTPUT);

  TIMER1_init();

  Serial.begin(BAUD_RATE);
  while (! Serial);


  for (int i=0; i<=7; i++)
  {
    sensor_corruption[i] = false; // false means it's working ok. true means it's open-circuit (or cannot be read anyway)
  }
}

void loop()
{

  //CODE FOR SERIAL INTERFACE (RESISTANCE SELECTION)
  if (Serial.available())
  {
    /***** DEFINE MEASUREMENT MODE *****/
    String input = Serial.readString();
    if (input[0] == 'r' && interrupts_enabled == false)
    {
      if (input[1] == 'f')
      {
        full_mode = true;
        sensor_coord = 0;
      } else
        sensor_coord = input[2] - '0';  // r *SPACE* [0-7]

      select_sensor();

      pulse_counter = 0;
      TIMER1_clear();

      interrupts_enabled = true;
    }
  }

  //no_interrupts area-------
  // TIMEOUT CODE HERE. TO DETERMINE IF A RESISTANCE IS OPEN CIRCUITED
  if(interrupts_enabled && millis() - timestamp > measurement_timeout)
  {
    sensor_corruption[sensor_coord] = true; //label the resistance (indicated by sensor_coord) as true in the boolean array. this means it's open circuited (no signal from circuit)
    measurement_finished = true; ///we set this to true, so we can enter the next block of code
    ISR_unavailable = true; //small flag in order to not do calculations (some lines below) in case of an open circuit
  }
  //-------------------------

  if (measurement_finished)
  {

    if (!ISR_unavailable) //only make these calcs, if the ISR_unavailable is false. in other words if the ISR runs (so resistance is read)
    {
        ticks = (overflows * 65536) + TCNT1;
        period = (ticks * 0.0625) / (number_of_samples - 1);
    }

      TIMER1_print_results();
      ISR_unavailable = false; 
      if (full_mode)
      {
        sensor_coord++;
        select_sensor();
        pulse_counter = 0;
        TIMER1_clear();
        interrupts_enabled = true; 

        if (sensor_coord == NUM_OF_SENSORS)
        {
          full_mode = false;
          interrupts_enabled = false;

        }


        measurement_finished = false;
        timestamp = millis(); 

      }


       pulse_counter = 0;
       TIMER1_clear();
       interrupts_enabled = true; //NEW
       measurement_finished = false; // delete this bs
       timestamp = millis();

  }
 }

/***** INTERRUPT ROUTINES *****/

void count_time_of_k_pulses()
{
  if (interrupts_enabled)
  {
    pulse_counter++;

    if (pulse_counter == 1)
      TIMER1_start();

    if (pulse_counter == number_of_samples)
    {
      TIMER1_stop();

      measurement_finished = true;
      interrupts_enabled = false;
    }
  }
}

ISR (TIMER1_OVF_vect)
{
  overflows++;
}

/***** FUNCTION FOR SENSOR SELECTION *****/

void select_sensor()
{
  digitalWrite(OE_BAR_PIN, HIGH);
  digitalWrite(S2_PIN, ((sensor_coord & 4) == 4) ? HIGH : LOW );
  digitalWrite(S1_PIN, ((sensor_coord & 2) == 2) ? HIGH : LOW );
  digitalWrite(S0_PIN, ((sensor_coord & 1) == 1) ? HIGH : LOW );
  digitalWrite(OE_BAR_PIN, LOW);
}

/***** TIMER1 FUNCTIONS *****/

void TIMER1_init()
{
  TCCR1A  = 0;
  TCCR1B  = 0;
  TIMSK1 |= (1 << TOIE1);
}

void TIMER1_start()
{
   TCCR1B |= (0 << CS12) | (0 << CS11) | (1 << CS10);
}

void TIMER1_stop()
{
  TCCR1B  = 0;
}

void TIMER1_clear()
{
  TCNT1     = 0;
  overflows = 0;
}

void TIMER1_print_results()
{
  Serial.println("----------------------------------------");
  Serial.print("SENSOR COORDINATE         = ");
  Serial.println(sensor_coord);


  if (sensor_corruption[sensor_coord])
  {
    Serial.println("This resistance is open circuited!!!");
  }
  else
  {
    Serial.print("NUMBER OF PULSES MEASURED = ");
    Serial.println(pulse_counter);

    Serial.print("TIMER1 VALUE              = ");
    Serial.println(TCNT1);

    Serial.print("TIMER1 OVERFLOWS          = ");
    Serial.println(overflows);

    Serial.print("TICKS                     = ");
    Serial.println(ticks);

    Serial.print("MEASURED PERIOD           = ");
    Serial.print(period);
    Serial.println(" US");

    Serial.print("MEASURED RESISTANCE       = ");
    double resistanse = ((period * GAIN_VALUE * 1000) / (4 * CAPACITOR_VALUE)) - R_BIAS_VALUE; //kΩ
    Serial.print(resistanse);
    Serial.println(" kΩ");

    Serial.println("----------------------------------------");
  }
}
  • 2
    Is that your ISR? Then where should it get stuck? I don't see any while loops or similar. Also: What interrupts are you using here? I would assume that this ISR is used with an external interrupt pin. It starts a timer to measure the time of a pulse. Please provide a full working code. We need to see the whole code situation. – chrisl Mar 9 at 22:31
  • 1
    One moment, you already asked a question about that code some time ago: here. The problem seems quite similar, so I immediately thought about the same solution principle using millis(). Or do you need to use Timer0 somewhere else in your new code revision, so that you cannot use millis()? – chrisl Mar 9 at 22:37
  • Please, note that count_time_of_k_pulses() is not a timer interrupt. It's the handler of an external interrupt. – Edgar Bonet Mar 10 at 21:18
  • I updated the code. Yes, the code is the same from that thread. Although the problem is different. In that problem (which i solved thatnks to you guys) i wanted to detect when the timer interrupt does not run, because it does not get triggered. In this new problem, i am inside the interrupt, but for some reason the signal stops arriving, while inside (before i reach the number_of_samples). So the program is stuck inside the iterrupt, waiting for the signal to get equal the number_of_samples. – user1584421 Mar 10 at 21:20
  • It won't be stuck inside any interrupt. It will fire the interrupt and exit and then if the signal is gone it won't fire the interrupt again. So the easiest method may be to just keep track in loop of how long it has been since the last interrupt. If it has been a long time then the signal must be lost. You just need one more unsigned long in the ISR to keep track of the millis time of the last interrupt. – Delta_G Mar 10 at 22:24

Your Answer

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

Browse other questions tagged or ask your own question.