Is Pin 15/CS0/Touch an Irregular Analog Pin?

Status
Not open for further replies.

obbligato

Member
Teensy3.6: Is Pin 15/CS0/Touch an Irregular Analog Pin?

Hello -- first post here, and a fairly new teensy user.

I've built a MIDI controller using a Teensy 3.6 and the usbMIDI library where I'm using pins 14-19 as analog inputs using photoresistors. All of them work fine, except for pin 15 which I've noted also serves as a CS0/Touch pin. I've swapped out the photoresistor with known working ones, tried the existing circuit with alternate Teensies, quadruple checked my code, and can't seem to find the issue. I'm curious if this pin is special for any reason and I need to declare it differently as an analog input.

My implementation for this pin is exactly the same as the other 5. My code is long but relevant references are to 'newPhotoPinReading1', and 'photoPin1'.

Thank you for any insight!

Code:
/*In order to use the usbMIDI library, the teensy must be designated as a MIDI device (or combination) under
   the Tools menu, USB Type.



*/

#include <Bounce.h>

//Constant Variables
//Constant Variables
//Constant Variables


//The channel to send MIDI messages on
const int channel = 1;

//LED Pins
const int ledPin0 = 2;
const int ledPin1 = 3;
const int ledPin2 = 4;
const int ledPin3 = 5;
const int ledPin4 = 6;
const int ledPin5 = 7;

//Pot Pins
const int potPin0 = 33;
const int potPin1 = 34;
const int potPin2 = 35;
const int potPin3 = 36;
const int potPin4 = 37;
const int potPin5 = 38;

//Photoresistor Pins
const int photoPin0 = 14;
const int photoPin1 = 15;
const int photoPin2 = 16;
const int photoPin3 = 17;
const int photoPin4 = 18;
const int photoPin5 = 19;

//Changing Variables
//Changing Variables
//Changing Variables

//Pot Readings
int potSensorReading0;
int potSensorReading1;
int potSensorReading2;
int potSensorReading3;
int potSensorReading4;
int potSensorReading5;


//Photo Readings
int photoPinReading0;
int photoPinReading1;
int photoPinReading2;
int photoPinReading3;
int photoPinReading4;
int photoPinReading5;

//use this to compare to previous reading to account for inaccurate readings
int newPhotoPinReading0;
int newPhotoPinReading1;
int newPhotoPinReading2;
int newPhotoPinReading3;
int newPhotoPinReading4;
int newPhotoPinReading5;

//Used for blinking
int ledPinState0 = LOW;
int ledPinState1 = LOW;
int ledPinState2 = LOW;
int ledPinState3 = LOW;
int ledPinState4 = LOW;
int ledPinState5 = LOW;

//Used to create a counter
unsigned long previousMillis0 = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
unsigned long previousMillis3 = 0;
unsigned long previousMillis4 = 0;
unsigned long previousMillis5 = 0;

//values for fadeWithoutDelay
int value0, value1, value2, value3, value4, value5;

//The interval between blinks to be set by the pot position
long intervalLED0 = 0;
long intervalLED1 = 0;
long intervalLED2 = 0;
long intervalLED3 = 0;
long intervalLED4 = 0;
long intervalLED5 = 0;

void setup() {
  pinMode(ledPin0, OUTPUT);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
  pinMode(ledPin5, OUTPUT);

  pinMode(potPin0, INPUT);
  pinMode(potPin1, INPUT);
  pinMode(potPin2, INPUT);
  pinMode(potPin3, INPUT);
  pinMode(potPin4, INPUT);
  pinMode(potPin5, INPUT);

  pinMode(photoPin0, INPUT);
  pinMode(photoPin1, INPUT);
  pinMode(photoPin2, INPUT);
  pinMode(photoPin3, INPUT);
  pinMode(photoPin4, INPUT);
  pinMode(photoPin5, INPUT);

  Serial.begin(115200);
}

