Pro-Mini vs Mini

I am using about 80 "Pro-Minis" clones on a project (very cost sensitive) - purchased from several places - HiLetGo on amazon and also Temu.
They look identical but:
About 60 of them only program as "Arduino Pro or Pro Mini" (Atmega 328P 3.3V 8MHz)
About 20 only program as "Arduino Mini" (Atmega 328P)

All 80 devices communicate correctly, eg: Serial.begin(115200) is received propertly with IDE serial port set to 115200. And millis() counts correctly, but what is weird is that the Pro/ProMinis are running 8 times SLOWER than the Minis when running the same code.

I'm guessing that there is some issue with the prescaler when setting which board to program using "Arduino Mini" or "Arduino Pro or Pro Mini"

I'm using Arduino IDE 1.8.19

How can I see what is being handled differently bw these two board options? Can I reset some register to make my ProMini boards run like the Minis boards? All devices are being programmed with an FTDI programmer at 3.3V and are running on LiPo batteries at 3.3V.

Your topic does not directly indicate a problem with IDE 1.x and therefore has been moved to a more suitable location on the forum.


If serial and millis work as expected I find it difficult to understand how you conclude that some are running 8 times slower.

Have you verified the processors that are on the board? The print might be difficult to read.

This is a (slightly) modified version of Read Fuse Bits via Arduino Software - #9 by westfw. The modification is that you can compile with a basic mode which will only display the fuse settings and it works with Serial.print instead of Serial <<. The sketch consists of two files.

ino file

//#define BASIC

//#include <Flash.h>
#include <avr/boot.h>
#include <EEPROM.h>
#include "cpuname.h"

/*
 * SIGRD is a "must be zero" bit on most Arduino CPUs; can we read the sig or not?
 */
#if (!defined(SIGRD))
#define SIGRD 5
#endif

unsigned char fuse_bits_low;
byte fuse_bits_extended;
byte fuse_bits_high;
byte lock_bits;
byte sig1, sig2, sig3;
byte oscal;

void setup()
{
  unsigned char xxx = fuse_bits_low >> 4;
  Serial.begin(115200);
  Serial.print(xxx);
}

void space()
{
  Serial.print(' ');
}

void print_serno(void)
{
  int i;
  int unoSerial[6];
  int startAddr = 1018;
  unsigned long serno = 0;

  for (i = 0; i < 6; i++)
  {
    unoSerial[i] = EEPROM.read(startAddr + i);
  }
  if (unoSerial[0] == 'U' && unoSerial[1] == 'N' && unoSerial[2] == 'O')
  {

    Serial.print(F("Your Serial Number is: UNO"));

    for (i = 3; i < 6; i = i + 1)
    {
      serno = serno * 256 + unoSerial[i];
      Serial.print(" ");
      Serial.print(unoSerial[i], HEX);
    }
    Serial.print(F(" ("));
    Serial.print(serno);
    Serial.print(F(")"));
  }
  else
  {
    Serial.print(F("No Serial Number"));
  }
  Serial.println();
}

void print_binary(byte b)
{
  for (byte i = 0x80; i > 0; i >>= 1)
  {
    if (b & i)
    {
      Serial.print('1');
    }
    else
    {
      Serial.print('0');
    }
  }
}

/*
 * Note that most fuses are active-low, and the the avr include files
 * define them as inverted bitmasks...
 */

void print_fuse_low(void)
{
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__)
  /*
 * Fuse Low is same on 48/88/168/328
     */
  Serial.print(F("Fuse Low = "));
  print_binary(fuse_bits_low);
  Serial.print(F(" ("));
  Serial.print(fuse_bits_low, HEX);
  Serial.print(F(")\n"));
  Serial.print(F("           ||||++++______"));
  switch (fuse_bits_low & 0xF)
  {
    case 0:
      Serial.print(F("Reserved"));
      break;
    case 1:
      Serial.print(F("External Clock"));
      break;
    case 2:
      Serial.print(F("Calibrated 8MHz Internal Clock"));
      break;
    case 3:
      Serial.print(F("Internal 128kHz Clock"));
      break;
    case 4:
      Serial.print(F("LF Crystal, 1K CK Startup"));
      break;
    case 5:
      Serial.print(F("LF Crystal 32K CK Startup"));
      break;
    case 6:
      Serial.print(F("Full Swing Crystal "));
      break;
    case 7:
      Serial.print(F("Full Swing Crystal"));
      break;
    case 8:
    case 9:
      Serial.print(F("Low Power Crystal 0.4 - 0.8MHz"));
      break;
    case 10:
    case 11:
      Serial.print(F("Low Power Crystal 0.9 - 3.0MHz"));
      break;
    case 12:
    case 13:
      Serial.print(F("Low Power Crystal 3 - 8MHz"));
      break;
    case 14:
    case 15:
      Serial.print(F("Low Power Crystal 8 - 16MHz"));
      break;
  }

  Serial.println();
  Serial.print(F("           ||++__________"));
  Serial.print(F("Start Up Time="));
  Serial.print((fuse_bits_low >> 4) & 3, BIN);

  Serial.println();
  Serial.print(F("           |+____________"));
  Serial.print(F("Clock Output "));
  if (fuse_bits_low & (~FUSE_CKOUT))
    Serial.print(F("Disabled"));
  else
    Serial.print(F("Enabled"));

  Serial.println();
  Serial.print(F("           +_____________"));
  if (fuse_bits_low & (~FUSE_CKDIV8))
  {
    Serial.print(F("(no divide)"));
  }
  else
  {
    Serial.print(F("Divide Clock by 8"));
  }


