I2C clock signal interference from ATmega328 input pin 13

In I2C communications the ATmega pin A5 is used for clocking.
In a project I also have this pin A5 connected to ATmega pin 13 (due to dual schematic use for SPI, either-or).
I discovered that connecting pin 13 to the SCL line does interfere with the I2C clock signal.

  1. why is that (pin 13, by default, is an input hence high impedance)?
  2. can this be resolved in software?

Below a picture of the SCL line when connected to pin 13 of the ATmega328

Here a picture of a clean SCL signal (disconnected from pin 13 of the ATmega328)

And here the schematic used:
JMRI-CMRI_turnoutcontroller_MCP23S17_v3.pdf (23.9 KB)

EDIT: pin 13 apparently also is connected to the built-in LED (see schematic below). But why does this then not interfere when pin 13 is used in SPI mode (as a clock pin as well)?
Arduino Pro Mini Schematic.pdf (59.1 KB)

Does the code which you are using either include the SPI library or issue an SPI.begin() which may force the pin 13 (SCK) to OUTPUT ?
To rule out such effects , including the built-in led, try another pin for this test.

SPI.h is used only when the code is set to do so:

// Enable the following line to compile for SPI, comment for I2C
// #define COMPILE_FOR_SPI
// Enable the following line to compile with debug printout
#define DEBUG

#ifdef COMPILE_FOR_SPI
#include <SPI.h>
#endif

Full code may be provided if required.

EDIT: with pin 13 disconnected there is no issue. But on my PCB that will create another soldering pad which I would like to avoid if possible

What is the state of the solder jumper JP4 and where was the measuring point, on your board, for your trace with pin 13 connected?
Consider removing the built-in led or its current limiting resistor from the arduino board

