Yikes! Invalid device signature
It sometimes happens: you are trying to program an Attiny and you get an error. There might be many causes for errors: you may not have selected the proper board, your programmer might be rotten, you did something wrong or the connections of your programmer are not correct, but sometimes it can be caused by the wrong bits being set in your Attiny: e.g. you set pin 1 (reset) to be an I/O pin. That makes it impossible to program it with ISP, or you set the wrong oscillator. For these cases a High Voltage programmer can be of help.
It happened to me when i was trying to ‘burn the bootloader’ on my attiny85 (there is no bootlaoder for the attiny 85 but this means setting the fuses). My computer’s memory was kinda full when I was busy and suddenly something crashed and I got the dreaded error message Yikes! Invalid device signature. As said, often this is because of a bad connection, but another chip didnt have that problem so I knew something was very wrong.
Time to build a High Voltage Programmer
Below you will see such a circuit. It is fairly simple: 6 resistors, a transistor a DIL foot and a 12 Volt source from somewhere. As I didn’t expect to have to use the HVP often, I opted for a battery, but as I displaced it, I ended up using a 75 euroct 5 to 12 Volt converter that I plugged in.

And this is an easy way to build it on stripboard.


I have built it such that it sticks into the D8-D13,ground header of an Arduino UNO. The only thing you need to do is to attach a 12 Volt battery, or an other 12 Volt source.
There are various programs that can reset the bits back to factory setting. Below you will find 2 of them that all go back to some initial work by Jos Keyzer.
The first one expects you to set the factory bits in the program depending on the chip you are using, the 2nd program actually reads what chip you are using, so I ended up using that one. Both programs start after you send a random character to the serial port.
Well, as it turned out, my fuses were set for E4 and DF. That means that the Attiny was expecting a 128 kHz oscillator signal. No idea how that happened as I have disabled that choice in my menu so I guess it happened coz of my computer crashing. We will never know, but the HVP set it back to factory settings: i.e. 8MHz internal oscillator with a prescaler of 8.
After that, I could just program my Attiny again.
In principle this programmer can be used for Attiny 15 and 12 as well, but as far as I recall they have some wires crossed, so you would need to make a hardware change (connect the D12 resistor to pin 3 instead of pin2), but Attiny 13/25/45/85 should work like a charm.
It can also be done on the 24/44/84 series, but they need a 14 pins DIL:
Should you need a cheap 12 Volt source, consider this 5 to 12 Volt converter
Program:
// AVR High-voltage Serial Programmer // Originally created by Paul Willoughby 03/20/2010 // http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/ // Inspired by Jeff Keyzer http://mightyohm.com // Serial Programming routines from ATtiny25/45/85 datasheet // Desired fuse configuration #define HFUSE 0xDF // Defaults for ATtiny25/45/85 #define LFUSE 0x62 // For Attiny13 use // #define HFUSE 0xFF // #define LFUSE 0x6A #define RST 13 // Output to level shifter for !RESET from transistor to Pin 1 #define CLKOUT 12 // Connect to Serial Clock Input (SCI) Pin 2 #define DATAIN 11 // Connect to Serial Data Output (SDO) Pin 7 #define INSTOUT 10 // Connect to Serial Instruction Input (SII) Pin 6 #define DATAOUT 9 // Connect to Serial Data Input (SDI) Pin 5 #define VCC 8 // Connect to VCC Pin 8 int inByte = 0; // incoming serial byte Computer int inData = 0; // incoming serial byte AVR void setup() { // Set up control lines for HV parallel programming pinMode(VCC, OUTPUT); pinMode(RST, OUTPUT); pinMode(DATAOUT, OUTPUT); pinMode(INSTOUT, OUTPUT); pinMode(CLKOUT, OUTPUT); pinMode(DATAIN, OUTPUT); // configured as input when in programming mode // Initialize output pins as needed digitalWrite(RST, HIGH); // Level shifter is inverting, this shuts off 12V // start serial port at 9600 bps: Serial.begin(9600); establishContact(); // send a byte to establish contact until receiver responds } void loop() { // if we get a valid byte, run: if (Serial.available() > 0) { // get incoming byte: inByte = Serial.read(); Serial.println(byte(inByte)); Serial.println("Entering programming Mode\n"); // Initialize pins to enter programming mode pinMode(DATAIN, OUTPUT); //Temporary digitalWrite(DATAOUT, LOW); digitalWrite(INSTOUT, LOW); digitalWrite(DATAIN, LOW); digitalWrite(RST, HIGH); // Level shifter is inverting, this shuts off 12V // Enter High-voltage Serial programming mode digitalWrite(VCC, HIGH); // Apply VCC to start programming process delayMicroseconds(20); digitalWrite(RST, LOW); //Turn on 12v delayMicroseconds(10); pinMode(DATAIN, INPUT); //Release DATAIN delayMicroseconds(300); //Programming mode readFuses(); //Write hfuse Serial.println("Writing hfuse"); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x40, 0x4C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, HFUSE, 0x2C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x74); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x7C); //Write lfuse Serial.println("Writing lfuse\n"); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x40, 0x4C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, LFUSE, 0x2C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x64); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6C); readFuses(); Serial.println("Exiting programming Mode\n"); digitalWrite(CLKOUT, LOW); digitalWrite(VCC, LOW); digitalWrite(RST, HIGH); //Turn off 12v } } void establishContact() { while (Serial.available() <= 0) { Serial.println("Enter a character to continue"); // send an initial string delay(1000); } } int shiftOut2(uint8_t dataPin, uint8_t dataPin1, uint8_t clockPin, uint8_t bitOrder, byte val, byte val1) { int i; int inBits = 0; //Wait until DATAIN goes high while (!digitalRead(DATAIN)); //Start bit digitalWrite(DATAOUT, LOW); digitalWrite(INSTOUT, LOW); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); for (i = 0; i < 8; i++) { if (bitOrder == LSBFIRST) { digitalWrite(dataPin, !!(val & (1 << i))); digitalWrite(dataPin1, !!(val1 & (1 << i))); } else { digitalWrite(dataPin, !!(val & (1 << (7 - i)))); digitalWrite(dataPin1, !!(val1 & (1 << (7 - i)))); } inBits <<=1; inBits |= digitalRead(DATAIN); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); } //End bits digitalWrite(DATAOUT, LOW); digitalWrite(INSTOUT, LOW); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); return inBits; } void readFuses(){ //Read lfuse shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x04, 0x4C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x68); inData = shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6C); Serial.print("lfuse reads as "); Serial.println(inData, HEX); //Read hfuse shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x04, 0x4C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x7A); inData = shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x7E); Serial.print("hfuse reads as "); Serial.println(inData, HEX); //Read efuse shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x04, 0x4C); shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6A); inData = shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6E); Serial.print("efuse reads as "); Serial.println(inData, HEX); Serial.println(); }
An other program is:
// AVR High-voltage Serial Fuse Reprogrammer // Adapted from code and design by Paul Willoughby 03/20/2010 // http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/ // Fuse Calc: // http://www.engbedded.com/fusecalc/ #define RST 13 // Output to level shifter for !RESET from transistor #define SCI 12 // Target Clock Input #define SDO 11 // Target Data Output #define SII 10 // Target Instruction Input #define SDI 9 // Target Data Input #define VCC 8 // Target VCC #define HFUSE 0x747C #define LFUSE 0x646C #define EFUSE 0x666E // Define ATTiny series signatures #define ATTINY13 0x9007 // L: 0x6A, H: 0xFF 8 pin #define ATTINY24 0x910B // L: 0x62, H: 0xDF, E: 0xFF 14 pin #define ATTINY25 0x9108 // L: 0x62, H: 0xDF, E: 0xFF 8 pin #define ATTINY44 0x9207 // L: 0x62, H: 0xDF, E: 0xFFF 14 pin #define ATTINY45 0x9206 // L: 0x62, H: 0xDF, E: 0xFF 8 pin #define ATTINY84 0x930C // L: 0x62, H: 0xDF, E: 0xFFF 14 pin #define ATTINY85 0x930B // L: 0x62, H: 0xDF, E: 0xFF 8 pin void setup() { pinMode(VCC, OUTPUT); pinMode(RST, OUTPUT); pinMode(SDI, OUTPUT); pinMode(SII, OUTPUT); pinMode(SCI, OUTPUT); pinMode(SDO, OUTPUT); // Configured as input when in programming mode digitalWrite(RST, HIGH); // Level shifter is inverting, this shuts off 12V Serial.begin(19200); } void loop() { if (Serial.available() > 0) { Serial.read(); pinMode(SDO, OUTPUT); // Set SDO to output digitalWrite(SDI, LOW); digitalWrite(SII, LOW); digitalWrite(SDO, LOW); digitalWrite(RST, HIGH); // 12v Off digitalWrite(VCC, HIGH); // Vcc On delayMicroseconds(20); digitalWrite(RST, LOW); // 12v On delayMicroseconds(10); pinMode(SDO, INPUT); // Set SDO to input delayMicroseconds(300); unsigned int sig = readSignature(); Serial.print("Signature is: "); Serial.println(sig, HEX); readFuses(); if (sig == ATTINY13) { writeFuse(LFUSE, 0x6A); writeFuse(HFUSE, 0xFF); } else if (sig == ATTINY24 || sig == ATTINY44 || sig == ATTINY84 || sig == ATTINY25 || sig == ATTINY45 || sig == ATTINY85) { writeFuse(LFUSE, 0x62); writeFuse(HFUSE, 0xDF); writeFuse(EFUSE, 0xFF); } readFuses(); digitalWrite(SCI, LOW); digitalWrite(VCC, LOW); // Vcc Off digitalWrite(RST, HIGH); // 12v Off } } byte shiftOut (byte val1, byte val2) { int inBits = 0; //Wait until SDO goes high while (!digitalRead(SDO)) ; unsigned int dout = (unsigned int) val1 << 2; unsigned int iout = (unsigned int) val2 << 2; for (int ii = 10; ii >= 0; ii--) { digitalWrite(SDI, !!(dout & (1 << ii))); digitalWrite(SII, !!(iout & (1 << ii))); inBits <<= 1; inBits |= digitalRead(SDO); digitalWrite(SCI, HIGH); digitalWrite(SCI, LOW); } return inBits >> 2; } void writeFuse (unsigned int fuse, byte val) { shiftOut(0x40, 0x4C); shiftOut( val, 0x2C); shiftOut(0x00, (byte) (fuse >> 8)); shiftOut(0x00, (byte) fuse); } void readFuses () { byte val; shiftOut(0x04, 0x4C); // LFuse shiftOut(0x00, 0x68); val = shiftOut(0x00, 0x6C); Serial.print("LFuse "); // this line may show up corrupted in some browsers it is a Serial.print("LFuse: "); Serial.print(val, HEX); shiftOut(0x04, 0x4C); // HFuse shiftOut(0x00, 0x7A); val = shiftOut(0x00, 0x7E); Serial.print(", HFuse: "); Serial.print(val, HEX); shiftOut(0x04, 0x4C); // EFuse shiftOut(0x00, 0x6A); val = shiftOut(0x00, 0x6E); Serial.print(", EFuse: "); Serial.println(val, HEX); } unsigned int readSignature () { unsigned int sig = 0; byte val; for (int ii = 1; ii < 3; ii++) { shiftOut(0x08, 0x4C); shiftOut( ii, 0x0C); shiftOut(0x00, 0x68); val = shiftOut(0x00, 0x6C); sig = (sig << 8) + val; } return sig; } ---
One may find this article interesting as well
If you want to see how this board (in a skightly more luxurious build) is used in practice you may want to check a youtube video by Ralph Bacon.