Interrupt on teensy 4.0 + Adafruits Neotrellis

Moris526

Active member
Hi all.

Im using Teensy 4.0 to control Adafruits Neotrellis 16 LEd/button board programing it with Arduino Ide

All works fine with the Adafruit example but the interrupt function ( it works fine with an arduino uno board)


HTML:
/* This example shows basic usage of the NeoTrellis
  with the interrupt pin.
  The buttons will light up various colors when pressed.
*/

#include "Adafruit_NeoTrellis.h"

Adafruit_NeoTrellis trellis;

#define INT_PIN 8

// Input a value 0 to 255 to get a color value.
// The colors are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return trellis.pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return trellis.pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return trellis.pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

//define a callback for key presses
TrellisCallback blink(keyEvent evt){
  
  if(evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING)
    trellis.pixels.setPixelColor(evt.bit.NUM, Wheel(map(evt.bit.NUM, 0, trellis.pixels.numPixels(), 0, 255))); //on rising
  else if(evt.bit.EDGE == SEESAW_KEYPAD_EDGE_FALLING)
    trellis.pixels.setPixelColor(evt.bit.NUM, 0); //off falling
    
  trellis.pixels.show();
  return 0;
}

void setup() {
  Serial.begin(9600);
  //while(!Serial);

  pinMode(INT_PIN, INPUT);
  
  if(!trellis.begin()){
    Serial.println("could not start trellis");
    while(1);
  }
  else{
    Serial.println("trellis started");
  }

  //activate all keys and set callbacks
  for(int i=0; i<NEO_TRELLIS_NUM_KEYS; i++){
    trellis.activateKey(i, SEESAW_KEYPAD_EDGE_RISING);
    trellis.activateKey(i, SEESAW_KEYPAD_EDGE_FALLING);
    trellis.registerCallback(i, blink);
  }

  //do a little animation to show we're on
  for(uint16_t i=0; i<trellis.pixels.numPixels(); i++) {
    trellis.pixels.setPixelColor(i, Wheel(map(i, 0, trellis.pixels.numPixels(), 0, 255)));
    trellis.pixels.show();
    delay(50);
  }
  for(uint16_t i=0; i<trellis.pixels.numPixels(); i++) {
    trellis.pixels.setPixelColor(i, 0x000000);
    trellis.pixels.show();
    delay(50);
  }
}

void loop() {
  if(!digitalRead(INT_PIN)){
    Serial.println("Hello");
  }
  delay(2);
}



When I press the button I get "Hello" printed continuosly but when I let it go it keeps printing.

any idea?
 
Just wired up a Neotrellis to a T4 and using the above sketch get the same result so I did this :-
Code:
void loop() {
  if(!digitalRead(INT_PIN)){
    trellis.read(false); //This line is in the library example
    Serial.println("Hello");
  }
  delay(2);
}
and now the pressed button lights when pressed and the serial monitor prints Hello once when the button is either pressed or released. Hope that helps.
 
Thanks for the answer.

I try


HTML:
void loop() {
  if(!digitalRead(INT_PIN)){
    trellis.read(false);
  }


and I get



HTML:
Sketch: In function 'void loop()':
Sketch:107: error: no matching function for call to 'Adafruit_MultiTrellis::read(bool)'
     trellis.read(false); //This line is in the library example
                       ^
In file included from C:\Users\Moris\Desktop\Sketch\Sketch.ino:1:0:
C:\Users\Moris\Documents\Arduino\libraries\Adafruit_seesaw_Library/Adafruit_NeoTrellis.h:85:8: note: candidate: void Adafruit_MultiTrellis::read()
   void read();
        ^
C:\Users\Moris\Documents\Arduino\libraries\Adafruit_seesaw_Library/Adafruit_NeoTrellis.h:85:8: note:   candidate expects 0 arguments, 1 provided
Sketch: In function 'void (* blink(keyEvent))(keyEvent)':
Sketch:45: warning: control reaches end of non-void function 
 }
 ^
no matching function for call to 'Adafruit_MultiTrellis::read(bool)'

Sorry for my lack of knowledge. Im not a programmer, im trying to build a controller for a synth
 
Code:
delay(2);  //Is missing
}  // and more importantly, loop() needs this closing brace

I'm using some Neotrellis as a controller for a Synth controller.
 
Victory too soon.

I have new data.

Now sometimes does print Hello just once and sometimes keeps printing. When it keeps printing, sometimes, when I press again stops again.

Tha would mean its not a code problem and more of a hardware thing?
 
