DaisyDuino and Adafruit Trellis does not work together

Hi

I have been struggling to get my Trellis boards to work correctly with an oscillator. Basically I am making a soundboard that plays an oscillator frequency depending on button press on the Trellis.

The Trellis code works great without the oscillator, but as soon as I use any daisy code like DAISY.begin or DAISY.init, nothing works. The oscillator does not play and the Trellis boards are completely dead.

Here is the code that I strongly believe should work, but does not:

#include <DaisyDuino.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Trellis.h>

Adafruit_Trellis matrix0 = Adafruit_Trellis();
Adafruit_Trellis matrix1 = Adafruit_Trellis();
Adafruit_TrellisSet trellis =  Adafruit_TrellisSet(&matrix0, &matrix1);

constexpr int8_t numTrellis = 2;
constexpr int8_t numKeys = (numTrellis * 16);

constexpr uint8_t intPin = A6;

bool trellisKeysPressed[16] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false };

float pitchknob = 0.1;

static DaisyHardware hw;

size_t num_channels;
float sample_rate;
  
static Oscillator osc;

void setupOscillator(){
  // Initialize for Daisy seed at 48kHz
  hw = DAISY.init(DAISY_SEED, AUDIO_SR_48K);
  num_channels = hw.num_channels;
 // num_channels = 2;
  sample_rate = DAISY.get_samplerate();
  //sample_rate = 48;

  osc.Init(sample_rate);
  osc.SetFreq(440);
  osc.SetAmp(0.5);
  osc.SetWaveform(osc.WAVE_TRI);

  DAISY.begin(AudioCallback);
}

void setup() {
  Serial.begin(9600);

  pinMode(intPin, INPUT);
  digitalWrite(intPin, HIGH);
  trellis.begin(0x71, 0x72);
  setupOscillator();
  showTrellisStartSequence();
}

void loop() {
  readTrellis();
  delay(30);
  checkInput();
  delay(30);
}

void readTrellis() {
  if (trellis.readSwitches()) {
    // go through every button
    for (int8_t i = 0; i < numKeys; i++) {
      if (trellis.justPressed(i)) {
        trellisKeysPressed[i] = true;
        trellis.setLED(i);
        trellis.writeDisplay();
      }
      if (trellis.justReleased(i)) {
        trellisKeysPressed[i] = false;
        trellis.clrLED(i);
        trellis.writeDisplay();
      }
    }
  }
}

void checkInput() {
  for (int8_t i = 0; i < numKeys; i++) {
    // if it was pressed...
    if (trellisKeysPressed[i] == true) {
      pitchknob = 24.0 + (i) * 7;
    }
    else if (trellisKeysPressed[i] == false) {
      pitchknob = 0.1;
    }
  }
}

void showTrellisStartSequence() {
  for (int8_t i = 0; i < numKeys; i++) {
    trellis.setLED(i);
    trellis.writeDisplay();
    delay(50);
  }
  for (int8_t i = 0; i < numKeys; i++) {
    trellis.clrLED(i);
    trellis.writeDisplay();
    delay(50);
  }
}

void AudioCallback(float **in, float **out, size_t size){
  // Convert Pitchknob MIDI Note Number to frequency
    osc.SetFreq(mtof(pitchknob));
  for (size_t i = 0; i < size; i++) {
    float sig = osc.Process();

      
    for (size_t chn = 0; chn < num_channels; chn++) {
      out[chn][i] = sig;
    }
  }
}

What dev environment are you using? I had similar problems using NeoTrellis which were resolved by changing optimization levels. Might be worth taking a look: Code runs in Arduino IDE but not Platformio - #2 by duncan

Hm this does not seem to be my issues as I sketched this up in the Arduino IDE. I have not had the best of luck with PlatformIO myself :grimacing:

One interesting thing is that it compiles with no errors, but nothing works until I tag out either the oscillator or the trellis boards. Both work no problem independently.

Hi Exetic, do you have the most recent version of DaisyDuino installed?

The most recent version v1.5.1 resolved an issue specifically related to using the Wire library (and devices that use it) in conjunction with the DaisyDuino audio components.

Yes I have v1.5.1, but when I first started this project I was on 1.4. Do I need to manually upgrade the project to 1.5.1 or does it do that automatically when upgrading the library? If so, the library is still causing issues.

Hmm, it should be globally updated for anything using the Arduino IDE.

We’ll look into it, and see if we can recreate the issue here (we have some of these trellis boards we can plug into a daisy).

Thank you, I very much appreciate it!

  1. I thought I had a trellis board. Turns out I have a Neotrellis, which I wasn’t able to get working with your code, but I was able to get working with the seesaw library.
  2. I made a little example which just mashes up the seesaw neotrellis basic example with your audio code. The neotrellis still works in this example, but the audio just makes real high pitched sound based on whether you’re pressing a button or not.
  3. We patched a similar bug in 1.5.1 which is why we were hoping it would fix your issue.

So, based on all that I’m thinking it’s a similar thing to 1.5.1 where the neotrellis and the daisy’s codec are competing for the same i2c resource. That’s either the same I2C peripheral, or the same Wire instance or something like that.

That being said, you may have some luck from the arduino side of things if you change the Wire instance, or the I2C peripheral being used for the trellis from the default one. Not sure exactly how to do that but if you look over the neotrellis API it’s certainly there.

Other than that you might poke around in both DaisyDuino and the trellis library and try to work out exactly where it happens. For instance, exactly which function from DaisyDuino makes it break? Is it DAISY.Init, or DAISY.begin? Maybe it’s one of them, or both, or either.

