DigiSpark with 6 input/output pins, homebrew fuse-programmer
Posted: 16 Apr 2019, 02:13
One of the advantages of the old 8-pin PIC chips was that other than pos & neg, all six remaining pins
were available for I/O. This isnt the case for the Atmel ATTiny chips: as supplied the DigiSpark has five
I/O pins, as does the bare ATTiny85 on which its based. The sixth terminal, P5 on the DigiSpark board and
pin 1 on the Attiny85 chip is the 'Reset' pin used by the programmer.
However.... in fact this pin has two functions, it can be 'Reset' or it can be another I/O pin, with
interrupt, analogue and digital modes, and can be configured with 'pullup' just like any other pin.
In a nutshell, to program the board P5 must be configured as a Reset pin, and this is how its supplied
by default. To use P5 as I/O just like any other pin, it has to be set to I/O. This setting is determined by
one single bit of the high-fuse. For DigiSpark users, the only hfuse values of interest for this purpose
are DF which means P5 is a reset pin, and 5F which means its I/O.
To change any of the fuses requires a special high-voltage programmer, which few people have access to.
So after all this preparatory waffle, here's a project specifically designed to flip the DigiSpark P5
between Reset and I/O. Whilst the fuse-programming routines are by Paul Willoughby and Jeff Keyzer,
I've condensed the project into a small hand-held, stand-alone device and added an OLED display.
Being stand-alone means its self-contained, you dont need to plug it into your PC.
Its powered from something very near to 12v, I use a small 3S lipo which is perfect. It has to be close to 12v as thats the fuse programming voltage.
Initially the screen displays the current DigiSpark fuses. The one we're interested in is the hfuse, and
the hfuse values of DF and 5F. After showing the current fuse settings, if the power is held on,
then hfuse is set to DF. If the power is still held on, then hfuse is set to 5F. The programmer only powers up the DigiSpark for the duration of the fuse-setting - you can see the DigiSpark power LED going on/off.
An hfuse value of DF means P5 is RST and the DigiSpark can be programmed, 5F means P5 is I/O. Simply remove the power when desired setting is shown. I use a tiny 12v battery via a momentary push-button, so to read the DigiSpark I press and then read the screen. If hfuse is as required then the button can be released. If hfuse needs to be changed, just keep the button pressed until the desired value is shown.
I've done it this way to avoid any 'reset/io' switches, its easier to make and easier to use - but you could
add a selection switch if you prefer - though it really doesnt matter on an 'occasional use' tool.
You could make it even simpler by replacing the screen with a red/green bicolour LED - red is reset, green is go for i/o!
Of course this is all quite separate from normal Arduino IDE programming. Lets say as a test you want
to load 'blink' set to flash D5. In order to load the sketch "blink_D5" P5 needs to be a reset pin, hence hfuse
needs to be DF as it is when the DigiSpark is supplied. The sketch will load fine, but won't flash P5
yet as its not an I/O pin - its 'reset'.
So after loading 'blink_D5' you pop the DigiSpark into the fuse programmer and set hfuse to 5F.
The DigiSpark will now flash P5 as expected with D5 (P5) behaving just like any other I/O pin*.
But in this state, you cant reprogram it as the programmer needs a reset pin! So, if you need to make
changes, pop it back into the fuse programmer and set hfuse to DF. Now 'blink_D5' wont work, but
the DigiSpark is programmable again. Its a juggling act, so its best to be sure that P5's job is tested &
working, maybe temporarily using an 'easier' pin before moving the task onto P5.
Since it optionally has a pull-up, its ideal as a button input, an option switch or configuration link.
* though it doesnt have the full 20mA current capacity of other pins
Here's the project, I'll upload the sketch and do a vero layout (its very easy to make) and maybe a
video of it in use. Its much easier & quicker to use than to explain
... and a 20% increase in I/O capability is well worth having
I've posted a few pics so the stripboard layout can be seen. Note the cut between vcc and ground on the 2-pin DigiSpark header.
The two resistors nearest the transistor are both 1k, and the two leading to the DigiSpark P5 and Vcc are zero-ohm links. The transistor is a 2N3904, the same NPN as we use as a buzzer-buffering tranny.
The 12v battery will be replaced by a 27A 'fob' battery in a holder, On the two-pin header, the 12v rail is nearest the edge of the board. The link in the top-right corner connects 12v from the 2-pin battery header to the Raw input of the Nano - its not necessary, a solder bridge will do. I just used the link in testing.
were available for I/O. This isnt the case for the Atmel ATTiny chips: as supplied the DigiSpark has five
I/O pins, as does the bare ATTiny85 on which its based. The sixth terminal, P5 on the DigiSpark board and
pin 1 on the Attiny85 chip is the 'Reset' pin used by the programmer.
However.... in fact this pin has two functions, it can be 'Reset' or it can be another I/O pin, with
interrupt, analogue and digital modes, and can be configured with 'pullup' just like any other pin.
In a nutshell, to program the board P5 must be configured as a Reset pin, and this is how its supplied
by default. To use P5 as I/O just like any other pin, it has to be set to I/O. This setting is determined by
one single bit of the high-fuse. For DigiSpark users, the only hfuse values of interest for this purpose
are DF which means P5 is a reset pin, and 5F which means its I/O.
To change any of the fuses requires a special high-voltage programmer, which few people have access to.
So after all this preparatory waffle, here's a project specifically designed to flip the DigiSpark P5
between Reset and I/O. Whilst the fuse-programming routines are by Paul Willoughby and Jeff Keyzer,
I've condensed the project into a small hand-held, stand-alone device and added an OLED display.
Being stand-alone means its self-contained, you dont need to plug it into your PC.
Its powered from something very near to 12v, I use a small 3S lipo which is perfect. It has to be close to 12v as thats the fuse programming voltage.
Initially the screen displays the current DigiSpark fuses. The one we're interested in is the hfuse, and
the hfuse values of DF and 5F. After showing the current fuse settings, if the power is held on,
then hfuse is set to DF. If the power is still held on, then hfuse is set to 5F. The programmer only powers up the DigiSpark for the duration of the fuse-setting - you can see the DigiSpark power LED going on/off.
An hfuse value of DF means P5 is RST and the DigiSpark can be programmed, 5F means P5 is I/O. Simply remove the power when desired setting is shown. I use a tiny 12v battery via a momentary push-button, so to read the DigiSpark I press and then read the screen. If hfuse is as required then the button can be released. If hfuse needs to be changed, just keep the button pressed until the desired value is shown.
I've done it this way to avoid any 'reset/io' switches, its easier to make and easier to use - but you could
add a selection switch if you prefer - though it really doesnt matter on an 'occasional use' tool.
You could make it even simpler by replacing the screen with a red/green bicolour LED - red is reset, green is go for i/o!
Of course this is all quite separate from normal Arduino IDE programming. Lets say as a test you want
to load 'blink' set to flash D5. In order to load the sketch "blink_D5" P5 needs to be a reset pin, hence hfuse
needs to be DF as it is when the DigiSpark is supplied. The sketch will load fine, but won't flash P5
yet as its not an I/O pin - its 'reset'.
So after loading 'blink_D5' you pop the DigiSpark into the fuse programmer and set hfuse to 5F.
The DigiSpark will now flash P5 as expected with D5 (P5) behaving just like any other I/O pin*.
But in this state, you cant reprogram it as the programmer needs a reset pin! So, if you need to make
changes, pop it back into the fuse programmer and set hfuse to DF. Now 'blink_D5' wont work, but
the DigiSpark is programmable again. Its a juggling act, so its best to be sure that P5's job is tested &
working, maybe temporarily using an 'easier' pin before moving the task onto P5.
Since it optionally has a pull-up, its ideal as a button input, an option switch or configuration link.
* though it doesnt have the full 20mA current capacity of other pins
Here's the project, I'll upload the sketch and do a vero layout (its very easy to make) and maybe a
video of it in use. Its much easier & quicker to use than to explain
... and a 20% increase in I/O capability is well worth having
I've posted a few pics so the stripboard layout can be seen. Note the cut between vcc and ground on the 2-pin DigiSpark header.
The two resistors nearest the transistor are both 1k, and the two leading to the DigiSpark P5 and Vcc are zero-ohm links. The transistor is a 2N3904, the same NPN as we use as a buzzer-buffering tranny.
The 12v battery will be replaced by a 27A 'fob' battery in a holder, On the two-pin header, the 12v rail is nearest the edge of the board. The link in the top-right corner connects 12v from the 2-pin battery header to the Raw input of the Nano - its not necessary, a solder bridge will do. I just used the link in testing.
Code: Select all
/*
Blink P5 For Kickstarter ATTiny85. Use a 5v LED to avoid the need for a resistor.
*/
#define led 5 // Long leg (pos) of a 5v LED connected to P5
#define ground 4 // use P4 as a convenient 'negative' for the 5v LED short leg
void setup() {
pinMode(led, OUTPUT);
pinMode(ground, OUTPUT); // use P4 as a convenient 'ground' for the 5v LED short leg
digitalWrite(ground, LOW);
}
void loop() {
digitalWrite(led, HIGH); // make P5 high
delay(300); // wait
digitalWrite(led, LOW); // make P5 LOW
delay(700); // wait
}