A good pic of your setup and some idea of what you are trying to achieve might be helpful.

My setup uses a 15v wallwart and a 2.1 Amp 5v switchmode supply and a brownout can derail the Neotrellis but not necessarily the T4.0 that drives them.

For testing your code here I'm using a single Neotrellis connected to a T3.2 or 4.1 and powered via usb cable from laptop. Both combinations are fussy about cable length. Keep it short.

Neotrellises will misbehave if they don't get a clean startup.
 
Thank you for that.

I have 32 Neotrellis boards soldered together in a 4x8 grid with a 5v 20 amp supply.

Im closing in to the problem.

I try the Multitrellis Adafruits example (mine has additional problems i guess)

If I load 16 boards (even thou they are all soldered together) interrupt works perfect. If I load more boards the error starts to pop up.


Im with this proyect for a time now. When I was trying an Arduino mega board, having other problems, different people told that the entire grid had too many pullup resistors, each board has 10k pullup. So I unsoldered half of them with no differnece in behaviour. Thay suggested to unsolder 3/4

Could that thing be affecting the interrupt?
 
Have you tried an external pullup resistor to +3.3v on the interrupt pin? Suggesting 2k2.

Are you using the latest SeeSaw library? Was updated a few months ago.
 
Oh, now I *really* want to see a photo!




Very difficult to know without seeing the signal on an oscilloscope.


Neotrellis.jpg


Some extra characters
 
Thank you Defragster.

@Moris526, in the Multirellis example's void setup() we have this:-
Code:
void setup() {
  Serial.begin(9600);
  //while(!Serial);

  if(!trellis.begin()){
    Serial.println("failed to begin trellis");
    while(1);
  }

  /* the array can be addressed as x,y or with the key number */
  for(int i=0; i<Y_DIM*X_DIM; i++){
      trellis.setPixelColor(i, Wheel(map(i, 0, X_DIM*Y_DIM, 0, 255))); //addressed with keynum
      trellis.show();
      delay(50);
  }
  
  for(int y=0; y<Y_DIM; y++){
    for(int x=0; x<X_DIM; x++){
      //activate rising and falling edges on all keys
      trellis.activateKey(x, y, SEESAW_KEYPAD_EDGE_RISING, true);
      trellis.activateKey(x, y, SEESAW_KEYPAD_EDGE_FALLING, true);
      trellis.registerCallback(x, y, blink);
      trellis.setPixelColor(x, y, 0x000000); //addressed with x,y
      trellis.show(); //show all LEDs
      delay(50);
    }
  }

}

You might try:-
Code:
void setup() {
  Serial.begin(9600);
  //while(!Serial);

  if(!trellis.begin()){
    Serial.println("failed to begin trellis");
    while(1);
  }

  /* the array can be addressed as x,y or with the key number */
  for(int i=0; i<Y_DIM*X_DIM; i++){
      trellis.setPixelColor(i, Wheel(map(i, 0, X_DIM*Y_DIM, 0, 255))); //addressed with keynum
      trellis.show();
      delay(50);
  }
  
  for(int y=0; y<Y_DIM; y++){
    for(int x=0; x<X_DIM; x++){
      //activate rising and falling edges on all keys
      trellis.activateKey(x, y, SEESAW_KEYPAD_EDGE_RISING, true);
      trellis.activateKey(x, y, SEESAW_KEYPAD_EDGE_FALLING, true);
      trellis.registerCallback(x, y, blink);
      trellis.setPixelColor(x, y, 0x000000); //addressed with x,y
    }
  }
  trellis.show(); //show all LEDs
  delay(50);
}

Sorted out my issue with getting the second block working, with or without using the Int pin :)
 
Responding to your duplicate thread:


Im controlling an Adafruit Neotrellis button/led board with Teensy.40

https://learn.adafruit.com/adafruit-neotrellis 2

I have a 4 x 8 boards grid soldered together.

I have an issue with the interrupt pin.

If I load only 1 board ( thou they are soldered together) it works fine. I messured the interrupt pin voltage and get

Not button pressed 3.26 v
Button pressed between 3.10 and 3.20 v and goes back to 3.26 v


If I load 32 boards and messure the interrupt pin voltage I get

Not button pressed 3.26 v
Button pressed between 2.40 and 3.13 (mostly below 2.80) and back to 3.26v


But from time to time in this case the voltage goes down to 0.80 and stays there until I press again a few time and goes back up to 3.26v

I try PULL_UP in the code with no luck...

Any Idea?