Here’s the broken Neotrellis code I cooked up. We’ll revisit this one soon when we have some more time!
Let me know if you learn anything else. :slight_smile:

/* This example shows basic usage of the NeoTrellis.
  The buttons will light up various colors when pressed.
  The interrupt pin is not used in this example.
*/

#include <DaisyDuino.h>
#include "Adafruit_NeoTrellis.h"

Adafruit_NeoTrellis trellis;

static DaisyHardware hw;

size_t num_channels;
float sample_rate;
  
static Oscillator osc;
float pitchknob = 0.1;

//define a callback for key presses
TrellisCallback blink(keyEvent evt){
  // Check is the pad pressed?
  if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING) 
  {
    pitchknob = 24.0 + evt.bit.EDGE * 7;
    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) 
  {
    // or is the pad released?
    trellis.pixels.setPixelColor(evt.bit.NUM, 0); //off falling
    pitchknob = 0;
  }

  // Turn on/off the neopixels!
  trellis.pixels.show();

  return 0;
}

void setupOscillator(){
  // Initialize for Daisy seed at 48kHz
  hw = DAISY.init(DAISY_SEED, AUDIO_SR_48K);
  num_channels = hw.num_channels;
  num_channels = 2;
  sample_rate = DAISY.get_samplerate();
  sample_rate = 48;

  osc.Init(sample_rate);
  osc.SetFreq(440);
  osc.SetAmp(0.5);
  osc.SetWaveform(osc.WAVE_TRI);

  DAISY.begin(AudioCallback);
}

void setup() {
  Serial.begin(9600);
  // while(!Serial) delay(1);
  
  if (!trellis.begin()) {
    Serial.println("Could not start trellis, check wiring?");
    while(1) delay(1);
  } else {
    Serial.println("NeoPixel 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);
  }

  setupOscillator();

  //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() {
  trellis.read();  // interrupt management does all the work! :)
  
  delay(20); //the trellis has a resolution of around 60hz
}

void AudioCallback(float **in, float **out, size_t size){
  // Convert Pitchknob MIDI Note Number to frequency
    osc.SetFreq(mtof(pitchknob));
  for (size_t i = 0; i < size; i++) {
    float sig = osc.Process();

      
    for (size_t chn = 0; chn < num_channels; chn++) {
      out[chn][i] = sig;
    }
  }
}

/******************************************/

// 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);
  }
  return 0;
}

So I’ve fixed some errors in the test code and it works now with the neotrellis.
Important: For some reason arduino code often doesn’t work until you press the reset button after flashing. Make sure you do that!

The mistakes that apply to your code are:

  • pitchknob = 24 + i * 7. I’d just do pitchknob = 36 + i

The mistakes that only apply to my code are:

  • Using EDGE rather than NUM to set the note.
  • Overriding sample_rate to 48. This should be 48000 aka 48khz.
  • Overriding the number of channels. I’d let this and the sample_rate get set by the library.
  • You had the previous two items commented out in the snippet you posted. I’d leave them that way.

Let me know if the changes I suggested work for you. Otherwise there’s still a chance it’s something to do with the libraries and I2C.

Here’s my updated working test code

/* This example shows basic usage of the NeoTrellis.
  The buttons will light up various colors when pressed.
  The interrupt pin is not used in this example.
*/

#include <DaisyDuino.h>
#include "Adafruit_NeoTrellis.h"

Adafruit_NeoTrellis trellis;

static DaisyHardware hw;

size_t num_channels;
float sample_rate;
  
static Oscillator osc;
int pitchknob = 1;

//define a callback for key presses
TrellisCallback blink(keyEvent evt){
  // Check is the pad pressed?
  if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING) 
  {
    pitchknob = 36.0 + evt.bit.NUM;
    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) 
  {
    // or is the pad released?
    trellis.pixels.setPixelColor(evt.bit.NUM, 0); //off falling
    pitchknob = 0;
  }

  // Turn on/off the neopixels!
  trellis.pixels.show();

  return 0;
}

void setupOscillator(){
  // Initialize for Daisy seed at 48kHz
  hw = DAISY.init(DAISY_SEED, AUDIO_SR_48K);
  num_channels = hw.num_channels;
  sample_rate = DAISY.get_samplerate();

  osc.Init(sample_rate);
  osc.SetFreq(440);
  osc.SetAmp(0.5);
  osc.SetWaveform(osc.WAVE_TRI);

  DAISY.begin(AudioCallback);
}

void setup() {
  Serial.begin(9600);
  // while(!Serial) delay(1);
  
  if (!trellis.begin()) {
    Serial.println("Could not start trellis, check wiring?");
    while(1) delay(1);
  } else {
    Serial.println("NeoPixel 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);
  }

  setupOscillator();

  //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() {
  trellis.read();  // interrupt management does all the work! :)
  
  delay(20); //the trellis has a resolution of around 60hz
}

void AudioCallback(float **in, float **out, size_t size){
  // Convert Pitchknob MIDI Note Number to frequency
    osc.SetFreq(mtof(pitchknob));
  for (size_t i = 0; i < size; i++) {
    float sig = osc.Process();

      
    for (size_t chn = 0; chn < num_channels; chn++) {
      out[chn][i] = sig;
    }
  }
}

/******************************************/

// 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);
  }
  return 0;
}
1 Like

Okay I tried doing this and this actually seems to do the trick, what in the world. This was an unexpected solution!

Thank you very much for the help! I was getting quite frustrated I must admit :grin:

Edit: Maybe you can help me understand why I am not getting stereo sound? The reason I did overwrite the channels were to try and debug this issue. It is not a wiring issue, could potentially be a board or soldering issue, although I did try to resolder both audio pins multiple times just to be sure.