#elif defined(__AVR_ATmega8__)
#endif
  Serial.println();
}

void print_fuse_high()
{
  Serial.print(F("\nFuse High = "));
  print_binary(fuse_bits_high);
  Serial.print(F(" ("));
  Serial.print(fuse_bits_high, HEX);
  Serial.print(F(")\n"));

#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
  Serial.print(F("            |||||||+______"));
  if (fuse_bits_high & bit(FUSE_BOOTRST))
  {
    Serial.print(F("Reset to Start of memory\n"));
  }
  else
  {
    Serial.print(F("Reset to Bootstrap\n"));
  }
  Serial.print(F("            |||||++_______"));
  switch ((byte)(fuse_bits_high & ((~FUSE_BOOTSZ1) + (~FUSE_BOOTSZ0))))
  {
    case (byte)((~FUSE_BOOTSZ1) + (~FUSE_BOOTSZ0)):
      Serial.print(F("256 words (512 bytes)\n"));
      break;
    case (byte)((~FUSE_BOOTSZ1)):
      Serial.print(F("512 words (1024 bytes)\n"));
      break;
    case (byte)((~FUSE_BOOTSZ0)):
      Serial.print(F("1024 words (2048 bytes)\n"));
      break;
    case 0:
      Serial.print(F("2048 words (4096 bytes)\n"));
      break;
    default:
      Serial.println(fuse_bits_high & ((~FUSE_BOOTSZ1) + (~FUSE_BOOTSZ0)), BIN);
  }
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__)
  Serial .print( F("            |||||+++______");
  switch ((byte)(fuse_bits_high & 7))
  {
    case 7:
      Serial.print(F("Brownout Disabled\n"));
      break;
    case 6:
      Serial.print(F("Brownout at 1.8V\n"));
      break;
    case 5:
      Serial.print(F("Brownout at 2.7V\n"));
      break;
    case 4:
      Serial.print(F("Brownout at 4.3V\n"));
      break;
    default:
      Serial.print(F("Brownout Reserved value"));
      Serial.println(fuse_bits_high & 7, BIN);
      break;
  }

#elif defined(__AVR_ATmega8__)
#endif
  Serial.print(F("            ||||+_________"));
  if (fuse_bits_high & ~(FUSE_EESAVE))
  {
    Serial.print(F("EEPROM Erased on chip erase\n"));
  }
  else
  {
    Serial.print(F("EEPROM Preserved on chip erase\n"));
  }
  Serial.print(F("            |||+__________"));
  if (fuse_bits_high & ~(FUSE_WDTON))
  {
    Serial.print(F("Watchdog programmable\n"));
  }
  else
  {
    Serial.print(F("Watchdog always on\n"));
  }
  Serial.print(F("            ||+___________"));
  if (fuse_bits_high & ~(FUSE_SPIEN))
  {
    Serial.print(F("ISP programming disabled\n"));
  }
  else
  {
    Serial.print(F("ISP programming enabled\n"));
  }
  Serial.print(F("            |+____________"));
  if (fuse_bits_high & ~(FUSE_DWEN))
  {
    Serial.print(F("DebugWire off\n"));
  }
  else
  {
    Serial.print(F("DebugWire enabled\n"));
  }
  Serial.print(F("            +_____________"));
  if (fuse_bits_high & ~(FUSE_RSTDISBL))
  {
    Serial.print(F("RST enabled\n"));
  }
  else
  {
    Serial.print(F("RST disabled\n"));
  }
}

void print_lock_bits()
{
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__)

  Serial.print(F("\nLock Bits = "));
  print_binary(lock_bits);
  Serial.print(F(" ("));
  Serial.print(lock_bits, HEX);
  Serial.print(F(")\n"));
  Serial.print(F("            ||||||++______"));
  switch ((byte)(lock_bits & 3))
  {
    case 3:
      Serial.print(F("Read/Write to everywhere\n"));
      break;
    case 2:
      Serial.print(F("Programming of Flash/EEPROM disabled\n"));
      break;
    case 0:
      Serial.print(F("No Read/Write of Flash/EEPROM\n"));
      break;
    default:
      Serial.println();
  }
  Serial.print(F("            ||||++________"));
  switch ((byte)(lock_bits & 0b1100))
  {  //BLB0x
    case 0b1100:
      Serial.print(F("R/W Application\n"));
      break;
    case 0b1000:
      Serial.print(F("No Write to App\n"));
      break;
    case 0b0000:
      Serial.print(F("No Write to App, no read from Boot\n"));
      break;
    case 0b0100:
      Serial.print(F("No Write to App, no read from Boot, no Ints to App\n"));
      break;
  }

  Serial.print(F("            ||++__________"));
  switch ((byte)(lock_bits & 0b110000))
  {  //BLB0x
    case 0b110000:
      Serial.print(F("R/W Boot Section\n"));
      break;
    case 0b100000:
      Serial.print(F("No Write to Boot Section\n"));
      break;
    case 0b000000:
      Serial.print(F("No Write to Boot, no read from App\n"));
      break;
    case 0b010000:
      Serial.print(F("No Write to Boot, no read from App, no Ints to Boot\n"));
      break;
  }
#elif defined(__AVR_ATmega8__)
#endif
}

void print_fuse_extended()
{
  Serial.print(F("\nFuse Extended = "));
  print_binary(fuse_bits_extended);
  Serial.print(F(" ("));
  Serial.print(fuse_bits_extended, HEX);
  Serial.print(F(")\n"));
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
  Serial.print(F("                |||||+++______"));
  switch ((byte)(fuse_bits_extended & 7))
  {
    case 7:
      Serial.print(F("Brownout Disabled\n"));
      break;
    case 6:
      Serial.print(F("Brownout at 1.8V\n"));
      break;
    case 5:
      Serial.print(F("Brownout at 2.7V\n"));
      break;
    case 4:
      Serial.print(F("Brownout at 4.3V\n"));
      break;
    default:
      Serial.print(F("Brownout Reserved value"));
      Serial.println(fuse_bits_extended & 7, BIN);
      break;
  }
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__)
  Serial .print( F("                |||||||+______");
  if (fuse_bits_extended & bit(FUSE_BOOTRST))
  {
    Serial.print(F("Reset to Start of memory\n"));
  }
  else
  {
    Serial.print(F("Reset to Bootstrap\n"));
  }
  Serial.print( F("                |||||++_______"));
  switch ((byte)(fuse_bits_extended & ((~FUSE_BOOTSZ1) + (~FUSE_BOOTSZ0))))
  {
    case (byte)((~FUSE_BOOTSZ1) + (~FUSE_BOOTSZ0)):
      Serial.print(F("128 words (256 bytes)\n"));
      break;
    case (byte)((~FUSE_BOOTSZ1)):
      Serial.print(F("256 words (512 bytes)\n"));
      break;
    case (byte)((~FUSE_BOOTSZ0)):
      Serial.print(F("512 words (1024 bytes)\n"));
      break;
    case 0:
      Serial.print(F("1024 words (2048 bytes)\n"));
      break;
    default:
      Serial.println(fuse_bits_extended & ((~FUSE_BOOTSZ1) + (~FUSE_BOOTSZ0)), BIN);
  }
#elif defined(__AVR_ATmega8__)
#endif
}

void print_signature()
{
  Serial.print(F("\nSignature:         "));
  Serial.print(sig1, HEX);
  space();
  Serial.print(sig2, HEX);
  space();
  Serial.print(sig3, HEX);
  if (sig1 == 0x1E)
  { /* Atmel ? */
    switch (sig2)
    {
      case 0x92: /* 4K flash */
        if (sig3 == 0x0A)
          Serial.print(F(" (ATmega48P)"));
        else if (sig3 == 0x05)
          Serial.print(F(" (ATmega48A)"));
        else if (sig3 == 0x09)
          Serial.print(F(" (ATmega48)"));
        break;
      case 0x93: /* 8K flash */
        if (sig3 == 0x0F)
          Serial.print(F(" (ATmega88P)"));
        else if (sig3 == 0x0A)
          Serial.print(F(" (ATmega88A)"));
        else if (sig3 == 0x11)
          Serial.print(F(" (ATmega88)"));
        else if (sig3 == 0x08)
          Serial.print(F(" (ATmega8)"));
        break;
      case 0x94: /* 16K flash */
        if (sig3 == 0x0B)
          Serial.print(F(" (ATmega168P)"));
        else if (sig3 == 0x06)
          Serial.print(F(" (ATmega168A)"));
        break;
      case 0x95: /* 32K flash */
        if (sig3 == 0x0F)
          Serial.print(F(" (ATmega328P)"));
        else if (sig3 == 0x14)
          Serial.print(F(" (ATmega328)"));
        break;
    }
  }
  else
  {
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__)
    Serial.print(F(" (Fuses not readable on non-P AVR)"));
#else
    Serial.print(F("????"));
#endif
  }
}

void loop()
{
  delay(2000);
  Serial.print(F("\nCompiled for " __CPUNAME "\n"));
  print_serno();
  cli();
  fuse_bits_low = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS);
  fuse_bits_extended = boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS);
  fuse_bits_high = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
  lock_bits = boot_lock_fuse_bits_get(GET_LOCK_BITS);
  sig1 = boot_signature_byte_get(0);
  sig2 = boot_signature_byte_get(2);
  sig3 = boot_signature_byte_get(4);
  oscal = boot_signature_byte_get(1);
  sei();

  Serial.print(F("\nFuse bits (L/E/H): "));
  Serial.print(fuse_bits_low, HEX);
  space();
  Serial.print(fuse_bits_extended, HEX);
  space();
  Serial.print(fuse_bits_high, HEX);
  Serial.print(F("\nLock bits:         "));
  Serial.print(lock_bits, HEX);
  print_signature();
  Serial.print(F("\nOscal:             "));
  Serial.println(oscal, HEX);
  Serial.println();

#ifndef BASIC

  print_fuse_low();
  print_fuse_high();
  print_fuse_extended();
  print_lock_bits();

#endif

#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__)
#elif defined(__AVR_ATmega8__)
#endif
  while (1)
  {
    if (Serial.read() > 0)
      break;
  }
}

and cpuname.h

#ifndef _AVR_CPUNAME_H_
#define _AVR_CPUNAME_H_

