Using analog pins as digital on Leonardo

I'm running into something I can't quite explain. I have a setup of 8 floppy drives that can create music from MIDI files and know for a fact this has worked in the past (older project from someone else). It uses a Leonardo as a controller and Moppy 2 (Arduino + Java GUI) as software. This seems to work, but:

The two drives that are connected to the analog pins (14 through 17) will not respond to the signals being sent. The drives themselves work fine and all the connections have been thoroughly tested as OK.

I've read that there seems to be a bug with the 32U4 where pinMode() and digitalWrite() don't work as they should, but even simply writing to the register directly doesn't solve the problem.

I've written a short test program in Microchip Studio and uploaded code to the board and this did work (signals got through, pins behaved as they should). For maintainability and time constraints, I can't port the project.

Anyone here with any suggestions to get those pins to behave?

Post your sketch

// Mapping of analog pins as digital I/O
// A6-A11 share with digital pins
#define PIN_A0   (18)
#define PIN_A1   (19)
#define PIN_A2   (20)
#define PIN_A3   (21)
#define PIN_A4   (22)
#define PIN_A5   (23)
#define PIN_A6   (24)
#define PIN_A7   (25)
#define PIN_A8   (26)
#define PIN_A9   (27)
#define PIN_A10  (28)
#define PIN_A11  (29)

1 Like

These are the lines of code that are run at startup:

void FloppyDrives::setup() {

  // Prepare pins (0 and 1 are reserved for Serial communications)
  pinMode(2, OUTPUT); // Step control 1
  pinMode(3, OUTPUT); // Direction 1
  pinMode(4, OUTPUT); // Step control 2
  pinMode(5, OUTPUT); // Direction 2
  pinMode(6, OUTPUT); // Step control 3
  pinMode(7, OUTPUT); // Direction 3
  pinMode(8, OUTPUT); // Step control 4
  pinMode(9, OUTPUT); // Direction 4
  pinMode(10, OUTPUT); // Step control 5
  pinMode(11, OUTPUT); // Direction 5
  pinMode(12, OUTPUT); // Step control 6
  pinMode(13, OUTPUT); // Direction 6
  pinMode(14, OUTPUT); // Step control 7
  pinMode(15, OUTPUT); // Direction 7
  pinMode(16, OUTPUT); // Step control 8
  pinMode(17, OUTPUT); // Direction 8

  // With all pins setup, let's do a first run reset
  resetAll();
  delay(500); // Wait a half second for safety

  // Setup timer to handle interrupts for floppy driving
  MoppyTimer::initialize(TIMER_RESOLUTION, tick);

  // If MoppyConfig wants a startup sound, play the startupSound on the
  // first drive.
  if (PLAY_STARTUP_SOUND) {
    startupSound(FIRST_DRIVE);
	startupSound(2);
	startupSound(3);
	startupSound(4);
	startupSound(5);
	startupSound(6);
	startupSound(7);
	startupSound(8);
	delay(500);
    resetAll();
  }
}

With resetAll() being:

void FloppyDrives::resetAll()
{
  DDRF  |= (1 << PF6) | ( 1 << PF7) | ( 1 << PF4) | ( 1 << PF5);
  // Stop all drives and set to reverse
  for (byte d=FIRST_DRIVE;d<=LAST_DRIVE;d++) {
    byte stepPin = d * 2;
    currentPeriod[d] = 0;
    digitalWrite(stepPin+1,HIGH);
  }
  

  // Reset all drives together
  for (unsigned int s=0;s<MAX_POSITION[0];s+=2){ //Half max because we're stepping directly (no toggle); grab max from index 0
    for (byte d=FIRST_DRIVE;d<=LAST_DRIVE;d++) {
      byte stepPin = d * 2;
      digitalWrite(stepPin,HIGH);
      digitalWrite(stepPin,LOW);
    }
    delay(5);
  }

  // Return tracking to ready state
  for (byte d=FIRST_DRIVE;d<=LAST_DRIVE;d++) {
    byte stepPin = d * 2;
    currentPosition[d] = 0; // We're reset.
    currentState[stepPin] = LOW;
    digitalWrite(stepPin+1,LOW);
	stepPin = d*2;
    currentState[stepPin+1] = LOW; // Ready to go forward.
    setMovement(d, true); // Set movement to true by default
  }
}

And startupSound(); being:

void FloppyDrives::startupSound(byte driveNum) {
  unsigned int chargeNotes[] = {
      noteDoubleTicks[31],
      noteDoubleTicks[36],
      noteDoubleTicks[38],
      noteDoubleTicks[43],
      0
  };
  byte i = 0;
  unsigned long lastRun = 0;
  while(i < 5) {
    if (millis() - 200 > lastRun) {
      lastRun = millis();
      currentPeriod[driveNum] = chargeNotes[i++];
    }
  }
}

Sure, also, doesn't Microchip Studio have ready made identifiers for those pins?

So what you're saying is that if I want to use the analog pins as if they are digital outputs, they have been routed differently by using PIN_Ax or 18 through 29?

Close to that.

The basic Arduino pin numbering scheme is first digital only pins then analog capable pins,
on a Nano there are even pins that have only analog capability.
On a Leonardo, the first analog capable pin is 18 and there are 12 of them,
all can be used as digital I/Os also.

PIN_Ax or Ax are merely constants that evaluate to the respective (digital) pin numbers.

analogRead and analogWrite accept numbers between zero and the number of analog pins-1
as well as the pin number as an additional commodity.

Reasonably sure that those are the SPI pins :slight_smile:

And you can make your life a lot easier if you just refer to the analog pins as A0, A1 etc.

  pinMode(A0, OUTPUT); // Step control 7
  pinMode(A1, OUTPUT); // Direction 7
  pinMode(A2, OUTPUT); // Step control 8
  pinMode(A3, OUTPUT); // Direction 8

But looking at different pinout schematics for a Leonardo, they pretty much all show A0 as ADC7 and as digital pin 14. So...how?

Seems so, at least for the Arduino site.

I'm not to explain differences in core and documentation.

This is from the leonardo variant folder

// Map SPI port to 'new' pins D14..D17
#define PIN_SPI_SS    (17)
#define PIN_SPI_MOSI  (16)
#define PIN_SPI_MISO  (14)
#define PIN_SPI_SCK   (15)

static const uint8_t SS   = PIN_SPI_SS;
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK  = PIN_SPI_SCK;

// Mapping of analog pins as digital I/O
// A6-A11 share with digital pins
#define PIN_A0   (18)
#define PIN_A1   (19)
#define PIN_A2   (20)
#define PIN_A3   (21)
#define PIN_A4   (22)
#define PIN_A5   (23)
#define PIN_A6   (24)
#define PIN_A7   (25)
#define PIN_A8   (26)
#define PIN_A9   (27)
#define PIN_A10  (28)
#define PIN_A11  (29)

:unamused: I have no love for bad documentation. Thanks for the help!

Instead of simply going from D2 tot 3 to 4 etc. I now use a lookup table (array) with the last four pins as A0-A4). Easy hack in this code, just add 1 to the index instead of the pin number when in a loop.
Now I can get all drives to work, although there is still an annoying issue with drive 8..I'll get that fixed soon enough!

That is the proper way to do it.