I don't know the inner working of this Adafruit product, but my understanding of that interrupt pin is any 1 of the 32 pieces can pull it low. Then when the software communicates, it can query up to 32 pieces using I2C to figure out what really happened.

So it would seem to be pretty critical for all 32 to have a unique address config on these 5 solder points.

screenshot.jpg

If 2 or more use the same address, then which one replies and gets a message to tell it to stop pulling the INT pin low could be quite unpredictable.... maybe like the problem you're seeing where it sometimes works, other times does not.

Is there any chance 2 of them are really using the same address? Maybe inspect the soldering carefully with a magnifier on all 32.

Or try running File > Examples > Wire > Scanner. If the addresses are configured properly, the Scanner example should find all 32 devices. If it finds 31 or less, that's a sure sign the address pads aren't properly configured.
 
@Moris526. Please try this tested code, based on the MultiTrellis example and let us know what the Serial Monitor is telling you.

Note that we are using the INT pin and that will need to be changed to suit the pin you are using.

Code:
/* This example shows basic usage of the
  MultiTrellis object controlling an array of
  NeoTrellis boards

  As is this example shows use of two NeoTrellis boards
  connected together with the leftmost board having the
  default I2C address of 0x2E, and the rightmost board
  having the address of 0x2F (the A0 jumper is soldered)
*/
#define INT_PIN 3 // Change this to suit the Pin# in use

#include "Adafruit_NeoTrellis.h"

#define Y_DIM 4 //number of rows of key
#define X_DIM 8 //number of columns of keys

//create a matrix of trellis panels
Adafruit_NeoTrellis t_array[Y_DIM / 4][X_DIM / 4] = {

  { Adafruit_NeoTrellis(0x2E), Adafruit_NeoTrellis(0x2F) }

};

/*
  If you were using a 2x2 array of NeoTrellis boards, the above lines would be:

  #define Y_DIM 8 //number of rows of key
  #define X_DIM 8 //number of columns of keys

  //create a matrix of trellis panels
  Adafruit_NeoTrellis t_array[Y_DIM/4][X_DIM/4] = {

  { Adafruit_NeoTrellis(0x2E), Adafruit_NeoTrellis(0x2F) },

  { Adafruit_NeoTrellis(LOWER_LEFT_I2C_ADDR), Adafruit_NeoTrellis(LOWER_RIGHT_I2C_ADDR) }

  };
*/

//pass this matrix to the multitrellis object
Adafruit_MultiTrellis trellis((Adafruit_NeoTrellis *)t_array, Y_DIM / 4, X_DIM / 4);

// Input a value 0 to 255 to get a color value.
// The colors are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if (WheelPos < 85) {
    return seesaw_NeoPixel::Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    return seesaw_NeoPixel::Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
    WheelPos -= 170;
    return seesaw_NeoPixel::Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  return 0;
}

//define a callback for key presses
TrellisCallback blink(keyEvent evt) {

  if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING) {
    trellis.setPixelColor(evt.bit.NUM, Wheel(map(evt.bit.NUM, 0, X_DIM * Y_DIM, 0, 255))); //on rising    //
    Serial.print("Trellis Key ");
    Serial.print (evt.bit.NUM);  // (evt.bit.NUM) = the the KeyNumber
    Serial.println (" Is pressed");
  }
  else if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_FALLING) {
    trellis.setPixelColor(evt.bit.NUM, 0); 
    Serial.print("Trellis Key ");
    Serial.print (evt.bit.NUM);
    Serial.println (" Is released");
  }
  trellis.show();
  return 0;
}

void setup() {
  Serial.begin(9600);
  //while(!Serial);

  if (!trellis.begin()) {
    Serial.println("failed to begin trellis");
    while (1);
  }

  /* the array can be addressed as x,y or with the key number */
  for (int i = 0; i < Y_DIM * X_DIM; i++) {
    trellis.setPixelColor(i, Wheel(map(i, 0, X_DIM * Y_DIM, 0, 255))); //addressed with keynum
    trellis.show();
    delay(50);
  }

  for (int y = 0; y < Y_DIM; y++) {
    for (int x = 0; x < X_DIM; x++) {
      //activate rising and falling edges on all keys
      trellis.activateKey(x, y, SEESAW_KEYPAD_EDGE_RISING, true);
      trellis.activateKey(x, y, SEESAW_KEYPAD_EDGE_FALLING, true);
      trellis.registerCallback(x, y, blink);
      trellis.setPixelColor(x, y, 0x000000); //addressed with x,y
      trellis.show(); //show all LEDs
      delay(50);
    }
  }
}
//********************************************************************************************