#if defined (__AVR_AT94K__)
#  define __CPUNAME "AT94K"
#elif defined (__AVR_AT43USB320__)
#  define __CPUNAME "AT43USB320"
#elif defined (__AVR_AT43USB355__)
#  define __CPUNAME "AT43USB355"
#elif defined (__AVR_AT76C711__)
#  define __CPUNAME "AT76C711"
#elif defined (__AVR_AT86RF401__)
#  define __CPUNAME "AT86RF401"
#elif defined (__AVR_AT90PWM1__)
#  define __CPUNAME "AT90PWM1"
#elif defined (__AVR_AT90PWM2__)
#  define __CPUNAME "AT90PWM2"
#elif defined (__AVR_AT90PWM2B__)
#  define __CPUNAME "AT90PWM2B"
#elif defined (__AVR_AT90PWM3__)
#  define __CPUNAME "AT90PWM3"
#elif defined (__AVR_AT90PWM3B__)
#  define __CPUNAME "AT90PWM3B"
#elif defined (__AVR_AT90PWM216__)
#  define __CPUNAME "AT90PWM216"
#elif defined (__AVR_AT90PWM316__)
#  define __CPUNAME "AT90PWM316"
#elif defined (__AVR_ATmega32C1__)
#  define __CPUNAME "ATmega32C1"
#elif defined (__AVR_ATmega32M1__)
#  define __CPUNAME "ATmega32M1"
#elif defined (__AVR_ATmega32U4__)
#  define __CPUNAME "ATmega32U4"
#elif defined (__AVR_ATmega32U6__)
#  define __CPUNAME "ATmega32U6"
#elif defined (__AVR_ATmega128__)
#  define __CPUNAME "ATmega128"
#elif defined (__AVR_ATmega1280__)
#  define __CPUNAME "ATmega1280"
#elif defined (__AVR_ATmega1281__)
#  define __CPUNAME "ATmega1281"
#elif defined (__AVR_ATmega1284P__)
#  define __CPUNAME "ATmega1284P"
#elif defined (__AVR_ATmega2560__)
#  define __CPUNAME "ATmega2560"
#elif defined (__AVR_ATmega2561__)
#  define __CPUNAME "ATmega2561"
#elif defined (__AVR_AT90CAN32__)
#  define __CPUNAME "AT90CAN32"
#elif defined (__AVR_AT90CAN64__)
#  define __CPUNAME "AT90CAN64"
#elif defined (__AVR_AT90CAN128__)
#  define __CPUNAME "AT90CAN128"
#elif defined (__AVR_AT90USB82__)
#  define __CPUNAME "AT90USB82"
#elif defined (__AVR_AT90USB162__)
#  define __CPUNAME "AT90USB162"
#elif defined (__AVR_AT90USB646__)
#  define __CPUNAME "AT90USB646"
#elif defined (__AVR_AT90USB647__)
#  define __CPUNAME "AT90USB647"
#elif defined (__AVR_AT90USB1286__)
#  define __CPUNAME "AT90USB1286"
#elif defined (__AVR_AT90USB1287__)
#  define __CPUNAME "AT90USB1287"
#elif defined (__AVR_ATmega64__)
#  define __CPUNAME "ATmega64"
#elif defined (__AVR_ATmega640__)
#  define __CPUNAME "ATmega640"
#elif defined (__AVR_ATmega644__)
#  define __CPUNAME "ATmega644"
#elif defined (__AVR_ATmega644P__)
#  define __CPUNAME "ATmega644P"
#elif defined (__AVR_ATmega645__)
#  define __CPUNAME "ATmega645"
#elif defined (__AVR_ATmega6450__)
#  define __CPUNAME "ATmega6450"
#elif defined (__AVR_ATmega649__)
#  define __CPUNAME "ATmega649"
#elif defined (__AVR_ATmega6490__)
#  define __CPUNAME "ATmega6490"
#elif defined (__AVR_ATmega103__)
#  define __CPUNAME "ATmega103"
#elif defined (__AVR_ATmega32__)
#  define __CPUNAME "ATmega32"
#elif defined (__AVR_ATmega323__)
#  define __CPUNAME "ATmega323"
#elif defined (__AVR_ATmega324P__)
#  define __CPUNAME "ATmega324P"
#elif defined (__AVR_ATmega325__)
#  define __CPUNAME "ATmega325"
#elif defined (__AVR_ATmega325P__)
#  define __CPUNAME "ATmega325P"
#elif defined (__AVR_ATmega3250__)
#  define __CPUNAME "ATmega3250"
#elif defined (__AVR_ATmega3250P__)
#  define __CPUNAME "ATmega3250P"
#elif defined (__AVR_ATmega328P__)
#  define __CPUNAME "ATmega328P"
#elif defined (__AVR_ATmega329__)
#  define __CPUNAME "ATmega329"
#elif defined (__AVR_ATmega329P__)
#  define __CPUNAME "ATmega329P"
#elif defined (__AVR_ATmega3290__)
#  define __CPUNAME "ATmega3290"
#elif defined (__AVR_ATmega3290P__)
#  define __CPUNAME "ATmega3290P"
#elif defined (__AVR_ATmega32HVB__)
#  define __CPUNAME "ATmega32HVB"
#elif defined (__AVR_ATmega406__)
#  define __CPUNAME "ATmega406"
#elif defined (__AVR_ATmega16__)
#  define __CPUNAME "ATmega16"
#elif defined (__AVR_ATmega161__)
#  define __CPUNAME "ATmega161"
#elif defined (__AVR_ATmega162__)
#  define __CPUNAME "ATmega162"
#elif defined (__AVR_ATmega163__)
#  define __CPUNAME "ATmega163"
#elif defined (__AVR_ATmega164P__)
#  define __CPUNAME "ATmega164P"
#elif defined (__AVR_ATmega165__)
#  define __CPUNAME "ATmega165"
#elif defined (__AVR_ATmega165P__)
#  define __CPUNAME "ATmega165P"
#elif defined (__AVR_ATmega168__)
#  define __CPUNAME "ATmega168"
#elif defined (__AVR_ATmega168P__)
#  define __CPUNAME "ATmega168P"
#elif defined (__AVR_ATmega169__)
#  define __CPUNAME "ATmega169"
#elif defined (__AVR_ATmega169P__)
#  define __CPUNAME "ATmega169P"
#elif defined (__AVR_ATmega8HVA__)
#  define __CPUNAME "ATmega8HVA"
#elif defined (__AVR_ATmega16HVA__)
#  define __CPUNAME "ATmega16HVA"
#elif defined (__AVR_ATmega8__)
#  define __CPUNAME "ATmega8"
#elif defined (__AVR_ATmega48__)
#  define __CPUNAME "ATmega48"
#elif defined (__AVR_ATmega48P__)
#  define __CPUNAME "ATmega48P"
#elif defined (__AVR_ATmega88__)
#  define __CPUNAME "ATmega88"
#elif defined (__AVR_ATmega88P__)
#  define __CPUNAME "ATmega88P"
#elif defined (__AVR_ATmega8515__)
#  define __CPUNAME "ATmega8515"
#elif defined (__AVR_ATmega8535__)
#  define __CPUNAME "ATmega8535"
#elif defined (__AVR_AT90S8535__)
#  define __CPUNAME "AT90S8535"
#elif defined (__AVR_AT90C8534__)
#  define __CPUNAME "AT90C8534"
#elif defined (__AVR_AT90S8515__)
#  define __CPUNAME "AT90S8515"
#elif defined (__AVR_AT90S4434__)
#  define __CPUNAME "AT90S4434"
#elif defined (__AVR_AT90S4433__)
#  define __CPUNAME "AT90S4433"
#elif defined (__AVR_AT90S4414__)
#  define __CPUNAME "AT90S4414"
#elif defined (__AVR_ATtiny22__)
#  define __CPUNAME "ATtiny22"
#elif defined (__AVR_ATtiny26__)
#  define __CPUNAME "ATtiny26"
#elif defined (__AVR_AT90S2343__)
#  define __CPUNAME "AT90S2343"
#elif defined (__AVR_AT90S2333__)
#  define __CPUNAME "AT90S2333"
#elif defined (__AVR_AT90S2323__)
#  define __CPUNAME "AT90S2323"
#elif defined (__AVR_AT90S2313__)
#  define __CPUNAME "AT90S2313"
#elif defined (__AVR_ATtiny2313__)
#  define __CPUNAME "ATtiny2313"
#elif defined (__AVR_ATtiny13__)
#  define __CPUNAME "ATtiny13"
#elif defined (__AVR_ATtiny13A__)
#  define __CPUNAME "ATtiny13A"
#elif defined (__AVR_ATtiny25__)
#  define __CPUNAME "ATtiny25"
#elif defined (__AVR_ATtiny45__)
#  define __CPUNAME "ATtiny45"
#elif defined (__AVR_ATtiny85__)
#  define __CPUNAME "ATtiny85"
#elif defined (__AVR_ATtiny24__)
#  define __CPUNAME "ATtiny24"
#elif defined (__AVR_ATtiny44__)
#  define __CPUNAME "ATtiny44"
#elif defined (__AVR_ATtiny84__)
#  define __CPUNAME "ATtiny84"
#elif defined (__AVR_ATtiny261__)
#  define __CPUNAME "ATtiny261"
#elif defined (__AVR_ATtiny461__)
#  define __CPUNAME "ATtiny461"
#elif defined (__AVR_ATtiny861__)
#  define __CPUNAME "ATtiny861"
#elif defined (__AVR_ATtiny43U__)
#  define __CPUNAME "ATtiny43U"
#elif defined (__AVR_ATtiny48__)
#  define __CPUNAME "ATtiny48"
#elif defined (__AVR_ATtiny88__)
#  define __CPUNAME "ATtiny88"
#elif defined (__AVR_ATtiny167__)
#  define __CPUNAME "ATtiny167"
/* avr1: the following only supported for assembler programs */
#elif defined (__AVR_ATtiny28__)
#  define __CPUNAME "ATtiny28"
#elif defined (__AVR_AT90S1200__)
#  define __CPUNAME "AT90S1200"
#elif defined (__AVR_ATtiny15__)
#  define __CPUNAME "ATtiny15"
#elif defined (__AVR_ATtiny12__)
#  define __CPUNAME "ATtiny12"
#elif defined (__AVR_ATtiny11__)
#  define __CPUNAME "ATtiny11"
#elif defined (__AVR_ATxmega64A1__)
#  define __CPUNAME "ATxmega64A1"
#elif defined (__AVR_ATxmega64A3__)
#  define __CPUNAME "ATxmega64A3"
#elif defined (__AVR_ATxmega128A1__)
#  define __CPUNAME "ATxmega128A1"
#elif defined (__AVR_ATxmega128A3__)
#  define __CPUNAME "ATxmega128A3"
#elif defined (__AVR_ATxmega256A3__)
#  define __CPUNAME "ATxmega256A3"
#elif defined (__AVR_ATxmega256A3B__)
#  define __CPUNAME "ATxmega256A3B"
#else
#  if !defined(__COMPILING_AVR_LIBC__)
#    warning "device type not defined"
#  endif
#endif

