Using two timer libraries that are interfering with each other

Hi,

I have written a programme that will run a stepper motor with acceleration and deceleration to a set number of positions. The number of positions the motor has to travel to is set at the start, my programme will then jumble all of these positions up and the motor will travel to the positions randomly. While the motor is moving I have set a buzzer and LED to have different functions depending on what is set by a BCD (binary coded decimal) switch.

The reason I am using 2 timer libraries is so that I can accelerate and send pulses to the motor at the same time as beeping the buzzer & flashing the LED. The problem I am having is that when the buzzer and LED interrupt interrupts the programme, it also interrupts the pulses being sent to the motor, which creates an annoying clunking sound.

Atttached is a shortened version of my programme.

#include <TimerOne.h> // interrupt used to flash LED
#include <TimerThree.h> //interrupt used to operate motor


// Varibales used in in the relative and absolute movement functions and the SendPulse ISR
volatile int Q, accelOrDecel, minDelay, initialDelay;

volatile bool toggleA, bitt;

volatile long int count, decel, delA, check;
volatile long int G_reqSteps, totalCount, stepsTakenToAccel;
volatile long int _delayAtHalf, _halfOfReqSteps;

// Variables used in homing sequence
volatile bool H_accelOrConstant;
volatile int H_maxSpeed, H_initialDelay, H_delA;

int homePosition, ttoggle, button;

int homeSwitch;
int directionPin;
int enablePin;
int pulsePin;
int accelerationTestPin;

#define DECEL 0
#define ACCEL 1
#define CONSTANT 2
#define homeSwitch A0

///////////////////////////////////////////////////
// LISTED BELOW ARE ALL THE VARIABLES YOU CAN EDIT //
///////////////////////////////////////////////////
                                                 
float startPosI = 60;            // SETS THE START POSITION IN DEGREES
float endPosI = 120;             // SETS THE END POSITION IN DEGREES
#define NUMBEROFPOSITIONS 6      // SETS THE NUMBER OF POSITIONS THE MOTOR SHOULD STOP AT
int loopMax = 3;                 // SETS THE NUMBER OF TIMES YOU WANT THE OPERATION TO REPEAT
volatile int brightness = 255;   // SETS THE BRIGHTNESS OF THE INDICATOR LED
volatile int buzzerTone = 500;   // SETS THE TONE OF THE BUZZER
int delA_B = 2000;               // SETS THE DELAY PERIOD AT EACH POSITION, IN MILLISECONDS
int shufflePositions = 0;        //If set to 1, positions will be shuffled after each sequence.
                             
///////////////////////////////////////////////////

int posNo = NUMBEROFPOSITIONS;
float array[NUMBEROFPOSITIONS];

int countB;
int multiplier = 0;
volatile bool toggleB = true;
const int ledPin = 13;

int loopcountB;
#define ONEDEGINSTEPS 733.333333

int atHome = 0;


// Interrupt service routine used to send pulse and count acceleration and deceleration (ISR)
void SendPulse(){ // ISR
  
  togglePin(pulsePin);
  
  if(accelOrDecel == ACCEL){ //ACCEL is defined at the start at 1
    
    if(count == 2){
      Q = 2;
      check = (((Q * Q) + Q) /2); // check will = 3
      delA = initialDelay / Q; // delA will equal half of initial delay
    } else if(count == check){
      Q++;
      check = (((Q * Q) + Q) /2);
      delA = initialDelay / Q;
    }

  }else if(accelOrDecel == DECEL){ // DECEL is defined at the start as 0
   
    if(count != G_reqSteps){ // On the final count no more calculations are necessary
    
        if(decel == stepsTakenToAccel){
          digitalWrite(10, LOW);
          Q--;
          delA = initialDelay / Q;
          Q--;
          check = (((Q * Q) + Q) /2);
        }else if(decel == check){
          delA = initialDelay / Q;
          Q--;
          check = (((Q * Q) + Q) /2);
        }   
   }
   decel--; 
  }
  bitt = true; // bitt is used to allow the programme to wait for the interrupt
  
  Timer1.initialize(delA);
}

// This function moves the motor to an absulte position in relation to the 0 position that is
// usually set by the homing function but can also be set by typing totalCount = 0;
void MoveAbsolute(long int absoluteTarget){
  count = 0;
  delA = initialDelay;
  decel = stepsTakenToAccel;
  bool absoluteDIR;
  long int stepsRequired;
  stepsRequired = absoluteTarget - totalCount;
  G_reqSteps = stepsRequired;
  bitt = false;
  long int degree;
  
  if(stepsRequired < 0){
    stepsRequired = stepsRequired * -1;
    digitalWrite(directionPin, HIGH);
    absoluteDIR = digitalRead(directionPin);
  }else{
    digitalWrite(directionPin, LOW);
    absoluteDIR = digitalRead(directionPin);
  }
  
  if(stepsRequired/2 < stepsTakenToAccel){
    _halfOfReqSteps = stepsRequired/2; 
    _delayAtHalf = delayAtHalfRequiredSteps(_halfOfReqSteps);
    stepsTakenToAccel = accelerationStepCounter(_delayAtHalf);
    decel = stepsTakenToAccel;
  }
  
  digitalWrite(enablePin, LOW);
    
  accelOrDecel = ACCEL;
  Timer1.initialize(delA);
  Timer1.attachInterrupt(SendPulse);
  
  for(count = 1; count <= stepsRequired; count++){
   
      if(count < stepsTakenToAccel){
        digitalWrite(11, LOW);
        accelOrDecel = ACCEL;
        
      }else{
        if(count < (stepsRequired - stepsTakenToAccel)){
      
        digitalWrite(11, HIGH);
        accelOrDecel = CONSTANT;
        
        
      }else{
        digitalWrite(11, LOW);
        accelOrDecel = DECEL;   
        
      }
    }

    while(!bitt){}   
    bitt = false;
    
  }
  Timer1.detachInterrupt();
  count--;
  digitalWrite(enablePin, HIGH);  // Disables motor after position reached (HIGH = disabled)
  digitalWrite(pulsePin, LOW);  // Sets step pin LOW

  if(absoluteDIR){
    totalCount = totalCount - count;
  } else{
    totalCount = totalCount + count;
  }
  Serial.println("Moved absolute");
  Serial.print("Current position = ");
  degree = totalCount/ ONEDEGINSTEPS;
  Serial.print(degree);
  Serial.print("\n");

  count = 0;
  check = 0;
  Q = 0;
  bitt = false;
  toggleA = true;
  digitalWrite(pulsePin, LOW);
}

void case1Stim() { // Case 1 Stimulus Function - Flash BOTH  This is an ISR
  digitalWrite(A3, HIGH);
  if(toggleB){
    analogWrite(13, brightness);
    tone(8, buzzerTone);
    toggleB = false;
  } else {
    analogWrite(13, 0);
    noTone(8);
    toggleB = true;
  }
  digitalWrite(A3, LOW);
}

int CaseFunction(bool startend){
  
  int case_select = BCDread();
  if(case_select >=1 && case_select <= 8)
    switch(case_select){
      
      case 1 : //LED on, Buzzer on, Flash + Beep ON

            if(!startend){
              Timer3.attachInterrupt(case1Stim);
              for(countB = 0; countB < posNo; countB++){
                
                Timer3.start();
                MoveAbsolute(array[countB]);
                Timer3.stop();
                analogWrite(13, 0);
                noTone(8);
                delay(delA_B);
              }
              if(shufflePositions == 1){
                for(countB = 0; countB < posNo; countB++)
                  sswap(countB, random(posNo));
              }
            }
            Timer3.detachInterrupt();
            break;
    }
}

// Sets the first delay period used by the interrupt/ acceleration rate
void setInitialDelay(int _initialDelay){ 
  initialDelay = _initialDelay;
}

void setup() {

  Serial.begin(9600);
  
  Timer3.initialize(100000);
  Timer3.stop();

  pulsePinInit(6);   // Step
  enablePinInit(14);   // Enable
  directionPinInit(7);   // Direction
  accelerationTestPinInit(12);
  pinMode(homeSwitch, INPUT); // Home switch initialize
  
  
  setInitialDelay(5000);

  stepsTakenToAccel = accelerationStepCounter(minDelay);
  Serial.print("Steps taken to accelerate = ");
  Serial.print(stepsTakenToAccel);
  Serial.println("\n");

  homingSequence(1, 10);
  Serial.println("home");

  loopcountB = 0;

}

void loop() {
  int trigger = digitalRead(A2);
  int last_trigger;

  last_trigger = trigger;
  
  do{
    CaseFunction(1); //this runs the case function but does nothing.
    trigger = digitalRead(A2);
  }while(trigger && trigger == last_trigger);

  do{
    CaseFunction(trigger);
    loopcountB++;
    Serial.println("");
    Serial.print("Loop count = ");
    Serial.print(loopcountB);
    Serial.print("of ");
    Serial.print(loopMax);
    Serial.println("");
  }while(loopcountB < loopMax);
  loopcountB = 0;

}

In what way are the two libraries "interfering with each other"?

Can you provide pointers to the two libraries to save anyone willing to work on your problem the bother of having to track them down?

JohnWasser+1
and
Without spending too much time looking at your code, you need to read up on ISR and Math functions within the ISR. You need as little as possible going on while time is spent in the ISR.

If I look at the pulse signal being sent to the step driver and also look at a test signal (A3) that I set high at the start of the ISR for the buzzer and low at the end of it, I can see that when this interrupt fires it also interrupts the pulses being sent by the other interrupt and changes the width of the pulses, leaving it high or low for a longer period than it should be therefore making a clunking sound.

I have attached both the source and header files for the Timer1 and Timer3 libraries. Also here is the link to the webpage - Arduino Timer Lib Page

My motor seems to run perfectly if I don't another interrupt.

TimerOne.cpp (7.83 KB)

TimerOne.h (2.94 KB)

TimerThree.cpp (4.1 KB)

TimerThree.h (1.31 KB)

You shouldn't need a timer library for the buzzer and LED flashing. Just use 'millis()'-based timing, as shown in "BlinkWithoutDelay" and Demonstration code for several things at the same time

Then, besides getting rid of your problem, you'll learn some very useful techniques. Techniques that using libraries won't teach you.

Thanks for the help, especially the tip to use the millis function, my programme now works perfectly.