Introduction: Simple and Cheap Fuse Doctor for Attiny
When you are working with Attiny's like the Attiny 85 or the Attiny13, it is bound to happen sooner or later: you brick your Attiny.
I got faced with it while trying to burn a bootlaoder (i.e. setting the correct fuses), that I suddenly got the dreaded 'Yikes! Invalid device signature' error message. As I had just succesfully burned it on IDE1.06 and now was trying on IDE1.6.3, just to see if I installed everything OK, I knew the chip was OK and that my programmer was OK. Also, a new chip did well, so something ominous must have happened to my chip.
Could it be because my computer had some memory problems during the burning???
Well, not much choice but to try and reset my Attiny85.
For that you need a Serial High Voltage Programmer. Plenty of circuits to find, so no way I claim to be original here, but I am writing this ibble to take away any hesitation that people might have by showing how quick and easy it is.
All it takes are 6 resistors, a transistor, a DIL foot, a 9x20 piece of stripboard and a 7-pins male header and of course a 12 Volt supply. And yes, A UNO to stick it in.
As I didnt expect to use the programmer very often, I planned to use a battery, but as I couldnt find my 12 Volt battery, I ended up using a 0.75 USD (so 75 dollarcents) 5 to 12 Volt converter from aliexpress, that i had for another project.
I used the program below. The program starts when you send a random character to teh serial port. As it turns out, it was a fuse problem in my chip as the fuse bits were E4 DF which means it was set for 128 kHz oscillator. Not sure how that could happen as I removed that choice from my menu in the boards.txt file.
Anyway, it reset the fuses to factory setting and after that I could use my Attiny85 again.
Sadly, in order to build this unbricker, I had to use the 1k resistors I wanted to use for the very project I was programming the Attiny for :-) Oh well!!
All in all took me less than an hour to put it together So if you are having problems with your Attiny13/25/45/85 build one of these.
If you want to unbrick the 24/44/84 series, you need a bigger DIL Foot.
If you are trying to unbrick an Attiny15.. then remember that that has PB3 and PB4 switched compared to the 13/25/45/85 series, so you probably need a software or hardware change (Tar and feathers for the Atmel designer who did this)
// AVR High-voltage Serial Fuse Reprogrammer<br> // Adapted from code and design by Paul Willoughby 03/20/2010 // <a href="http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/" rel="nofollow"> http://www.rickety.us/2010/03/arduino-avr-high-vo...</a><br> // // Fuse Calc: // <a rel="nofollow">http://www.rickety.us/2010/03/arduino-avr-high-vo....</a>
#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); Serial.println("Reading: "); 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: "); 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; }
44 Comments
4 years ago
Perfect, thank you. Nearly perfect anyway, - it correctly reads the fuses and signature for my smd tiny85 but doesn't actually change the fuses. At least I now know that reset is disabled (which is why ISP reports that the signature is 000000 using avrdude). I'll update here if I ever get to the bottom of this ;)
Reply 4 years ago
Solved. tl;dr I needed to do a chip erase, then the fuses reset as expected.
Using the code and hardware here I worked out with the help of the datasheet how HV programming works. From that I was able to add some code to read the lock bits back. I was expecting the ATtiny85 to be locked as that should prevent the fuses being changed, but it wasn't. So, with nothing to lose, I tried erasing the whole chip...
void chipErase () {
Serial.print ("Erasing chip....");
shiftOut(0x80, 0x4C);
shiftOut(0x00, 0x64);
shiftOut(0x00, 0x6C);
Serial.println ("done");
}
I added the above routine to the code and called it after it reads the signature and fuses, but before it writes/re-reads the fuses. It worked perfectly first time.
Reply 1 year ago
You saved my day!
Having two attiny13a with lfuse set to: 0xC9, I first tried just using hv programming, but the fuses would not change.
Next I tried the solution by freskpe (below).
Also no change.
But adding your erase function did the trick.
Two more functional attiny13a. The were supposed to be 'new'.
Thank you.
Reply 11 months ago
Hi CarlP4, I accidently write the fuse 1 to RSTDISBL. Now whenever I write some pogramme the message shows "avrdude: Device signature = 0x000000
avrdude: Yikes! Invalid device signature."
Pls help me. if you have get out from the problem. Share the circuit and code also.
Mail is : t_tuku@yahoo.com
Reply 11 months ago
Hi sekharathome,
All I did was to follow the excellent description after having connected the components as shown on a breadboard.
The npn transistor was another type, but fine for the purpose.
You did not mention the type of mcu, attiny13 or other.
If the original sketch does not work then try adding the chipErase() function.
For the attiny13 I added the function above the loop().
And in the loop(), the functions was called like:
if (sig == ATTINY13) {
chipErase();
Serial.println("The ATtiny is detected as ATtiny13/ATtiny13A..");
Serial.print("LFUSE: ");
writeFuse(LFUSE, 0x6A);
Serial.print("HFUSE: ");
Reply 11 months ago
Thanx for reply. I was successfully reprogram the attiny13a with the default code. Did not use erase function. Thanks all for retrive my mcu back in life. Though it is cheap, but i am not giving up for simple error.
Reply 1 year ago
i found two ways to solve the problem and avoid the chipErase (that erase firmware and bootloader, i think).
1. Connect VCC of attiny85 directly to 5V
2. move instruction <digitalWrite(VCC, HIGH)> 5 lines up and Add a delay (30ms).
i know is too late for your case but could be good for another user... i was breaking my mind for 2 days :(.
Reply 1 year ago
Great. Thank you
3 years ago
Thank you sir. Your instructable help to reborn my ATtiny85
Reply 2 years ago
I am happy it helped you
4 years ago
Hi, Diy-BlokHi DIY-Bloke, I have 15 Attiny13 (smd) as many as 15 pieces that can not be filled programmed while still sealed from the factory, I've tried it by soldered directly to IC foot with wire (worried socket IC dip to SSU problem) but the effort was not successful with the description of Chip not found) whether it can be cured with Attiny Doctor? thanks.
Reply 4 years ago
interesting, you are in fact the 2nd one to approach me about chips not working straight from the factory. Asian Webstore??
Not sure if the attiny doctor can help as the chip apparently isn't found but with 15 it might be worth a try
4 years ago
hey diy_bloke, my attiny84a is returning FF for the three flags, 0xFFFFFF for the signature, and avrdude -F tries but can't write the fuses. Is that indicative of a bricked tiny? I don't want to bother with a 'doctor' if that's not the problem. Here are the errors: https://gist.github.com/tedder/8edc3c598e427652f7004d9fd23e94ca
Reply 4 years ago
I am not too familiar with the 84a. but it seems indeed yours is bricked
4 years ago
Hello and thank you for this simple but very useful circuit, I added some cosmetic printings to your code, to help my failing memory :-) !
<a href="https://github.com/jeanrocco/cheap-fuse-doctor/blob/master/Attiny85_fuse_doctor.ino">cheap-fuse-doctor</a>
Reply 4 years ago
thank you
4 years ago
hem ! markdown not working here !
https://github.com/jeanrocco/cheap-fuse-doctor/blob/master/Attiny85_fuse_doctor.ino
4 years ago
Thank you SO much! It took me hours to figure out why this damned attiny wouldn't flash. Now I can just reset it and everything works nicely.
Reply 4 years ago
Let me add that I built it also for an attiny that wouldnt flash without me having the foggiest why. Turned out to be a fuse i had no idea I had set
Reply 4 years ago
Happy I/my instructable could be of help :-)