issue with interrupts

Krischomat

Well-known member
Hey! I am in the process of migrating a project from the arduino to a teensy 4.0. It is a Sequencer Module for a Eurorack Synth. It can take to trigger inputs for counting through the 2 Sequences of my module. In the arduino I was using this to set it up.

I run this in the setup of my program

Code:
  pinMode(interruptPinA, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPinA), countingA, RISING);
  pinMode(interruptPinB, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPinB), countingB, RISING);

where these are the interrupt functions

Code:
void countingA()
{
  counterA = (counterA == 7) ? 0 : counterA + 1;
}

void countingB()
{
  counterB = (counterB == 7) ? 0 : counterB + 1;
}

and the counterA and B are defined like so:
Code:
volatile uint8_t counterA = 0;
volatile uint8_t counterB = 0;

and these are my interrupt Pins:
Code:
const uint8_t interruptPinA = 2;
const uint8_t interruptPinB = 3;

This works on the arduino but on the teensy it looks kind of irregular/ glitchy. Do I have to set it up differently?

ah and on the breadboard the triggers from the synth is going through a diode via a resistor to the base of a transitor and collector is connected to one of the interrupt pins and the emiiter is going to ground with a resistor.

edit: resistors are all 10k
 
Last edited:
okay hardware and interrupt pins seem to work. I have two function that are disturbing the interrupts/counting. when this is running in the mainloop:
Code:
void showPresetOnMatrix(int preset)
{
  for (int i = 0; i < ROWS; i++)
  {
    ledMatrix.setLed(0, 0, i, Presets[preset][i]);
    ledMatrix.setLed(0, 1, i, Presets[preset][i + ROWS]);
    ledMatrix.setLed(0, 2, i, Presets[preset][i + ROWS * 2]);
    ledMatrix.setLed(0, 3, i, Presets[preset][i + ROWS * 3]);
    ledMatrix.setLed(0, 4, i, Presets[preset][i + ROWS * 4]);
    ledMatrix.setLed(0, 5, i, Presets[preset][i + ROWS * 5]);
  }
}

or this
Code:
void configPresetCounter(int bits[])
{
  //byte states[4] = {B00000000, B11100000, B00011100, B11111100};
  byte states[2] = {B00000000, B11100000};

  for (int i = 0; i < 6; i++)
  {
    if (buttonsX[i].rose())
    {
      setStates[i] = !setStates[i];
    }
    //ledMatrix.setRow(0, i, states[bits[i] + setStates[i] * 2]);
    ledMatrix.setRow(0, i, states[bits[i]]);
  }
}

oth are displaying leds on a led matrix. I am using the LedControl Library for that. As I said, it was running on the arduino. Any Idea what I should do differently on the teensy? One thing I had to change in my code when I was swichting to PlatformIO is that it complained that my functions where declared at the end and after I was using them. Now I declare them before the setup and loop. Dont know if this plays a role...

or can it be that I am not doing an interrupt on the interrupt pins that should read a trigger signal since it seems to be glitchy when i run for loops in my code that should be interrupted right?
 
here is my full source code...
Code:
/**
 * @file main.cpp
 * @author Christian Grothe 
 * @brief 
 * @version 0.1
 * @date 2023-01-27
 * 
 * @copyright Copyright (c) 2023
 * 
 */
#include <Arduino.h>
#include <EEPROM.h>
#include <Bounce2.h>
#include "LedControl.h"

/**
 * @brief Constants
 * 
 */
const uint8_t NUM_BUTTONS = 3;
const uint8_t NUM_BITOUT = 6;
const uint8_t NUM_BITS = 3;
const uint8_t DOTS = 36;
const uint8_t ROWS = 6;

// Matrix Buttons
Bounce *buttonsX = new Bounce[8];
Bounce *buttonsY = new Bounce[8];


/**
 * @brief GPIO
 * 
 */
const uint8_t interruptPinA = 2;
const uint8_t interruptPinB = 3;
const uint8_t gateOutA = 4;
const uint8_t gateOutB = 5;

// bit outs for 4051 Buttons
const uint8_t muxOut1 = 6;
const uint8_t muxOut2 = 7;
const uint8_t muxOut3 = 8;
const uint8_t muxReturnA = 9;
const uint8_t muxReturnB = 10;

const uint8_t din = 15;  
const uint8_t clck = 14; 
const uint8_t load = 13;
LedControl ledMatrix = LedControl(din, clck, load, 1);