#endif /* _AVR_CPUNAME_H_ */

You can run it and compare the L/E/H fuses between the two boards and compare them against the fuse settings defined in boards.txt and against the data sheet.

I did run it on a Nano with old bootloader as well as on an Uno to check for the expected difference in the high fuse to cater for the size of the respective boot loaders.

Output for Nano with old boot loader

11:21:23.888 -> Compiled for ATmega328P
11:21:23.888 -> No Serial Number
11:21:23.888 -> 
11:21:23.888 -> Fuse bits (L/E/H): FF FD DA
11:21:23.888 -> Lock bits:         CF
11:21:23.888 -> Signature:         1E 95 F (ATmega328P)
11:21:23.888 -> Oscal:             93
11:21:23.888 -> 
11:21:23.888 -> Fuse Low = 11111111 (FF)
11:21:23.922 ->            ||||++++______Low Power Crystal 8 - 16MHz
11:21:23.922 ->            ||++__________Start Up Time=11
11:21:23.922 ->            |+____________Clock Output Disabled
11:21:23.922 ->            +_____________(no divide)
11:21:23.922 -> 
11:21:23.922 -> Fuse High = 11011010 (DA)
11:21:23.922 ->             |||||||+______Reset to Bootstrap
11:21:23.922 ->             |||||++_______1024 words (2048 bytes)
11:21:23.922 ->             ||||+_________EEPROM Erased on chip erase
11:21:23.922 ->             |||+__________Watchdog programmable
11:21:23.955 ->             ||+___________ISP programming enabled
11:21:23.955 ->             |+____________DebugWire off
11:21:23.955 ->             +_____________RST enabled
11:21:23.955 -> 
11:21:23.955 -> Fuse Extended = 11111101 (FD)
11:21:23.955 ->                 |||||+++______Brownout at 2.7V
11:21:23.955 -> 
11:21:23.955 -> Lock Bits = 11001111 (CF)
11:21:23.955 ->             ||||||++______Read/Write to everywhere
11:21:23.955 ->             ||||++________R/W Application
11:21:23.955 ->             ||++__________No Write to Boot, no read from App

