Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

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

  1. #1
    Junior Member
    Join Date
    Dec 2018
    Posts
    4

    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 by obbligato; 12-02-2018 at 05:44 AM.

  2. #2
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,068
    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.

  3. #3
    Junior Member
    Join Date
    Dec 2018
    Posts
    4
    Quote Originally Posted by Theremingenieur View Post
    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!

  4. #4
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,068
    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.

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,691
    Try pinMode(15, INPUT_DISABLE)

  6. #6
    Junior Member
    Join Date
    Dec 2018
    Posts
    4
    Quote Originally Posted by Theremingenieur View Post
    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.

    Quote Originally Posted by PaulStoffregen View Post
    Try pinMode(15, INPUT_DISABLE)
    This didn't help either, unfortunately. I'll keep trying to debug and will report back. Thanks again.

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,691
    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.

  8. #8
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,068
    Thus I suspect an external (perhaps wiring) problem. What about schematics and pictures?

  9. #9
    Junior Member
    Join Date
    Dec 2018
    Posts
    4
    Quote Originally Posted by Theremingenieur View Post
    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.

    Click image for larger version. 

Name:	Screen Shot 2018-12-07 at 2.11.22 AM.jpg 
Views:	14 
Size:	90.2 KB 
ID:	15306

    Click image for larger version. 

Name:	Screen Shot 2018-12-07 at 2.16.22 AM.jpg 
Views:	10 
Size:	144.1 KB 
ID:	15307

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •