Teensy LC and IntervalTimer - working proprely ?

Status
Not open for further replies.

nicolas_soundforce

Active member
Hi,

I read on the IntervalTimer page that it's working only on Teensy 3.0. It seems that I can begin the function but I can't end it with .end().
Is this a known issue ?

I am building en enveloppe generator for a modular synth.
I am testing now with a switch, when I press the switch I start the ADSR, it goes through an AD function and when it gets to the sustain phase, I would like to stop calling the AD function. When the knob is released it should also call the release at the same interval until the output value gets to 0.

Just wondering if there is something to do or if I should better using the other timing functions.

The problem now is that even when it gets to the sustain phase, it still calls the AD function every interval and it does not seem to execute the .end() proprely.

Here is the code:

Code:
#include <SPI.h>
#include <MCPDAC.h>
#include <Bounce.h>

#define trigger_ 2
#define switch_p 23

Bounce switch_ = Bounce(switch_p, 150);
int volts = 0;

// Values below are in micro seconds!!
float attack_ = 1500 ;
float decay_ = 2000;
float release_ = 2000;

float sustain_ = 50;

bool gate = 0;
bool linear = 1;

bool start_env = 1;
bool restart_rel = 1;

bool sustain_phase = 0;

int knob = 0;

float counter = 0;
float time_counter = 0;

float release_counter = 0;
float release_time_counter = 0;

float output_signal = 0;

IntervalTimer AD;
IntervalTimer R;

void setup()
{

  pinMode(13, OUTPUT);
  pinMode(switch_p, INPUT_PULLUP);

  digitalWrite(13, HIGH);
  delay(100);

  Serial.begin(9600);
  //attachInterrupt(trigger_, trigger_env, RISING) ;

  MCPDAC.begin(10);

  MCPDAC.setGain(CHANNEL_A, GAIN_HIGH);

  MCPDAC.shutdown(CHANNEL_A, false);
  MCPDAC.shutdown(CHANNEL_B, true);

  MCPDAC.setVoltage(CHANNEL_A, 500);
}

void loop() {

  switch_.update();

  //if switch pressed then start AD
  if (switch_.fallingEdge()) {
    AD.begin(AD_generator, 10);
    //Serial.print("pressed");
    start_env = 1;
  }

  //if switched release then start R
  if (switch_.risingEdge()) {
    // AD.end();
    R.begin(R_generator, 10);
    //Serial.print("released");
    restart_rel = 1;
  }

}

void AD_generator() {
  if (start_env) {
    counter = 0;
    start_env = 0;
  }

  counter++;
  time_counter = counter * 10; //each increment of the counter  = 10 microseconds

  //Attack phase
  if (time_counter < attack_) {
    output_signal = (time_counter / attack_);

    // Serial.println();
    Serial.print(1);
    Serial.print(",");
    Serial.print(time_counter / 1000);
    Serial.print(",");
    Serial.println(output_signal);
  }

  //Decay phase
  if ((time_counter >= attack_) && (time_counter < (attack_ + decay_))) {
    //  output_signal = (1 - ((time_counter - attack_) * ((1 - sustain_) / decay_)));
    output_signal = 1 + (((sustain_ / 100) - 1) / (decay_) * (time_counter - attack_));

    //Serial.println();
    Serial.print(2);
    Serial.print(",");
    Serial.print(time_counter / 1000);
    Serial.print(",");
    Serial.println(output_signal);
  }

  //Enter sustain phase
  if (time_counter >= (attack_ + decay_)) {
    // Serial.println();
    Serial.print(3);
    Serial.print(",");
    Serial.print(time_counter / 1000);
    Serial.print(",");
    Serial.println(output_signal);

    MCPDAC.setVoltage(CHANNEL_A, sustain_);

    AD.end();
  }

  //If there is a new out_signal value then send it to the DAC
  MCPDAC.setVoltage(CHANNEL_A, output_signal);
}

void R_generator() {

  if (restart_rel) {
    release_counter = 0;
    restart_rel = 0;
  }

  counter++;
  time_counter = counter * 10; //each increment of the counter  = 10 microseconds

  release_counter++;
  release_time_counter = release_counter * 10; //time counted in microsecond

  output_signal = sustain_ / 100 -  release_time_counter * (sustain_ / release_);
  MCPDAC.setVoltage(CHANNEL_A, output_signal);

  Serial.println();
  Serial.print(4);
  Serial.print(", ");
  Serial.println(time_counter);
  Serial.print(", ");
  Serial.print(output_signal);

  if (output_signal == 0) {
    R.end();
  }
}
 
Last edited:
.end() works for me. On T3.2 and LC

Code:
IntervalTimer sampleTimer;

void blink() {
static int c = 0;  
    digitalWrite(13, !digitalRead(13));
    c++;
    if (c==50) sampleTimer.end();
}

void setup() {
  pinMode(13, OUTPUT);
  sampleTimer.begin(blink, 50000);
}

void loop (void) {
}

Hints (may not be related to the exact problem with your sketch):
- Use the keyword "volatile" for global variables that are used in interrupts. <- this one is important !
- using print() and other complex functions inside an interrupt is a bad idea.

- Are you sure that ouput_signal reaches 0 _exactly_ ?
 
Last edited:
thanks! I overlooked those things. I will try right away.

.end() works for me. On T3.2 and LC

Code:
IntervalTimer sampleTimer;

void blink() {
static int c = 0;  
    digitalWrite(13, !digitalRead(13));
    c++;
    if (c==50) sampleTimer.end();
}

void setup() {
  pinMode(13, OUTPUT);
  sampleTimer.begin(blink, 50000);
}

void loop (void) {
}

Hints (may not be related to the exact problem with your sketch):
- Use the keyword "volatile" for global variables that are used in interrupts. <- this one is important !
- using print() and other complex functions inside an interrupt is a bad idea.

- Are you sure that ouput_signal reaches 0 _exactly_ ?
 
Status
Not open for further replies.
Back
Top