Output for Uno

11:23:59.682 -> Compiled for ATmega328P
11:23:59.682 -> No Serial Number
11:23:59.682 -> 
11:23:59.682 -> Fuse bits (L/E/H): FF FD DE
11:23:59.682 -> Lock bits:         CF
11:23:59.682 -> Signature:         1E 95 F (ATmega328P)
11:23:59.682 -> Oscal:             AE
11:23:59.682 -> 
11:23:59.682 -> Fuse Low = 11111111 (FF)
11:23:59.682 ->            ||||++++______Low Power Crystal 8 - 16MHz
11:23:59.682 ->            ||++__________Start Up Time=11
11:23:59.682 ->            |+____________Clock Output Disabled
11:23:59.682 ->            +_____________(no divide)
11:23:59.714 -> 
11:23:59.714 -> Fuse High = 11011110 (DE)
11:23:59.714 ->             |||||||+______Reset to Bootstrap
11:23:59.714 ->             |||||++_______256 words (512 bytes)
11:23:59.714 ->             ||||+_________EEPROM Erased on chip erase
11:23:59.714 ->             |||+__________Watchdog programmable
11:23:59.715 ->             ||+___________ISP programming enabled
11:23:59.715 ->             |+____________DebugWire off
11:23:59.715 ->             +_____________RST enabled
11:23:59.715 -> 
11:23:59.715 -> Fuse Extended = 11111101 (FD)
11:23:59.750 ->                 |||||+++______Brownout at 2.7V
11:23:59.750 -> 
11:23:59.750 -> Lock Bits = 11001111 (CF)
11:23:59.750 ->             ||||||++______Read/Write to everywhere
11:23:59.750 ->             ||||++________R/W Application
11:23:59.750 ->             ||++__________No Write to Boot, no read from App

The Mini has a clock speed of 16MHz, the Pro/Pro Mini uses either 16MHz or 8MHz, since you state millis() works properly then you have the 8MHz version. The difference in clock speed should make the Pro Mini execute code at 1/2 the speed of the Mini, but anything based on millis() timing should execute at the proper interval.

The 1/8th speed does not make sense, unless there is something in your code that is non-millis based that is giving that result. How are you checking the communications with the Serial monitor, the Pro Mini has no USB-to-serial converter chip, and must be programmed using an ISP programmer. forgot it could use an external USB-to-serial board. ( I see someone already corrected me)

Or a proper FTDI adapter.

Yes - thanks for responding.
I think I figured it out The short versions is this.

Like you said --- the Mini is 16MHz and the ProMini is 8Mhz. My code interacts with SPI and the radiohead library which probably uses interrupts. The 16MHz Mini can manage the timing much better than the 8MHz ProMini so I'm seeing a much bigger performance hit than just 2x.

Iif you are interested in the longer story, here it is:

Here was my puzzle. When I ran identical code, on both devices I saw this:

Yellow Trace is the ProMini - Blue Trace is the Mini.
So .... the Mini is going ~8 times faster. Why??

I used a simple timing loop:

