Can't Upload Sketches To Arduino Nano RP2040 Connect

Hello,
I recently bought the Arduino Nano RP2040 Connect for one of my projects, however I am having difficulties uploading sketches to the board.
I have installed the Arduino Nano MBed Boards Library.

What happens when I try uploading a sketch

When I try to upload a sketch the controller disconnects and starts in bootloadder mode (as a storage device), before disconnecting again an not responding.
It is possible to fix this by pressing the button twice and uploading the blink.ino.elf.uf2 file like discribed here, but once thats done the same thing happens again when trying to upload a sketch.

What I already tried

  • In this article, it is mentioned that you can simply drag the compiled uf2-file onmto the board when it is in bootloader mode, however this did not work for me
  • I have tried all troubleshooting steps mentioned in the official guide
  • I have tried different PCs and cables
  • I have tied reinstalling the drivers
  • I have tried running the post_install.sh script that gets mentioned in many tutorials about the board (however I think that is strictly for Linux)

I know there already are a couple of discussions about this topic on here, however none of the could provide a solution that worked for me.
I am really hoping someone can help me fix this, as I desperatly need the controller to work for my masters thesis.

Hi @phlipinator. This behavior might be caused by something in the code of the sketch you are uploading.

Please try this experiment and then report back here with the results:

  1. Recover your Nano RP2040 Connect to the state where a sketch upload is possible, as you did before.
  2. Select File > Examples > 01.Basics > BareMinimum from the Arduino IDE menus.
    A basic sketch that contains only the minimum code will open.
  3. Select the board and port of the Nano RP2040 Connect from the Arduino IDE menus.
  4. Select Sketch > Upload from the Arduino IDE menus.
  5. Wait for the upload to finish.

Now please reply here on this forum thread with the answers to the following questions:

  • Did the upload performed at step (4) complete successfully?
  • Did the board remain in a functional state after the sketch upload?

4.6 Board Recovery
All Arduino boards have a built-in bootloader which allows flashing the board via USB. In case a sketch locks up the
processor and the board is not reachable anymore via USB it is possible to enter bootloader mode by double-
tapping the reset button right after power up

Hello,
thank you for your quick response!

I have tried the steps you mentioned at this works.
I had also tried this before with a simple printline output, but forgot to mention it in my post.
To directly answer your 2 questions:

  1. Yes, the upload completed successfully
  2. Yes, the board remained functional

