# Configuring the Digispark ATTINY85 board for Arduino IDE and upgrading the bootloader This note describes the configuration of an [ATtiny85](http://www.microchip.com/wwwproducts/en/ATtiny85) based microcontroller development board named [Digispark](http://digistump.com/products/1) and similar to the [Arduino](https://www.arduino.cc/) line. It is available in many online marketplaces for roughly 1 dollar (e.g., Ebay, Amazon, AliExpress) and is shipped fully assembled, including a [V-USB](https://www.obdev.at/products/vusb/index.html) interface (a software-only implementation of a low-speed [USB](https://en.wikipedia.org/wiki/USB) device for [Atmel]( http://www.atmel.com/)'s [AVR](http://www.atmel.com/products/microcontrollers/avr/) microcontrollers). Coding is similar to Arduino: it uses the familiar [Arduino IDE](https://www.arduino.cc/en/main/software) and is already provided with a ready-to-use bootloader (fully integrated with Arduino), also allowing to be upgraded. Comparing it with the [ATmega328P](http://www.microchip.com/wwwproducts/en/ATmega328P) microcontroller, it is cheaper, smaller, and a bit less powerful. Digispark is [copyrighted](http://digistump.com/wiki/digispark/policy) by [Digistump LLC](http://digistump.com/) under the [Creative Commons Attribution-ShareAlike 3.0](https://creativecommons.org/licenses/by-sa/3.0/). ## Adding Digispark support to Arduino The Arduino IDE needs to be installed first. Check [Basic Arduino Installation]( https://www.arduino.cc/en/Main/Software) and [Install the Arduino Software (IDE) on Windows PCs](https://www.arduino.cc/en/guide/windows) for guided installation procedures. A [tutorial](http://digistump.com/wiki/digispark/tutorials/connecting) published at the [Digispark wiki](http://digistump.com/wiki/digispark) describes how to add the Digispark support to Arduino 1.6.X (1.6.4+) via the Arduino Boards Manager. Notice the last message of the *Preferences* form: “More preferences can be edited directly in the file”. If clicking the file name, the related installation directory is opened (the *digistump* root directory can be found under the *packages* subdirectory). To configure the Arduino IDE for the Digispark board, select your target device Tools -> Boards -> Digispark (Default - 16.5MHz) Select your programmer Tools -> Programmer -> Micronucleus Digispark comes with an old bootloader version (generally 1.06), anyway allowing upgrade. ## Digispark Windows PC Driver installation Three different Windows drivers can be installed for supporting the Digispark board: - the firmware upload driver, to upload [Arduino sketches](https://www.arduino.cc/en/tutorial/sketch) with the Arduino IDE via the V-USB virtual serial port included in the Micronucleus bootloader - the Micronucleus driver, to upload the bootloader via *micronucleus.exe* (e.g., for bootloader upgrade or bootloader customization) - optionally, [DigiCDC - Digispark USB CDC Serial Library](https://digistump.com/wiki/digispark/tutorials/digicdc), requiring appropriate Arduino library as well as the [V-USB driver](https://www.obdev.at/products/vusb/index.html) on the PC. The firmware upload driver is installed via the Arduino IDE and the Micronucleus bootloader upgrade driver can be set-up via https://github.com/digistump/DigistumpArduino. To install the Micronucleus driver, expand *DigistumpArduino-master.zip* into *DigistumpArduino-master*. Select *tools* directory; expand *micronucleus-2.0a4-win.zip*, Select *micronucleus-2.0a4*. Then run: Install Digistump Drivers.bat ### Upload the latest version of the bootloader [Micronucleus](https://github.com/micronucleus/micronucleus) is a bootloader designed for AVR ATtiny microcontrollers; its latest version offers significant improvements over V1.x; upgrading the bootloader allows taking advantage of the benefits described in the [Micronucleus README](https://github.com/micronucleus/micronucleus/blob/master/Readme.txt): mainly a significantly compact size. Download https://github.com/micronucleus/micronucleus and expand it to a local Windows directory. At the time of writing, the latest bootloader is Micronucleus V2.04; its file is */firmware/releases/t85_default.hex* The command to flash the bootloader is the following: https://github.com/micronucleus/micronucleus/tree/master/commandline/builds/Windows/micronucleus.exe Notice that *t85_default.hex* bootloader cannot be loaded directly to the Digispark board, as it is too big. The allow loading the bootloader, it needs to be converted into a compressed version; we will generate it with name *upgrade.hex*. Check https://github.com/micronucleus/micronucleus/issues/22 for further notes. To generate *upgrade.hex* with Windows, open a CMD at the *micronucleus* directory. Check that *micronucleus.exe* can be executed: micronucleus /? Connect the Digispark USB to the PC and check that the PC can recognize it by assigning a virtual USB port. Check the version of the bootloader (notice that 1.6 means 1.06). The old [micronucleus version v1.11](https://github.com/micronucleus/micronucleus/tree/v1.11) already comes with the upgrade releases for this version (and with the related *upgrade* directory): * micronucleus-1.11-entry_ext_reset.hex * micronucleus-1.11-entry_jumper_pb0.hex * micronucleus-1.11-entry_jumper_pb0.hex * micronucleus-1.11-ledpb1.hex * micronucleus-1.11.hex The file [*bootloaderconfig.h*](https://github.com/micronucleus/micronucleus/blob/v1.11/firmware/bootloaderconfig.h) describes these upgrade bootloader releases. To load them: micronucleus --run **.hex The default bootloader version 1.11 can be uploaded with the command micronucleus --run micronucleus-1.11.hex All option files are in the same directory. The default *micronucleus-1.11.hex* bootloader starts the device in firmware update option and keeps it waiting for software upload for 6 seconds, then runs the software. An interesting option allows initializing the Digispark to immediately run the software without the 6 seconds delay; the software upload can be accomplished via the reset pin: micronucleus --run micronucleus-1.11-entry-ext-reset-upgrade.hex Coming back to the last bootloader version, as mentioned, the reference file *t85_default.hex* (*micronucleus-master/firmware/releases/t85_default.hex*) cannot be directly uploaded as too big. Example: micronucleus --run t85_default.hex It should fail with an error like: "Program file is 1602 bytes too big for the bootloader!" In order to compress the bootloader to allow flashing the microcontroller, it has to be recompiled. Requirements: [Cygwin](https://www.cygwin.com/), [Ruby]( https://www.ruby-lang.org). The *upgrade* directory is needed. As it is not included in the latest version, it needs to be downloaded from the v.1.11 old release: Download https://github.com/micronucleus/micronucleus/tree/v1.11 Expand the zip file, select the *upgrade* directory and copy it to *micronucleus-master\upgrade* Also copy the *ruby* directory to *micronucleus-master\ruby* Keep all directory tree. Then open a CMD to *micronucleus-master*: ```bash cd upgrade gem install libusb ruby generate-data.rb t85_default.hex ``` It generates *bootloader_data.c* in the *upgrade* directory. To compile it, the AVR compiler needs to be set in the path; it generally can be found at *C:\Program Files\Arduino\hardware\tools\avr\bin*. Open a Cygwin Bash to the *upgrade* directory ```bash export PATH=$PATH:/cygdrive/c/Program\ Files/Arduino/hardware/tools/avr/bin make clean make ``` Return to the CMD; run the following: micronucleus --run upgrade.hex The bootloader upgrade should succeed. Check now the bootloader version: micronucleus -? Device should have bootloader version 2.3 (or newer). ### Other Micronucleus implementations [ArminJo](https://github.com/ArminJo) implemented a [fork for the micronucleus repository of the digispark firmware](https://github.com/ArminJo/micronucleus-firmware) with detailed documentation of installation and configuration options and many [precompiled and ready-to-install firmware releases](https://github.com/ArminJo/micronucleus-firmware/tree/master/firmware/releases). ### How to also generate the bootloader hex file Open cygwin to the *firmware* directory (it should include a *Makefile* and the configuration directory). Run export PATH=$PATH:/cygdrive/c/Program\ Files/Arduino/hardware/tools/avr/bin Note: to revise the configuration: [*firmware\configuration\t85_default\bootloaderconfig.h*](https://github.com/micronucleus/micronucleus/blob/master/firmware/configuration/t85_default/bootloaderconfig.h). This file includes comment notes describing the allowed configuration settings. For instance, edit: #define AUTO_EXIT_NO_USB_MS 1 Then run the following: ```bash make clean make CONFIG=t85_default ``` A file named *main.hex* is generated Move *main.hex* to the *upgrade* directory You can then run *ruby generate-data.rb main.hex*; this can be also achieved with Windows: with a CMD run the following: ruby generate-data.rb main.hex Return to the cygwin shell; run the following: ```bash cd ../upgrade make clean make ``` return to the CMD; run the following: micronucleus --run upgrade.hex Example: ..\commandline\builds\Windows\micronucleus.exe --run upgrade.hex Notice that the Arduino IDE configuration has to be modified in order to change the maximum sketch size allowed to be upload. ### Changing the maximum sketch size of the Arduino IDE Open a CMD Insert the Digispark to the PC USB. Run the following: micronucleus /? Check the max size of the executable program. Open the directory mentioned in the last message of the *Preferences* form (*Arduino IDE*, *File*, *Preferences*): “More preferences can be edited directly in the file”. If clicking the file name, the related installation directory is opened. Move to the *packages\digistump\hardware\avr\* subdirectory. Edit boards.txt with a UNIX editor. Set *digispark-tiny.upload.maximum_size* to the value returned by *micronucleus /?*. Example: digispark-tiny.upload.maximum_size=6520 ### Configuring and generating the v1.11 micronucleus hex bootloader Similarily to the latest bootloader version previously described, also version v1.11 can be configured and generated. Even if the hex files are ready available at the *firmware/releases* directory, the following procedure describes how to produce them. Download [micronucleus version v1.11](https://github.com/micronucleus/micronucleus/tree/v1.11). It comes with the *upgrade* directory. Edit *micronucleus/firmware/bootloaderconfig.h* For instance, set: #define AUTO_EXIT_NO_USB_MS 1 Open a cygwin bash to the *micronucleus/firmware* directory (it should include a *Makefile*) ```bash export PATH=$PATH:/cygdrive/c/Program\ Files/Arduino/hardware/tools/avr/bin make clean make ``` A file named *main.hex* is generated Move *main.hex* to the *upgrade* directory You can then run *ruby generate-data.rb main.hex*; this can be also achieved with Windows: with a Windows CMD run the following: ```bash cd upgrade gem install libusb ruby generate-data.rb main.hex ``` Return to the cygwin shell; run the following: ```bash cd ../upgrade make clean make ``` return to the CMD; run the following: micronucleus --run upgrade.hex Example: ..\commandline\builds\Windows\micronucleus.exe --run upgrade.hex The bootloader is flashed. # Schematic Diagram A valid schematic diagram for the Digispark module is at this url: http://www.electroschematics.com/wp-content/uploads/2015/08/Circuit-Diagram-of-the-ATtiny85-USB-Mini-Development-Board.png The diode between the USB and 5V shall have the cathode (+) connected to +5V and the anode (–) connected with USB V+. The Digispark [schematic diagram](https://s3.amazonaws.com/digispark/DigisparkSchematicFinal.pdf) incorrectly inverts this diode. Pinout: - https://neonaut.neocities.org/images/digispark-pinout.png - https://camo.githubusercontent.com/776b358cb7412939e03a65990fb36d0aa39e890f/687474703a2f2f6472617a7a792e636f6d2f652f696d672f50696e6f75745438352e706e67 - https://github.com/SpenceKonde/ATTinyCore Digispark pin numbering from 0 to 5: - Digispark Pin 1 is generally the internal LED (ATTINY85 pin 6, PB1) - Digispark Pin 3 is USB D- with pullup on Digispark board (ATTINY85 pin 2, PB3) - Digispark Pin 4 is USB D+ (ATTINY85 pin 3, PB4) - Digispark Pin 5 is the RESET (ATTINY85 pin 1, PB5) - Digispark Pins 0 and 2 are just wired to ATTINY85 pins 5 (PB0) and 7 (PB2). # Digispark board power consumption The power consumption of the Digispark board is influenced by: - the microcontroller (which support SLEEP mode); - the power LED (which can be removed); - the 78L05 linear regulator (which can be removed); - the LED connected to PB1 (only when the related output is set to HIGH); - the USB circuit including Zener LED (current permanently flowing between +5V, the D- pull-up resistor and the zener diode). This can be eliminated by disconnecting the D- pull-up resistor from +5V and connecting it to USB V+ instead; in this case, the power consumption only happens when the USB is connected. The Digispark ATtiny85 device has to be modified as follows to save power: - remove the power led; - remove the linear voltage regulator of the Digispark (LM78L05 has a quiescent current of about 2.5 to 3 milliamperes) and in case substitute it with diodes in series (or zener) to reduce the voltage to about 3.2V (this contributes to reduce quiescent current to the minimum); - enable D- pull-up only when the USB is connected (it can be achieved by moving the pull-up resistor connection to take the positive voltage directly from the USB +5V and not from the Digispark internal +5V, which is after the schottky diode separating USB from the internal +5V; this configuration reduces power consumption by avoiding current flow throgh the D- zener during normal operation and in parallel preserving the D- pull-up when USB is connected, which is anyway needed by the USB hw interface); Notice that after the modification of the D- pull-up resistor, the Digispark bootloader has to be flashed with "#define ENTRYMODE ENTRY_EXT_RESET" in micronucleus-master/firmware/configuration/t85_default/bootloaderconfig.h; then use the Digispark reset pin to enable the firmware upload. Setting ENTRYMODE to ENTRY_EXT_RESET avoids to hang the Digispark if D- is not pulled-up. A micro-switch between D5 and ground is appropriate, also pulling up D5 to VCC with a 22kohm resistor. # Notes ## Notes on serial monitoring ATtiny85 does not provide a native serial interface, but it can be generated via software: - [bit-bang two-way serial half-duplex (two pins)](https://github.com/digistump/DigistumpArduino/tree/master/digistump-avr/libraries/DigisparkSoftSerial) - [bit-bang serial-out (one pin)](https://github.com/ArminJo/ATtinySerialOut) Both provide a TTL UART hardware interface (using one or two pins different from P3 and P4, used for USB). If the PC has a physical serial port, an external TTL-to-RS232 hardware interface is needed. If USB is required to connect a PC, an external UART-USB hardware converter is needed. The above described options are ways to monitor a Digispark via Arduino "serial monitor". Similarly to the UART serial port, USB monitoring can be emulated via a bit-bang software implementation of the Digispark USB interface, emulating a serial port. All these options do not allow monitoring via Arduino "serial monitor". - [DigiCDC](https://digistump.com/wiki/digispark/tutorials/digicdc), based on the [V-USB project](https://www.obdev.at/products/vusb), needs appropriate Windows PC driver; it uses a software interrupt and needs no other timers or interrupts to be enabled in parallel to correctly work. Besides, to avoid USB problems, DigiCDC shall be started just after the microcontroller boot and shall be kept always active. It is slow and if you don't call a DigiCDC function (write, print, read, available, etc) every 10ms or less then you must throw in some *DigiCDC.refresh();* for the USB to be kept alive - also replace your delays (i.e., "*delay(100);*") with *DigiCDC.delays* (i.e., "*DigiCDC.delay(100);*"). - In order to to limit the code size, the suggested method for debugging and monitoring is [emulating an USB keyboard](https://digistump.com/wiki/digispark/tutorials/digikeyboard) through the [DKeyboard library](https://github.com/Ircama/AtTinyTestIR/tree/master/libraries/DKeyboard). No software driver is needed for the PC. It is suggested to include all monitoring code within related *#define*, so that it can be disabled for normal operation, when not needed. Avoid using punctuation and symbols in text strings (use just letters and numbers). DKeyboard example: ```c #define USE_KEYBOARD #define KEYBOARD_DELAY 1500 // Time to wait for the PC keyboard driver to become ready #ifdef USE_KEYBOARD #include "DKeyboard.h" // Use a modified tiny DigisparkKeyboard library DKeyboardDevice Db = DKeyboardDevice(); // instantiate the Keyboard driver #endif void setup() { ... #ifdef USE_KEYBOARD Db.sendKeyStroke(0); Db.delay(KEYBOARD_DELAY); // This is needed to wait for the PC keyboard driver to become ready Db.sendKeyStroke(0); // This will ensure no character will be lost #endif ... } void loop() { ... #ifdef USE_KEYBOARD Db.print("Value result is "); Db.println(value); Db.print("Hex value is "); Db.println(hexvalue, HEX); Db.delay(300); // ensure that the transmission is performed before the interrupt is turned off #endif ... } ``` Steps to use DKeyboard for debug log monitoring: - Create a new folder called [DKeyboard](https://github.com/digistump/DigistumpArduino/tree/master/digistump-avr/libraries/DigisparkKeyboard) under the folder named "libraries" in your Arduino sketchbook folder. Create the folder "libraries" in case it does not exist yet. Copy all the files under libraries/DKeyboard to the target "DKeyboard" subfolder. This is a modified version of DKeyboard that slightly reduces its size so that it can be loaded to the Digispark ATTINY85 device. ATtiny85 presents itself to the PC as a keyboard USB HID. - Connect the Digispark to the PC via USB - Compile and load. If getting ["operator '*' has no left operand" in "usbdrv.h:662:33"](https://digistump.com/board/index.php?topic=2942.0), with an editor open *usbdrv.h* in the Arduino *libraries* directory (e.g., *Arduino\libraries\DKeyboard\usbdrv.h*) and replace `define USB_INTR_PENDING GIFR` with any value above 0x40, like `define USB_INTR_PENDING 0x41`. - Immediately after the code is successfully uploaded, remove the Digispark USB from the PC (to prevent interference of the emulated keyboard) - Open a Notepad and put the Windows focus there (maximizing the Notepad window is also suggested to prevent accidentally losing the focus) - Insert the USB to the PC (do not move the focus out of the Notepad window until the USB is connected) False errors of missing USB driver messages can occur with Windows (should be ignored). If no data is shown, increase KEYBOARD_DELAY timer. The following DKeyboard *Hello World* code takes 2784 bytes (42% of the available rooms): ```c #define KEYBOARD_DELAY 1500 #include "DKeyboard.h" DKeyboardDevice Db = DKeyboardDevice(); void setup() { Db.sendKeyStroke(0); Db.delay(KEYBOARD_DELAY); Db.sendKeyStroke(0); } void loop() { Db.println("Hello World"); Db.delay(300); } ``` DKeyboard needs timer interrupt disabled. If timer interrupt is used (e.g, [IRMP](https://github.com/ukw100/IRMP) or [IRemote](https://github.com/z3t0/Arduino-IRremote), interrupts shall be temporarily disabled. ## Note on sleep mode The following sample allows calling *sleep()* to enter sleep mode to the lowest power level. It puts the processor in quiescent mode and uses Pin 0 to resume from sleep. ```c #include #include void sleep() { #if defined (__AVR_ATtiny85__) cli(); // Disable interrupts GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts PCMSK |= _BV(PCINT0); // Use Pin 0 interrupt pin to resume from sleep ADCSRA &= ~_BV(ADEN); // ADC off set_sleep_mode(SLEEP_MODE_PWR_DOWN); // set sleep to the lowest power mode sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT) sei(); // Enable interrupts sleep_cpu(); // sleep cli(); // Disable interrupts PCMSK &= ~_BV(PCINT0); // Turn off interrupt on pin 0 GIMSK &= ~_BV(PCIE); // Turn off Pin Change Interrupts sleep_disable(); // Clear SE bit ADCSRA &= ~_BV(ADEN); // ADC off (if needed...) sei(); // Enable interrupts #endif } // sleep #if defined (__AVR_ATtiny85__) ISR(PCINT0_vect) { // This is called when the interrupt occurs TIMER_RESET; // reset irrecv timer irrecv.resume(); // reset irrecv counter previousTime = millis(); // reset sleep timer } #endif ``` ## Note on the RESET pin P5 (PB5) is the reset pin. Depending on the Digispark hardware, the reset function can be enabled or disabled. [The default hardware implementation should have it disabled](https://digistump.com/wiki/digispark/tutorials/programming); in this case, bootloaders can be upgraded (the Micronucleus bootloader works and sketches can be uploaded using the bootloader), but ISP programming is disabled (as ISP connection needs the enabled RESET function; notice that ISP programming can be done via ISP device or via an appropriately confugured Arduino or Digispark). Disabling the reset-function can be done through the RSTDISBL fuse via either ISP or HVSP programming (without High-voltage Serial Programmer), but cannot be done via Micronucleus bootloader. Enabling the reset needs an [High-voltage Serial Programmer](https://www.instructables.com/id/How-to-unlock-Digispark-ATtiny85-and-convert-it-to/) and cannot be done via ISP device (or Micronucleus bootloader). When reset is disabled, you get a full application pin. If reset is enabled, pin 5 resets the microcontroller if the voltage is lower than around 2.5V. Anyway [this pin can still be used as input](https://electronics.stackexchange.com/questions/195146/use-the-reset-pin-on-attiny85-as-input-with-voltage-divider) with *analogRead(0)* when staying over 3V. *analogRead(0)* values between 620 and 1023 are generally safe to be used for applications without generating unwanted resets. Notice that *0* is the pin number to read the reset pin via *analogRead*. The reset pin has a 30 to 60 kOhm [internal pull-up resistor](https://electronics.stackexchange.com/questions/422895/does-attiny-reset-pin-need-a-resistor) and the default value read by *analogRead(0)* is a bit lower than 1023 (empirically, 984 to 986, meaning about 96%). Reading 1023 can be done through an external pull-up. ## Note on analogRead The analog pins are referenced by their [analog port number](https://digistump.com/wiki/digispark/tutorials/basics), not the Digispark pins: ```c analogRead(1); // Read Digispark pin P2 analogRead(2); // Read Digispark pin P4 analogRead(3); // Read Digispark pin P3 analogRead(0); // Read Digispark pin P5 ``` ## Note on LED Depending on the hardware, the internal Digispark LED is connected to P1 in model A (most used), or on P0 in model B.