Solder jumper JP4 is bridged (as is JP5).
The oscilloscope measured on the SCL/SCK line (the wire linking A5, pin 13 of the ATmega328 and pin 12 of the MCP23017.

Removal of R6 (the series LED resistor) does not solve the issue, but the signal from A5 (SCL) looks a bit better (compared to picture 20, the first picture in the first post):

You should supply the full code then. Did the led glow permanently before you removed it?

No LED glow when built-in led was still connected.

#define GPIO_ADDR     0x27 // LCD I2C address

// Enable the following line to compile for SPI, comment for I2C
// #define COMPILE_FOR_SPI
// Enable the following line to compile with debug printout
#define DEBUG

#ifdef COMPILE_FOR_SPI
#include <SPI.h>
#endif

#include <LCD.h>
#include <Wire.h>
#include <EEPROM.h>
#include <VarSpeedServo.h>
#include <LiquidCrystal_I2C.h>
#include "MCP23S17.h"
#include "ServoDefaults.h"

LiquidCrystal_I2C lcd(GPIO_ADDR, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

// Comment out the following define to re-load EEPROM
//#define SERVOS_LOADED

#define TWI_FREQ_PCA      400000L     // Sets the I2C speed to 400KHz

#define MCP_ADDRESS         0x20      // MCP address (all address bits grounded)

#define NUMBER_SERVOS          8      // Number of servos handled by the MCP23S17
#define ENTRIES_PER_SERVO      4      // Number of EEPROM entries reserved for each servo

// Create lcd instance
// LiquidCrystal_I2C lcd(0x27,20,4);           // Set the I2C address and display size.

// Create an instance for each servo
VarSpeedServo varServo[NUMBER_SERVOS];      // Create NUMBER_SERVOS servo instances to control the servos
// A maximum of eight servo objects can be created
uint8_t SERVOpin[] = {4, 5, 6, 7, 8, 9, A0, A1}; // Define the drive pins for each servo

#ifdef COMPILE_FOR_SPI
const uint8_t SPIslave = 0x20;                        // MCP23S17 address, all ADDR pins are grounded
const uint8_t MCP_WRITE = (SPIslave << 1 | 0x00);     // MCP23S17 opcode write has LSB clear
const uint8_t MCP_READ  = (SPIslave << 1 | 0x01);     // MCP23S17 opcode read  has LSB set
#endif

#define MASTER_RESET  120       // THIS IS THE ADDRESS FOR A FULL RESET - Set = 120

// Rotary Encoder defines and global (volatile) variables
#define ENC_SWITCH  A3            // Encoder switch pin
#define PIN_A  2                  // Hardware interrupt pin 2 (interupt 0)
#define PIN_B  3                  // Hardware interrupt pin 3 (interupt 1)
volatile byte aFlag = 0;          // Flag to expect a rising edge on pinA to signal a detent
volatile byte bFlag = 0;          // Flag to expect a rising edge on pinB to signal a detent (opposite direction to when aFlag is set)
volatile int16_t encoderValue;    // Current encoder value.

struct QUEUE  {
  bool inUse;
  uint8_t direction;
  uint8_t servoSpeed;
  uint8_t straightAngle;
  uint8_t divergeAngle;
  uint8_t currentAngle;
  uint32_t timeOut;
};
QUEUE* servoQueue = new QUEUE[NUMBER_SERVOS];

uint8_t interruptPin = PC2;     // Pin A2
uint16_t detachDelay;           // Variable for servo detach delay

///////////////////////////////////////////////////////////////////////////////
//
void setup() {
  // put your setup code here, to run once:
#ifdef DEBUG
  Serial.begin(9600);
  delay(250);
  Serial.println("DCCpp_Willem_turnoutcontroller_single_MCP_v4.ino");
  Serial.println();
#endif

#ifdef COMPILE_FOR_SPI
  pinMode(SS, OUTPUT);                    // Configure controller's Slave Select pin to output
  digitalWrite(SS, HIGH);                 // Disable Slave Select (pin 10)
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV8);    // Divide the SPI clock by 8
#endif
  Wire.begin();
  Wire.setClock(TWI_FREQ_PCA);            // Switch the I2C speed to 400KHz

  // Setup Rotary Encoder
  pinMode(ENC_SWITCH, INPUT_PULLUP);
  pinMode(PIN_A, INPUT_PULLUP);             // set pinA as an input, pulled HIGH to the logic voltage
  pinMode(PIN_B, INPUT_PULLUP);             // set pinB as an input, pulled HIGH to the logic voltage
  attachInterrupt(0, encoderPinA, RISING);  // set an interrupt on PinA, looking for a rising edge signal and
  // executing the "PinA" Interrupt Service Routine (below)
  attachInterrupt(1, encoderPinB, RISING);  // set an interrupt on PinB, looking for a rising edge signal and
  // executing the "PinB" Interrupt Service Routine (below)

  //  DDRB |= (1 << PB0);                       // Set pins PB0 (pin 8) as output

  // If not already saved, save the default Servos values to EEPROM
#ifdef SERVOS_LOADED
  if ( readEEPROM(MASTER_RESET) == MASTER_RESET )  // This entry is initialised = 0; Set = MASTER_RESET to force reset
#endif
  {
    for (uint16_t servo = 0; servo < sizeof(servoDefaults) / sizeof(servoPair); servo++ )
      writeEEPROM( servoDefaults[servo].Servo, servoDefaults[servo].Value);
  }

  // Initialize the MCP23017
  MCP_begin();

  // Initialize the Queue enabling all servos
  Serial.println("Setting up the servoQueue.");
  for ( uint8_t servo = 0; servo < NUMBER_SERVOS; servo++ ) {
    uint16_t servoOffset = servo * ENTRIES_PER_SERVO;
    servoQueue[servo].inUse = true;
    servoQueue[servo].servoSpeed = int (readEEPROM(34 + servoOffset));
    servoQueue[servo].straightAngle = int (readEEPROM(35 + servoOffset));
    servoQueue[servo].divergeAngle = int (readEEPROM(36 + servoOffset));
    servoQueue[servo].currentAngle = int (readEEPROM(37 + servoOffset));
    servoQueue[servo].direction = 2;    // Initially set to non valid value

#ifdef DEBUG
    Serial.print("speed = ");
    Serial.print(servoQueue[servo].servoSpeed);
    Serial.print("; straight = ");
    Serial.print(servoQueue[servo].straightAngle);
    Serial.print("; divert = ");
    Serial.print(servoQueue[servo].divergeAngle);
    Serial.print("; current = ");
    Serial.println(servoQueue[servo].currentAngle);
#endif

    // Write servo position and attach it
    varServo[servo].write(servoQueue[servo].currentAngle, 50, false);
    varServo[servo].attach(SERVOpin[servo]);     // attaches the servo to its pin
  }
  detachDelay = uint16_t (readEEPROM(33)) * 10;
  Serial.print("servoQueue done. - ");
  Serial.println(detachDelay);

#ifdef DEBUG
  // Temporary debug printout
#ifdef COMPILE_FOR_SPI
  uint8_t IntCap = readSPIbyte(INTFA);    // Read INTFA
#else
  uint8_t IntCap = readMCPbyte(INTFA);    // Read INTFA
#endif
  Serial.print("INTFA:");
  Serial.print(IntCap, HEX);

#ifdef COMPILE_FOR_SPI
  IntCap = readSPIbyte(INTFB);            // Read INTFB
#else
  IntCap = readMCPbyte(INTFB);            // Read INTFB
#endif
  Serial.print(" B:");
  Serial.println(IntCap, HEX);
#endif
}

///////////////////////////////////////////////////////////////////////////////
//
void loop() {

  // Check if any servos should be detached
  for ( uint8_t servo = 0; servo < NUMBER_SERVOS; servo++ ) {
    // Check if servo is in use
    if ( servoQueue[servo].inUse )  {
      // Has servo reached destination angle? If so, remove from use and set timeout
      if ( varServo[servo].read() == servoQueue[servo].currentAngle )  {
        servoQueue[servo].inUse = false;
        servoQueue[servo].timeOut = millis();
      }
    }  else  {
      // If servo is still attached and timeout has lapsed, detach
      if ( varServo[servo].attached() && ((millis() - servoQueue[servo].timeOut) >= detachDelay) )
        varServo[servo].detach();
    }
  }

  // Check for interrupt on MCP23x17
  if ( PINC & (1 << interruptPin) ) {
    checkMCP();
  }

  // Check if the emcoder switch was pressed to start setup
  if ( readEncSwitch() )
    servoMenu();

}

///////////////////////////////////////////////////////////////////////////////
//
void checkMCP() {

#ifdef COMPILE_FOR_SPI
  uint16_t intFlags = readSPIword( (uint8_t)INTFA );      // Read both interrupt flag registers
#else
  uint16_t intFlags = readMCPword( (uint8_t)INTFA );
#endif

#ifdef DEBUG
  Serial.print("INTF:");
  Serial.print(intFlags, HEX);
#endif

  if ( intFlags > 0 )  {
    // separate the interrupts for INTFA and INTFB
    uint8_t intFlagsA = intFlags & 0x00FF;
    uint8_t intFlagsB = (intFlags >> 8);
#ifdef DEBUG
    Serial.print("; flags B:A = ");
    Serial.print(intFlagsB, HEX);
    Serial.print(":");
    Serial.print(intFlagsA, HEX);
#endif
    // Read the capture registers which also clears the interrupt flags registers
    delay(50);  // Add a possible debounce delay

#ifdef COMPILE_FOR_SPI
    uint16_t captureStatus = readSPIword( (uint8_t)INTCAPA );       // Read both interrupt capture registers
#else
    uint16_t captureStatus = readMCPword( (uint8_t)INTCAPA );       // Read both interrupt capture registers
#endif

#ifdef DEBUG
    Serial.print("; INTCAP = ");
    Serial.print(captureStatus, HEX);
#endif

    // If interrupt is for GPIOA set servo to straight
    if ( intFlagsA ) {
      for ( int8_t servo = 0; servo < NUMBER_SERVOS; servo++ )  {   // Checking NUMBER_SERVOS intFlags bits
        if ( intFlagsA & (1 << servo) ) {
          // If the captureStatus bit is low update the servo direction - else ignore
          if  ( !(captureStatus & (1 << servo)) ) {                 // Check against low byte of captureStatus
            //            if ( 0b01010101 & (1 << servo) ) {
            if ( 0b01010101 & (1 << servo) ) {
              setServo(servo / 2, 0);
#ifdef DEBUG
              Serial.print("; Servo-");
              Serial.print(servo / 2);
              Serial.print(" = Straight");
#endif
            }
            else {
              setServo(servo / 2, 1);
#ifdef DEBUG
              Serial.print("; Servo-");
              Serial.print(servo / 2);
              Serial.print(" = Divert");
#endif
            }
          }
        }
      }
    }

    // If interrupt is for GPIOB set servo to divert
    if ( intFlagsB ) {
      for ( int8_t servo = 0; servo < NUMBER_SERVOS; servo++ )  {   // Checking NUMBER_SERVOS intFlags bits
        if ( intFlagsB & (1 << servo) ) {
          // If the captureStatus bit is low update the servo direction - else ignore
          if  ( !(captureStatus & (1 << (servo + 8))) ) {           // Check against high byte of captureStatus
            //            if ( 0b01010101 & (1 << servo) ) {
            if ( 0b01010101 & (1 << servo) ) {
              setServo(4 + servo / 2, 0);
#ifdef DEBUG
              Serial.print("; Servo-");
              Serial.print(4 + servo / 2);
              Serial.print(" = Straight");
#endif
            }
            else {
              setServo(4 + servo / 2, 1);
#ifdef DEBUG
              Serial.print("; Servo-");
              Serial.print(4 + servo / 2);
              Serial.print(" = Divert");
#endif
            }
          }
        }
      }
    }

  }
#ifdef DEBUG
  Serial.println();
#endif
}

///////////////////////////////////////////////////////////////////////////////
// Servo direction: 0 - Straight; 1 - Divert
void setServo(int16_t servo, int8_t direction) {

  if ( direction != servoQueue[servo].direction ) {
    switch ( direction )  {
      case 0:   // Change to straight
        varServo[servo].write(servoQueue[servo].straightAngle, servoQueue[servo].servoSpeed, false);
        servoQueue[servo].currentAngle = servoQueue[servo].straightAngle;
        servoQueue[servo].direction = 0;
        break;
      case 1:   // Change to divert
        varServo[servo].write(servoQueue[servo].divergeAngle, servoQueue[servo].servoSpeed, false);
        servoQueue[servo].currentAngle = servoQueue[servo].divergeAngle;
        servoQueue[servo].direction = 1;
        break;
    }

    if ( !servoQueue[servo].inUse )  {
      servoQueue[servo].inUse = true;
      varServo[servo].attach(SERVOpin[servo]);
    }

#ifdef DEBUG
    Serial.print(" Servo -> Speed = ");
    Serial.print(servoQueue[servo].servoSpeed);
    Serial.print("; Set Target = ");
    Serial.print(servoQueue[servo].currentAngle);
#endif
  }
}

///////////////////////////////////////////////////////////////////////////////
//
void MCP_begin()  {
  // NOTE: The following register addresses assume IOCON.BANK = 0
  // Setup MCP23017 Ports - PortA all inputs with pull-up
#ifdef COMPILE_FOR_SPI

  // ... - Port A all inputs with pull-up
  writeSPIbyte(IODIRA, 0xFF);               // Set MCP23017 Port A as all Input (0=output; 1=input)
  writeSPIbyte(GPPUA, 0xFF);                // Enable internal pullup for Port A inputs

  // ... - Port B all inputs with pull-up
  writeSPIbyte(IODIRB, 0xFF);               // Set MCP23017 Port B as all Input (0=output; 1=input)
  writeSPIbyte(GPPUB, 0xFF);                // Enable internal pullup for Port B inputs

  // Interrupt_On_Change for all pins on both Ports
  writeSPIbyte(GPINTENA, 0xFF);             // GPINTENA - Enable all bits for Int_On_Change
  writeSPIbyte(GPINTENB, 0xFF);             // GPINTENB - Enable all bits for Int_On_Change

  // Set a default value for when Interrupt_On_Change from default value is used for both Ports
  writeSPIbyte(DEFVALA, 0xFF);             // DEFVALA - Set default value to all HIGH
  writeSPIbyte(DEFVALB, 0xFF);             // DEFVALB - Set default value to all HIGH

  // Set Interrupt_On_Change from previous for both Ports
  writeSPIbyte(INTCONA, 0x00);              // INTCONA - Set all bits for trigger on change from previous
  writeSPIbyte(INTCONB, 0x00);              // INTCONB - Set all bits for trigger on change from previous

  // Set INT pins MIRRORed and INT active high
  writeSPIbyte(IOCON, 0x42);                // IOCON - Interrupt Mirror and Interrupt active high

  // Read GPIOA & B to clear all possible interrupts
#ifdef DEBUG
  uint16_t intGPIO = readSPIword(GPIOA);
  Serial.print("Init GPIOA = ");
  Serial.println(intGPIO, HEX);
#else
  readSPIword(GPIOA);
#endif

#else

  writeMCPbyte(IODIRA, 0xFF);               // Set MCP23017 Port A as all Input (0=output; 1=input)
  writeMCPbyte(GPPUA, 0xFF);                // Enable internal pullup for Port A inputs

  // ... - PortB all inputs with pull-up
  writeMCPbyte(IODIRB, 0xFF);               // Set MCP23017 Port B as all Input (0=output; 1=input)
  writeMCPbyte(GPPUB, 0xFF);                // Enable internal pullup for Port B inputs

  // Interrupt_On_Change for all pins on both Ports
  writeMCPbyte(GPINTENA, 0xFF);             // GPINTENA - Enable all bits for Int_On_Change
  writeMCPbyte(GPINTENB, 0xFF);             // GPINTENB - Enable all bits for Int_On_Change

  // Set a default value for when Interrupt_On_Change from default value is used for both Ports
  writeMCPbyte(DEFVALA, 0xFF);             // DEFVALA - Set default value to all HIGH
  writeMCPbyte(DEFVALB, 0xFF);             // DEFVALB - Set default value to all HIGH

  // Set Interrupt_On_Change from previous for both Ports
  writeMCPbyte(INTCONA, 0x00);              // INTCONA - Set all bits for trigger on change from previous
  writeMCPbyte(INTCONB, 0x00);              // INTCONB - Set all bits for trigger on change from previous

  // Set INT pins MIRRORed and INT active high
  writeMCPbyte(IOCON, 0x42);                // IOCON - Interrupt Mirror and Interrupt active high

  // Read GPIOA & B to clear all possible interrupts
#ifdef DEBUG
  uint16_t intGPIO = readMCPword(GPIOA);
  Serial.print("Init GPIOA = ");
  Serial.println(intGPIO, HEX);
#else
  readMCPword(GPIOA);
#endif

#endif
}

///////////////////////////////////////////////////////////////////////////////
//
uint16_t readMCPword(uint8_t port) {
  Wire.beginTransmission(MCP_ADDRESS);
  Wire.write(port);                         // set MCP23017 register pointer
  Wire.endTransmission();
  Wire.requestFrom(MCP_ADDRESS, 2);         // request two bytes of data
  uint16_t value = Wire.read() & 0xFF;      // Read from PortA
  value |= (Wire.read() << 8);              // Read from PortB
  return value;                             // read and return the requested byte
}

///////////////////////////////////////////////////////////////////////////////
//
uint8_t readMCPbyte(uint8_t port) {
  Wire.beginTransmission(MCP_ADDRESS);
  Wire.write(port);                         // set MCP23017 register pointer
  Wire.endTransmission();
  Wire.requestFrom(MCP_ADDRESS, 1);         // request a single byte of data from PortA
  return Wire.read();                       // read and return the requested byte
}

///////////////////////////////////////////////////////////////////////////////
//
void writeMCPbyte(uint8_t port, uint8_t value)  {
  Wire.beginTransmission(MCP_ADDRESS);
  Wire.write(port);         // Set required port
  Wire.write(value);        // Load value into port
  Wire.endTransmission();
}

#ifdef COMPILE_FOR_SPI

///////////////////////////////////////////////////////////////////////////////
//
uint16_t readSPIword(uint8_t port) {

  SPI.beginTransaction(SPISettings (SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); // Gain control of SPI bus

  PORTB &= ~0x04;             // Write SS (pin 10) LOW

  SPI.transfer(MCP_READ);     // Read command
  SPI.transfer(port);         // Register address to read data from
  uint16_t SPIdata = SPI.transfer(0) & 0xFF;     // Save the data (0 is dummy data to send)
  SPIdata |= (SPI.transfer(0) << 8);

  PORTB |= 0x04;              // Write SS HIGH

  SPI.endTransaction();       // Release the SPI bus

  return SPIdata;
}

///////////////////////////////////////////////////////////////////////////////
//
uint8_t readSPIbyte(byte port) {

  SPI.beginTransaction(SPISettings (SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); //gain control of SPI bus

  PORTB &= ~0x04;             // Write SS LOW

  SPI.transfer(MCP_READ);     // read command
  SPI.transfer(port);         // register address to read data from
  uint8_t SPIdata = SPI.transfer(0);     // save the data (0 is dummy data to send)

  PORTB |= 0x04;              // Write SS HIGH

  SPI.endTransaction();       //release the SPI bus

  return SPIdata;
}

///////////////////////////////////////////////////////////////////////////////
//
void writeSPIbyte(uint8_t port, uint8_t value)  {

  SPI.beginTransaction(SPISettings (SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); //gain control of SPI bus

  PORTB &= ~0x04;             // Write SS low

  SPI.transfer(MCP_WRITE);    // read command
  SPI.transfer(port);         // register address to read data from
  SPI.transfer(value);        // register address to read data from

  PORTB |= 0x04;              // Write SS HIGH

  SPI.endTransaction();       //release the SPI bus
}

#endif

///////////////////////////////////////////////////////////////////////////////
//
uint8_t readEEPROM( uint16_t Servo )  {
  uint8_t Value;

  Value = EEPROM.read(Servo);

  return Value;
}

///////////////////////////////////////////////////////////////////////////////
//
uint8_t writeEEPROM( uint16_t Servo, uint8_t Value )  {

  /*  if ( EEPROM.read(Servo) != Value )  {
      EEPROM.write(Servo,Value);
    }  */
  EEPROM.update(Servo, Value);

  return EEPROM.read(Servo);
}

///////////////////////////////////////////////////////////////////////////////
//
void servoMenu() {
  uint8_t encSwitchStatus;
  uint8_t oldEncValue;            // used as hold limit for the previous encoder position value.
  uint8_t servo;                // the address of servo to be adjusted
  bool exitSet = false;
  bool switchPressed = false;

  oldEncValue = 0;
  encoderValue = 0;
  servo = 0;

  // Initialise LCD display
  lcd.begin(20, 4);               // initialize the LCD
  lcd.clear();
  // lcd.noBacklight();          // Turn off the backlight

  showMenu(0, 0);

  lcd.setCursor(19, 0);
  lcd.print("<");
  // lcd.backlight();          // Turn off the backlight

  while ( !exitSet )  {
    if ( oldEncValue != encoderValue )  {               // Encoder was rotated - update the current servo
      encoderValue = constrain( encoderValue, 0, 2);    // Ensure encoderValue is within bounds
      lcd.setCursor(19, oldEncValue);
      lcd.print(" ");
      lcd.setCursor(19, encoderValue);
      lcd.print("<");
      oldEncValue = encoderValue;
    }

    encSwitchStatus = readEncSwitch();                  // Read the Encoder switch

    if ( encSwitchStatus && !switchPressed )  {
      switchPressed = true;
    }
    if ( switchPressed )  {
      switch ( encoderValue ) {
        case 0:
          servo = selectServo(servo);
          showMenu(0, servo);
          lcd.setCursor(19, 0);
          lcd.print("<");
          break;
        case 1:
          setAngles(servo);
          showMenu(0, servo);
          lcd.setCursor(19, 1);
          lcd.print("<");
          break;
        case 2:
          lcd.clear();
          lcd.noBacklight();          // Turn off the backlight
          exitSet = true;
          break;
      }
      switchPressed = false;
      encoderValue = oldEncValue;
      while ( readEncSwitch() );      // ensure encoder switch released
    }
  }
}

///////////////////////////////////////////////////////////////////////////////
//
uint8_t selectServo(uint8_t servo) {
  uint8_t encSwitchStatus;
  uint8_t oldEncValue;            // used as hold limit for the previous encoder position value.
  bool exitSet = false;

  oldEncValue = servo;
  encoderValue = servo;

  // Initialise LCD display for servo ID
  showMenu(1, servo);

  while ( readEncSwitch() );       // ensure encoder switch released

  while ( !exitSet )  {
    if ( oldEncValue != encoderValue )  {               // Encoder was rotated - update the current servo
      encoderValue = constrain( encoderValue, 0, NUMBER_SERVOS - 1);    // Ensure encoderValue is within bounds
      lcd.setCursor(17, 1);
      lcd.print(encoderValue);
      lcd.print(" ");
      oldEncValue = encoderValue;
    }

    encSwitchStatus = readEncSwitch();                  // Read the Encoder switch

    if ( encSwitchStatus )
      exitSet = true;
  }
  return encoderValue;
}

///////////////////////////////////////////////////////////////////////////////
//
void setAngles(uint8_t servo) {
  uint32_t timePressed = 0;       // Time when switch status changed
  uint8_t encSwitchStatus;
  uint8_t oldEncValue;            // used as hold limit for the previous encoder position value.
  bool exitSet = false;
  bool switchPressed = false;

  uint8_t straightAngle = servoQueue[servo].straightAngle;
  uint8_t divertAngle = servoQueue[servo].divergeAngle;
  uint8_t direction = 0;
  oldEncValue = straightAngle;
  encoderValue = straightAngle;

  // Move servo to initially straight
  sendServoAngle(servo, straightAngle);

  // Initialise LCD display for setting angles
  showMenu(2, servo);
  lcd.setCursor(19, 1);
  lcd.print("<");

  while ( readEncSwitch() );       // ensure encoder switch released

  while ( !exitSet )  {
    if ( oldEncValue != encoderValue )  {                 // Encoder was rotated - update the current servo
      encoderValue = constrain( encoderValue, 0, 180);    // Ensure encoderValue is within bounds
      switch ( direction ) {
        case 0:   // straight
          straightAngle = encoderValue;
          lcd.setCursor(15, 1);
          break;
        case 1:   // straight
          divertAngle = encoderValue;
          lcd.setCursor(15, 2);
          break;
      }
      sendServoAngle(servo, encoderValue);
      lcd.print(encoderValue);
      lcd.print(" ");
      oldEncValue = encoderValue;
    }

    encSwitchStatus = readEncSwitch();                  // Read the Encoder switch

    if ( encSwitchStatus && !switchPressed )  {
      timePressed = millis();
      switchPressed = true;
    }
    if ( switchPressed )  {
      if ( encSwitchStatus )  {                         // Switch currently pressed
        if ( (millis() - timePressed) >= 1200 )  {      // Hold for 1.2sec to exit setup function
          // Ensure current direction angle gets set before save
          switch ( direction )  {
            case 0:   // Straight
              straightAngle = encoderValue;
              break;
            case 1:   // Divert
              divertAngle = encoderValue;
              break;
          }
          // Save the new angles to EEPROM
          if ( writeAngles(servo, straightAngle, divertAngle) ) {
            servoQueue[servo].straightAngle = straightAngle;
            servoQueue[servo].divergeAngle = divertAngle;
          } else
            sendServoAngle(servo, servoQueue[servo].straightAngle);
          exitSet = true;
        }
      } else {
        switch ( direction )  {                    // Save current direction angle and set for new
          case 0:   // From straight to divert
            straightAngle = encoderValue;
            encoderValue = divertAngle;
            lcd.setCursor(19, 1);
            lcd.print(" ");
            lcd.setCursor(19, 2);
            lcd.print("<");
            break;
          case 1:   // From divert to straight
            divertAngle = encoderValue;
            encoderValue = straightAngle;
            lcd.setCursor(19, 2);
            lcd.print(" ");
            lcd.setCursor(19, 1);
            lcd.print("<");
            break;
        }
        direction = ( direction ) ? 0 : 1;        // Toggle active servo direction
        switchPressed = false;
      }
    }
  }
}

///////////////////////////////////////////////////////////////////////////////
//
void sendServoAngle(int servo, int angle)  {

  varServo[servo].write(angle, 0, false);
  if ( !servoQueue[servo].inUse )  {
    servoQueue[servo].inUse = true;
    varServo[servo].attach(SERVOpin[servo]);
  }

}

///////////////////////////////////////////////////////////////////////////////
//
bool writeAngles(int servo, int straight, int divert)  {
  uint8_t encSwitchStatus;
  uint8_t oldEncValue;            // used as hold limit for the previous encoder position value.
  bool exitSet = false;
  bool exitStatus = false;

  oldEncValue = 1;
  encoderValue = 1;

  showMenu(3, servo);
  lcd.setCursor(19, 1);
  lcd.print("<");

  while ( readEncSwitch() );      // ensure encoder switch released

  while ( !exitSet )  {
    if ( oldEncValue != encoderValue )  {                 // Encoder was rotated - update the current servo
      encoderValue = constrain( encoderValue, 1, 2);    // Ensure encoderValue is within bounds
      lcd.setCursor(19, oldEncValue);
      lcd.print(" ");
      lcd.setCursor(19, encoderValue);
      lcd.print("<");
      oldEncValue = encoderValue;
    }

    encSwitchStatus = readEncSwitch();                  // Read the Encoder switch

    if ( encSwitchStatus )  {
      if ( encoderValue == 2 ) {
        uint8_t servoOffset = servo * ENTRIES_PER_SERVO;
        writeEEPROM(35 + servoOffset, straight);
        writeEEPROM(36 + servoOffset, divert);
        exitStatus = true;
      }
      exitSet = true;
      while ( readEncSwitch() );      // ensure encoder switch released
    }
  }
  return exitStatus;
}

///////////////////////////////////////////////////////////////////////////////
//
void showMenu(uint8_t menu, uint8_t servo) {
  lcd.clear();
  for (int k = 0; k < 4; k++) {    // clear LCD
    for (int j = 0; j < 16; j++) {
      lcd.setCursor(j, k);
      lcd.print(" ");
    }
  }
  switch (menu) {
    case 0:
      lcd.setCursor(0, 0);
      lcd.print("Select Servo (");
      lcd.print(servo);
      lcd.print(") ");
      lcd.setCursor(0, 1);
      lcd.print("Set Servo Angles");
      lcd.setCursor(0, 2);
      lcd.print("Exit");
      break;
    case 1:
      lcd.setCursor(3, 0);
      lcd.print("Select Servo");
      lcd.setCursor(0, 1);
      lcd.print("Required Servo - ");
      lcd.print(servo);
      break;
    case 2:
      lcd.setCursor(3, 0);
      lcd.print("Adjust Servo ");
      lcd.print(servo);
      lcd.setCursor(0, 1);
      lcd.print("Straight Angle ");
      lcd.print(servoQueue[servo].straightAngle);
      lcd.setCursor(0, 2);
      lcd.print("Divert Angle   ");
      lcd.print(servoQueue[servo].divergeAngle);
      lcd.setCursor(0, 3);
      lcd.print(" Long press to Exit");
      break;
    case 3:
      lcd.setCursor(2, 0);
      lcd.print("Save new angles? ");
      lcd.setCursor(10, 1);
      lcd.print("No  ");
      lcd.setCursor(10, 2);
      lcd.print("Yes ");
      break;
  }

}

///////////////////////////////////////////////////////////////////////////////
//
int8_t readEncSwitch()  {
  // switch debounce values
  static uint8_t nDebounce = 150;         // 50;
  static uint32_t lTimeOfChange = 0;      // Time when button state changed
  static int8_t lastStatus = 0;

  //  int encSwitch;

  if ( (millis() - lTimeOfChange) >= nDebounce )  {
    int encSwitch = !digitalRead(ENC_SWITCH);    // Read the Encoder switch (low = pressed so invert)

    if ( encSwitch != lastStatus )  {
      lastStatus = encSwitch;
      lTimeOfChange = millis();
    }
  }
  return lastStatus;
}

///////////////////////////////////////////////////////////////////////////////
//
void encoderPinA() {
  byte reading;

  cli(); // stop interrupts happening before we read pin values
  reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
  if (reading == B00001100 && aFlag) {      // check that we have both pins at detent (HIGH) and that we are expecting
    // detent on this pin's rising edge
    encoderValue -= 1;                      // decrement the encoder's position count

    bFlag = 0;                              // reset flags for the next turn
    aFlag = 0;                              // reset flags for the next turn
  }
  else if (reading == B00000100) bFlag = 1; // signal that we're expecting pinB to signal the transition to
  // detent from free rotation
  sei(); //restart interrupts
}

///////////////////////////////////////////////////////////////////////////////
//
void encoderPinB() {
  byte reading;

  cli(); // stop interrupts happening before we read pin values
  reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
  if (reading == B00001100 && bFlag) {      // check that we have both pins at detent (HIGH) and that we are expecting
    // detent on this pin's rising edge
    encoderValue += 1;                      // increment the encoder's position count

    bFlag = 0;                              // reset flags for the next turn
    aFlag = 0;                              // reset flags for the next turn
  }
  else if (reading == B00001000) aFlag = 1; // signal that we're expecting pinA to signal the transition to
  // detent from free rotation
  sei(); //restart interrupts
}

And MCP23S17.h:

// MCP23017 registers (everything except direction defaults to 0)
#define IODIRA    0x00    // IO direction  (0 = output, 1 = input (Default))
#define IODIRB    0x01
#define IOPOLA    0x02    // IO polarity   (0 = normal, 1 = inverse)
#define IOPOLB    0x03
#define GPINTENA  0x04    // Interrupt on change (0 = disable, 1 = enable)
#define GPINTENB  0x05
#define DEFVALA   0x06    // Default comparison for interrupt on change (interrupts on opposite)
#define DEFVALB   0x07
#define INTCONA   0x08    // Interrupt control (0 = interrupt on change from previous, 1 = interrupt on change from DEFVAL)
#define INTCONB   0x09
#define IOCON     0x0A    // IO Configuration: bank/mirror/seqop/disslw/haen/odr/intpol/notimp
//#define IOCON     0x0B    // same as 0x0A
#define GPPUA     0x0C    // Pull-up resistor (0 = disabled, 1 = enabled)
#define GPPUB     0x0D
#define INTFA     0x0E    // Interrupt flag (read only) : (0 = no interrupt, 1 = pin caused interrupt)
#define INTFB     0x0F
#define INTCAPA   0x10    // Interrupt capture (read only) : value of GPIO at time of last interrupt
#define INTCAPB   0x11
#define GPIOA     0x12    // Port value. Write to change, read to obtain value
#define GPIOB     0x13
#define OLLATA    0x14    // Output latch. Write to latch output.
#define OLLATB    0x15

And ServoDefaults.h:

#define MASTER_RESET  120   // THIS IS THE ADDRESS FOR A FULL RESET - Set = 120

struct servoPair  {
  uint16_t  Servo;
  uint8_t   Value;
};
servoPair servoDefaults[] = {
  // These two CVs define the Long Accessory Address
  {MASTER_RESET, 0},    // Servo120 = 0; Set to 120 to reset

  {33, 120},  // Servo delay before detach - delay = Value*10msec

  {34, 20},   // SERVO0: servoSpeed
  {35, 45},   // Straight Angle Direction=0
  {36, 135},  // Diverge Angle  Direction=1
  {37, 90},   // Current Angle

  {38, 10},   // SERVO1: servoSpeed
  {39, 45},   // Straight Angle Direction=0
  {40, 135},  // Diverge Angle  Direction=1
  {41, 90},   // Current Angle

  {42, 30},   // SERVO2: servoSpeed
  {43, 45},   // Straight Angle Direction=0
  {44, 135},  // Diverge Angle  Direction=1
  {45, 90},   // Current Angle

  {46, 30},   // SERVO3: servoSpeed
  {47, 45},   // Straight Angle Direction=0
  {48, 135},  // Diverge Angle  Direction=1
  {49, 90},   // Current Angle

  {50, 30},   // SERVO4: servoSpeed
  {51, 45},   // Straight Angle Direction=0
  {52, 135},  // Diverge Angle  Direction=1
  {53, 90},   // Current Angle

  {54, 30},   // SERVO5: servoSpeed
  {55, 45},   // Straight Angle Direction=0
  {56, 135},  // Diverge Angle  Direction=1
  {57, 90},   // Current Angle

  {58, 30},   // SERVO6: servoSpeed
  {59, 45},   // Straight Angle Direction=0
  {60, 135},  // Diverge Angle  Direction=1
  {61, 90},   // Current Angle

  {62, 30},   // SERVO7: servoSpeed
  {63, 45},   // Straight Angle Direction=0
  {64, 135},  // Diverge Angle  Direction=1
  {65, 90},   // Current Angle
};

For LiquidCrystal_I2C.h the library by Malpartida is used: https://github.com/fmalpartida/New-LiquidCrystal/blob/master/LiquidCrystal_I2C.h

Is there a non-human posting in this thread ?

What is that?

Incidentally, how have you joined pin 13 and pin A5 . Simply a jumper across the two directly on the pro mini?
There are 2 leds on that board. You are sure you have disconnected the correct one ?
I can't otherwise find a hidden reference to pin 13 in your sketch which could explain the different effect when it is connected. As you say, it should be high impedance.

Sometimes, poor rise time can be caused by an out of specification heater voltage. Typically for an octal tube/valve this would be 5 volts. For B9A and similar, 6.3 volts is normal. Please refer to the data sheet for more specific details.

Hi 6v6gt, pin 13 and A5 are joined with a jumper wire on the breadboard; on the pcb as well (JP3).

Yes, I did disconnect the built-in LED, in my little test here above in response to your post #4.

Now when I add this #else line (in setup() at line 115):

#ifdef COMPILE_FOR_SPI
  pinMode(SS, OUTPUT);                    // Configure controller's Slave Select pin to output
  digitalWrite(SS, HIGH);                 // Disable Slave Select (pin 10)
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV8);    // Divide the SPI clock by 8
**#else**
**  pinMode(13, INPUT);**

The issue seems solved!????

EDIT: not yet; on the breadboard it is ok, not on the pcb.

???

Ok. I don't understand it fully because pin 13 , unless set explicitly, should be an input pin. Your code appears to avoid doing that (by not including SPI.h etc.)
The bootloader may flash the pin 13 led but should restore the pin state afterwards.
Anyway, good that it is solved.

Solved on breadboard, not yet on pcb. but I guess I need to examine more closely what is happening there.

Indeed SPI.h is not included, but why would the pinMode(13, INPUT); , when used in I2C mode result in the I2C clock to function (when SCL is connected also to pin 13)?

Pin 13 is inert when it is an input pin so behaves as if it is not connected. Are you closing/shorting the jumper j3? You are clearing doing something on the PCB which you are not duplicating on your breadboard setup.

Maybe try the simple blink sketch on (a) pin 13 then (b) on pin A5 both with and without the D13/A5 bridge and see if there is a difference with the scope.