loading

Digispark ATtiny85 boards come with the Micronucleus bootloader and with the reset pin disabled. When reset is disabled you get an additional digital pin, and you must upload sketches using the bootloader. You may not use ISP programming.

There are projects where I want to use Digispark and need to enable the reset pin for various reasons:

  • Reset Digispark via a signal from another device or via a button
  • Use ISP programming to upload sketches
  • Remove bootloader start up delay
  • Upgrade bootloader
  • Use a different bootloader, such as Trinket
  • Change fuses

This Instructable documents how I unlock the reset pin and program the Digispark with ISP programming to convert it to a Trinket. I have a clone Digispark, which works the same as the Kickstarter Digispark from Digistump.

In this Instructable, I use an Uno as the high voltage programmer, and later I use it as an ISP. You can also use a Nano or Pro Mini, which are simply small Unos.

Using this method you can continue to use the board as a Digispark, or use it as a plain ATtiny85 breakout board and program it via ISP, or use it as a Trinket. If you continue to use the board as a Digispark, the P5 pin has been converted from a regular I/O pin to a reset pin.

Since the Digispark is simply a small break out board for the ATtiny85 MCU, you can also use this Instructable to rescue fuses on a stand alone ATtiny85 MCU.

Step 1: Sketch for High Voltage Programming

A sketch for Uno is available here for unlocking ATtiny85:

http://www.rickety.us/wp-content/uploads/2010/03/hv_serial_prog.pde

Code is by Paul Willoughby and original article for unlocking bare ATtiny85 ICs here:

http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/

Sketch:

// 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 #define HFUSE 0xDF // Defaults for ATtiny25/45/85 #define LFUSE 0x62

#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(); }

