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

AVR Tutorial - Fuses

 

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.

Engbedded AVR Fuse Calculator

 

 

 

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