MIDI.read causing incorrect Encoder readings.

Status
Not open for further replies.

cfredisded

Active member
Hi all,
I have a teensy 3.6 and was working on an audio project until I ran into a problem. When ever I start to send a midiclock signal into the teensy my program thinks I'm turning an encoder. This is only a problem when I use pin 1 and 2 for the encoder. Using Pin 3 and 4 for Encoder.read works as intended. When I remove MIDI.read from the code the encoder works as intended. I skimmed the code down to just the problem:

Code:
#include <MIDI.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#define ENCODER_DO_NOT_USE_INTERRUPTS //If you define ENCODER_DO_NOT_USE_INTERRUPTS *before* including Encoder, the library will never use interrupts.
#include <Encoder.h>

Encoder EncoderEnc(1, 2); 
//Encoder EncoderEnc(4, 3); //pins 4 and 3 connected to encoder works as intended. 

MIDI_CREATE_DEFAULT_INSTANCE();

//Global Variable
bool EncoderTurned;
long oldEncoderPos;
//Global Variable

void setup() {
  Serial.begin(9600);
  MIDI.begin(MIDI_CHANNEL_OMNI);
}
  
void loop(){
  if (MIDI.read()){  // Remove MIDI.read() and EncoderEnc.read() works as expected
  }
  
  ///Encoder Read///
  long newEncoderPos = EncoderEnc.read(); // When MIDI.read() is present EncoderEnc.read() returns a -1 once every 30 to 100 or so reads.
  if (newEncoderPos != oldEncoderPos){ 
    EncoderTurned = true;
    oldEncoderPos = newEncoderPos;
    Serial.println("Encoder Turned"); 
  }
  else{
    EncoderTurned = false;    
  }
  ///Encoder Read///
}

Does the Teensy think I am using pin 1 as a midi output or something?

Can anyone replicate this issue? If so I think this is a bug.
Any help is greatly appreciated.
 
Pin 0 and 1 is the hardware serial port, so if you are using conventional MIDI wiring there will be data there. It is MIDI out so it may be possible to partially disable the serial hardware in various ways but none of them trivial. Simpler option if at all possible is to leave the pin to be MIDI out.
 
Could Thru be on and its repeating the input.

Line 667 of file MIDI.hpp. shows thru is called at read. Maybe it's resetting the pin's state even when a Thru is off??

If you comment that out you can eliminate or confirm Thru as the source.

BTW... Do you really really need pin 1 for something else?
 
The problem is more the line
Serial.begin(9600);
Which will set pin 1 as an output driven by the serial out buffer, so regardless of the MIDI stuff there will be a problem using it as an encoder input. There is a very real risk of damage to the pin if you have the encoder rotated to short it to ground.
So to get this to work you would need to configure the Serial hardware to NOT be connected to pin 1, and there is not an Arduino way to do that, this will involve directly setting the hardware registers the way you want.
 
If you really want to use pin one for something else you need to do either set TX pin to be pin 5 is it is free https://www.pjrc.com/teensy/td_uart.html , manually disable the port config bits or possibly simple comment out this section of Serial.Begin in your arduino installation/hardware/teensy/cores/teensy3/serial1
Code:
	switch (tx_pin_num) {
		case 1:  CORE_PIN1_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break;
		case 5:  CORE_PIN5_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break;
		#if defined(KINETISL)
		case 4:  CORE_PIN4_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2); break;
		case 24: CORE_PIN24_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(4); break;
		#endif
		#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
		case 26: CORE_PIN26_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break;
		#endif
Which should avoid it becoming active in the first place
It may also be possible to simple put
Serial1.setTX(34);
before your Serial1.Begin(9600);
in your setup, which due to the above code not throwing exceptions if passed an illegal pin may just never assign a TX pin in the first place, have not yet actually dug out a spare teensy to test with.
 
The problem is more the line
Serial.begin(9600);
Which will set pin 1 as an output driven by the serial out buffer, so regardless of the MIDI stuff there will be a problem using it as an encoder input. There is a very real risk of damage to the pin if you have the encoder rotated to short it to ground.
So to get this to work you would need to configure the Serial hardware to NOT be connected to pin 1, and there is not an Arduino way to do that, this will involve directly setting the hardware registers the way you want.
I wasnt having any issues with my project until I added the MIDI.read but ill keep that in mind for future projects. Thanks

Could Thru be on and its repeating the input.

Line 667 of file MIDI.hpp. shows thru is called at read. Maybe it's resetting the pin's state even when a Thru is off??

If you comment that out you can eliminate or confirm Thru as the source.

BTW... Do you really really need pin 1 for something else?

I did switch over to use another pin. But it looks like you were right. Commenting out line 667 of the midi.hpp "thruFilter(inChannel);" did indeed fix the encoder acting erroneously. Thank You.
 
Status
Not open for further replies.
Back
Top