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