void loop() {
  if (usbMIDI.read()) {
    processMIDI();
  }

  unsigned long currentMillis0 = millis();
  unsigned long currentMillis1 = millis();
  unsigned long currentMillis2 = millis();
  unsigned long currentMillis3 = millis();
  unsigned long currentMillis4 = millis();
  unsigned long currentMillis5 = millis();


  //
  //  delay(2);

  /*
       Fade Code
       Fade Code
       Fade Code
  */

  potSensorReading0 = analogRead(potPin0);

  int period0 = 5000;
  int displace0 = 500;
  //displace = potSensorReading0;
  period0 = map(potSensorReading0, 0, 1023, 0, 5000);

  value0 = 128 + 127 * cos(2 * PI / period0 * currentMillis0);
  //value0 = 128+127*cos(2*PI/period*(displace-currentMillis0));
  analogWrite(ledPin0, value0);

  newPhotoPinReading0 = analogRead(photoPin0);


  bool bigChange0 = false;
  if (newPhotoPinReading0 - photoPinReading0 > 150 || newPhotoPinReading0 - photoPinReading0 < -150) {
    bigChange0 = true;
  } else {
    bigChange0 = false;
  }

  if (photoPinReading0 != newPhotoPinReading0 && bigChange0 == true) {
    photoPinReading0 = newPhotoPinReading0;
    //delay(2);
    if (newPhotoPinReading0 > 900) {
      //MIDI Controllers 102-127 are undefined
      //usbMIDI.sendControlChange(control, value, channel);
      usbMIDI.sendControlChange(108, newPhotoPinReading0, channel);
    }

  }

  //  delay(2);
  potSensorReading1 = analogRead(potPin1);


  int period1 = 5000;
  int displace1 = 500;
  //displace1 = potSensorReading0;
  period1 = map(potSensorReading1, 0, 1023, 0, 5000);

  value1 = 128 + 127 * cos(2 * PI / period1 * currentMillis1);
  //value1 = 128+127*cos(2*PI/period1*(displace1-currentMillis1));
  analogWrite(ledPin1, value1);

  newPhotoPinReading1 = analogRead(photoPin1);

  bool bigChange1 = false;
  if (newPhotoPinReading1 - photoPinReading1 > 150 || newPhotoPinReading1 - photoPinReading1 < -150) {
    bigChange1 = true;
  } else {
    bigChange1 = false;
  }

  if (photoPinReading1 != newPhotoPinReading1 && bigChange1 == true) {
    photoPinReading1 = newPhotoPinReading1;
    //delay(2);
    if (newPhotoPinReading1 > 900) {
      //MIDI Controllers 102-127 are undefined
      //usbMIDI.sendControlChange(control, value, channel);
      usbMIDI.sendControlChange(109, newPhotoPinReading1, channel);
    }

  }

  //delay(2);
  potSensorReading2 = analogRead(potPin2);
  Serial.println(potSensorReading2);

  int period2 = 5000;
  int displace2 = 500;
  //displace2 = potSensorReading2;
  period2 = map(potSensorReading2, 0, 1023, 0, 5000);

  value2 = 128 + 127 * cos(2 * PI / period2 * currentMillis2);
  //value2 = 128+127*cos(2*PI/period2*(displac2-currentMillis2));

  analogWrite(ledPin2, value2);

  newPhotoPinReading2 = analogRead(photoPin2);


  bool bigChange2 = false;
  if (newPhotoPinReading2 - photoPinReading2 > 150 || newPhotoPinReading2 - photoPinReading2 < -150) {
    bigChange2 = true;
  } else {
    bigChange2 = false;
  }

  if (photoPinReading2 != newPhotoPinReading2 && bigChange2 == true) {
    photoPinReading2 = newPhotoPinReading2;
    //delay(2);
    if (newPhotoPinReading2 > 900) {
      //MIDI Controllers 102-127 are undefined
      //usbMIDI.sendControlChange(control, value, channel);
      usbMIDI.sendControlChange(110, newPhotoPinReading2, channel);
    }

  }
  //delay(2);

  /*
      Blink Code
      Blink Code
      Blink Code
  */
  potSensorReading3 = analogRead(potPin3);
  intervalLED3 = potSensorReading3;
  //delay(5);
  if (currentMillis3 - previousMillis3 >= intervalLED3) {
    // save the last time you blinked the LED
    previousMillis3 = currentMillis3;
    // if the LED is off turn it on and vice-versa:
    if (ledPinState3 == LOW) {
      ledPinState3 = HIGH;
    } else {
      ledPinState3 = LOW;
    }
    digitalWrite(ledPin3, ledPinState3);
  }

  newPhotoPinReading3 = analogRead(photoPin3);


  bool bigChange3 = false;
  if (newPhotoPinReading3 - photoPinReading3 > 150 || newPhotoPinReading3 - photoPinReading3 < -150) {
    bigChange3 = true;
  } else {
    bigChange3 = false;
  }

  if (photoPinReading3 != newPhotoPinReading3 && bigChange3 == true) {
    photoPinReading3 = newPhotoPinReading3;
    //delay(2);
    if (newPhotoPinReading3 > 900) {
      //MIDI Controllers 102-127 are undefined
      //usbMIDI.sendControlChange(control, value, channel);
      usbMIDI.sendControlChange(111, newPhotoPinReading3, channel);
    }

  }
  //delay(2);
  potSensorReading4 = analogRead(potPin4);
  intervalLED4 = potSensorReading4;
  //delay(5);
  if (currentMillis4 - previousMillis4 >= intervalLED4) {
    // save the last time you blinked the LED
    previousMillis4 = currentMillis4;
    // if the LED is off turn it on and vice-versa:
    if (ledPinState4 == LOW) {
      ledPinState4 = HIGH;
    } else {
      ledPinState4 = LOW;
    }
    digitalWrite(ledPin4, ledPinState4);
  }

  newPhotoPinReading4 = analogRead(photoPin4);


  bool bigChange4 = false;
  if (newPhotoPinReading4 - photoPinReading4 > 150 || newPhotoPinReading4 - photoPinReading4 < -150) {
    bigChange4 = true;
  } else {
    bigChange4 = false;
  }

  if (photoPinReading4 != newPhotoPinReading4 && bigChange4 == true) {
    photoPinReading4 = newPhotoPinReading4;
    //delay(2);
    if (newPhotoPinReading4 > 900) {
      //MIDI Controllers 102-127 are undefined
      //usbMIDI.sendControlChange(control, value, channel);
      usbMIDI.sendControlChange(112, newPhotoPinReading4, channel);
    }

  }

  //delay(2);
  potSensorReading5 = analogRead(potPin5);
  intervalLED5 = potSensorReading5;
  //delay(5);
  if (currentMillis5 - previousMillis5 >= intervalLED5) {
    // save the last time you blinked the LED
    previousMillis5 = currentMillis5;
    // if the LED is off turn it on and vice-versa:
    if (ledPinState5 == LOW) {
      ledPinState5 = HIGH;
    } else {
      ledPinState5 = LOW;
    }
    digitalWrite(ledPin5, ledPinState5);
  }

  newPhotoPinReading5 = analogRead(photoPin5);


  bool bigChange5 = false;
  if (newPhotoPinReading5 - photoPinReading5 > 150 || newPhotoPinReading5 - photoPinReading5 < -150) {
    bigChange5 = true;
  } else {
    bigChange5 = false;
  }

  if (photoPinReading5 != newPhotoPinReading5 && bigChange5 == true) {
    photoPinReading5 = newPhotoPinReading5;
    //delay(2);
    if (newPhotoPinReading5 > 900) {
      //MIDI Controllers 102-127 are undefined
      //usbMIDI.sendControlChange(control, value, channel);
      usbMIDI.sendControlChange(113, newPhotoPinReading5, channel);
    }

  }
  Serial.print("pot 0 = ");
  Serial.println(potSensorReading0);
  Serial.print("pot 1 = ");
  Serial.println(potSensorReading1);
  Serial.print("pot 2 = ");
  Serial.println(potSensorReading2);
  Serial.print("pot 3 = ");
  Serial.println(potSensorReading3);
  Serial.print("pot 4 = ");
  Serial.println(potSensorReading4);
  Serial.print("pot 5 = ");
  Serial.println(potSensorReading5);
//
  Serial.print("photoSensor 0 = ");
  Serial.println(newPhotoPinReading0);
  Serial.print("photoSensor 1 = ");
  Serial.println(newPhotoPinReading1);
  Serial.print("photoSensor 2 = ");
  Serial.println(newPhotoPinReading2);
  Serial.print("photoSensor 3 = ");
  Serial.println(newPhotoPinReading3);
  Serial.print("photoSensor 4 = ");
  Serial.println(newPhotoPinReading4);
  Serial.print("photoSensor 5 = ");
  Serial.println(newPhotoPinReading5);

  delay(50);

}