// bit outs for 4051 Seqence
const uint8_t BitOut[NUM_BITOUT] = {16, 17, 18, 19, 20, 21}; 


/**
 * @brief Variable Variables
 * 
 */
// Sequence Counters
volatile int counterA = 3;
volatile int counterB = 3;

// populated with presets in setup
bool Presets[6][DOTS] = {{}, {}, {}, {}, {}, {}};

// handle gate Out
bool isGateOnA = false;
bool isGateOnB = false;
unsigned long millisCountA = 0;
unsigned long millisCountB = 0;
unsigned int gateLengthA = 20;
unsigned int gateLengthB = 20;

// bit counts for 4051
int muxBit1;
int muxBit2;
int muxBit3;

// populated with bit read
int bits[ROWS];

// menu
int shownPreset = 0;
int usedPreset = 1;
int presetCount = 0;
bool setStates[6] = {0, 0, 0, 0, 0, 0};
bool lastStates[6] = {0, 0, 0, 0, 0, 0};

bool lastBitStatesA[3] = {0,0,0};
bool lastBitStatesB[3] = {0,0,0};

int presetToggler = 0;

enum Menue
{
  main,
  setPresetCount,
  setChangePresets
};
Menue menue = setPresetCount;

// temp
bool PresetA[DOTS] = {1, 0, 0, 0, 0, 0,
                      0, 1, 0, 0, 0, 0,
                      0, 0, 1, 0, 0, 0,
                      0, 0, 0, 1, 0, 0,
                      0, 0, 0, 0, 1, 0,
                      0, 0, 0, 0, 0, 1};

bool PresetB[DOTS] = {0, 0, 0, 0, 0, 0,
                      0, 0, 0, 1, 0, 0,
                      0, 0, 0, 0, 0, 0,
                      0, 1, 0, 0, 0, 1,
                      0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 1, 0};

bool PresetC[DOTS] = {0, 0, 0, 0, 0, 0,
                      0, 0, 0, 1, 0, 0,
                      0, 0, 0, 0, 0, 0,
                      1, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 1, 0,
                      0, 0, 1, 0, 0, 0};

bool PresetD[DOTS] = {0, 0, 0, 0, 0, 0,
                      0, 0, 1, 0, 0, 0,
                      0, 0, 0, 0, 0, 1,
                      1, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 0, 0,
                      0, 0, 0, 1, 0, 0};

bool PresetE[DOTS] = {0, 1, 0, 0, 0, 0,
                      0, 0, 0, 0, 0, 1,
                      0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 1, 0,
                      0, 1, 0, 0, 0, 0};

bool PresetF[DOTS] = {0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 1, 0,
                      0, 0, 1, 0, 0, 0,
                      0, 0, 0, 0, 0, 0,
                      0, 0, 0, 1, 0, 0,
                      0, 0, 0, 0, 0, 1};

/**
 * @brief Functions
 * 
 */
void presetToggling()
{
  presetToggler++;

  if (presetToggler == 6)
  {
    presetToggler = 0;
  }
}

void configPresetCounter(int bits[])
{
  //byte states[4] = {B00000000, B11100000, B00011100, B11111100};
  byte states[2] = {B00000000, B11100000};

  for (int i = 0; i < 6; i++)
  {
    if (buttonsX[i].rose())
    {
      setStates[i] = !setStates[i];
    }
    //ledMatrix.setRow(0, i, states[bits[i] + setStates[i] * 2]);
    ledMatrix.setRow(0, i, states[bits[i]]);
  }
}

void presetCounter(int bits[])
{
  for (int i = 0; i < 6; i++)
  {
    if (bits[i] != lastStates[i])
    {
      if (setStates[i])
      {
        presetCount++;
        if (presetCount == 6)
        {
          presetCount = 0;
        }
        lastStates[i] = bits[i];
      }
    }
  }
}

void changePreset(int preset) {
  for (int i = 0; i < 6; i++) {
    for (int j = 0; j < 6; j++) {
      if ((buttonsX[i].rose() && buttonsY[j].read() == HIGH) || (buttonsX[i].read() == HIGH && buttonsY[j].rose())) {        
        Presets[preset][i + 6 * j] = !Presets[preset][i + 6 * j];
    }
    }
  }
}

