My full code is very long, but I will post the relevant parts (setup, ISR). I'm using Serial printing for debug, and I've found that when the motorshield commands are used (setspeed, run) the ISR is terminated and stops running. When I comment those lines out it runs as expected.
Code: Select all
//Motorshield objects
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *pumpMotor = AFMS.getMotor(1);
/* ----------setup----------
*
* This is the setup function which is automatically run one time during startup,
* which happens at powerup or reset. This function should include all
* initialization tasks.
*
* Do NOT change the name of this function!
*/
void setup()
{
// Copyright (c) 2016 Steve Southward <[email protected]>
// Declare variables local to the setup function
// Initialize the serial monitor (required if you are printing to the Serial Monitor)
// the entered number is called the "baud rate" which means "bits per second"
Serial.begin(9600); // can choose {4800, 9600, 19200, 38400, 57600, 115200, 230400, or 250000}
// Configure the digital I/O pins we want to use
pinMode(switchRockPin, INPUT);
pinMode(controlRockPin, INPUT);
pinMode(LEDvPin, OUTPUT);
pinMode(LEDpPin, OUTPUT);
pinMode(LEDboardPin, OUTPUT);
pinMode(lim1Pin, INPUT);
pinMode(lim2Pin, INPUT);
pinMode(motPWMPin, OUTPUT);
pinMode(motDIRPin, OUTPUT);
// Initialize and configure the low-pass filter for operation
digital_lpf(0, true);
// Configure the TIMERS
/* see the following links for more details on configuring PWM Timers on the Arduino platform
* <http://www.engblaze.com/microcontroller-tutorial-avr-and-arduino-timer-interrupts/>
* <https://arduino-info.wikispaces.com/Arduino-PWM-Frequency>
* <https://arduinodiy.BANNED.com/2012/02/28/timer-interrupts/>
* <https://arduino-info.wikispaces.com/Timers-Arduino>
* <http://playground.arduino.cc/Main/TimerPWMCheatsheet>
*/
noInterrupts(); // first disable all global processor interrupts
// Configure TIMER1 to drive the Interrupt Service Routine
TCCR1A = 0; // initialize entire TCCR1A register to zero (upper half of a 2-byte register)
TCCR1B = 0; // initialize entire TCCR1B register to zero (lower half of a 2-byte register)
TCNT1 = 0; // reset the initial Timer1 CouNT value
if (FS >= 10) { // configure for higher sample rates
OCR1A = (int)(62500 / FS); // define the total counts in the Output Control Register to achieve FS Hz
TCCR1B |= (1 << WGM12); // set the WGM12 bit to enable Clear Timer on Compare (CTC) mode
TCCR1B |= (1 << CS12); // set the CS12 bit
// the CS12 bit creates a prescaled 16MHz/256=62.5kHz base clock
} else { // cofigure for lower sample rates
OCR1A = (int)(15625 / FS); // define the total counts in the Output Control Register to achieve FS Hz
TCCR1B |= (1 << WGM12); // set the WGM12 bit to enable Clear Timer on Compare (CTC) mode
TCCR1B |= (1 << CS12); // set the CS12 bit
TCCR1B |= (1 << CS10); // set the CS10 bit
// the CS12 and CS10 bits create a prescaled 16MHz/1024=15.625kHz base clock
}
TIMSK1 |= (1 << OCIE1A); // enable the timer Output Compare Interrupt bit OCIE1A
// Configure TIMER2 to drive the PWM's (for generating analog outputs in pins 9 and 10 on the Mega)
TCCR2B &= 0b11111000; // set bits 7, 6, 5, 4, and 3 to define the PWM waveform generator mode
TCCR2B |= (1 << CS11); // set the CS11 bit
// the CS11 bit defines a divisor of 8 to create a prescaled 16MHz/510/8 = 3921.57 Hz base PWM frequency
interrupts(); // now it is ok to enable all global processor interrupts
//Start the motorshield
AFMS.begin();
pumpMotor->setSpeed(0);
}
/* ----------ISR----------
*
* This is the Interrupt Service Routine function. This function will be called at
* the fixed uniform sample rate of FS Hz. All of the real-time functional tasks
* that must run at a fixed clock frequency should be implemented inside this function.
*
* Do NOT change the name of this function!
*/
ISR(TIMER1_COMPA_vect)
{
// Copyright (c) 2016 Steve Southward <[email protected]>
Serial.println(7);
//If Active Control is not enabled
if(manualControlEnable)
{
Serial.println(9);
//Get current pressure
sensorVoltage = .0049*analogRead(sensorPin);
actualPressure = (sensorVoltage-0.5)/(.04);
if(positivePressure)
{
//Get command pressure
potValue = analogRead(potpPin);
//Normalize
commandPressure = (85.5/1024)*potValue + 14.5;
}
else
{
//Get command pressure
potValue = analogRead(potvPin);
//Normalize
commandPressure = 14.5 - (14.5/1024)*potValue;
}
error = commandPressure - actualPressure;
if(error < 0) //If command pressure is less than actual pressure
{
//Backwards
motDir = 0;
error = error*-1;
//digitalWrite(motDIRPin, LOW);
//SHIELD
pumpMotor->run(BACKWARD);
}
else
{
//Forwards
motDir = 1;
//digitalWrite(motDIRPin, HIGH);
//SHIELD
pumpMotor->run(FORWARD);
}
// compute the control signal
motPWM = (int)(error / 4);
// Note: the value of control_out MUST be an 8-bit unsigned integer in the range of 0 to 255
// because the PWM output is only 8-bit, so it can only accept values between 0 and 255
motPWM = constrain(motPWM, 0, 255); // saturate the control_out value between 0 and 255
// Output the control_out signal as a PWM output
// for a PWM output: 0 = 0% duty cycle, 255 = 100% duty cycle, operation duration: ~16.6us
//analogWrite(motPWMPin, (int)motPWM);
//SHIELD
pumpMotor->setSpeed(motPWM);
//Check Rocker Switch (vac to pos)
if (digitalRead(switchRockPin) == LOW)
{
rockerSelect = 0;
if (prevRockerSelect == 1)
{
rockerTransition = 1;
positivePressure = false;
}
prevRockerSelect = 0;
}
else if (digitalRead(switchRockPin) == HIGH)
{
rockerSelect = 1;
if (prevRockerSelect == 0)
{
rockerTransition = 1;
positivePressure = true;
}
prevRockerSelect = 1;
}
//Check Rocker Switch (Control on/off)
if (digitalRead(controlRockPin) == LOW)
{
controlSelect = 0;
if (prevControlSelect == 1)
{
rockerTransition = 1;
controlEnable = false;
manualControlEnable = true;
}
prevControlSelect = 0;
}
else if (digitalRead(controlRockPin) == HIGH)
{
controlSelect = 1;
if (prevControlSelect == 0)
{
rockerTransition = 1;
controlEnable = true;
manualControlEnable = false;
}
prevControlSelect = 1;
}
if(rockerTransition == 1)
{
Serial.println(1000);
Serial.println(rockerSelect);
Serial.println(controlSelect);
rockerTransition = 0;
}
//Print for plotting
Serial.println(actualPressure);
Serial.println(elapsedTime);
Serial.println(commandPressure);
if(Serial.available() > 0)
{
if(Serial.parseInt() == 2)
{
state = false;
}
}
}
if(controlEnable)
{
//Get current pressure
sensorVoltage = .0049*analogRead(sensorPin);
// Digitally filter the analog input signal
sensorVoltageFilter = digital_lpf((float)sensorVoltage, false);
actualPressure = (sensorVoltage-0.5)/(.04);
error = activeCommandPressure - actualPressure;
if(error < 0)
{
//Backwards
motDir = 0;
error = error*-1;
//digitalWrite(motDIRPin, LOW);
//SHIELD
pumpMotor->run(BACKWARD);
}
else
{
//Forwards
motDir = 1;
//digitalWrite(motDIRPin, HIGH);
//SHIELD
pumpMotor->run(FORWARD);
}
// compute the control signal
motPWM = (int)(error / 4); // replace this simple example with your desired control function
// Note: the value of control_out MUST be an 8-bit unsigned integer in the range of 0 to 255
// because the PWM output is only 8-bit, so it can only accept values between 0 and 255
motPWM = constrain(motPWM, 0, 255); // saturate the control_out value between 0 and 255
// Output the control_out signal as a PWM output
// for a PWM output: 0 = 0% duty cycle, 255 = 100% duty cycle, operation duration: ~16.6us
//analogWrite(motPWMPin, (int)motPWM);
//SHIELD
pumpMotor->setSpeed(motPWM);
//Check Rocker Switch (vac to pos)
if (digitalRead(switchRockPin) == LOW)
{
rockerSelect = 0;
if (prevRockerSelect == 1)
{
rockerTransition = 1;
positivePressure = false;
}
prevRockerSelect = 0;
}
else if (digitalRead(switchRockPin) == HIGH)
{
rockerSelect = 1;
if (prevRockerSelect == 0)
{
rockerTransition = 1;
positivePressure = true;
}
prevRockerSelect = 1;
}
//Check Rocker Switch (Control on/off)
if (digitalRead(controlRockPin) == LOW)
{
controlSelect = 0;
if (prevControlSelect == 1)
{
rockerTransition = 1;
controlEnable = false;
manualControlEnable = true;
}
prevControlSelect = 0;
}
else if (digitalRead(controlRockPin) == HIGH)
{
controlSelect = 1;
if (prevControlSelect == 0)
{
rockerTransition = 1;
controlEnable = true;
manualControlEnable = false;
}
prevControlSelect = 1;
}
if(rockerTransition == 1)
{
Serial.println(1000);
Serial.println(rockerSelect);
Serial.println(controlSelect);
rockerTransition = 0;
}
Serial.println("alive");
//Print for plotting
Serial.println(actualPressure);
Serial.println(elapsedTime);
Serial.println(activeCommandPressure);
if(Serial.available() > 0)
{
if(Serial.parseInt() == 2)
{
state = false;
}
}
}
//If control is happening, increase the time stamp
if(timing)
{
elapsedTime = elapsedTime + 1/FS;
}
}
Thank you for your help!