Hi friends. Sorry in advance for the long post...
For several weeks now, I’ve been attempting to implement a program on the Teensy 4.0 which is a development of code that was previously working fine on the T3.2. The program is the “OHMs” or “Open Horn Music System”, which uses the Audio adapter, and is much too large to usefully share in this forum. So I’ve shared the full code on github https://github.com/KontinuumLab/newOHMs/tree/main/newOHMs_nov22_024_exp , and put just the main .ino file here below. This code is not complete, or in any way functional as an instrument, but I’m unable to keep developing it until I solve this more immediate problem.
I’m using Arduino 1.8.19 and Teensy loader 1.57, on Ubuntu 18.04.5
When I run this code, I get the first few Serial messages, up until “After ‘readMpTouch’”, plus the first text on the OLED, and then the Teensy 4.0 resets, giving the same output again after a pause. The whole cycle takes about 10 seconds.
Screenshot:
I’m assuming that the problem is one of two things. Either electrical issues, or problems in my code.
I considered that all the external components might be overloading the 3.3v output of the Teensy, but some research seems to indicate that this isn’t the case. Here are the main current consumption candidates:
Given that the Teensy 3.3v can provide 250ma, the power consumption of external components doesn’t appear to be the problem.
For normal operation of the instrument I run the Teensy off of a 1s lipo connected to Vin. (USB and Vin have been separated at the pads of course) The battery is connected through an Adafruit Lipo backpack, which is powered from the USB pin on the Teensy for charging I’ve checked the voltage at the Teensy Vin pin, which is at 4.15v, so that should work. But just in case, I’ve also tried supplying a stable 5v directly to Vin to bypass the whole battery/backpack setup, which doesn’t solve the problem.
The audio adapter works. I’ve added a line out jack, and when running the “PlaySynthMusic” example I get good outputs on both headphone and line out.
The Teensy is soldered straight to the audio adapter with extra long pins. And under that, an improvised breakout board is soldered straight to those same pins. The whole setup has to fit in a small space inside the instrument, and the final version will have an actual pcb instead of the home-grown breakout (if I ever get it to work…)
I’ve tested all the sensors and outputs separately, and they all work, although some tests revealed similar “spontaneous reset” problems.
For example: While running the code below, which just tests the two MPR121 capacitive sensors, the Serial output freezes at about 2000 ms in, and then picks up again after a couple of seconds, clearing the Serial monitor as shown in the screenshots. So it’s not a complete cyclical reset as in the actual “OHMs” code, but still similar symptoms.
I’m including a couple of photos of my setup, although given the ratsnest that it is, I don’t know how useful it will be. However, as I’m able to get all the sensors, audio and display to work separately (except for the "reset problems"), my conclusion is that there are no shorts or other such problems. The pins used for each component can be seen in the first part of the .ino file. I’ve taken care not to use the pins that are reserved for audio adapter functionality.
So that leaves me with a possible code problem, which I’ve not been able to find.
Of course I've googled a lot, mostly ending up right here on the forum, but haven't been able to find the solution
I realize this is quite a mouthful, and that maybe there are too many variables at play here for anyone to be able to untangle the problem. Even so, I thought I’d give it a shot, sharing as much info as possible.
Thanks in advance for any info, advice, or even just good questions that might set me on the right track.
Jeppe
For several weeks now, I’ve been attempting to implement a program on the Teensy 4.0 which is a development of code that was previously working fine on the T3.2. The program is the “OHMs” or “Open Horn Music System”, which uses the Audio adapter, and is much too large to usefully share in this forum. So I’ve shared the full code on github https://github.com/KontinuumLab/newOHMs/tree/main/newOHMs_nov22_024_exp , and put just the main .ino file here below. This code is not complete, or in any way functional as an instrument, but I’m unable to keep developing it until I solve this more immediate problem.
Code:
//#####################################################
//#####################################################
// New Open Horn Midi system / "New OHMs"
// Teensy 3.2 - Main Code v1.00
// Copyright 2022, Jeppe Tofthøj Rasmussen
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#include "Adafruit_MPR121.h"
Adafruit_MPR121 capA = Adafruit_MPR121();
Adafruit_MPR121 capB = Adafruit_MPR121();
uint16_t MPRbinaryA = 0;
uint16_t MPRbinaryB = 0;
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
//#include <SD.h>
//#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioSynthWavetable wavetable1; //xy=178.56666564941406,463.99998474121094
AudioSynthWavetable wavetable2; //xy=197.56666564941406,504.99998474121094
AudioSynthWavetable wavetable3; //xy=200.56666564941406,546.9999847412109
AudioSynthWavetable wavetable4; //xy=211.56666564941406,586.9999847412109
AudioMixer4 voice; //xy=362.56666564941406,523.9999847412109
AudioFilterStateVariable filter1; //xy=483.56666564941406,574.9999847412109
AudioFilterStateVariable filter2; //xy=609.5666656494141,625.9999847412109
AudioFilterStateVariable filter3; //xy=725.5666656494141,687.9999847412109
AudioMixer4 filter_mix; //xy=829.5666656494141,563.9999847412109
AudioEffectBitcrusher bitcrusher1; //xy=965.5666656494141,623.9999847412109
AudioMixer4 distortion_mix; //xy=1128.566665649414,549.9999847412109
AudioEffectFreeverb freeverb1; //xy=1286.566650390625,588
AudioMixer4 reverb_mix; //xy=1459.566665649414,582.9999847412109
AudioEffectDelay delay1; //xy=1633,806
AudioMixer4 delay_feedback_mix; //xy=1648,649
AudioMixer4 delay_mix; //xy=1862,602
AudioOutputI2S i2s1; //xy=2034.566650390625,601
AudioConnection patchCord1(wavetable1, 0, voice, 0);
AudioConnection patchCord2(wavetable2, 0, voice, 1);
AudioConnection patchCord3(wavetable3, 0, voice, 2);
AudioConnection patchCord4(wavetable4, 0, voice, 3);
AudioConnection patchCord5(voice, 0, filter1, 0);
AudioConnection patchCord6(voice, 0, filter_mix, 0);
AudioConnection patchCord7(filter1, 0, filter_mix, 1);
AudioConnection patchCord8(filter1, 0, filter2, 0);
AudioConnection patchCord9(filter2, 0, filter_mix, 2);
AudioConnection patchCord10(filter2, 0, filter3, 0);
AudioConnection patchCord11(filter3, 0, filter_mix, 3);
AudioConnection patchCord12(filter_mix, 0, distortion_mix, 0);
AudioConnection patchCord13(filter_mix, bitcrusher1);
AudioConnection patchCord14(bitcrusher1, 0, distortion_mix, 1);
AudioConnection patchCord15(distortion_mix, freeverb1);
AudioConnection patchCord16(distortion_mix, 0, reverb_mix, 0);
AudioConnection patchCord17(freeverb1, 0, reverb_mix, 1);
AudioConnection patchCord18(reverb_mix, 0, delay_feedback_mix, 0);
AudioConnection patchCord19(reverb_mix, 0, delay_mix, 0);
AudioConnection patchCord20(delay1, 0, delay_feedback_mix, 1);
AudioConnection patchCord21(delay_feedback_mix, delay1);
AudioConnection patchCord22(delay_feedback_mix, 0, delay_mix, 1);
AudioConnection patchCord23(delay_mix, 0, i2s1, 0);
AudioConnection patchCord24(delay_mix, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=2043.566650390625,504
// GUItool: end automatically generated code
#define LOGO16_GLCD_WIDTH 16
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000
};
#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
unsigned long displayTimer = 0;
unsigned long lastDisplay = 0;
//-------------------------------------------------------
// -------------------- PINS: ---------------------------
//-------------------------------------------------------
// touchRead() pins:
const int octavePin1 = 0;
const int octavePin2 = 16;
const int octavePin3 = 17;
const int mpTouchPin = 11;
//const int mpTouchPin2 = 33;
//
//// Multiplexer pins:
//const int muxPin1 = 5;
//const int muxPin2 = 4;
//const int muxPin3 = 3;
//const int muxPin4 = 2;
//const int mux1SensorPin = 1;
// Encoder pins:
const int encButtonPin = 9;
const int encPin1 = 4;
const int encPin2 = 5;
// BreathPin:
const int breathPin = 14;
// Pitchbend pins:
const int pitchbendPin1 = 22;
const int pitchbendPin2 = 17;
const int switchPin1 = 2;
const int switchPin2 = 3;
const int knob1Pin = 15;
const int knob2Pin = 16;
//-------------------------------------------------------
// ------------------ VARIABLES: ------------------------
//-------------------------------------------------------
//Keys / notes:
int keyTouchVal[15];
int octTouchVal[4];
bool keysPressed[15];
bool octPressed[4];
uint16_t keyThreshold[15];
uint16_t octThreshold[4];
bool newNote;
bool correct;
byte baseNote;
byte currentNote;
byte lastNote;
int octave = 0;
int lastOctave = 0;
//"Must be pressed", "0", "Must be open", "0", "Special funct"([< 12]), "Note"([12])
// byte note1[] = {6, 14, 0, 7, 9, 10, 0, 0, 0, 0, 0, 0, 63};
static byte ActiveFingSet[20][13];
// Factory Fingering Set:
static byte fingerings[20][13] = {
// {0, 8, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 63}, // High Eb
// {0, 100, 8, 100, 0, 0, 0, 0, 0, 0, 0, 0, 62}, // High D
{100, 1, 3, 100, 0, 0, 0, 0, 0, 0, 0, 0, 61}, // C#
{3, 100, 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 60}, // C
{1, 100, 2, 3, 100, 0, 0, 0, 0, 0, 0, 0, 59}, // B
{1, 2, 100, 3, 100, 0, 0, 0, 0, 0, 0, 0, 58}, // Extra Bb
{1, 3, 7, 100, 4, 100, 0, 0, 0, 0, 0, 0, 58}, // Side Bb
{1, 3, 100, 4, 7, 100, 0, 0, 0, 0, 0, 0, 57}, // A
{1, 3, 4, 5, 100, 9, 10, 100, 0, 0, 0, 0, 56}, // Ab
{1, 3, 4, 100, 5, 9, 10, 100, 0, 0, 0, 0, 55}, // G
{1, 3, 4, 10, 100, 9, 100, 0, 0, 0, 0, 0, 54}, // F#
{1, 3, 4, 9, 100, 10, 100, 0, 0, 0, 0, 0, 53}, // F
{1, 3, 4, 9, 10, 100, 11, 100, 0, 0, 0, 0, 52}, // E
{1, 3, 4, 9, 10, 11, 12, 100, 13, 100, 0, 0, 51}, // Eb
{1, 3, 4, 9, 10, 11, 100, 6, 12, 13, 100, 0, 50}, // D
{1, 3, 4, 5, 9, 10, 11, 13, 100, 6, 100, 0, 49}, // C#
{1, 3, 4, 9, 10, 11, 13, 100, 5, 6, 100, 0, 48}, // C
{1, 3, 4, 6, 9, 10, 11, 100, 12, 13, 100, 0, 47}, // B
{1, 3, 4, 6, 9, 10, 11, 13, 100, 100, 0, 0, 46}, // Bb
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
// biphonic modes:
const int biphonicModeKeys[2] = {0, 8};
bool splitActive = 0;
bool lastSplitActive = 0;
byte currentSplitHighNote;
byte duplicateSplitHighNote;
byte currentSplitLowNote;
byte lastSplitHighNote;
byte lastSplitLowNote;
byte currentSplitNote;
byte lastSplitNote;
byte splitHighPressed;
byte splitLowPressed;
bool newHighNote = 0;
bool newLowNote = 0;
byte currentSustainNote;
byte lastSustainNote;
bool sustainActive = 0;
bool lastSustainActive = 0;
byte sustainInterval;
byte currentIntervalNote;
bool intervalActive = 0;
bool lastIntervalActive = 0;
//Encoder:
long encDir;
bool currentEncButton = 0;
bool encBtnPressed;
bool encBtnReleased;
int encCounter;
int lastEncCounter;
int encVal1 = 0;
int encVal2 = 0;
int encLastVal1 = 0;
int encLastVal2 = 0;
int encButtonVal = 0;
int encButtonLastVal = 0;
bool newValueBool = 0;
bool pin1Flag;
bool pin2Flag;
int reading;
long unsigned extEncTimer;
//Breath:
int breath;
int lastBreath;
int breathRaw;
int lastBreathRaw;
uint16_t breathMin;
uint16_t breathMax;
// Pitchbend
int pitchbend;
int lastPitchbend;
int pitchbendVal1;
int pitchbendVal2;
int lastPitchbendVal1;
int lastPitchbendVal2;
int pitchbendVal1Raw;
int pitchbendVal2Raw;
int lastPitchbendVal1Raw;
int lastPitchbendVal2Raw;
int16_t pitchbendVal1Min;
int16_t pitchbendVal2Min;
int16_t pitchbendVal1Max;
int16_t pitchbendVal2Max;
//mpTouchSensors:
int mpTouchVal;
int lastmpTouchVal;
int mpTouchVal2;
int lastMpTouchVal2;
int mpTouchValRaw;
int lastmpTouchValRaw;
int mpTouchVal2Raw;
int lastMpTouchVal2Raw;
uint16_t mpTouchValMin;
uint16_t mpTouchValMax;
uint16_t mpTouchVal2Min;
uint16_t mpTouchVal2Max;
int mode = 0; // 0 = play / 1 = menu
int lastMode;
int16_t calibrateState;
int16_t midiChannel1 = 1; //done
int16_t midiChannel2 = 2; //done
int16_t transpose = 0; //done
int16_t splitOctave = 0; //done
int16_t detune = 0; // Not done yet
int16_t midiOutputOn = 0; //done
int16_t audioOutputOn = 1; //done
int16_t breathCC = 2; //done
int16_t extraBreathCC = 0; //done
int16_t lipCC = 112; //done
int16_t pitchbendLowRes = 1; //done
int16_t pitchbendHighRes = 0; //done
int16_t activeInstrument = 0; //done
int16_t filterLayers = 2; //done
int16_t filterFreqMin = 0; //done
int16_t filterFreqMax = 10000;//done
int16_t filterResonance = 0; //done
int16_t vibratoSpeed; // Haven't even started
int16_t extraFilter; //done (bitcrusher)
int16_t pitchbendRange = 2; //done
int16_t pitchbendVal1Curve; //done
int16_t pitchbendVal2Curve; //done
int16_t reverbRoomSize = 2; //done
int16_t reverbDamping = 2; //done
int16_t reverbMix; //done
//
int16_t breathCurve; //done
int16_t mpTouchValCurve; //done
int16_t mpTouchVal2Curve; //done
int16_t keySensitivity; //done (uses "keyThreshold at calibration)
int16_t keyResponsiveness; // Like a "debounce" but for the capacitive keys
// encoderMode:
int16_t encoderInstr = 1; //done
int16_t encoderVol = 0; //done
int16_t encoderNone = 0; //done
int16_t audioVolume = 5;
float tempVol; // INCLUDE AS MENU OPTION
int16_t breathSpeed; //done
int16_t pitchbendSpeed; //done
int16_t lipSpeed; //done
int16_t bitcrusherBits = 16; //done
//>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//>>>>>>>>>>>>>>>>>>>>>>>>> NEW: <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int knob1ValRaw;
int lastKnob1ValRaw;
int knob2ValRaw;
int lastKnob2ValRaw;
int16_t switch1DelayRec;
int16_t switch1Reverb;
int16_t switch1SecondaryFilter;
int16_t switch2DelayType;
int16_t switch2Reverb;
int16_t switch2LipFilter;
uint16_t knob1ValMin;
uint16_t knob1ValMax;
uint16_t knob2ValMin;
uint16_t knob2ValMax;
uint16_t knob1Curve;
uint16_t knob1Speed;
uint16_t knob2Curve;
uint16_t knob2Speed;
uint16_t delayTime;
uint16_t delayFeedback;
uint16_t delayMix;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
long unsigned menuBtnTimer;
// Audio variables;
int midiOn;
float Fpitchbend;
float floatBreath;
int Wind1CurrentWavetable;
float Wind1currentWavetableFreq;
int Wind2CurrentWavetable;
float Wind2currentWavetableFreq;
const float DIV127 = (1.0 / 127.0);
const float DIV64 = (1.0 / 64.0);
// Woodwind:
#include "altosax_samples.h"
#include "clarinet_samples.h"
#include "oboe_samples.h"
// Flutes:
//#include "flute_samples.h"
#include "ocarina_samples.h"
#include "panflute_samples.h"
// Brass:
#include "brass_samples.h"
#include "trumpet_samples.h"
#include "mutedtrumpet_samples.h"
#include "trombone_samples.h"
// Other reed instruments:
#include "accordian_samples.h"
//#include "harmonica_samples.h"
//#include "organ_samples.h"
#include "eorgan_samples.h"
// Waveforms:
#include "squarewave_samples.h"
#include "sawStack_samples.h"
#include "InstrSelectFunctions.h"
#include "Memory.h"
#include "MiscFunctions.h"
#include "Calibration.h"
#include "Keys.h"
#include "Mouthpiece.h"
#include "SynthFunctions.h"
#include "MenuContent.h"
#include "MenuFunctions.h"
void setup() {
Serial.begin(115200);
// pinMode(muxPin1, OUTPUT);
// pinMode(muxPin2, OUTPUT);
// pinMode(muxPin3, OUTPUT);
// pinMode(muxPin4, OUTPUT);
pinMode(encPin1, INPUT_PULLUP);
pinMode(encPin2, INPUT_PULLUP);
pinMode(encButtonPin, INPUT_PULLUP);
pinMode(switchPin1, INPUT_PULLUP);
pinMode(switchPin2, INPUT_PULLUP);
// INTERRUPT HANDLING:
attachInterrupt(encPin1, isrEncPin1, CHANGE); // set an interrupt on PinA, looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below)
attachInterrupt(encPin2, isrEncPin2, CHANGE); // set an interrupt on PinB, looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below)
// Set analog sensor resolution (0-4095)
// analogReadResolution(12);
if (!capA.begin(0x5A)) {
Serial.println("MPR121 on 0x5A NOT found");
}
else {
Serial.println("MPR121 on 0x5A active");
// activeMPR121[0] = 1;
}
if (!capB.begin(0x5B)) {
Serial.println("MPR121 on 0x5B NOT found");
}
else {
Serial.println("MPR121 on 0x5B active");
// activeMPR121[1] = 1;
}
// MPR121 setup:
capA.writeRegister(0x2E, 0b11111111);
capA.writeRegister(0x32, 0b11111111);
capA.writeRegister(0x35, 0b11111111);
capA.setThresholds(20, 16);
capB.writeRegister(0x2E, 0b11111111);
capB.writeRegister(0x32, 0b11111111);
capB.writeRegister(0x35, 0b11111111);
capB.setThresholds(20, 16);
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(18);
// turn on the output
sgtl5000_1.enable();
wavetable1.setInstrument(altosax);
wavetable2.setInstrument(altosax);
wavetable3.setInstrument(altosax);
wavetable4.setInstrument(altosax);
WindWavetableAmplitude(1.0);
Wind1CurrentWavetable = 1;
Wind2CurrentWavetable = 3;
bitcrusher1.bits(16);
bitcrusher1.sampleRate(44100);
distortion_mix.gain(0, 1.0);
distortion_mix.gain(1, 0.0);
loadSettings(1); // fix memory.h ???
audioVolume = 5; // Always start on volume = 0.5
tempVol = float(audioVolume) / 10;
sgtl5000_1.volume(tempVol);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x64)
delay(500);
display.clearDisplay();
display.display();
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);
display.setCursor(20, 10);
display.print("Loading settings");
display.display();
Serial.println("Loading settings");
// delay(500);
display.clearDisplay();
display.display();
// Serial.println("hello!");
// filter1.frequency(7000);
}
void loop() {
// Serial.println("hello!");
// Read encoder - calibration
// - Press encButton to start mouthpiece calibration
// - Release button to go to key calibration
// - Press again to save settings.
lastMode = mode;
encRead();
Serial.println(encBtnPressed);
if(mode == 0){
if(encBtnPressed == 1){
encBtnPressed = 0;
menuBtnTimer = millis();
while(encBtnReleased != 1){
encRead();
if(millis() - menuBtnTimer > 500){
mode = 1;
menu = 0;
menuItem = 1;
displayBasicMenuPage(mainMenu, mainMenuSize);
// display.setTextSize(1);
// display.setTextColor(WHITE, BLACK);
// display.setCursor(30, 13);
// display.print("Opening menu");
// display.display();
}
}
encBtnReleased = 0;
}
}
Serial.println("After 'mode=0'");
if(mode == 1){
if(encBtnPressed == 1){
encBtnPressed = 0;
menuBtnTimer = millis();
while(encBtnReleased != 1){
encRead();
if(millis() - menuBtnTimer > 500){
mode = 0;
menu = 0;
menuItem = 1;
display.clearDisplay();
display.display();
}
}
}
}
// if(encBtnPressed == 1){
// prepareCalibration();
//
// while(encBtnReleased != 1){
// mpCalibration();
// encRead();
// }
// display.clearDisplay();
// display.display();
// while(encBtnPressed == 0){
// keysCalibration();
// encRead();
// }
// saveSettings();
// display.clearDisplay();
// display.display();
// display.setTextSize(1);
// display.setTextColor(WHITE, BLACK);
// display.setCursor(3, 8);
// display.print("saving settings");
// display.display();
// delay(1500);
// display.clearDisplay();
// display.display();
// }
// if(lastEncCounter != encCounter){
// instrSelection();
// }
// lastEncCounter = encCounter;
// lastBreath = breath;
readBreath();
readKeys();
readPitchbend();
readMpTouch();
Serial.println("After 'readMpTouch'");
// int lastMidiOn = midiOn;
// midiOn = digitalRead(switchPin);
// if(lastMidiOn != midiOn){
// display.clearDisplay();
// display.display();
// display.setTextSize(1);
// display.setTextColor(WHITE, BLACK);
// display.setCursor(22, 8);
// if(midiOn == 1){
// display.print("MIDI output on");
// }
// else{
// display.print("AUDIO output on");
// }
// display.display();
// delay(1500);
// display.clearDisplay();
// display.display();
// }
//
//
// if(midiOn == 1){
// midiOutput();
// }
// lastMode = mode;
// mode = digitalRead(switchPin);
if (mode == 1) {
updateMenu();
Serial.println("After 'updateMenu'");
}
else {
// Set volume or instrument on encoder wheel input:
if(extEncTimer != 0){
if(millis() - extEncTimer >= 1000){
display.clearDisplay();
display.display();
extEncTimer = 0;
}
}
if(encDir != 0){
extEncTimer = millis();
if(encoderVol == 1){ // if encoder mode set to "volume":
audioVolume = audioVolume + encDir;
audioVolume = constrain(audioVolume, 0, 10);
tempVol = float(audioVolume) / 10;
sgtl5000_1.volume(tempVol);
display.clearDisplay();
display.display();
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);
display.setCursor(20, 10);
display.print("Audio Volume: ");
display.print(audioVolume);
display.display();
}
else if(encoderInstr == 1){ // if encoder mode set to "instrument":
activeInstrument = activeInstrument + encDir;
activeInstrument = constrain(activeInstrument, 0, 12);
instrSelection();
display.clearDisplay();
display.display();
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);
display.setCursor(20, 10);
display.print("Active Instrument: ");
display.setCursor(20, 19);
display.print(setInstrumentMenu[activeInstrument + 2]);
display.display();
}
encDir = 0;
}
if (midiOutputOn == 1) {
midiOutput();
}
if (audioOutputOn == 1) {
audioOutput();
}
}
Serial.println("End of loop");
}
void audioOutput() {
//---------------------------------------------
//----------Filter adjustments: ----------------
//---------------------------------------------
if(filterLayers == 0){
filter_mix.gain(0, 1.0);
filter_mix.gain(1, 0.0);
filter_mix.gain(2, 0.0);
filter_mix.gain(3, 0.0);
}
else if(filterLayers == 1){
filter_mix.gain(0, 0.0);
filter_mix.gain(1, 1.0);
filter_mix.gain(2, 0.0);
filter_mix.gain(3, 0.0);
}
else if(filterLayers == 2){
filter_mix.gain(0, 0.0);
filter_mix.gain(1, 0.0);
filter_mix.gain(2, 1.0);
filter_mix.gain(3, 0.0);
}
else if(filterLayers == 3){
filter_mix.gain(0, 0.0);
filter_mix.gain(1, 0.0);
filter_mix.gain(2, 0.0);
filter_mix.gain(3, 1.0);
}
// chorus_mix.gain(0, 0.0);
// chorus_mix.gain(1, 1.0);
// chorus_mix.gain(2, 0.0);
// chorus_mix.gain(3, 0.0);
float reverbMixPos = float(reverbMix) / 10;
reverb_mix.gain(1, reverbMixPos);
reverbMixPos = 1 - (float(reverbMix) / 10);
reverb_mix.gain(0, reverbMixPos);
float room = float(reverbRoomSize) / 10;
freeverb1.roomsize(room);
float damp = float(reverbDamping) / 10;
freeverb1.damping(damp);
// int tempMin = breathMin - breathMax;
// floatBreath = float(breathRaw) / tempMin;
int tempBreath = map(breath, 0, 127, 0, 127); // Skip lower breath range because of instability
floatBreath = float(tempBreath) / 127.0;
floatBreath = constrain(floatBreath, 0.0, 1.0);
// Serial.println(floatBreath);
//// ---------------------------------------------------------
//// ------------ Pitchbend calculation section: -------------
////----------------------------------------------------------
Fpitchbend = float(pitchbend);
byte secondaryNote;
byte primaryNote;
if (splitActive == 1) {
secondaryNote = currentSplitLowNote;
primaryNote = currentSplitHighNote;
}
else {
secondaryNote = currentSustainNote;
primaryNote = currentNote;
}
if (pitchbend < 0) {
float lowFreq = noteToFreq(primaryNote - pitchbendRange);
Wind1currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind1currentWavetableFreq);
lowFreq = noteToFreq(secondaryNote - pitchbendRange);
Wind2currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind2currentWavetableFreq);
}
else if (pitchbend > 0) {
float highFreq = noteToFreq(primaryNote + pitchbendRange);
Wind1currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind1currentWavetableFreq, highFreq);
highFreq = noteToFreq(secondaryNote + pitchbendRange);
Wind2currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind2currentWavetableFreq, highFreq);
}
else if (pitchbend == 0) {
Wind1currentWavetableFreq = noteToFreq(primaryNote);
Wind2currentWavetableFreq = noteToFreq(secondaryNote);
}
Wind1WavetableSetFreq(Wind1currentWavetableFreq);
Wind2WavetableSetFreq(Wind2currentWavetableFreq);
//// ----------------------------------------------
//// -------- Key / note output section: ----------
////-----------------------------------------------
if (breath != 0) {
if (splitActive == 0) {
if (lastSustainActive == 0) {
currentSustainNote = currentNote;
}
else if (sustainActive == 1 && intervalActive == 1) {
if (lastIntervalActive == 0) {
sustainInterval = currentSustainNote - currentNote;
}
lastSustainNote = currentSustainNote;
currentSustainNote = currentNote + sustainInterval;
}
Wind1currentWavetableFreq = noteToFreq(currentNote);
Wind2currentWavetableFreq = noteToFreq(currentSustainNote);
if (pitchbend < 0) {
float lowFreq = noteToFreq(currentNote - pitchbendRange);
Wind1currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind1currentWavetableFreq);
lowFreq = noteToFreq(currentSustainNote - pitchbendRange);
Wind2currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind2currentWavetableFreq);
}
else if (pitchbend > 0) {
float highFreq = noteToFreq(currentNote + pitchbendRange);
Wind1currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind1currentWavetableFreq, highFreq);
highFreq = noteToFreq(currentSustainNote + pitchbendRange);
Wind2currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind2currentWavetableFreq, highFreq);
}
if (lastSplitActive == 1) {
// usbMIDI.sendNoteOn(currentSplitLowNote, 0, 1);
// usbMIDI.sendNoteOn(currentSplitHighNote, 0, 2);
WindWavetableStop(Wind1CurrentWavetable);
WindWavetableStop(Wind2CurrentWavetable);
WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
}
if (sustainActive == 1) {
if (lastSustainActive == 0) {
WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
WindWavetablePlayFreq(Wind2CurrentWavetable, Wind2currentWavetableFreq);
}
}
else if (lastSustainActive == 1) {
// usbMIDI.sendNoteOn(currentSustainNote, 0, 1);
// usbMIDI.sendNoteOn(currentNote, 0, 2);
WindWavetableStop(Wind1CurrentWavetable);
WindWavetableStop(Wind2CurrentWavetable);
WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
}
if (newNote == 1) {
// stop old note:
WindWavetableStop(Wind1CurrentWavetable);
// Change wavetable:
if (Wind1CurrentWavetable == 1) {
Wind1CurrentWavetable = 2;
}
else {
Wind1CurrentWavetable = 1;
}
// sustain/split:
if (sustainActive == 1) {
WindWavetableStop(Wind2CurrentWavetable);
// Change wavetable:
if (Wind2CurrentWavetable == 3) {
Wind2CurrentWavetable = 4;
}
else {
Wind2CurrentWavetable = 3;
}
//sustain:
if (sustainActive == 1) {
Wind1currentWavetableFreq = noteToFreq(currentNote);
Wind2currentWavetableFreq = noteToFreq(currentSustainNote);
if (pitchbend < 0) {
float lowFreq = noteToFreq(currentNote - pitchbendRange);
Wind1currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind1currentWavetableFreq);
lowFreq = noteToFreq(currentSustainNote - pitchbendRange);
Wind2currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind2currentWavetableFreq);
}
else if (pitchbend > 0) {
float highFreq = noteToFreq(currentNote + pitchbendRange);
Wind1currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind1currentWavetableFreq, highFreq);
highFreq = noteToFreq(currentSustainNote + pitchbendRange);
Wind2currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind2currentWavetableFreq, highFreq);
}
}
// start new note:
WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
WindWavetablePlayFreq(Wind2CurrentWavetable, Wind2currentWavetableFreq);
}
// single note:
else {
Wind1currentWavetableFreq = noteToFreq(currentNote);
if (pitchbend < 0) {
float lowFreq = noteToFreq(currentNote - pitchbendRange);
Wind1currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind1currentWavetableFreq);
}
else if (pitchbend > 0) {
float highFreq = noteToFreq(currentNote + pitchbendRange);
Wind1currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind1currentWavetableFreq, highFreq);
}
// start new note:
WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
}
}
}
// SPLIT OUTPUT SECTION:
else if (splitActive == 1) {
Wind1currentWavetableFreq = noteToFreq(currentSplitHighNote);
Wind2currentWavetableFreq = noteToFreq(currentSplitLowNote);
if (pitchbend < 0) {
float lowFreq = noteToFreq(currentSplitHighNote - pitchbendRange);
Wind1currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind1currentWavetableFreq);
lowFreq = noteToFreq(currentSplitLowNote - pitchbendRange);
Wind2currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind2currentWavetableFreq);
}
else if (pitchbend > 0) {
float highFreq = noteToFreq(currentSplitHighNote + pitchbendRange);
Wind1currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind1currentWavetableFreq, highFreq);
highFreq = noteToFreq(currentSplitLowNote + pitchbendRange);
Wind2currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind2currentWavetableFreq, highFreq);
}
if (newHighNote == 1) {
// Change wavetable:
if (Wind1CurrentWavetable == 1) {
WindWavetableStop(Wind1CurrentWavetable);
Wind1CurrentWavetable = 2;
}
else {
WindWavetableStop(Wind1CurrentWavetable);
Wind1CurrentWavetable = 1;
}
WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
}
if (newLowNote == 1 && splitLowPressed != 0) {
if (Wind2CurrentWavetable == 3) {
WindWavetableStop(Wind2CurrentWavetable);
Wind2CurrentWavetable = 4;
}
else {
WindWavetableStop(Wind2CurrentWavetable);
Wind2CurrentWavetable = 3;
}
WindWavetablePlayFreq(Wind2CurrentWavetable, Wind2currentWavetableFreq);
}
else if (splitLowPressed == 0) {
WindWavetableStop(Wind2CurrentWavetable);
}
}
}
// ----------------------------------------------
// ---------- Breath output section: -------------
//------------------------------------------------
WindWavetableAmplitude(floatBreath);
if (breath != lastBreath) {
// WindWavetableAmplitude(floatBreath);
if (breath == 0) {
WindWavetableStop(Wind1CurrentWavetable);
// Change wavetable:
if (Wind1CurrentWavetable == 1) {
Wind1CurrentWavetable = 2;
}
else {
Wind1CurrentWavetable = 1;
}
if (sustainActive == 1 || splitActive == 1) {
WindWavetableStop(Wind2CurrentWavetable);
// Change wavetable:
if (Wind2CurrentWavetable == 3) {
Wind2CurrentWavetable = 4;
}
else {
Wind2CurrentWavetable = 3;
}
}
}
else if (lastBreath == 0) {
if (correct == 1) {
// usbMIDI.sendControlChange(2, breath, 1);
// usbMIDI.sendControlChange(2, breath, 2);
if (splitActive == 0) {
if (sustainActive == 1) {
// Wind2currentWavetableFreq = noteToFreq(currentSustainNote);
WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
WindWavetablePlayFreq(Wind2CurrentWavetable, Wind2currentWavetableFreq);
}
else {
WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
}
}
else {
// Wind1currentWavetableFreq = noteToFreq(currentSplitLowNote);
// Wind2currentWavetableFreq = noteToFreq(currentSplitHighNote);
WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
WindWavetablePlayFreq(Wind2CurrentWavetable, Wind2currentWavetableFreq);
}
}
}
}
// ----------------------------------------------
// ------------ Misc output section: -------------
//------------------------------------------------
if (breath != lastBreath) {
filter1.frequency(filterFreqMax * (breath * DIV127) + 10);
filter2.frequency(filterFreqMax * (breath * DIV127) + 10);
filter3.frequency(filterFreqMax * (breath * DIV127) + 10);
if(filterResonance == 0){
filter1.resonance((4.3 * (breath * DIV127)) + 0.7);
filter2.resonance((4.3 * (breath * DIV127)) + 0.7);
filter3.resonance((4.3 * (breath * DIV127)) + 0.7);
}
else{
filter1.resonance(filterResonance);
filter2.resonance(filterResonance);
filter3.resonance(filterResonance);
}
// Serial.print(mpTouchVal);
// Serial.print(" - ");
}
// if(mpTouchVal != lastmpTouchVal){
// LFOdepth = mpTouchVal * DIV127;
// }
bitcrusher1.bits(bitcrusherBits);
if(mpTouchVal2 != lastMpTouchVal2){
if(bitcrusherBits == 1){
mpTouchVal2 = mpTouchVal2 * 0.4;
}
else if(bitcrusherBits == 2){
mpTouchVal2 = mpTouchVal2 * 0.65;
}
float tempMix = (float)mpTouchVal2 / 127.0;
float tempOtherMix = 1 - tempMix;
distortion_mix.gain(0, tempOtherMix);
distortion_mix.gain(1, tempMix);
// Serial.print(tempMix);
// Serial.println();
}
}
void midiOutput() {
// ----------------------------------------------
// ---------- Breath output section: -------------
//------------------------------------------------
if (breath != lastBreath) {
if (breath == 0) {
usbMIDI.sendControlChange(123, 0, midiChannel1);
usbMIDI.sendControlChange(123, 0, midiChannel2);
// if(splitActive == 1){
//// usbMIDI.sendControlChange(123, 0, 1);
//// usbMIDI.sendControlChange(123, 0, 2);
// usbMIDI.sendNoteOn(currentSplitLowNote, 0, 1);
// usbMIDI.sendNoteOn(currentSplitHighNote, 0, 2);
// }
// else{
// if(sustainActive == 1){
//// usbMIDI.sendControlChange(2, 0, 1);
//// usbMIDI.sendControlChange(2, 0, 2);
// usbMIDI.sendNoteOn(currentSustainNote, 0, 1);
// usbMIDI.sendNoteOn(currentNote, 0, 2);
// }
// else{
//// usbMIDI.sendControlChange(2, 0, 1);
// usbMIDI.sendNoteOn(currentNote, 0, 1);
// }
// }
}
else if (lastBreath == 0) {
if (correct == 1) {
usbMIDI.sendControlChange(breathCC, breath, midiChannel1);
usbMIDI.sendControlChange(breathCC, breath, midiChannel2);
if(extraBreathCC != 0){
usbMIDI.sendControlChange(extraBreathCC, breath, midiChannel1);
usbMIDI.sendControlChange(extraBreathCC, breath, midiChannel2);
}
if (splitActive == 0) {
if (sustainActive == 1) {
usbMIDI.sendNoteOn(currentSustainNote, 127, midiChannel1);
usbMIDI.sendNoteOn(currentNote, 127, midiChannel2);
}
else {
usbMIDI.sendNoteOn(currentNote, 127, midiChannel1);
}
}
else {
usbMIDI.sendNoteOn(currentSplitLowNote, 127, midiChannel1);
usbMIDI.sendNoteOn(currentSplitHighNote, 127, midiChannel2);
}
}
}
else {
usbMIDI.sendControlChange(breathCC, breath, midiChannel1);
usbMIDI.sendControlChange(breathCC, breath, midiChannel2);
if(extraBreathCC != 0){
usbMIDI.sendControlChange(extraBreathCC, breath, midiChannel1);
usbMIDI.sendControlChange(extraBreathCC, breath, midiChannel2);
}
}
}
// ----------------------------------------------
// -------- Key / note output section: ----------
//-----------------------------------------------
if (breath != 0) {
if (splitActive == 0) {
if (lastSplitActive == 1) {
// usbMIDI.sendNoteOn(currentSplitLowNote, 0, 1);
// usbMIDI.sendNoteOn(currentSplitHighNote, 0, 2);
usbMIDI.sendControlChange(123, 0, midiChannel1);
usbMIDI.sendControlChange(123, 0, midiChannel2);
usbMIDI.sendNoteOn(currentNote, 127, midiChannel1);
}
if (sustainActive == 1 && intervalActive == 0) {
if (lastSustainActive == 0) {
currentSustainNote = currentNote;
usbMIDI.sendNoteOn(currentNote, 127, midiChannel2);
}
}
else if (sustainActive == 1 && intervalActive == 1) {
if (lastIntervalActive == 0) {
sustainInterval = currentSustainNote - currentNote;
}
lastSustainNote = currentSustainNote;
currentSustainNote = currentNote + sustainInterval;
}
else if (lastSustainActive == 1) {
// usbMIDI.sendNoteOn(currentSustainNote, 0, 1);
// usbMIDI.sendNoteOn(currentNote, 0, 2);
usbMIDI.sendControlChange(123, 0, midiChannel1);
usbMIDI.sendControlChange(123, 0, midiChannel2);
if(extraBreathCC != 0){
usbMIDI.sendControlChange(extraBreathCC, 0, midiChannel1);
usbMIDI.sendControlChange(extraBreathCC, 0, midiChannel2);
}
usbMIDI.sendNoteOn(currentNote, breath, midiChannel1);
if(extraBreathCC != 0){
usbMIDI.sendControlChange(extraBreathCC, breath, midiChannel1);
}
}
if (newNote == 1) {
if (sustainActive == 1) {
usbMIDI.sendNoteOn(lastNote, 0, midiChannel2);
usbMIDI.sendNoteOn(currentNote, 127, midiChannel2);
if (intervalActive == 1) {
usbMIDI.sendNoteOn(lastSustainNote, 0, midiChannel1);
usbMIDI.sendNoteOn(currentSustainNote, 127, midiChannel1);
}
}
else {
usbMIDI.sendNoteOn(lastNote, 0, midiChannel1);
usbMIDI.sendNoteOn(currentNote, 127, midiChannel1);
}
}
}
else if (splitActive == 1) {
if (lastSplitActive == 0) {
// if(sustainActive == 1){
// usbMIDI.sendNoteOn(currentNote, 0, 2);
// usbMIDI.sendNoteOn(currentSustainNote, 0, 1);
// }
// else{
// usbMIDI.sendNoteOn(currentNote, 0, 1);
// }
usbMIDI.sendControlChange(123, 0, midiChannel1);
usbMIDI.sendControlChange(123, 0, midiChannel2);
usbMIDI.sendNoteOn(currentSplitLowNote, 127, midiChannel1);
usbMIDI.sendNoteOn(currentSplitHighNote, 127, midiChannel2);
}
else {
if (currentSplitLowNote != lastSplitLowNote) {
usbMIDI.sendNoteOn(lastSplitLowNote, 0, midiChannel1);
usbMIDI.sendNoteOn(currentSplitLowNote, 127, midiChannel1);
}
if (currentSplitHighNote != lastSplitHighNote) {
usbMIDI.sendNoteOn(lastSplitHighNote, 0, midiChannel2);
usbMIDI.sendNoteOn(currentSplitHighNote, 127, midiChannel2);
}
}
}
}
else {
if (sustainActive == 1 && intervalActive == 0) {
if (lastSustainActive == 0) {
currentSustainNote = currentNote;
// usbMIDI.sendNoteOn(currentNote, breath, 2);
}
}
else if (sustainActive == 1 && intervalActive == 1) {
if (lastIntervalActive == 0) {
sustainInterval = currentSustainNote - currentNote;
}
lastSustainNote = currentSustainNote;
currentSustainNote = currentNote + sustainInterval;
}
}
// ----------------------------------------------
// ------------ Misc output section: -------------
//------------------------------------------------
if (lastPitchbend != pitchbend) {
if(pitchbendLowRes == 1){
usbMIDI.sendPitchBend(pitchbend << 7, midiChannel1);
usbMIDI.sendPitchBend(pitchbend << 7, midiChannel2);
}
else if(pitchbendHighRes == 1){
usbMIDI.sendPitchBend(pitchbend, midiChannel1);
usbMIDI.sendPitchBend(pitchbend, midiChannel2);
}
// Serial.print(pitchbend);
// Serial.print(" - ");
}
if (mpTouchVal != lastmpTouchVal) {
usbMIDI.sendControlChange(lipCC, mpTouchVal, midiChannel1);
usbMIDI.sendControlChange(lipCC, mpTouchVal, midiChannel2);
// Serial.print(mpTouchVal);
// Serial.print(" - ");
}
// Serial.println();
}
I’m using Arduino 1.8.19 and Teensy loader 1.57, on Ubuntu 18.04.5
When I run this code, I get the first few Serial messages, up until “After ‘readMpTouch’”, plus the first text on the OLED, and then the Teensy 4.0 resets, giving the same output again after a pause. The whole cycle takes about 10 seconds.
Screenshot:
I’m assuming that the problem is one of two things. Either electrical issues, or problems in my code.
I considered that all the external components might be overloading the 3.3v output of the Teensy, but some research seems to indicate that this isn’t the case. Here are the main current consumption candidates:
- CNY70 LED - 50 ma (abs. max)
- CNY70 transistor - 50 ma (abs. max)
- OLED display - 20.7 ma (max)
- 49E hall effect x2 - 5ma x2
- MPR121x2 - 29ua x2
- + A couple of potentiometers, switches and an encoder
- Audio adapter
Given that the Teensy 3.3v can provide 250ma, the power consumption of external components doesn’t appear to be the problem.
For normal operation of the instrument I run the Teensy off of a 1s lipo connected to Vin. (USB and Vin have been separated at the pads of course) The battery is connected through an Adafruit Lipo backpack, which is powered from the USB pin on the Teensy for charging I’ve checked the voltage at the Teensy Vin pin, which is at 4.15v, so that should work. But just in case, I’ve also tried supplying a stable 5v directly to Vin to bypass the whole battery/backpack setup, which doesn’t solve the problem.
The audio adapter works. I’ve added a line out jack, and when running the “PlaySynthMusic” example I get good outputs on both headphone and line out.
The Teensy is soldered straight to the audio adapter with extra long pins. And under that, an improvised breakout board is soldered straight to those same pins. The whole setup has to fit in a small space inside the instrument, and the final version will have an actual pcb instead of the home-grown breakout (if I ever get it to work…)
I’ve tested all the sensors and outputs separately, and they all work, although some tests revealed similar “spontaneous reset” problems.
For example: While running the code below, which just tests the two MPR121 capacitive sensors, the Serial output freezes at about 2000 ms in, and then picks up again after a couple of seconds, clearing the Serial monitor as shown in the screenshots. So it’s not a complete cyclical reset as in the actual “OHMs” code, but still similar symptoms.
Code:
#include <Wire.h>
#include "Adafruit_MPR121.h"
int activeMPR121[4] = {0, 0};
int mprAReadings[12];
int mprBReadings[12];
Adafruit_MPR121 capA = Adafruit_MPR121();
Adafruit_MPR121 capB = Adafruit_MPR121();
uint16_t MPRbinaryA = 0;
uint16_t MPRbinaryB = 0;
uint16_t lasttouched = 0;
uint16_t currtouched = 0;
void setup() {
Serial.begin(9600);
delay(1000);
Serial.println("Adafruit MPR121 Capacitive Touch sensor test");
if (!capA.begin(0x5A)) {
Serial.println("MPR121 on 0x5A NOT found");
}
else {
Serial.println("MPR121 on 0x5A active");
activeMPR121[0] = 1;
}
if (!capB.begin(0x5B)) {
Serial.println("MPR121 on 0x5B NOT found");
}
else {
Serial.println("MPR121 on 0x5B active");
activeMPR121[1] = 1;
}
delay(100);
// if(activeMPR121[0] == 1){
capA.writeRegister(0x2E, 0b11111111);
capA.writeRegister(0x32, 0b11111111);
capA.writeRegister(0x35, 0b11111111);
capA.setThresholds(20, 16);
// }
// if(activeMPR121[1] == 1){
capB.writeRegister(0x2E, 0b11111111);
capB.writeRegister(0x32, 0b11111111);
capB.writeRegister(0x35, 0b11111111);
capB.setThresholds(20, 16);
// }
}
void loop() {
int lastMPRbinaryA = MPRbinaryA;
int lastMPRbinaryB = MPRbinaryB;
if (activeMPR121[0] == 1) {
MPRbinaryA = capA.touched();
}
if (activeMPR121[1] == 1) {
MPRbinaryB = capB.touched();
}
Serial.print(millis());
Serial.print(" - ");
Serial.print(MPRbinaryA, BIN);
Serial.print(" - ");
Serial.print(MPRbinaryB, BIN);
Serial.print(" - ");
Serial.print(capA.filteredData(11));
Serial.println();
delay(20);
}
I’m including a couple of photos of my setup, although given the ratsnest that it is, I don’t know how useful it will be. However, as I’m able to get all the sensors, audio and display to work separately (except for the "reset problems"), my conclusion is that there are no shorts or other such problems. The pins used for each component can be seen in the first part of the .ino file. I’ve taken care not to use the pins that are reserved for audio adapter functionality.
So that leaves me with a possible code problem, which I’ve not been able to find.
Of course I've googled a lot, mostly ending up right here on the forum, but haven't been able to find the solution
I realize this is quite a mouthful, and that maybe there are too many variables at play here for anyone to be able to untangle the problem. Even so, I thought I’d give it a shot, sharing as much info as possible.
Thanks in advance for any info, advice, or even just good questions that might set me on the right track.
Jeppe