void processMIDI(void) {
  byte type, channel, data1, data2, cable;

  // fetch the MIDI message, defined by these 5 numbers (except SysEX)
  //
  type = usbMIDI.getType();       // which MIDI message, 128-255
  channel = usbMIDI.getChannel(); // which MIDI channel, 1-16
  data1 = usbMIDI.getData1();     // first data byte of message, 0-127
  data2 = usbMIDI.getData2();     // second data byte of message, 0-127
  cable = usbMIDI.getCable();     // which virtual cable with MIDIx8, 0-7

  // uncomment if using multiple virtual cables
  //Serial.print("cable ");
  //Serial.print(cable, DEC);
  //Serial.print(": ");

  // print info about the message
  //

  int ccChange = random(5, 100);
  switch (type) {
    case usbMIDI.NoteOff: // 0x80
      Serial.print("Note Off, ch=");
      Serial.print(channel, DEC);
      Serial.print(", note=");
      Serial.print(data1, DEC);
      Serial.print(", velocity=");
      Serial.println(data2, DEC);
      break;

    case usbMIDI.NoteOn: // 0x90
      //usbMIDI.sendControlChange(controllerA1, ccChange, channel);
      Serial.print("Note On, ch=");
      Serial.print(channel, DEC);
      Serial.print(", note=");
      Serial.print(data1, DEC);
      Serial.print(", velocity=");
      Serial.println(data2, DEC);
      Serial.print("ccChange is: ");
      Serial.println(ccChange);
      break;

    case usbMIDI.AfterTouchPoly: // 0xA0
      Serial.print("AfterTouch Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", note=");
      Serial.print(data1, DEC);
      Serial.print(", velocity=");
      Serial.println(data2, DEC);
      break;

    case usbMIDI.ControlChange: // 0xB0
      Serial.print("Control Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", control=");
      Serial.print(data1, DEC);
      Serial.print(", value=");
      Serial.println(data2, DEC);
      break;

    case usbMIDI.ProgramChange: // 0xC0
      Serial.print("Program Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", program=");
      Serial.println(data1, DEC);
      break;

    case usbMIDI.AfterTouchChannel: // 0xD0
      Serial.print("After Touch, ch=");
      Serial.print(channel, DEC);
      Serial.print(", pressure=");
      Serial.println(data1, DEC);
      break;

    case usbMIDI.PitchBend: // 0xE0
      Serial.print("Pitch Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", pitch=");
      Serial.println(data1 + data2 * 128, DEC);
      break;

    case usbMIDI.SystemExclusive: // 0xF0
      // Messages larger than usbMIDI's internal buffer are truncated.
      // To receive large messages, you *must* use the 3-input function
      // handler.  See InputFunctionsComplete for details.
      Serial.print("SysEx Message: ");
      printBytes(usbMIDI.getSysExArray(), data1 + data2 * 256);
      Serial.println();
      break;

    case usbMIDI.TimeCodeQuarterFrame: // 0xF1
      Serial.print("TimeCode, index=");
      Serial.print(data1 >> 4, DEC);
      Serial.print(", digit=");
      Serial.println(data1 & 15, DEC);
      break;

    case usbMIDI.SongPosition: // 0xF2
      Serial.print("Song Position, beat=");
      Serial.println(data1 + data2 * 128);
      break;

    case usbMIDI.SongSelect: // 0xF3
      Serial.print("Sond Select, song=");
      Serial.println(data1, DEC);
      break;

    case usbMIDI.TuneRequest: // 0xF6
      Serial.println("Tune Request");
      break;

    case usbMIDI.Clock: // 0xF8
      Serial.println("Clock");
      break;

    case usbMIDI.Start: // 0xFA
      Serial.println("Start");
      break;

    case usbMIDI.Continue: // 0xFB
      Serial.println("Continue");
      break;

    case usbMIDI.Stop: // 0xFC
      Serial.println("Stop");
      break;

    case usbMIDI.ActiveSensing: // 0xFE
      Serial.println("Actvice Sensing");
      break;

    case usbMIDI.SystemReset: // 0xFF
      Serial.println("System Reset");
      break;

    default:
      Serial.println("Opps, an unknown MIDI message type!");
  }
}

void printBytes(const byte *data, unsigned int size) {
  while (size > 0) {
    byte b = *data++;
    if (b < 16) Serial.print('0');
    Serial.print(b, HEX);
    if (size > 1) Serial.print(' ');
    size = size - 1;
  }
}
 
Last edited:
The different alternative functions of a pin don’t play a role here. After studying the MK20 reference manual, you will understand that there is an internal multiplexer (kind of crossbar switch) which allows to attribute exactly one specific hardware function to a pin, among a list of up to 8 different functions Alt0 to Alt7 which are individually different for each pin. Normally, you do not have to care about that. After boot, most pins are in analog or hi-z mode (Alt0) which is perfect for doing analog reads. Thus, as long as you do not explicitely switch the pin to another mode (i.e. setting it to GPIO with the pinMode() function), analogRead() would and should work as expected. If it doesn’t, check your code (I admit I’m too lazy to go through it line by line) if there is nothing which risks to reconfigure your pin either directly addressing the PIN number 15 or via one of its aliases (A1), thus having the pin MUX interfering with the ADC.

Edit: As I see at a first glance, you are configuring all photoresistor pins as INPUT with the pinMode() function. This is a no-no! Then, the ADC would measure the photo resistor in parallel with the GPIO engine for these pins which can provide different individual source impedances, depending on the different default GPIO pin settings for slew rate, drive strength and so on, which risks to give wrong results.

Precise (photo) resistor readings on the Teensy are only possible without the pin MUX interfering and with external pull-up or pull-down resistors.
 
The different alternative functions of a pin don’t play a role here. After studying the MK20 reference manual, you will understand that there is an internal multiplexer (kind of crossbar switch) which allows to attribute exactly one specific hardware function to a pin, among a list of up to 8 different functions Alt0 to Alt7 which are individually different for each pin. Normally, you do not have to care about that. After boot, most pins are in analog or hi-z mode (Alt0) which is perfect for doing analog reads. Thus, as long as you do not explicitely switch the pin to another mode (i.e. setting it to GPIO with the pinMode() function), analogRead() would and should work as expected. If it doesn’t, check your code (I admit I’m too lazy to go through it line by line) if there is nothing which risks to reconfigure your pin either directly addressing the PIN number 15 or via one of its aliases (A1), thus having the pin MUX interfering with the ADC.

Edit: As I see at a first glance, you are configuring all photoresistor pins as INPUT with the pinMode() function. This is a no-no! Then, the ADC would measure the photo resistor in parallel with the GPIO engine for these pins which can provide different individual source impedances, depending on the different default GPIO pin settings for slew rate, drive strength and so on, which risks to give wrong results.

Precise (photo) resistor readings on the Teensy are only possible without the pin MUX interfering and with external pull-up or pull-down resistors.

Hi, thank you so much for your reply.

I don't completely understand the response in your edit, however. This is the only manner in which I've ever defined input/output pins. What is the alternative? I should have said in my first post that the behavior I'm seeing is that the pin always reads at 1023 in all use cases and on different teensies. Thank you again!
 
To make it short: On the Teensy, pinMode() is for defining digital input and output pins. It should not be used for defining analog input pins (this is default for the corresponding pins). Setting a pin which is already by default an analog input pin into whatever digital mode with pinMode() risks to give wrong readings with analogRead() afterwards.

You ask “what is the alternative?” : Just use analogRead() on these pins without setting any pinMode() before.
 
To make it short: On the Teensy, pinMode() is for defining digital input and output pins. It should not be used for defining analog input pins (this is default for the corresponding pins). Setting a pin which is already by default an analog input pin into whatever digital mode with pinMode() risks to give wrong readings with analogRead() afterwards.

You ask “what is the alternative?” : Just use analogRead() on these pins without setting any pinMode() before.

Thanks again for your reply. Unfortunately I wasn't able to resolve it by removing the pinMode() references.

Try pinMode(15, INPUT_DISABLE)

This didn't help either, unfortunately. I'll keep trying to debug and will report back. Thanks again.
 
Looked at your code again just now. Can't see any reason why pin 15 would behave differently than 14, 16, 17, 18, 19.

The alternate functions of pin 15 aren't used. The situation is the same as all the other analog pins. They have alternate functions, but those other functions don't have access to the pin unless you manipulate the pin mux or touch sensor stuff. Your code doesn't seem to do any of that.
 
Thus I suspect an external (perhaps wiring) problem. What about schematics and pictures?

Apologies, I seem to have missed an email notification. Here is my schematic and eagle board view. I can upload pictures of my actual board as well however it's enclosed at the moment so difficult to get at.

Screen Shot 2018-12-07 at 2.11.22 AM.jpg

Screen Shot 2018-12-07 at 2.16.22 AM.jpg
 
Status
Not open for further replies.
Back
Top