Resulta que compré un puñado de ATmega328, pensando que podría usarlos sin ningún problema para mis futuros proyectos con arduino, como por ejemplo, realizar circuitos compactos (no modulares) y poder usar el microcontrolador ya programado... o programandolo como si fuese un arduino externo.

Instrucciones para construir el programador
Preparé el programador externo usando un cristal de cuarzo de 16 Mhz, montandolo en una placa de topos.
Circuito programador para arduino
Circuito programador con arduino

Entonces cargué el software de programación en mi arduino ( File > Examples > ArduinoISP ), y al volcar el BootLoader me dice que el código de identificación no es correcto. ( y solo era el principio ... )

Buscando, encontré que la opción mas usada es modificar el archivo de configuración del compilador (<arduino>/hardware/tools/avrdude.conf) para decirle que un ATmega328P(0x1e 0x95 0x0F) tiene el código de identificación correpondiente al ATmega328(0x1e 0x95 0x14)

De todas formas, esto resulta un engorro, ya que al tener que grabar código en arduino, tenemos el mismo problema, pero al revés, y tenemos que dejar el archivo como estaba.

Después de unos cuantos cambios, decidí que esto no podía seguir así. Así que decidí duplicar la información del ATmega328:

La configuración original la renombré como:
#------------------------------------------------------------ # ATmega328P #------------------------------------------------------------ part id = "m328p"; desc = "ATMEGA328P"; has_debugwire = yes; flash_instr = 0xB6, 0x01, 0x11; eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, 0x99, 0xF9, 0xBB, 0xAF; stk500_devcode = 0x86; # avr910_devcode = 0x; signature = 0x1e 0x95 0x0F; pagel = 0xd7; bs2 = 0xc2; chip_erase_delay = 9000; pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", "x x x x x x x x x x x x x x x x"; chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", "x x x x x x x x x x x x x x x x"; timeout = 200; stabdelay = 100; cmdexedelay = 25; synchloops = 32; bytedelay = 0; pollindex = 3; pollvalue = 0x53; predelay = 1; postdelay = 1; pollmethod = 1; pp_controlstack = 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; hventerstabdelay = 100; progmodedelay = 0; latchcycles = 5; togglevtg = 1; poweroffdelay = 15; resetdelayms = 1; resetdelayus = 0; hvleavestabdelay = 15; resetdelay = 15; chiperasepulsewidth = 0; chiperasepolltimeout = 10; programfusepulsewidth = 0; programfusepolltimeout = 5; programlockpulsewidth = 0; programlockpolltimeout = 5; memory "eeprom" paged = no; page_size = 4; size = 1024; min_write_delay = 3600; max_write_delay = 3600; readback_p1 = 0xff; readback_p2 = 0xff; read = " 1 0 1 0 0 0 0 0", " 0 0 0 x x x a9 a8", " a7 a6 a5 a4 a3 a2 a1 a0", " o o o o o o o o"; write = " 1 1 0 0 0 0 0 0", " 0 0 0 x x x a9 a8", " a7 a6 a5 a4 a3 a2 a1 a0", " i i i i i i i i"; loadpage_lo = " 1 1 0 0 0 0 0 1", " 0 0 0 0 0 0 0 0", " 0 0 0 0 0 0 a1 a0", " i i i i i i i i"; writepage = " 1 1 0 0 0 0 1 0", " 0 0 x x x x a9 a8", " a7 a6 a5 a4 a3 a2 0 0", " x x x x x x x x"; mode = 0x41; delay = 20; blocksize = 4; readsize = 256; ; memory "flash" paged = yes; size = 32768; page_size = 128; num_pages = 256; min_write_delay = 4500; max_write_delay = 4500; readback_p1 = 0xff; readback_p2 = 0xff; read_lo = " 0 0 1 0 0 0 0 0", " 0 0 a13 a12 a11 a10 a9 a8", " a7 a6 a5 a4 a3 a2 a1 a0", " o o o o o o o o"; read_hi = " 0 0 1 0 1 0 0 0", " 0 0 a13 a12 a11 a10 a9 a8", " a7 a6 a5 a4 a3 a2 a1 a0", " o o o o o o o o"; loadpage_lo = " 0 1 0 0 0 0 0 0", " 0 0 0 x x x x x", " x x a5 a4 a3 a2 a1 a0", " i i i i i i i i"; loadpage_hi = " 0 1 0 0 1 0 0 0", " 0 0 0 x x x x x", " x x a5 a4 a3 a2 a1 a0", " i i i i i i i i"; writepage = " 0 1 0 0 1 1 0 0", " 0 0 a13 a12 a11 a10 a9 a8", " a7 a6 x x x x x x", " x x x x x x x x"; mode = 0x41; delay = 6; blocksize = 128; readsize = 256; ; memory "lfuse" size = 1; min_write_delay = 4500; max_write_delay = 4500; read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", "x x x x x x x x o o o o o o o o"; write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", "x x x x x x x x i i i i i i i i"; ; memory "hfuse" size = 1; min_write_delay = 4500; max_write_delay = 4500; read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", "x x x x x x x x o o o o o o o o"; write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", "x x x x x x x x i i i i i i i i"; ; memory "efuse" size = 1; min_write_delay = 4500; max_write_delay = 4500; read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", "x x x x x x x x x x x x x o o o"; write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", "x x x x x x x x x x x x x i i i"; ; memory "lock" size = 1; min_write_delay = 4500; max_write_delay = 4500; read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", "x x x x x x x x x x o o o o o o"; write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", "x x x x x x x x 1 1 i i i i i i"; ; memory "calibration" size = 1; read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", "0 0 0 0 0 0 0 0 o o o o o o o o"; ; memory "signature" size = 3; read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", "x x x x x x a1 a0 o o o o o o o o"; ; ;
y la copiada, la dejé como:
#------------------------------------------------------------ # ATmega328 #------------------------------------------------------------ part id = "m328"; desc = "ATMEGA328"; has_debugwire = yes; flash_instr = 0xB6, 0x01, 0x11; eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, 0x99, 0xF9, 0xBB, 0xAF; stk500_devcode = 0x86; # avr910_devcode = 0x; signature = 0x1e 0x95 0x14; pagel = 0xd7; bs2 = 0xc2; chip_erase_delay = 9000; pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", "x x x x x x x x x x x x x x x x"; chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", "x x x x x x x x x x x x x x x x"; timeout = 200; stabdelay = 100; cmdexedelay = 25; synchloops = 32; bytedelay = 0; pollindex = 3; pollvalue = 0x53; predelay = 1; postdelay = 1; pollmethod = 1; pp_controlstack = 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; hventerstabdelay = 100; progmodedelay = 0; latchcycles = 5; togglevtg = 1; poweroffdelay = 15; resetdelayms = 1; resetdelayus = 0; hvleavestabdelay = 15; resetdelay = 15; chiperasepulsewidth = 0; chiperasepolltimeout = 10; programfusepulsewidth = 0; programfusepolltimeout = 5; programlockpulsewidth = 0; programlockpolltimeout = 5; memory "eeprom" paged = no; page_size = 4; size = 1024; min_write_delay = 3600; max_write_delay = 3600; readback_p1 = 0xff; readback_p2 = 0xff; read = " 1 0 1 0 0 0 0 0", " 0 0 0 x x x a9 a8", " a7 a6 a5 a4 a3 a2 a1 a0", " o o o o o o o o"; write = " 1 1 0 0 0 0 0 0", " 0 0 0 x x x a9 a8", " a7 a6 a5 a4 a3 a2 a1 a0", " i i i i i i i i"; loadpage_lo = " 1 1 0 0 0 0 0 1", " 0 0 0 0 0 0 0 0", " 0 0 0 0 0 0 a1 a0", " i i i i i i i i"; writepage = " 1 1 0 0 0 0 1 0", " 0 0 x x x x a9 a8", " a7 a6 a5 a4 a3 a2 0 0", " x x x x x x x x"; mode = 0x41; delay = 20; blocksize = 4; readsize = 256; ; memory "flash" paged = yes; size = 32768; page_size = 128; num_pages = 256; min_write_delay = 4500; max_write_delay = 4500; readback_p1 = 0xff; readback_p2 = 0xff; read_lo = " 0 0 1 0 0 0 0 0", " 0 0 a13 a12 a11 a10 a9 a8", " a7 a6 a5 a4 a3 a2 a1 a0", " o o o o o o o o"; read_hi = " 0 0 1 0 1 0 0 0", " 0 0 a13 a12 a11 a10 a9 a8", " a7 a6 a5 a4 a3 a2 a1 a0", " o o o o o o o o"; loadpage_lo = " 0 1 0 0 0 0 0 0", " 0 0 0 x x x x x", " x x a5 a4 a3 a2 a1 a0", " i i i i i i i i"; loadpage_hi = " 0 1 0 0 1 0 0 0", " 0 0 0 x x x x x", " x x a5 a4 a3 a2 a1 a0", " i i i i i i i i"; writepage = " 0 1 0 0 1 1 0 0", " 0 0 a13 a12 a11 a10 a9 a8", " a7 a6 x x x x x x", " x x x x x x x x"; mode = 0x41; delay = 6; blocksize = 128; readsize = 256; ; memory "lfuse" size = 1; min_write_delay = 4500; max_write_delay = 4500; read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", "x x x x x x x x o o o o o o o o"; write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", "x x x x x x x x i i i i i i i i"; ; memory "hfuse" size = 1; min_write_delay = 4500; max_write_delay = 4500; read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", "x x x x x x x x o o o o o o o o"; write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", "x x x x x x x x i i i i i i i i"; ; memory "efuse" size = 1; min_write_delay = 4500; max_write_delay = 4500; read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", "x x x x x x x x x x x x x o o o"; write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", "x x x x x x x x x x x x x i i i"; ; memory "lock" size = 1; min_write_delay = 4500; max_write_delay = 4500; read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", "x x x x x x x x x x o o o o o o"; write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", "x x x x x x x x 1 1 i i i i i i"; ; memory "calibration" size = 1; read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", "0 0 0 0 0 0 0 0 o o o o o o o o"; ; memory "signature" size = 3; read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", "x x x x x x a1 a0 o o o o o o o o"; ; ;
y entonces encontré la referencia que buscaba en <arduino>/hardware/tools/boards.txt :
Copiando la sección correspondiente, y cambiando las identificaciones, tenemos:
############################################################## atmega328.name=Arduino Duemilanove w/ ATmega328 atmega328.upload.protocol=arduino atmega328.upload.maximum_size=30720 atmega328.upload.speed=57600 atmega328.bootloader.low_fuses=0xFF atmega328.bootloader.high_fuses=0xDA atmega328.bootloader.extended_fuses=0x05 atmega328.bootloader.path=atmega atmega328.bootloader.file=ATmegaBOOT_168_atmega328.hex atmega328.bootloader.unlock_bits=0x3F atmega328.bootloader.lock_bits=0x0F atmega328.build.mcu=atmega328 atmega328.build.f_cpu=16000000L atmega328.build.core=arduino atmega328.build.variant=standard ############################################################## atmega328p.name=Arduino Duemilanove w/ ATmega328P atmega328p.upload.protocol=arduino atmega328p.upload.maximum_size=30720 atmega328p.upload.speed=57600 atmega328p.bootloader.low_fuses=0xFF atmega328p.bootloader.high_fuses=0xDA atmega328p.bootloader.extended_fuses=0x05 atmega328p.bootloader.path=atmega atmega328p.bootloader.file=ATmegaBOOT_168_atmega328.hex atmega328p.bootloader.unlock_bits=0x3F atmega328p.bootloader.lock_bits=0x0F atmega328p.build.mcu=atmega328p atmega328p.build.f_cpu=16000000L atmega328p.build.core=arduino atmega328p.build.variant=standard
Ahora, en la selección de placas arduino, tenemos el Duemilanove ATmega328P (nombre cambiado, opciones originales) y el Duemilanove ATmega328 (Que es el nuevo, y el que tenemos que seleccionar como destino para grabar el BootLoader en los nuevos integrados).
y con esto creía que sería suficiente, y por suerte así fué:
Para compilar el código seleccionando el ATmega328, tengo errores de id no soportado, y necesitaría tocar mas cosas, pero resulta que el ATmega328 con el BootLoader cargado en la placa de arduino se identifica como si fuese un ATmega328P, por lo que respecta al compilador, así que lo dejé estar.


Lo que ya no me pareció tan normal, es que de cada 10 veces que intentaba grabar el BootLoader, 9 veces recibía un error de sincronismo.
Y ya no digo nada cuando intenté grabar un ATmega328 poniendo en la placa base de arduino otro igual ya programado, misión : imposible.
Entonces volví a la carga, empezé a revisar el código del programador, y lo que no me gustó es que pusiesen un delay() en la función heartbeat()

void heartbeat() { if (hbval > 192) hbdelta = -hbdelta; if (hbval < 32) hbdelta = -hbdelta; hbval += hbdelta; analogWrite(LED_HB, hbval); delay(40); } No tenía ni tengo intención de reescribir el código, pero algo había que hacer.
Tras varias pruebas, funciona perfectamente así :

void heartbeat() { if (hbval > 192) hbdelta = -hbdelta; if (hbval < 32) hbdelta = -hbdelta; hbval += hbdelta; analogWrite(LED_HB, hbval); delay(30); } Pues por hoy, es suficiente, buena suerte y a disfrutar el código y el hardware.