void loop() {
  if (!digitalRead(INT_PIN)) {// In this line, we are checking if a Trellis Key has been pressed.

    // If so, trellis.read() figures out which actual Key has been pressed but CANNOT tell us here
    // We need to get that info from the TrellisCallback() function. See line 63 Above.
    // It is NOT helpful to insert any code here coz we're gonna mess up the hard work that trellis.read() is trying to do.

    trellis.read(); // Here we call trellis.read() so the driver can figure out which actual Key has been pressed.
  }
  delay(2);
}
 
@Moris526 - Any progress? Did the Wire library Scanner example find all 32 addresses?

If there's any resolution to this problem, please post a followup here. As far as I know, this thread is the first time this particular Adafruit product has been discussed on this forum. Could really help others who later find this thread if you can share anything learned.
 
Thanks for the attention.

Its getting a little frustrating. Been a year with this project now. My first, with no background knowledge.


Here is more data about the project, it may ring something..



I started the project with an Arduino mega but the processor wasnt fast enough. Then I try with a RAspberry zero, but couldnt make the interrupt pin work...

When working with the Arduino Mega people told me that there were too much pullup resistors in the 32 boards combined. I should remove 3/4. I did with no change in behaviour.

(Each module has level shifters with 10k pull up resistors, plus the one from the Mega,
that's a combined pull up of ~300 ohm... )

Link to that discussion

https://forum.arduino.cc/t/large-button-led-board-multiple-scl-sda-connections/677233/2

Could the removal of the Pullups be affecting the interrupt???

Here is a schematic of the board

https://cdn-learn.adafruit.com/assets/assets/000/062/094/original/led_matrices_schem.png?1537373850



The 32 addresses are Ok. I also checked all the V G SDA SCL INT connections. They all seem fine.... Besides, The matrix works fine in every other respect but the interrupt.


I checked the interrupt pin with a volt tester with these results

With only one board loaded (thou they are all soldered together)

Not button pressed 3.26 v
Button pressed between 3.10 and 3.20 v and goes back to 3.26 v


With 32 boards loaded

Not button pressed 3.26 v
Button pressed between 2.40 and 3.13 (mostly below 2.80) and back to 3.26v

And here is the point.
When it keeps printing it goes down to 0.80 and stays there until I press again and goes back up.



Lastly, maybe dumb questio. I have the headers soldered to the teensy and the wire from the Neotrellis board connected with a socket. Should I try soldering it?
 
@Moris526. Please try this tested code, based on the MultiTrellis example and let us know what the Serial Monitor is telling you.

Note that we are using the INT pin and that will need to be changed to suit the pin you are using.

Code:
/* This example shows basic usage of the
  MultiTrellis object controlling an array of
  NeoTrellis boards

  As is this example shows use of two NeoTrellis boards
  connected together with the leftmost board having the
  default I2C address of 0x2E, and the rightmost board
  having the address of 0x2F (the A0 jumper is soldered)
*/
#define INT_PIN 3 // Change this to suit the Pin# in use

#include "Adafruit_NeoTrellis.h"

#define Y_DIM 4 //number of rows of key
#define X_DIM 8 //number of columns of keys

//create a matrix of trellis panels
Adafruit_NeoTrellis t_array[Y_DIM / 4][X_DIM / 4] = {

  { Adafruit_NeoTrellis(0x2E), Adafruit_NeoTrellis(0x2F) }

};

/*
  If you were using a 2x2 array of NeoTrellis boards, the above lines would be:

  #define Y_DIM 8 //number of rows of key
  #define X_DIM 8 //number of columns of keys

  //create a matrix of trellis panels
  Adafruit_NeoTrellis t_array[Y_DIM/4][X_DIM/4] = {

  { Adafruit_NeoTrellis(0x2E), Adafruit_NeoTrellis(0x2F) },

  { Adafruit_NeoTrellis(LOWER_LEFT_I2C_ADDR), Adafruit_NeoTrellis(LOWER_RIGHT_I2C_ADDR) }

  };
*/

//pass this matrix to the multitrellis object
Adafruit_MultiTrellis trellis((Adafruit_NeoTrellis *)t_array, Y_DIM / 4, X_DIM / 4);

// Input a value 0 to 255 to get a color value.
// The colors are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if (WheelPos < 85) {
    return seesaw_NeoPixel::Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    return seesaw_NeoPixel::Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
    WheelPos -= 170;
    return seesaw_NeoPixel::Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  return 0;
}