void showPresetOnMatrix(int preset)
{
  for (int i = 0; i < ROWS; i++)
  {
    ledMatrix.setLed(0, 0, i, Presets[preset][i]);
    ledMatrix.setLed(0, 1, i, Presets[preset][i + ROWS]);
    ledMatrix.setLed(0, 2, i, Presets[preset][i + ROWS * 2]);
    ledMatrix.setLed(0, 3, i, Presets[preset][i + ROWS * 3]);
    ledMatrix.setLed(0, 4, i, Presets[preset][i + ROWS * 4]);
    ledMatrix.setLed(0, 5, i, Presets[preset][i + ROWS * 5]);
  }
}

bool sumofbits_function(int column, int preset) {
  for (int i = 0; i < 6; i++) {
    if (bits[i] && Presets[preset][column + i * 6]) {
      return 1;
    }
  }
  return 0;
}

void countingA()
{
  counterA = (counterA == 7) ? 0 : counterA + 1;
}

void countingB()
{
  counterB = (counterB == 7) ? 0 : counterB + 1;
}

void saveChangesToEEPROM()
{
  for (int i = 0; i < DOTS; i++)
  {
    EEPROM.update(i, Presets[0][i]);
    EEPROM.update(i + DOTS, Presets[1][i]);
    EEPROM.update(i + (DOTS * 2), Presets[2][i]);
    EEPROM.update(i + (DOTS * 3), Presets[3][i]);
    EEPROM.update(i + (DOTS * 4), Presets[4][i]);
    EEPROM.update(i + (DOTS * 5), Presets[5][i]);
  }
}

/**
 * @brief Teensy Setup
 * 
 */
void setup()
{
  Serial.begin(9600);

  pinMode(interruptPinA, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPinA), countingA, FALLING);
  pinMode(interruptPinB, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPinB), countingB, FALLING);

  // Display Setup
  ledMatrix.shutdown(0, false);
  ledMatrix.setIntensity(0, 5);
  ledMatrix.clearDisplay(0);

  // reading from the EEPROM
  for (int i = 0; i < DOTS; i++)
  {
    Presets[0][i] = PresetA[i];
    Presets[1][i] = PresetB[i];
    Presets[2][i] = PresetC[i];
    Presets[3][i] = PresetD[i];
    Presets[4][i] = PresetE[i];
    Presets[5][i] = PresetF[i];

    // Presets[0][i] = EEPROM.read(i);
    // Presets[1][i] = EEPROM.read(i + DOTS);
    // Presets[2][i] = EEPROM.read(i + DOTS * 2);
    // Presets[3][i] = EEPROM.read(i + DOTS * 3);
    // Presets[4][i] = EEPROM.read(i + DOTS * 4);
    // Presets[5][i] = EEPROM.read(i + DOTS * 5);
  }

  // Set Up BitOut to 4051 SQ
  for (int i = 0; i < NUM_BITOUT; i++)
  {
    pinMode(BitOut[i], OUTPUT);
  }

  for (int i = 0; i < 8; i++)
  {
    buttonsX[i].attach(muxReturnA, INPUT);
    buttonsX[i].interval(20);

    buttonsY[i].attach(muxReturnB, INPUT);
    buttonsY[i].interval(20);
  }

  pinMode(muxOut1, OUTPUT);
  pinMode(muxOut2, OUTPUT);
  pinMode(muxOut3, OUTPUT);
  pinMode(gateOutA, OUTPUT);
  pinMode(gateOutB, OUTPUT);

}

/**
 * @brief Teensy Main Loop
 * 
 */