void setup() {
    Serial.begin(115200);
    pinMode(3, OUTPUT);
}

int t1;
int t2;

void loop(){
    t1 = millis(); 
    for(long i=0;i<10000;i++){ 
      digitalWrite(3, HIGH);
      digitalWrite(3, LOW);
    }
    t2 = millis(); 
    Serial.println(t2-t1);
}

and yes, you are right, for this code, my ProMinis are running at 1/2 the rate of my Minis.
ProMini prints: 182
Mini prints: 91

My larger program (~700 lines) uses both SPI to run a DotStar led strip (from adafruit) and code from the RadioHead library with a 433MHz radio unit (SYN470R).

So, I expanded the timing snippet to include these two libraries so it can receive rf packets and send SPI commands. For testing, my transmitter sends a packet each 1000 ms.

void loop(){
    counter++;
    setStripSolid(blu);
    digitalWrite(3, HIGH);
    setStripSolid(red);
    digitalWrite(3, LOW);

    if ( (counter%100)== 0){
       Serial.print(millis()-t1);
       Serial.print("\t");       
       t1 = millis(); 
    }
    read_rf_commands();
}

Using SPI AND checking for RF packets:

Pro Mini:
645	651	rf[:5]	  cmd:4406316117
615	rf[:5]	  cmd:44063164250
633	645	rf[:5]	  cmd:44063168225
643	rf[:5]	  cmd:44063172201
616	601	rf[:5]	  cmd:44063176177

Mini: 
91	90	91	90	90	90	90	90	89	90	90	rf[:5]	  cmd:440664981
92	90	90	90	90	91	90	90	90	90	90	rf[:5]	  cmd:440665357
91	90	91	90	89	89	89	90	90	90	90	rf[:5]	  cmd:440665733
92	90	90	90	90	90	90	90	89	90	89	rf[:5]	  cmd:44066619
92	90	90	90	90	90	91	90	90	90	90	rf[:5]	  cmd:4406664241

So mini runs 90ms loops and the ProMini takes ~630ms. Faster, but not exactly 8x - only about 630/90 = 7 times faster with this code. Hmm, maybe not simply a prescaling issue.

Then I commented out the SPI commands:
// setStripSolid(blu);
// setStripSolid(red);
and changed
if ( (counter%100)== 0){
to
if ( (counter%1000)== 0){
to get better timing resolution.

ProMini
434	426	rf[:5]	  cmd:440753873
430	666	rf[:5]	  cmd:440754249
440	424	rf[:5]	  cmd:440754625
444	453	442	rf[:5]	  cmd:44075501
453	440	rf[:5]	  cmd:4407553233
435	434	rf[:5]	  cmd:4407557209
446	443	rf[:5]	  cmd:4407561185

Mini:
61	59	59	59	59	58	59	58	59	58	58	59	59	58	59	58	60	rf[:5]	  cmd:440731449
93	61	62	61	62	61	60	61	61	61	60	62	60	60	62	61	rf[:5]	  cmd:44073147241
63	61	62	61	62	61	60	61	61	61	60	62	60	61	61	61	rf[:5]	  cmd:44073151217
63	58	59	58	59	59	58	59	59	59	59	58	58	60	58	60	59	rf[:5]	  cmd:44073155193

Still Mini is running 430/60 or a bit more than 7x faster than the ProMini.

Then I restored the setStripSolid calls and just commented out the read_rf_commands();

Exactly 206ms for the ProMini and 69 for the Mini --- so just 3x faster.

So it looks like interacting with SPI and the interrupts that the radiohead library might be using slows the ProMini down much more than the 50% that one might expect when comparing 8MHz device vs the 16MHz Mini.

I looked on the boards and the microcontroller ICs are different:
ProMini - Atmel 328PB
Mini - Atmel 328P

The 328PB (ProMini) has additional features as described in:
[https://www.pololu.com/file/0J1464/Atmel-42559-Differences-between-ATmega328P-and-ATmega328PB_ApplicationNote_AT15007.pdf](https://328P vs 328PB)

But the 328PB it is supposed to be able to do everything that the 328P does:

from the dataSheet:

The ATmega328PB is not a drop-in replacement for ATmega328 variants, but a
new device. However, the functions are backward compatible with the
existing ATmega328 functions. Existing code for these devices will work in
the new devices without changing existing configuration or enabling new
functions. The code that is available for your existing ATmega328 variants
will continue to work on the new ATmega328PB device.

So maybe what I'm seeing has more to do with 8MHz vs 16MHz than processor capability.

Thanks sterretje.
This looks fascinating and I will have to check it out but I think my issue is more mundane.
Please See my other answer.
Thanks,