HOWEVER, during the upload process the Nano still connects as a storage device and then disconnects again (which isn't much of a problem I suppose).

AND MORE IMPORTANTLY, the code I tried uploading was previously tested extensivley on a regular Arduino Nano.
I even removed the parts that reqiure extra libraries.

This is the code that I am trying to upload:

const byte TILE_PIN = 26;
const byte ROW_PIN = 28;
const byte COL_PIN = 27;

void setup() {
  Serial.begin(9600);
}

void loop() {
  debug();
  //Serial.println(analogRead(TILE_PIN));

  delay(5000);  // Wait for 5 seconds before next measurement
}

int getTileNumber() {
  int rawValue = analogRead(TILE_PIN);
  // Define tiles based on measured analog values and assumed thresholds
  // Format: {lower_bound, upper_bound, tile_number}
  int tiles[16][3] = {
    { 1000, 1023, 1 }, { 952, 999, 2 }, { 890, 940, 3 }, { 825, 875, 4 }, 
    { 556, 616, 5 }, { 622, 682, 6 }, { 686, 746, 7 }, { 752, 812, 8 }, 
    { 490, 550, 9 }, { 425, 485, 10 }, { 356, 416, 11 }, { 292, 352, 12 }, 
    { 32, 92, 13 }, { 100, 160, 14 }, { 162, 222, 15 }, { 228, 288, 16 }
  };

  for (int i = 0; i < 16; i++) {
    if (rawValue >= tiles[i][0] && rawValue <= tiles[i][1]) {
      return tiles[i][2];
    }
  }

  return 0;  // Return -1 if no tile matches
}

int getConsistentTile() {
  int firstMeasurement = getTileNumber();
  delay(100);  // Short delay between measurements
  int secondMeasurement = getTileNumber();
  delay(100);
  int thirdMeasurement = getTileNumber();

  if (firstMeasurement == secondMeasurement && secondMeasurement == thirdMeasurement) {
    return firstMeasurement;  // All three measurements match
  } else {
    return 0;  // Measurements do not match
  }
}


int getColumnNumber() {
  int rawValue = analogRead(COL_PIN);
  // Format: {lower_bound, upper_bound, column_number}
  int columns[4][3] = {
    { 850, 1023, 1 },  // Average of highest readings for column 1
    { 550, 849, 2 },   // Average of middle-high readings for column 2
    { 250, 549, 3 },   // Average of middle-low readings for column 3
    { 0, 249, 4 }      // Lowest readings for column 4
  };

  for (int i = 0; i < 4; i++) {
    if (rawValue >= columns[i][0] && rawValue <= columns[i][1]) {
      return columns[i][2];
    }
  }

  return 0;  // Return -1 if no column matches
}

int getRowNumber() {
  int rawValue = analogRead(ROW_PIN);
  // Format: {lower_bound, upper_bound, row_number}
  int rows[4][3] = {
    { 1000, 1023, 1 },  // First row
    { 700, 999, 2 },    // Second row
    { 400, 699, 3 },    // Third row
    { 0, 399, 4 }       // Fourth row
  };

  for (int i = 0; i < 4; i++) {
    if (rawValue >= rows[i][0] && rawValue <= rows[i][1]) {
      return rows[i][2];
    }
  }

  return 0;  // Return -1 if no row matches
}

void debug() {
  Serial.print("Tile: ");
  Serial.println(getTileNumber());
  Serial.print("Row: ");
  Serial.println(getRowNumber());
  Serial.print("Column: ");
  Serial.println(getColumnNumber());
  Serial.println(" ");
}

EDIT:
I was now able to upload the code, by changing the Pin declaration to

const byte TILE_PIN = A0;
const byte ROW_PIN = A1;
const byte COL_PIN = A2;

Now it seems to be working fine.

Hello,
Thank you for your response!
As mentioned in my post, that is not the problem I am having and I used the bootloader method already to connect to the board.

OK, this is very useful information because it allows us to focus our troubleshooting efforts.

This is normal and expected. The board is temporarily put into a "USB mass storage device" mode during the upload process. When in this mode, the board appears as if it was a USB flash drive connected to your computer (just like it did when you performed the recovery process with the blink.ino.elf.uf2 file).

The problem is you are passing invalid pin numbers to analogRead. Here is a minimal sketch that demonstrates how such code "soft bricks" the board:

// Demonstration of soft-bricking of Nano RP2040 Connect board by passing invalid pin number to analogRead.
// Press and release the reset button on the board twice quickly and then upload a valid sketch to recover.
const byte TILE_PIN = 26; // This is not a valid analog pin.
void setup() {
  analogRead(TILE_PIN);
}
void loop() {}

You should change the pin numbers in the sketch to valid analog pins on the board.

These are also not valid analog pin numbers for the classic Nano.

Even though the two boards have the same form factor and similar names, there are significant technical differences:

The classic Nano has a dedicated USB to serial bridge chip separate from the primary ATmega328P microcontroller. This means that, no matter how bugged the program running on the ATmega328P is, it will never interfere with the Nano's ability to produce a serial port and accept uploads.

The situation is different with the Nano RP2040 Connect because on this board the RP2040 microcontroller is connected directly to the computer. The USB code that creates the CDC serial port is running on the same microcontroller as your sketch. This means your sketch code can break the USB code, or stop it from running. When that happens, the board no longer produces a serial port. Fortunately that isn't a significant problem because it is easy enough to recover the board from that state (normally it only requires a double reset and the "factory reset" with the .uf2 file is not necessary).

Okay, thank you so much.

I also found that out a bit later, like i posted in the edit of my last post.
I thought you were supposed to use the GPIO numbers from the PinOut, as the other numbers were not correctly highlighted by the IDE.

You are welcome. I'm glad it is working now.

Regards,
Per

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.