void loop()
{
  //multiplexer for buttons
for (int i = 0; i < 8 ; i++)
  {
    buttonsX[i].update();
    buttonsY[i].update();

    muxBit1 = ((i + 1) & 0b001);
    muxBit3 = ((i + 1) & 0b100) >> 2;
    muxBit2 = ((i + 1) & 0b010) >> 1;

    digitalWrite(muxOut1, muxBit1);
    digitalWrite(muxOut2, muxBit2);
    digitalWrite(muxOut3, muxBit3);
  }

  // convert count to bits
  for (int i = 0; i < NUM_BITS; i++)
  {
    bits[i] = bitRead(counterA, i);
    bits[i + 3] = bitRead(counterB, i);
  }

  // change preset
  for (int i = 0; i < 6; i++)
  {
    if (buttonsY[6].read() == HIGH && buttonsX[i].rose())
    {
      shownPreset = i;
      usedPreset = i;
    }
  }

  // bit output to 4051 SQ
  for (int i = 0; i < 3; i++)
  {
    int stateA = sumofbits_function(i + 3, presetCount);
    int stateB = sumofbits_function(i, presetCount);
    
    digitalWrite(BitOut[i], stateA);
    digitalWrite(BitOut[i+3], stateB);

    if (stateA != lastBitStatesA[i]){
      digitalWrite(gateOutA, HIGH);
      lastBitStatesA[i] = stateA;
      isGateOnA = true;
      millisCountA = millis();
    }

    if (stateB != lastBitStatesB[i]){
      digitalWrite(gateOutB, HIGH);
      lastBitStatesB[i] = stateB;
      isGateOnB = true;
      millisCountB = millis();
    }
  }

  if(millis() - millisCountA >= gateLengthA && isGateOnA){
    digitalWrite(gateOutA, LOW);
    isGateOnA = false;
    gateLengthA = random(20,30);
  }
  if(millis() - millisCountB >= gateLengthB && isGateOnB){
    digitalWrite(gateOutB, LOW);
    isGateOnB = false;
    gateLengthB = random(20,30);
  }

  // toggle menue

  if (buttonsY[7].rose())
  {
    menue = setPresetCount;
  }
  else if (buttonsY[6].rose())
  {
    menue = main;
  }
  else if (buttonsX[7].rose())
  {
    menue = setChangePresets;
    presetToggling();
  }
  else if (buttonsX[6].rose())
  {
    saveChangesToEEPROM();
  }

  switch (menue)
  {
  case main:
    showPresetOnMatrix(presetCount);
    //changePreset(presetCount);
    //presetCounter(bits);
    break;
  case setPresetCount:
    // presetCounter(bits);
    configPresetCounter(bits);
    break;
  case setChangePresets:
    //showPresetOnMatrix(presetToggler);
    // changePreset(presetToggler);
    // presetCounter(bits);
    break;

  default:
    break;
  }
} 
/// End Of Main Loop ///
 
It's going to be a bit difficult to help since I don't understand your hardware, what you are counting on CounterA and CounterB, or what is glitchy, but I'll take a wild guess and mention that Teensy 4.0 is very fast, perhaps much faster than the Arduino, so you might need to slow some things down with calls to delay(ms).
 
This works on the arduino but on the teensy it looks kind of irregular/ glitchy. Do I have to set it up differently?

ah and on the breadboard the triggers from the synth is going through a diode via a resistor to the base of a transitor and collector is connected to one of the interrupt pins and the emiiter is going to ground with a resistor.

edit: resistors are all 10k

I assume that you are using an NPN transistor, and when the input goes high, the transistor turns on and pulls down the Teensy input pin. This is a circuit that calls for some filtering capacitors either at the Teensy input pin or at the base of the transistor. The input pullup on the Teensy is not very strong, and transistor with reasonable gain will pull the input pin down when it picks up local noise. The size of the input filter capacitors depends on the response time you desire for your inputs.
 
I found out that the problem has to do something with the LedControl library I am using. Even when I place this somewhere in the main loop

Code:
  ledMatrix.setLed(0, 0, 0, true);

to set the first led of my led matrix on, my counter becomes glitchy. With glitchy I mean, it does count in a random order so not just from 0 - 7, and also irregular. When I dont use and uncomment all the ledMatrix code in my program, the counter works as expected.

I am using this Library:

LedControl by Eberhard Fahle
A library for the MAX7219 and the MAX7221 Led display drivers. The library supports multiple daisychained drivers and supports Led-Matrix displays as well as 7-Segment displays.

there is also a newer version of this
LedControl by Eberhard Fahle
Control MAX7219/MAX7221 LED display drivers. Choose between hardware SPI (fast) or software SPI (flexible).

But I could not successfully include this in my project with PlatformIO.
 
ah and on the breadboard the triggers from the synth is going through a diode via a resistor to the base of a transitor and collector is connected to one of the interrupt pins and the emiiter is going to ground with a resistor.

edit: resistors are all 10k

If the circuit is as this description reads, you should remove the 10k emitter resistor and connect the emitter to ground.
 
so I wont get a short when the teensies pin is connected to ground via the transitor?

I could actually fix the problem by getting rid of the interrupt. Since the teensy is much faster than the arduino there is no need to use an interrupt to check the pin change at any point in my program. just doing it once on every cycle seems to be enough!

But what I dont know why the interrput routine and the LedControl library are conflicting on the teensy but not on the arduino.
 
Back
Top