//define a callback for key presses
TrellisCallback blink(keyEvent evt) {

  if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING) {
    trellis.setPixelColor(evt.bit.NUM, Wheel(map(evt.bit.NUM, 0, X_DIM * Y_DIM, 0, 255))); //on rising    //
    Serial.print("Trellis Key ");
    Serial.print (evt.bit.NUM);  // (evt.bit.NUM) = the the KeyNumber
    Serial.println (" Is pressed");
  }
  else if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_FALLING) {
    trellis.setPixelColor(evt.bit.NUM, 0); 
    Serial.print("Trellis Key ");
    Serial.print (evt.bit.NUM);
    Serial.println (" Is released");
  }
  trellis.show();
  return 0;
}

void setup() {
  Serial.begin(9600);
  //while(!Serial);

  if (!trellis.begin()) {
    Serial.println("failed to begin trellis");
    while (1);
  }

  /* the array can be addressed as x,y or with the key number */
  for (int i = 0; i < Y_DIM * X_DIM; i++) {
    trellis.setPixelColor(i, Wheel(map(i, 0, X_DIM * Y_DIM, 0, 255))); //addressed with keynum
    trellis.show();
    delay(50);
  }

  for (int y = 0; y < Y_DIM; y++) {
    for (int x = 0; x < X_DIM; x++) {
      //activate rising and falling edges on all keys
      trellis.activateKey(x, y, SEESAW_KEYPAD_EDGE_RISING, true);
      trellis.activateKey(x, y, SEESAW_KEYPAD_EDGE_FALLING, true);
      trellis.registerCallback(x, y, blink);
      trellis.setPixelColor(x, y, 0x000000); //addressed with x,y
      trellis.show(); //show all LEDs
      delay(50);
    }
  }
}
//********************************************************************************************

void loop() {
  if (!digitalRead(INT_PIN)) {// In this line, we are checking if a Trellis Key has been pressed.

    // If so, trellis.read() figures out which actual Key has been pressed but CANNOT tell us here
    // We need to get that info from the TrellisCallback() function. See line 63 Above.
    // It is NOT helpful to insert any code here coz we're gonna mess up the hard work that trellis.read() is trying to do.

    trellis.read(); // Here we call trellis.read() so the driver can figure out which actual Key has been pressed.
  }
  delay(2);
}


The behavior is erratic. But with less boards activated less often the issue.
I just activated 2 boards, tested for a while with no problem
 
Please click File > Examples > Wire > Scanner. Upload to Teensy, then open the serial monitor to view the results.

Feel free to copy & paste it here, or share a screenshot, if you're unsure whether the result looks good.

This test is so incredibly easy... just upload a program and copy whatever it prints from the serial monitor to your next reply. You've spent so much time and trouble on the interrupt pin and voltages, the least you can do is run this very easy test which might shine some light on the problem, or it might only rule out the I2C addresses. But either way, it's just an already-written program, one quick upload, and a copy-paste. Easy, right?


Lastly, maybe dumb questio. I have the headers soldered to the teensy and the wire from the Neotrellis board connected with a socket. Should I try soldering it?

Very difficult to advise when we can't see. Maybe shoot some photos?
 
Sorry, Paul.. sometimes you should really read the questions (and other posts) with more thought



(Each module has level shifters with 10k pull up resistors, plus the one from the Mega,
that's a combined pull up of ~300 ohm... )
[...]
The matrix works fine in every other respect but the interrupt.
[...]
I checked the interrupt pin with a volt tester with these results

With only one board loaded (thou they are all soldered together)

Not button pressed 3.26 v
Button pressed between 3.10 and 3.20 v and goes back to 3.26 v

[...]

There is no I2C problem here. It's just the pullup-resistance, I think.

Moris526, if you test the int pin of one board only - disconnect the other 31 int pins - what are the voltages, then? (pressed/not pressed)
Does your program work then?

Perhaps the 11mA it has to pull down are just a little to much for the poor ATSAMD
 
Last edited:
@Frank - Is there really any solid confirmation all 32 boards really are responding to their own unique address? Did I miss that info on this thread?

I could be completely wrong, but my hunch is this might at least partially be a race condition between nearly identical boards which the same I2C address.

Yeah, I know everyone wants to talk of voltages and combined pullup impedance. But what is the harm in just quickly running the Wire library Scanner, just to confirm all 32 addresses really are correct? It's so easy, just literally a dozen mouse clicks - no soldering, no test equipment.
 
"The matrix works fine in every other respect but the interrupt. " tells me that it works?

And, in the first post: "All works fine with the Adafruit example but the interrupt function ( it works fine with an arduino uno board)"
 
Last edited:
Back
Top