IOT123 - HV ATTINY85 Fuse Resetter

1,947

24

2

Introduction: IOT123 - HV ATTINY85 Fuse Resetter

About: The tension between novelty and familiarity...

There are many versions of the ATTINY85 Fuse Resetters on the NET. This is based on the work of diy_bloke (Instructable, the above schematic) and Ralph Bacon (GIT, Youtube video below). The main benefit of this device is sacrificing the reset pin on an ATTINY85 for use as a GPIO.

The main differences with the previous builds are I embed a dedicated Arduino Pro Mini and give a simplified build instruction.

My desk real estate is precious and I did not want to dedicate an UNO for this infrequent process. A separate 12V power supply is needed. I use an unused 4A Switching Mode Power Supply. I understand 12V batteries can be used. A 500mA smooth supply seems a prerequisite.

As a nod to Ralph, I included to optional steps of including a Buzzer and LED indicator.

Step 1: Materials and Tools

    There is a full Bill of Material and Sourcing list.

    1. 4x6cm Universal PCB (1)
    2. 5V Arduino Pro Mini with male headers (1)
    3. ATTINY85-20PU (1)
    4. 8 Pin DIL IC Socket (1)
    5. 2.1 x 5.5 mm DC Power Supply Jack Socket (1)
    6. BC547 NPN Transistor (1)
    7. 1K resistors (6)
    8. 150R resistor (1)
    9. 5V Buzzer (optional)
    10. LED (optional)
    11. Hookup wire (~12)
    12. Solder and Iron (1)
    13. Strong Cyanoachrylate Adhesive (1)
    14. 12V Power Supply (1)
    15. RTL-232 FTDI chip (1)

    Step 2: PCB Assembly

      The assembly below suits the power supply I had. The Power Socket and 2P male header can be swapped out with a screw terminal if it suits...

      1. On the top, insert Power Socket (glue to board), 2P header, Arduino Pro Mini, 8P DIL Socket, BC547 and solder off on bottom.
      2. Bend tabs from power socket to 2P pins and solder (+ve to WHITE3).
      3. On the top, trace a 1K resistor into BLUE1 and BLUE2 and solder. Bend lead from BLUE1 onto ORANGE9 and solder.
      4. On the top, trace a 1K resistor into BLUE3 and BLUE3 and solder. Bend lead from BLUE3 onto ORANGE10 and solder.
      5. On the top, trace a 1K resistor into BLUE5 and BLUE6 and solder. Bend lead from BLUE5 onto ORANGE11 and solder.
      6. On the top, trace a 1K resistor into BLUE7 and BLUE8 and solder. Bend lead from BLUE7 onto ORANGE12 and solder.
      7. On the top, trace a 1K resistor into BLUE9 and BLUE10 and solder. Bend lead from BLUE9 onto ORANGE13 and solder.
      8. On the top, trace a 1K resistor into WHITE5 and WHITE6 and solder. Bend lead from WHITE5 onto WHITE3 and solder.
      9. On the bottom, trace a yellow wire into YELLOW5 and BLUE2, and solder.
      10. On the bottom, trace a yellow wire into YELLOW6 and BLUE4, and solder.
      11. On the bottom, trace a yellow wire into YELLOW7 and BLUE6, and solder.
      12. On the bottom, trace a yellow wire into YELLOW2 and BLUE8, and solder.
      13. On the bottom, trace a yellow wire into YELLOW8 and ORANGE8, and solder.
      14. On the bottom, trace a black wire into WHITE2 and WHITE4, and solder.
      15. On the bottom, trace a red wire into WHITE1 and WHITE3, and solder.
      16. On the bottom, trace the lead from WHITE8 to BLUE10, and solder.
      17. On the bottom, trace the lead from WHITE7 to WHITE5, and solder.
      18. On the bottom, trace the lead from WHITE9 to WHITE4, and solder.
      19. On the bottom, trace a black wire into WHITE4 and YELLOW4, and solder.
      20. On the bottom, trace a red wire into WHITE7 and YELLOW1, and solder.
      21. [Buzzer, OPTIONAL] On the top, insert Buzzer into PINK1 and PINK2, solder on bottom.
      22. [Buzzer, OPTIONAL] On the bottom, trace a red wire into PINK1 and PINK3, and solder.
      23. [Buzzer, OPTIONAL] On the bottom, trace a black wire into PINK2 and PINK5, and solder.
      24. [LED, OPTIONAL] On the top, insert LED into PINK6 (short cathode) and PINK7 (long anode), solder on bottom.
      25. [LED, OPTIONAL] On the bottom, bend lead from PINK6 onto YELLOW4, and solder.
      26. [LED, OPTIONAL] On the top, trace a 150ohm resistor into PINK7 and PINK4 and solder.

      Step 3: Firmware Upload

      The codebase used has passed through a few hands. It has come unmodified from Ralph's GIT.

      The Arduino Pro Mini is conveniently flashed using a FTDI232 USB to TTL converter. Insert the 6P right angle pins from the Mini into the female header of the converter.
      Ensure the 5V setting is chosen on your FTDI232. Follow the instructions here using the code below (use link to GIST).

      From https://github.com/RalphBacon/ATTiny85_Fuse_Resetter/blob/master/ATTiny85_Reset.ino. For embed in Instructables.

      #include"Arduino.h"
      // AVR High-voltage Serial Programmer
      // Originally created by Paul Willoughby 03/20/2010
      // www.rickety.us slash 2010/03/arduino-avr-high-voltage-serial-programmer/
      // Inspired by Jeff Keyzer mightyohm.com
      // Serial Programming routines from ATtiny25/45/85 datasheet
      // Desired fuse configuration
      #defineHFUSE0xDF// Defaults for ATtiny25/45/85
      #defineLFUSE0x62
      #defineRST13// Output to level shifter for !RESET from transistor to Pin 1
      #defineCLKOUT12// Connect to Serial Clock Input (SCI) Pin 2
      #defineDATAIN11// Connect to Serial Data Output (SDO) Pin 7
      #defineINSTOUT10// Connect to Serial Instruction Input (SII) Pin 6
      #defineDATAOUT9// Connect to Serial Data Input (SDI) Pin 5
      #defineVCC8// Connect to VCC Pin 8
      // Added by Ralph S Bacon just for enhanced user experience
      #defineGND5// GND for buzzer
      #definePWRLED6// Power on LED
      #defineBUZZ7// Beeper pin
      int inData = 0; // incoming serial byte AVR
      int targetValue = HFUSE;
      voidsetup() {
      // 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
      // RSB "enhancements"
      // Sink the Buzzer to ground
      pinMode(GND, OUTPUT);
      digitalWrite(GND, LOW);
      // Turn on power LED
      pinMode(PWRLED, OUTPUT);
      // Buzzer / beeper
      pinMode(BUZZ, OUTPUT);
      digitalWrite(PWRLED, HIGH);
      // Let user know we're ready to go
      digitalWrite(BUZZ, HIGH);
      delay(50);
      digitalWrite(BUZZ, LOW);
      // End of RSB
      // 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);
      }
      voidloop() {
      switch (establishContact()) {
      case49:
      targetValue = HFUSE;
      break;
      case50:
      targetValue = 0x5F;
      break;
      default:
      targetValue = HFUSE;
      }
      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
      int hFuse = readFuses();
      //Write hfuse if not already the value we want 0xDF (to allow RST on pin 1)
      if (hFuse != targetValue) {
      delay(1000);
      Serial.print("Writing hfuse as ");Serial.println(targetValue, HEX);
      shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x40, 0x4C);
      // The default RESET functionality
      //shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, HFUSE, 0x2C);
      // this turns the RST pin 1 into a (weak) IO port
      //shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x5F, 0x2C);
      // User selected option
      shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, targetValue, 0x2C);
      shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x74);
      shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x7C);
      }
      //Write lfuse
      delay(1000);
      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);
      // Confirm new state of play
      hFuse = readFuses();
      digitalWrite(CLKOUT, LOW);
      digitalWrite(VCC, LOW);
      digitalWrite(RST, HIGH); //Turn off 12v
      // Let user know we're done
      digitalWrite(BUZZ, HIGH);
      delay(50);
      digitalWrite(BUZZ, LOW);
      delay(50);
      digitalWrite(BUZZ, HIGH);
      delay(50);
      digitalWrite(BUZZ, LOW);
      Serial.println("\nProgramming complete. Press RESET to run again.");
      while (1==1){};
      }
      intestablishContact() {
      Serial.println("Turn on the 12 volt power/\n\nYou can ENABLE the RST pin (as RST) "
      "to allow programming\nor DISABLE it to turn it into a (weak) GPIO pin.\n");
      // We must get a 1 or 2 to proceed
      int reply;
      do {
      Serial.println("Enter 1 to ENABLE the RST pin (back to normal)");
      Serial.println("Enter 2 to DISABLE the RST pin (make it a GPIO pin)");
      while (!Serial.available()) {
      // Wait for user input
      }
      reply = Serial.read();
      }
      while (!(reply == 49 || reply == 50));
      return reply;
      }
      intshiftOut2(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)) {
      // Nothing to do here
      }
      //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;
      }
      // Returns the value of the HFUSE
      intreadFuses() {
      Serial.println("Reading fuses");
      //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);
      int hFuse = inData;
      //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();
      return hFuse;
      }

      Step 4: Using The​ HV ATTINY85 Fuse Resetter

      1. Ensure the Serial Monitor in the Arduino IDE is set for 9600 baud.
      2. Remove the Voltage selector Jumper from FTDI converter so that all the power is derived from the 12V source.
      3. Plug the 12V power into the board.
      4. Plug the FTDI converter onto the Arduino FTDI pins and then into the USB port of the PC.
      5. Choose the correct COM port in the Arduino IDE.
      6. Open the serial monitor.
      7. Follow the instructions in the serial monitor, inputing your choice (1 or 2) into the text box and hitting enter.

      Step 5: A Simple Test

      The general workflow for enabling the use of the RESET pin as a GPIO is:

      1. Ensure the reset function is enabled, using this device, so that firmware upload is possible.
      2. Upload the firmware to the ATTINY85 that makes use of the reset pin as a GPIO.
      3. Ensure the reset function is disabled, using this device, so that using the pin as a GPIO does not trigger a reset.

      For this test, for #2 load Examples > 01. Basics > Blink, and change all pin references from 13 to 5. Without the resetting of the fuse bit this would normally reboot the ATTINY85 when setting the pin LOW.

      Step 6: Next Steps

      I initially went down this road in prototyping some RF24Mesh nodes using the ATTINY85, based on this great article.

      I'm sure having an extra usable pin on the ATTINY85 will be considered at some point.

      Share

        Recommendations

        • Tiny Home Contest

          Tiny Home Contest
        • Metalworking Contest

          Metalworking Contest
        • Water Contest

          Water Contest

        2 Discussions

        Well done. The one in my blog that you refer to is mainly meant for those who incidentally need to unbrick an attiny13/25/45/85 or reset P1.

        If one plans to do it on a regular base, a build with a dedicated Arduino such as in your project might be a more suitable option

        1 reply