<p>When I found the Digispark clones on Banggood, I bought a handful because I became addicted to SMALL -- if all you want to do is drive a couple of LEDs or some NeoPixels, who needs an Uno, right? Cheap too, but mostly small. This is a great, detailed tutorial with sharp pictures, details and (forgive me for this) understandable English. Very educational, I will benefit from your experience, thanks. You are bookmarked.</p>
<p>Not sure why that comment posted twice and even more not sure why it took me so long to see that it had posted twice and delete the second one.</p>
<p>I made an all-in-one plug-in board with HV programmer for Digispark (left) and regular ICSP programmer for Digispark (right) and ATmega328/168. I have room for a 5V-to-12V booster lower left to be added (item ordered and in transit). The capacitor for the reset is activated by a simple jumper. I added two tiny LED (from analog outputs 18 &amp; 19): one that flashes at low intensity while waiting for character entry, and runs full light when in program mode, and one that runs full light when 12V is active. ..a bit of gadgetry but fun to see.</p><p>Delay time for 12V kick-in in program adapted to 40usec. Fuses for Digispark adapted equally: see my previous note here.</p>
<p>Forgot to add this spaghetti-picture-underside.</p>
<p>How do you set the extended fuse with this program? Or don't you need a HV programmer for this fuse?</p>
I think that is the case, you don't need a HV programmer for the extended fuse because nothing about the extended fuse could cause the chip to be non-programmable via ISP. I did not study this programmer code in detail or alter it, it is from a different blog and I just adapted the schematic a little bit to work with Digispark boards. <br><br>I have another Instructable https://www.instructables.com/id/HV-Rescue-Simple/ that is based on Jeff Keyzer's version 2 of his HV Rescue Shield. I simplified the hardware to make it breadboard-based with fewer components, and enhanced the sketch to work with most Arduinos and give it a menu with control of the fuse values.
I looked at this instruction; can you upload the &quot;HV Rescue Simple schematic.png&quot; with higher resolution? The current one is barely readable. Thks!<br>
<p>I just downloaded the zip file and in it is the schematic. I was able to zoom the schematic to any size with my favorite image editing program. I think you just need to zoom in if it is too small.</p>
<p>Fuse settings are wrong if you want to emulate the Digispark settings without pin5 reset disabled. Lfuse needs to be E1 and Hfuse need to be DD. Efuse should be FE.</p>
<p>I don't think I agree with using the word &quot;wrong.&quot; Those are my preferred fuse values. The differences between those and what the Digispark comes set with are brown out detection, EESAVE, and start up time. Digispark's official values are on this page: http://digistump.com/wiki/digispark/tutorials/programming </p>
<p>You are right, your instructable says &quot;..return to a trinket.&quot;, not &quot;return to Digispark&quot;. I should have used the word &quot;different&quot;.</p><p>However, it would still be usefull for anyone wanting to use their Digispark with the USB downloader, that the fuse settings must be adapted in your program.</p>
<p>Works well, except on two Digispark where I had the RSTDSBL set (pin5 as output, no reset). On one Digispark the program hangs 2 minutes at reading lfuse, then finalises ok. The other Digispark causes the program to hang after lfuse reading as E0.</p><p>Strange thing is it works well on Digisparks where RSTDSBL is not set.</p><p>What could be the reason?</p><p>Erik</p>
<p>I think I may have solved it: I increased &quot;delayMicroseconds(20);&quot; to 60: page 156 of the datasheets specifies between 20 and 60 microseconds delay between Vcc and Reset High..</p>
<p>This is an interesting instructable, in regards to the reference to the 12v battery . I haven't seen a battery on other programmers, so this bears making time for more reading. Thanks for the clarification on why you used 100-ohm resistors, versus the 1k used in the other page you referenced. :-)</p>
<p>Great instructable and thank you for sharing it :-D</p><p>Your instructable solved my problem to an extent.</p><p>When I tried to program digispark's attiny85 to run a blink code with a delay of 1000ms, the delay doesnt seem to be 1000ms. Instead it is observed to be around 16000ms. I measured it using a stopwatch I programmed the attiny85 with the method that you have decribed. Any solutions to the above problem? TIA :-)</p>
<p>You may also want to check out this Fuse Calculator (http://www.engbedded.com/fusecalc), if you want to get a bit deeper into the AVR programming side. Clock speed is just one facet you can modify in that programming sketch. This helped me to get the Tiny85 running at 16 MHz internal clock. More clues can be found in one of my Instructables, https://www.instructables.com/id/IKEA-Star-With-ATtiny-and-NeoPixels/</p>
I think the fuse settings and the core you use when you compile a sketch for it determine how fast the processor runs. It sounds like your sketch is compiled for 16MHz but your processor is actually running at 1MHz if you are noticing that speed difference. If you have put the Micronucleus bootloader back onto it and are programming it as a Digispark, then you should be able to find information on the Digispark website or wiki about speeds. If you have put the Trinket bootloader on it and are programming it as a Trinket, you should be able to find information in Adafruit's tutorials or forums about that. There are a variety of cores you can use to add on to the Arduino IDE to program plain ATtiny85's using an ISP programmer, and most of those will involve using the Burn Bootloader function of the IDE to set the fuses to the appropriate values. Help for using those cores could probably be found at the arduino.cc website in the Microcontrollers section of the forum.
<p>Thanks for this great Instructable!</p><p>This worked really nicely. I had a bricked clone-spark due to a failed bootloader attempt. This brought it back to life and upgraded it with the addition of the Digispark bootloader (so it's much easier to program now).</p><p>Worked like a charm - it was so easy I almost thought I'd screwed it up :D</p><p>In case it helps others to know: I used a PN2222A transistor, and a direct-clip-on adapter that allowed me to directly connect to the chip (I haven't put headers on the board, to keep it tiny).</p>
<p>Thanks! I was messing with my digisparks bootloader and bricked it, this tutorial helped me save it! After hours of searching on the web, this is the absolute best tutorial i found! It should be noted that I did not use the 100ohm resistors or pin 13 to transistor and it still worked! (although it was probably risky), i just connected the 1kohm resistor from the battery to pin 5 manually without a transistor. Thanks again!</p>
<p>Thanks, I have edited the Instructable to include the alternate wiring. </p>

About This Instructable

17,412views

48favorites

License:

Bio: These Arduinos are driving me up the wall.
More by dmjlambert:HV Rescue Simple How to unlock Digispark ATtiny85 and convert it to a Trinket Bluetooth Serial Adapter for Pro Mini 
Add instructable to: