Arduino's serial monitor doesn't show anything

PASY

New member
Hello guys,
I'm quite new to all this...
I have a teensy 3.2, actually I ordered a kit from KontinuumLab: https://www.kontinuumlab.com/shop.
I able to upload the Blink exemple in the board but when I try to upload the code of the project (https://github.com/KontinuumLab/KontinuumLAB_Instrument_Kit/tree/main/KLIK_KLIKsophone_001) it upload perfectly but nothing shows in the serial monitor.
I tried unplug-replug, reset and different "usb type" (midi and serial+midi+audio) nothing seems to work.

Any suggestions?
Thanks a lot for your time!
PASY
 
The link to the code is dead.

Copy and paste the text of the code (using code tags using the # icon).

Pete
 
Uncomment the lines 240..252 in the ino file.
I have shown a code snipped below. ( The Serial was never turned on in the code ).
Code:
  Serial.begin(9600);                 // <- UnComment
  // Read "Serial" pin. If "on" then start Serial.?

  

  // Read saved settings from memory:
  delay(1000);
  loadSettings();

  
  Serial.print(modeSetting);         // <- UnComment
  Serial.print("_");                 // <- UnComment
  Serial.print(instrumentSetting);   // <- UnComment
 
Thanks a lot, it works!
It doesn't show anything but I can see scrollbar moving...:confused:

I guess I'll wait for a response from the creator... It's my fault, I wiped the pre-programed teensy he sent...
Here is the code in case someone is interested :)

Code:
/*
    KontinuumLAB Instrument Kit - "KLIKsophonea" individual instrument sketch
    Copyright (C) 2021 Jeppe Rasmussen - KontinuumLAB
    www.kontinuumlab.com
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/



#include <EEPROM.h>

//--------- PINS -----------//

// Settings pins:
const int optionPin0 = 1;
const int optionPin1 = 3;
const int optionPin2 = 4;

const int instrPin0 = 2;
const int instrPin1 = 5;
const int instrPin2 = 6;

const int modePin0 = 7;
const int modePin1 = 8;

const int ledPin = 13;
const int calPin = 26;

// Analog sensor pins:
const int aPin[2] = {24, 25};
const int aPinArrayLength = 2;

// Capacitive touch pins:
const int touchPin[11] = {0, 1, 3, 4, 16, 17, 18, 19, 22, 23, 15};
const int touchPinArrayLength = 11;

// Multiplexer pins:
const int mux1SensorPin = 0;

const int muxPin1 = 12;
const int muxPin2 = 11;
const int muxPin3 = 10;
const int muxPin4 = 9;

const int muxEnablePin = 14;

//-------- SENSOR VARIABLES --------//

// SETTINGS:
int optionPin0Val;
int optionPin1Val;
int optionPin2Val;

int instrPin0Val;
int instrPin1Val;
int instrPin2Val;
int instrumentSetting = 0;

int modePin0Val;
int modePin1Val;
int modeSetting = 0;


// SENSORS VALUES:
int aPinVal[2];
uint16_t aPinRawVal[2];
int lastAPinVal[2];
uint16_t lastAPinRawVal[2];

uint16_t aPinMin[2];
uint16_t aPinCent[2];
uint16_t aPinMax[2];


int touchPinVal[11];
uint16_t touchPinRawVal[11];
int lastTouchPinVal[11];
uint16_t lastTouchPinRawVal[11];

uint16_t touchPinMin[11];
uint16_t touchPinMax[11];


int mux1Val[16];
uint16_t mux1RawVal[16];
int lastMux1Val[16];
uint16_t lastMux1RawVal[16];

uint16_t mux1Min[16];
uint16_t mux1Max[16];


// For wind instruments MIDI output values:
int breath;
int lastBreath;

int currentNote;
int lastNote;

// Other stuff:
int volumeCC = 2;

// Pitch bend reading values:
int pitchBend;
int lastPitchBend;

unsigned int ledStart = 0;
unsigned int ledTimer = 0;

int MIDIchannel = 1;

//------------ Generic Functions------------------


// Error value for the exponential filter:
float error;

// Helper function for the exponential filter function:
float snapCurve(float x){
  float y = 1.0 / (x + 1.0);
  y = (1.0 - y) * 2.0;
  if(y > 1.0) {
    return 1.0;
  }
  return y;
}

// Main exponential filter function. Input "snapMult" = speed setting. 0.001 = slow / 0.1 = fast:
int expFilter(int newValue, int lastValue, float snapMult){
  unsigned int diff = abs(newValue - lastValue);
  error += ((newValue - lastValue) - error) * 0.4;
  float snap = snapCurve(diff * snapMult);
  float outputValue = lastValue;
  outputValue  += (newValue - lastValue) * snap;
  return (int)outputValue;
}


// Function for accessing individual multiplexer sensors. Input: mux number, sensor number: 
int readSingleCap(int number){
  digitalWrite(muxPin1, bitRead(number, 0)); 
  digitalWrite(muxPin2, bitRead(number, 1));
  digitalWrite(muxPin3, bitRead(number, 2));
  digitalWrite(muxPin4, bitRead(number, 3));
  uint16_t value = touchRead(mux1SensorPin);
  return value;
}

// DEBOUNCE FUNCTION FOR BUTTONS:
int debounce(int pin){
  int temp = !digitalRead(pin);
  if(temp == 1){
    delay(2);
    temp = !digitalRead(pin);
    return(temp);
  }
  else{
    return 0;
  }
}


//Include rest of sketch:
#include "KLIK_Memory.h"
#include "KLIK_Calibration.h"


void setup() {
  pinMode(modePin0, INPUT_PULLUP);
  pinMode(modePin1, INPUT_PULLUP);
  
  pinMode(instrPin0, INPUT_PULLUP);
  pinMode(instrPin1, INPUT_PULLUP);
  pinMode(instrPin2, INPUT_PULLUP);

  pinMode(calPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  
  pinMode(muxPin1, OUTPUT);
  pinMode(muxPin2, OUTPUT);
  pinMode(muxPin3, OUTPUT);
  pinMode(muxPin4, OUTPUT);

  pinMode(muxEnablePin, OUTPUT);
  digitalWrite(muxEnablePin, LOW);

  modePin0Val = !digitalRead(modePin0);
  modePin1Val = !digitalRead(modePin1);

  instrPin0Val = !digitalRead(instrPin0);
  instrPin1Val = !digitalRead(instrPin1);
  instrPin2Val = !digitalRead(instrPin2);


  bitWrite(modeSetting, 0, modePin0Val);
  bitWrite(modeSetting, 1, modePin1Val);

  bitWrite(instrumentSetting, 0, instrPin0Val);
  bitWrite(instrumentSetting, 1, instrPin1Val);
  bitWrite(instrumentSetting, 2, instrPin2Val);

  if(modeSetting == 0){
    pinMode(optionPin0, INPUT_PULLUP);
    pinMode(optionPin1, INPUT_PULLUP);
    pinMode(optionPin2, INPUT_PULLUP);
    optionPin0Val = !digitalRead(optionPin0);
    optionPin1Val = !digitalRead(optionPin1);
    optionPin2Val = !digitalRead(optionPin2);
    
    if(instrumentSetting == 0){
      // do nothing....
    }
  }
  

  /////////For all modes:://///////
  
  // All instruments output on alternative MIDI channel:
  if(optionPin2Val == 1){
    MIDIchannel = 2;
  }
//  All volume control outputs CC#7 instead of CC#2:
  pinMode(aPin[0], INPUT_PULLUP);
  if(!digitalRead(aPin[0]) == 1){
    volumeCC = 7;
  }
  
//  Serial.begin(9600);
  // Read "Serial" pin. If "on" then start Serial.?

  

  // Read saved settings from memory:
  delay(1000);
  loadSettings();

  
//  Serial.print(modeSetting);
//  Serial.print("_");
//  Serial.print(instrumentSetting);
}



//--------------------------------------------------------------//
//----------------------MAIN FUNCTION---------------------------//
//--------------------------------------------------------------//

void loop() {

  calibrationCheck();
  
  KLIKsophone();
}


int keyPhase;
int correct;
int newNote;

int octave = 0;

int firstLoop = 1;

const int KLIKsophoneOctaveSensors[3] = {13, 14, 15};

int activeKLIKsophoneKeys[16];

const int KLIKsophoneKeyThreshold = 30;



int looperSensors[6] = {4, 5, 6, 7};
int looperNotes[6] = {48, 50, 52, 55};
int strokeThreshold = 20;
int offThreshold = 5;

int noteOnArray[4];

// Fingering arrays, used to determine which note is currently being played:
// Each array represents a specific note, as stated at the last position of each array. 
// Numbers 0 - 12 represent a specific key, "100" means go to next stage.
// Far left values (until first "100") are keys that HAVE to be pressed to produce the note in question.
// Next series of keys (until next "100") are keys that must NOT be pressed for the note to be valid.

const int KLIKsophoneFingerings[20][14] = {
  {0, 7, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 63}, // Eb
  {0, 100, 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 62}, // 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}, // Bb
  {1, 3, 7, 100, 4, 100, 0, 0, 0, 0, 0, 0, 58}, // Bb
  {1, 3, 100, 4, 7, 100, 0, 0, 0, 0, 0, 0, 57}, // A
  {1, 3, 4, 5, 100, 8, 9, 100, 0, 0, 0, 0, 56}, // Ab
  {1, 3, 4, 100, 5, 8, 9, 100, 0, 0, 0, 0, 55}, // G
  {1, 3, 4, 9, 100, 8, 100, 0, 0, 0, 0, 0, 54}, // F#
  {1, 3, 4, 8, 100, 9, 100, 0, 0, 0, 0, 0, 53}, // F
  {1, 3, 4, 8, 9, 100, 10, 100, 0, 0, 0, 0, 52}, // E
  {1, 3, 4, 8, 9, 10, 11, 100, 12, 100, 0, 0, 51}, // Eb
  {1, 3, 4, 8, 9, 10, 100, 6, 11, 12, 100, 0, 50}, // D
  {1, 3, 4, 5, 8, 9, 10, 12, 100, 6, 100, 0, 49}, // C#
  {1, 3, 4, 8, 9, 10, 12, 100, 5, 6, 100, 0, 48}, // C
  {1, 3, 4, 6, 8, 9, 10, 100, 12, 100, 0, 0, 47}, // B 
  {1, 3, 4, 6, 8, 9, 10, 12, 100, 100, 0, 0, 46}, // Bb
};




void KLIKsophone(){
  int i;
  int looperPins;
  
  // Save previous breath sensor raw value, then read and filter new value:
  lastAPinVal[1]= aPinVal[1];
  aPinVal[1] = analogRead(aPin[1]);
  aPinVal[1] = expFilter(aPinVal[1], lastAPinVal[1], 0.01);
  // Save previous breath sensor output value, then map new value from raw reading:
  lastBreath = breath;
  breath = map(aPinVal[1], aPinMin[1], aPinMax[1], 0, 127);
//  Serial.println(breath);

  // Limit output to MIDI range:
  breath = constrain(breath, 0, 127);

//  Serial.println(breathOut);
  // If breath sensor output value has changed: 
  if(breath != lastBreath){
//    Serial.println(breathOut);
    // Send CC2 volume control:
    usbMIDI.sendControlChange(volumeCC, breath, MIDIchannel);
    // If breath sensor recently DEactivated, send note off message:
    if(breath == 0){
      usbMIDI.sendControlChange(123, 0, MIDIchannel);
    }
    // Else if breath sensor recently activated, send note on message:
    else if(breath != 0 && lastBreath == 0){
      usbMIDI.sendNoteOn(currentNote, 127, MIDIchannel);
    }
  }

  looperPins = 4;
    
// Looper controller section
  if(optionPin0Val == 1){
    for(i = 0; i < looperPins; i++){
      lastTouchPinRawVal[looperSensors[i]] = touchPinRawVal[looperSensors[i]];
      lastTouchPinVal[looperSensors[i]] = touchPinVal[looperSensors[i]];
      touchPinRawVal[looperSensors[i]] = touchRead(touchPin[looperSensors[i]]);
      touchPinRawVal[looperSensors[i]] = expFilter(touchPinRawVal[looperSensors[i]], lastTouchPinRawVal[looperSensors[i]], 0.005);
      touchPinVal[looperSensors[i]] = map(touchPinRawVal[looperSensors[i]], touchPinMin[looperSensors[i]], touchPinMax[looperSensors[i]], 0, 127);
      touchPinVal[looperSensors[i]] = constrain(touchPinVal[looperSensors[i]], 0, 127);

      int MIDIchannelExtra = MIDIchannel + 1;
      if(touchPinVal[looperSensors[i]] >= strokeThreshold && lastTouchPinVal[looperSensors[i]] < strokeThreshold && noteOnArray[i] == 0){
        int velocity = touchPinVal[looperSensors[i]];
        usbMIDI.sendNoteOn(looperNotes[i], velocity, MIDIchannelExtra);
        noteOnArray[i] = 1;
      }
      else if(touchPinVal[looperSensors[i]] < offThreshold && lastTouchPinVal[looperSensors[i]] >= offThreshold){
        usbMIDI.sendNoteOn(looperNotes[i], 0, MIDIchannelExtra);
        noteOnArray[i] = 0;
      }
        
//      Serial.print(touchPinVal[looperSensors[i]]);
//      Serial.print(" - ");
    }
//    Serial.println();
  }


    //------------- READING KEYS-----------------//

  // Key reading for loop is only done if breath sensor output is NOT equal to zero:
  if(breath != 0){ 


    // Pitch bend section:
    if(optionPin1Val == 1){
      
      lastPitchBend = pitchBend;
      lastTouchPinRawVal[8] = touchPinRawVal[8];
      lastTouchPinRawVal[9] = touchPinRawVal[9];
      
      touchPinRawVal[8] = touchRead(touchPin[8]);
      touchPinRawVal[9] = touchRead(touchPin[9]);
      touchPinRawVal[8] = expFilter(touchPinRawVal[8], lastTouchPinRawVal[8], 0.01);
      touchPinRawVal[9] = expFilter(touchPinRawVal[9], lastTouchPinRawVal[9], 0.01);
      touchPinVal[8] = map(touchPinRawVal[8], touchPinMin[8], touchPinMax[8], 0, 64);
      touchPinVal[9] = map(touchPinRawVal[9], touchPinMin[9], touchPinMax[9], 0, 63);
      // Limit values to sane range:
      touchPinVal[8] = constrain(touchPinVal[8], 0, 64);
      touchPinVal[9] = constrain(touchPinVal[9], 0, 63);
  
      // Calculate final pitchBend value, as "0" plus bend up minus bend down:
      pitchBend = 0 - touchPinVal[9] + touchPinVal[8];
      if(pitchBend != lastPitchBend){
        usbMIDI.sendPitchBend(pitchBend<<7, MIDIchannel);
      }
      //  
    }

    // Main key reading for loop. "i" is sensor number:
    for(i = 0; i < 16; i++){
      // Remember last key reading:
      lastMux1RawVal[i] = mux1RawVal[i];
      // Read sensor at current position:
      mux1RawVal[i] = readSingleCap(i);
      
      // Filter reading for smoothness:
      mux1RawVal[i] = expFilter(mux1RawVal[i], lastMux1RawVal[i], 0.01);
//      Serial.print(touchPinRawVal[recorderKeys[i]]);
//      Serial.print(" - ");
      // Map reading to MIDI range:
      mux1Val[i] = map(mux1RawVal[i], mux1Min[i], mux1Max[i], 0, 127);
      // Limit reading to MIDI range:
      mux1Val[i] = constrain(mux1Val[i], 0, 127);
//      Serial.print(mux1Val[i]);
//      Serial.print(" - ");
      // Activate "activeKeys" at current position, if reading is higher than threshold:
      if(mux1Val[i] > KLIKsophoneKeyThreshold){
        activeKLIKsophoneKeys[i] = 1;
      }
      // Else, DEactivate "activeKeys" at current position:
      else{
        activeKLIKsophoneKeys[i] = 0;
      }
//      Serial.print(activeKLIKsophoneKeys[i]);
//      Serial.print(" - ");
    }
    Serial.println();

    
    //-------------KEY ANALISYS-------------------//
  
    // Variables for the fingering-analysis section:
    correct = 0;
    newNote = 0;
    lastNote = currentNote;

    // If octave key is activated, add 12 semitones to final result, else add zero:
    if(activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[0]] == 0 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[1]] == 0 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[2]] == 0){
      octave = 36;
    }
    else if(activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[0]] == 1 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[1]] == 0 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[2]] == 0){
      octave = 24;
    }
    else if(activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[0]] == 1 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[1]] == 1 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[2]] == 0){
      octave = 12;
    }
    else if(activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[0]] == 0 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[1]] == 1 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[2]] == 0){
      octave = 0;
    }
    else if(activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[0]] == 0 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[1]] == 1 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[2]] == 1){
      octave = -12;
    }
    else if(activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[0]] == 0 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[1]] == 0 && activeKLIKsophoneKeys[KLIKsophoneOctaveSensors[2]] == 1){
      octave = -24;
    }
    
    // Main fingering-analysis for-loop.
    // "n" = fingering array, "i" = position within the fingering loop:
    int n;
    for(n = 0; n < 19; n++){
      // During first keyPhase, check if the requested sensor is active. 
      keyPhase = 0;
      for(i = 0; i < 16; i++){
        if(KLIKsophoneFingerings[n][i] != 100){
          // If active sensors coincide with "fingerings" array requirements: "correct" = yes.
          // Else: "correct" = no and exit current "fingering" array.
          if(keyPhase == 0){  // Check "closed" keys
            if(activeKLIKsophoneKeys[KLIKsophoneFingerings[n][i]] == 1){
              correct = 1;
            }
            else{
              correct = 0;
              break;
            }
          }
          // During second keyPhase, check 
          else if(keyPhase == 1){ // Check "open" keys
            if(activeKLIKsophoneKeys[KLIKsophoneFingerings[n][i]] == 0){
              correct = 1;
            }
            else{
              correct = 0;
              break;
            }
          }       
        }
        // When a "100" is encountered, add 1 to keyPhase, except if keyPhase is 1, exit loop:
        else if(KLIKsophoneFingerings[n][i] == 100){
          if(keyPhase == 1){
            break;
          }
          else{
            keyPhase ++;
          }
        }
      }
      // if "correct" is still yes after all loops finish, then a "fingerings" array has perfectly coincided with
      // current situation. Set "currentNote to the note defined at the end of that array:
      if(correct == 1){
        currentNote = KLIKsophoneFingerings[n][12];
        break;
      }
    }
    // If correct is 1, then there is a new note to report, so set "newNote" to 1, and set "currentNote" to
    // currentNote plus octave: 
    if(correct == 1){
      currentNote = currentNote + octave;
      if(currentNote != lastNote){
        newNote = 1;
      }
    }
    // If newNote is a yes, then send MIDI messages. lastNote off and currentNote On
    if(newNote == 1){
//      Serial.print("Note: ");
//      Serial.println(currentNote);
//      delay(1000);
      usbMIDI.sendNoteOn(lastNote, 0, MIDIchannel);
      usbMIDI.sendNoteOn(currentNote, 127, MIDIchannel);
    }
  }
}
 
Back
Top