0

I have this snippet of code:

 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;
    } //first if ends here
    else if (input[0] == 'C' || input[0] == 'c') 
    {
      interrupts_enabled = false;  //If the user types 'C' OR 'c', stop the measurement
    }
 } 

So when i send 'rf' to the arduino, a measurement to all my sensors starts hapening indefinetely. (There is another mode as well, typing 'r 0' will start an infinite measurement on the first sensor.) When all the eight sensors, are measured, it will start from the beggining.

I wanted to be able to stop this operation when i typed a command in the serial. This is why i addded the else if (input[0] == 'C' || input[0] == 'c') portion.

So that, when the infinite measurement occurs and i press 'C', it is supposed to stop.

But it didn't work. Not only that, but if i am in full mode and i then press another serial command, such as previously mentioned 'r 0'. , nothing happens as well.

So what i am asking is: Is there a way to stop an operation triggered frmo serial that is underway? And by stopping it, i mean from serial as well. Perhaps, when an operation is uderway taht is triggered from serial, it cannot be stopped until the operation is finished? Maybe it has to do something with when i have already typed 'rf' and sometime later i type 'C', maybe that 'C' is no longer on position input[0] of the serial buffer?

EDIT: This is the full 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 - thus are declared volatile!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
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);

  //Initializing all array elements to false!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  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;
    } //first if ends here
    else if (input[0] == 'C' || input[0] == 'c') //not sure if it's case sensitive, but just to make sure i added both capitals and lower-case
    {
      interrupts_enabled = false;  //If the user types 'C' OR 'c', stop the measurement
    }
  } //Serial.available portion ends here

  //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);

        //RESET THE SENSOR CORRUPTION TO FALSE HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!
        sensor_corruption[sensor_coord] = false;
        // if the res goes from open-circuited to working, this will restore the array so it's not labelled as open-circuited anymore
        // THE PROBLEM IS: THE FIRST MEASUREMENT AFTER IT GOES FROM OPEN -> CLOSED IS CORRUPTED. IT'S ALWAYS TO HIGH
        // MAYBE IT'S CAUSED BY THE FRICTION OF WIRES????
    }

      TIMER1_print_results();
      ISR_unavailable = false; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! reset ISR_unavailable for the next measurement
      if (full_mode)
      {
        sensor_coord++;
        select_sensor();
        //pulse_counter = 0;
        //TIMER1_clear();
        //interrupts_enabled = true; //necessary in full mode. useless if res is open-circuit, as this value never changed. but it doesn't hurt

        if (sensor_coord == NUM_OF_SENSORS)
        {

          sensor_coord = 0; //back from the beginning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
          // full_mode = false; //no i want to continue having full mode
          // interrupts_enabled = false; //no, i want to continue having interrupts

          //after i measure all 8 resistances, the interrupt_enabled will be false. so code will be stuck in my no_interrupts area
          //this means the no_interrupts() area should run only when interrupts_enabled is true

          //remove the full mode line and reset sensor coord
        }

        /* We only enter the block of code we are now, when a measurement has happened (or when the no_interrupts
        area fired).
        We know that a measurement happened because the 'measurement_finished' variable is set by the interrupt
        (or set by the no_interrupts area, in order to enter the block we are now).
        But we ONLY want to enter the block we are now, when a measurement is finished, in order to process it.
        So now, that we did process it, in the end of this block, we have to reset the value.
        So we set measurement_finished to false, in order to not enter the block we are now, unless a new
        measurement has occured (or the no_interrupts area fired).
         */
        //measurement_finished = false;
        //timestamp = millis();  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        //if i measure 1 resistance. here, interrupts_enabled will be false. this means no interupts.
        //this means my no_interrupts code will run. so it will always print. so no_interrupts area should run only whe interrupts_enabled is true
      }

      //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       pulse_counter = 0;
       TIMER1_clear();
       interrupts_enabled = true;
       measurement_finished = false;
       timestamp = millis();  // refresh timer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  }
 } //loop ends

/***** 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 (MODIFIED) *****/

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);

  //Added the if-else statement, to cover the possibility of open circuited resistance !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  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("----------------------------------------");
  }
}
5
  • You need to check serial inbetween of your infinite measurement loop. readString() is a bad choice for that, because it uses a 1s timeout. Please show us your full code or - if its too long - a minimal working example
    – chrisl
    Commented Mar 25, 2020 at 22:03
  • I edited the question with the full code. Commented Mar 25, 2020 at 22:06
  • But the end of the loop, wont the execution always flow to the part where there is the Serial.available() check? Commented Mar 25, 2020 at 22:20
  • Maybe i should place the interrupts_enaled not at the end of the loop, but at the beginning? Because maybw now they are always enabled, so maybe my program doesnt have time to access the serial chekcing part. Commented Mar 26, 2020 at 1:04
  • why do you need to use interrupts?
    – jsotola
    Commented Mar 26, 2020 at 2:25

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.