The other week I was playing with a Digispark clone, and it turns out that the suppliers have not programmed them correctly.
Let me explain
When Erik created the Digispark, he wanted to use all 6 pins of the ATTiny85 for I/O.
Because there is a bootloader, you can program them as per any other Arduino (slight differences but essentally the same), rather than having to use an ISP programmer.
The reset pin has been disabled via the fuse setting, and therefore becomes a normal I/O pin.
The schematic is published here.
https://s3.amazonaws.com/digispark/DigisparkSchematicFinal.pdf
What about the clones
The clones have a micro USB connector, which suited my project, while the proper Digispark have the USB plug as part of the board design.
For my application, I wanted something that you could plug into and hide the cable underneath.
Hence these suited my physical need, but it turns out the electrical spec was something else.
The sketch I wrote needed three pins.
Neopixel out.
Hall effect sensor #1 in.
Hall effect sensor #2 in.
Since two pins are already in use for the USB and are either held high, or dragged down by a 3v6 zener, it meant I needed to be very careful about what was where, which is why that extra pin is so useful.
These clones I purchased have the bootloader programmed, but the reset pin remains as a reset.
The simple test is to program the blink porgram into it, then using a 220 ohm resistor, connect pin P5 to ground, and the blinking will stop for 5 secs, while it restarts.
So the only way to resolve it was to reset the fuses, and program the correct fuse setting to remove the reset pin function.
Fuses
We tend to think of fuses as one time devices, that are used to protect circuits or wiring from an overload.
In the world of micro's, the term fuse is a part in the device that is set, and remains that way unless it is reset.
For the ATTiny range, they apply 12v to the reset pin, and send some data into the device to reset the fuse.
Lady Ada has a good intro here
Hackady had an article that linked to here
https://embedderslife.wordpress.com/2012/08/20/fuse-bits-arent-that-scary/
All about Circuits have this (which links to the calculator)
https://www.allaboutcircuits.com/Projects/atmega328p-fuse-bits-and-an-external-crystal-oscillator/
This looks like a very good resource to calculate any fuse on any Atmel micro.
Fuse Resetter
I did some digging around and found this on the Digispark forums.
http://digistump.com/board/index.php/topic,1039.0.html
The sketch includes a link to here, which includes the sketch
https://sites.google.com/site/wayneholder/attiny-fuse-reset
// 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: "); 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; }
You need some form of micro to drive the pins and control the 12v.
In each of the discussions, they talk about using an external 12v source, and I thought why not just feed the Arduino with 12v via the external input, and use that.
Warning the ATmel chips want 11.5-12.5v only.
Since I was going to be making some hardware, it seemed only sensible to include a 8pin socket and the normal ISP connections, that way it could be used for other projects.
Protoboard
Freetronics (Australia) make a range of Arduino and a couple of Prototyping boards.
They are great but I do wish they would allow more material around the holes, as soldering to the rails is a bit difficult with the heat loss.
I wired it onto one of their short boards, and starting thinking if I'd started a few months earlier, I could have made a pcb.
Regardless it got wired and I resisted skipping the other bits.
It's not the tidyiest work, and as you can see, a modification was required.
Some eagle eyed readers may ask, "how come the clone board is stting up, what magic does he use".
In order to get a good contact, I chose to use slightly longer header pins, and after the clone was fitted, to bend the pins so that each pin is alternately bent away from straight.
You need to use something to put a little pressure on the pin to straighten it when fitting another board, but it works well for this purpose.
Whats the deal with D12.
When I first tried this it didn't work.
The sketch either hung or gave nulls for the readings, and it took a while to sink in.
D12 goes to PB3, which is held at approx 3.6v via R3 and the Zener, it connects via R1 which is 68 ohms, so the 1k in series with the Arduino had no chance of pulling the pin low.
The 1K series resistor is there to prevent accidents, but since this was hard-wired to the Digispark, this wasn't an issue.
Hence there is a wire from D12 to PB3, and the 1K resistor is in series to the 8 pin socket and ISP connector.
Digispark Fuses
There was some debate about the fuse setting.
Erik kindly resolved that in this post http://digistump.com/board/index.php/topic,2257.msg12219.html#msg12219
where he stated the fuses are :-
Here are the fuse settings we use:
Low fuse: 0xe1
High fuse: 0x5d
Extended fuse: 0xfe
Bootloader
During all my playing, I have wiped out the bootloader, and generally messed it up.
The good news is that you can reprogram them, but you can't use an ISP programmer once you've done the fuse setting thing.
There is a full story here http://digistump.com/board/index.php/topic,1414.msg6547.html#msg6547
but essentually :-
- you have to ensure the computer recognises the device
- Obtain the bootloader (under xxxxxxx\hardware\digispark\bootloaders\micronucleus where xxxxxx represents the directory you have the Digispark IDE stored in)
- Program it using
avrdude.exe -p attiny85 -c usbasp -U flash:w:ZZZZZ.hex:i -U lfuse:w:0xe1:m -U efuse:w:0xfe:m -U hfuse:w:0x5d:m (
and ZZZZZZ represents the bootloader chosen) - Wait 10 secs or so for it to write.
5 sec boot delay
The original bootloader allowed a 5 sec wait period during bootup to enable a new program to be downloaded.
After some discussion, Bluebie (Genna Fox) wrote a version that required P5 to be held low when it started which then forced the bootloader to look for a new program.
You simply upload it following the instructions, but a warning that micronucleus can have issues with some PC's due to speed.
So here is something that I wasn't planning on doing, but got forced into it in order to complete the project.
As some of you will be aware, adding another week sorting out hardware issues into a tight deadline is not the best receipe for reducing stress.
Hopefully some time next week, I might be able to share the other project that caused this issue.
Cheers
Mark
Top Comments